Permalink
Browse files

add preview support for images

  • Loading branch information...
1 parent d631597 commit 6b37c0a29152fda6639730d8d288f2c812f8ee36 @gregjan gregjan committed Aug 9, 2012
@@ -344,7 +344,8 @@
</menu>
<command
commandId="cdr-workbench.commandOpenCopySystemEditor"
- label="Open copy in default editor"
+ label="Open a Copy"
+ mnemonic="o"
style="push">
<visibleWhen
checkEnabled="false">
@@ -426,7 +427,7 @@
</command>
<command
commandId="cdr-workbench.commandOpenCopySystemEditor"
- label="Open copy in default editor"
+ label="Open a Copy"
style="push">
<visibleWhen
checkEnabled="false">
@@ -1000,6 +1001,16 @@
<adapter
type="unc.lib.cdr.workbench.originals.OriginalFileStore">
</adapter>
+ <adapter
+ type="unc.lib.cdr.workbench.views.ImageProvider">
+ </adapter>
+ </factory>
+ <factory
+ adaptableType="org.eclipse.core.filesystem.IFileStore"
+ class="unc.lib.cdr.workbench.arrange.DivAdapterFactory">
+ <adapter
+ type="unc.lib.cdr.workbench.views.ImageProvider">
+ </adapter>
</factory>
</extension>
<extension
@@ -1045,6 +1056,17 @@
showTitle="true"
visible="true">
</view>
+ <view
+ closeable="false"
+ id="workbench_plugin.previewFile"
+ minimized="false"
+ moveable="true"
+ ratio=".8"
+ relationship="bottom"
+ relative="org.eclipse.ui.editorss"
+ showTitle="true"
+ visible="true">
+ </view>
<!--<view
id="org.eclipse.ui.views.ProblemView"
minimized="false"
@@ -1137,6 +1159,13 @@
name="Problems"
restorable="true">
</view>
+ <view
+ class="unc.lib.cdr.workbench.views.ViewPartPreviewFile"
+ icon="icons/read_obj.gif"
+ id="workbench_plugin.previewFile"
+ name="Preview"
+ restorable="true">
+ </view>
</extension>
<extension
point="org.eclipse.ui.popupMenus">
@@ -17,14 +17,17 @@
import gov.loc.mets.DivType;
+import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.runtime.IAdapterFactory;
import unc.lib.cdr.workbench.originals.OriginalFileStore;
import unc.lib.cdr.workbench.project.MetsProjectNature;
+import unc.lib.cdr.workbench.views.FileStoreImageProvider;
+import unc.lib.cdr.workbench.views.ImageProvider;
public class DivAdapterFactory implements IAdapterFactory {
@SuppressWarnings("rawtypes")
- Class[] adapterTypes = new Class[] { OriginalFileStore.class };
+ Class[] adapterTypes = new Class[] { OriginalFileStore.class, ImageProvider.class };
@SuppressWarnings("rawtypes")
@Override
@@ -36,13 +39,27 @@ public Object getAdapter(Object adaptableObject, Class adapterType) {
return MetsProjectNature.getOriginal(d);
}
}
+ if(ImageProvider.class.equals(adapterType)) {
+ if (adaptableObject instanceof DivType) {
+ DivType d = (DivType) adaptableObject;
+ OriginalFileStore store = MetsProjectNature.getOriginal(d);
+ if(!store.fetchInfo().isDirectory()) {
+ return new FileStoreImageProvider(store);
+ }
+ } else if(adaptableObject instanceof IFileStore) {
+ IFileStore store = (IFileStore)adaptableObject;
+ if(!store.fetchInfo().isDirectory()) {
+ return new FileStoreImageProvider(store);
+ }
+ }
+ }
return result;
}
@SuppressWarnings("rawtypes")
@Override
public Class[] getAdapterList() {
- return null;
+ return adapterTypes;
}
}
@@ -0,0 +1,57 @@
+package unc.lib.cdr.workbench.views;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.Image;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FileStoreImageProvider implements ImageProvider {
+
+ @SuppressWarnings("unused")
+ private static final Logger LOG = LoggerFactory.getLogger(FileStoreImageProvider.class);
+
+ private IFileStore fs = null;
+
+ public FileStoreImageProvider(IFileStore fs) {
+ this.fs = fs;
+ }
+
+ @Override
+ public Image getImage(Device device) {
+ /*
+ * TODO Do we need to be smarter? It might make sense to check the file extension to see if it's worth attempting
+ * to extract an image from the file. For now, performance seems adequate and there does not seem to be any
+ * bizarre side-effects.
+ */
+ InputStream in = null;
+ try {
+ in = fs.openInputStream(EFS.NONE, new NullProgressMonitor());
+ return new Image(device, in);
+ } catch (SWTException e) {
+ if (e.code != SWT.ERROR_UNSUPPORTED_FORMAT)
+ LOG.info("unsupported image format", e);
+ } catch (Exception e) {
+ LOG.error("unexpected error", e);
+ } finally {
+ try {
+ in.close();
+ } catch (IOException e) {
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void disposeImage(Image image) {
+ image.dispose();
+ }
+
+}
@@ -0,0 +1,25 @@
+package unc.lib.cdr.workbench.views;
+
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.Image;
+
+public interface ImageProvider {
+ /**
+ * This method returns an {@link Image}. The implementor must return an image that can be disposed() by the caller.
+ * The implementor is not given any notification that the dispose is occurring.
+ *
+ * @param target
+ * The device the image will be displayed on.
+ *
+ * @return {@link Image}
+ */
+ Image getImage(Device target);
+
+ /**
+ * This method is used to dispose an image obtained by the getImage(Device) method.
+ *
+ * @param image
+ * the image that needs to be disposed of.
+ */
+ void disposeImage(Image image);
+}
@@ -0,0 +1,140 @@
+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;
+ redraw();
+ }
+}
Oops, something went wrong.

0 comments on commit 6b37c0a

Please sign in to comment.