/** * Copyright 2010 The University of North Carolina at Chapel Hill * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package unc.lib.cdr.workbench.views; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; public class ImageViewer extends Canvas { /* * Note that instances of this class do not manage the image. That is, the image will not be disposed() by this * instance under any conditions. Users of this class must manage the image. */ private Image image; private boolean stayClosed = false; protected boolean showingEnlargedImage = false; public ImageViewer(Composite parent, int style) { super(parent, style); initialize(); } private void initialize() { addPaintListener(new org.eclipse.swt.events.PaintListener() { public void paintControl(org.eclipse.swt.events.PaintEvent e) { if (image == null) return; drawImage(e.gc); } }); // addListener(SWT.MouseMove, new Listener() { // public void handleEvent(Event event) { // if (image == null) // return; // if (getDrawingBounds().contains(event.x, event.y)) // showEnlargedImage(); // else // stayClosed = false; // } // }); // addListener(SWT.MouseExit, new Listener() { // public void handleEvent(Event event) { // stayClosed = false; // } // }); } private void drawImage(GC gc) { if (image == null) return; if (image.isDisposed()) return; Rectangle imageBounds = image.getBounds(); Rectangle drawingBounds = getDrawingBounds(); gc.drawImage(image, 0, 0, imageBounds.width, imageBounds.height, drawingBounds.x, drawingBounds.y, drawingBounds.width, drawingBounds.height); } private Rectangle getDrawingBounds() { Rectangle imageBounds = image.getBounds(); Rectangle canvasBounds = getBounds(); double hScale = (double) canvasBounds.width / imageBounds.width; double vScale = (double) canvasBounds.height / imageBounds.height; double scale = Math.min(1.0d, Math.min(hScale, vScale)); int width = (int) (imageBounds.width * scale); int height = (int) (imageBounds.height * scale); int x = (canvasBounds.width - width) / 2; int y = (canvasBounds.height - height) / 2; return new Rectangle(x, y, width, height); } private void showEnlargedImage() { if (showingEnlargedImage) return; if (stayClosed) return; if (image == null) return; if (image.isDisposed()) return; final Rectangle imageBounds = image.getBounds(); Rectangle canvasBounds = getBounds(); // Don't bother if the image is smaller than the canvas. if (imageBounds.width < canvasBounds.width & imageBounds.height < canvasBounds.height) return; Rectangle displayBounds = getDisplay().getBounds(); int x = (canvasBounds.width - imageBounds.width) / 2; int y = (canvasBounds.height - imageBounds.height) / 2; Point where = toDisplay(new Point(x, y)); x = Math.max(0, Math.min(where.x, displayBounds.width - imageBounds.width)); y = Math.max(0, Math.min(where.y, displayBounds.height - imageBounds.height)); final Shell shell = new Shell(getShell(), SWT.NO_TRIM); shell.setBounds(x - 1, y - 1, imageBounds.width + 2, imageBounds.height + 2); shell.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { e.gc.drawImage(image, 1, 1); e.gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLACK)); e.gc.drawRectangle(0, 0, imageBounds.width + 1, imageBounds.height + 1); } }); shell.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent e) { stayClosed = true; showingEnlargedImage = false; shell.close(); } }); shell.addListener(SWT.MouseExit, new Listener() { public void handleEvent(Event event) { showingEnlargedImage = false; shell.close(); } }); shell.open(); } /** * This method sets the image that the receiver is responsible for drawing. This class does not manage the image; it * only displays it. Any image the receiver is currently displaying will simply be replaced by the value provided in * the parameter. The caller is responsible for disposing the images. * * @param image * the Image to display. */ public void setImage(Image image) { this.image = image; this.getDisplay().asyncExec(new Runnable() { @Override public void run() { redraw(); }}); } }