Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
add preview support for images
Browse files Browse the repository at this point in the history
  • Loading branch information
gregjan committed Aug 9, 2012
1 parent d631597 commit 6b37c0a
Show file tree
Hide file tree
Showing 6 changed files with 371 additions and 4 deletions.
33 changes: 31 additions & 2 deletions workbench_plugin/plugin.xml
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -344,7 +344,8 @@
</menu> </menu>
<command <command
commandId="cdr-workbench.commandOpenCopySystemEditor" commandId="cdr-workbench.commandOpenCopySystemEditor"
label="Open copy in default editor" label="Open a Copy"
mnemonic="o"
style="push"> style="push">
<visibleWhen <visibleWhen
checkEnabled="false"> checkEnabled="false">
Expand Down Expand Up @@ -426,7 +427,7 @@
</command> </command>
<command <command
commandId="cdr-workbench.commandOpenCopySystemEditor" commandId="cdr-workbench.commandOpenCopySystemEditor"
label="Open copy in default editor" label="Open a Copy"
style="push"> style="push">
<visibleWhen <visibleWhen
checkEnabled="false"> checkEnabled="false">
Expand Down Expand Up @@ -1000,6 +1001,16 @@
<adapter <adapter
type="unc.lib.cdr.workbench.originals.OriginalFileStore"> type="unc.lib.cdr.workbench.originals.OriginalFileStore">
</adapter> </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> </factory>
</extension> </extension>
<extension <extension
Expand Down Expand Up @@ -1045,6 +1056,17 @@
showTitle="true" showTitle="true"
visible="true"> visible="true">
</view> </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 <!--<view
id="org.eclipse.ui.views.ProblemView" id="org.eclipse.ui.views.ProblemView"
minimized="false" minimized="false"
Expand Down Expand Up @@ -1137,6 +1159,13 @@
name="Problems" name="Problems"
restorable="true"> restorable="true">
</view> </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>
<extension <extension
point="org.eclipse.ui.popupMenus"> point="org.eclipse.ui.popupMenus">
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@


import gov.loc.mets.DivType; import gov.loc.mets.DivType;


import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.core.runtime.IAdapterFactory;


import unc.lib.cdr.workbench.originals.OriginalFileStore; import unc.lib.cdr.workbench.originals.OriginalFileStore;
import unc.lib.cdr.workbench.project.MetsProjectNature; 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 { public class DivAdapterFactory implements IAdapterFactory {
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
Class[] adapterTypes = new Class[] { OriginalFileStore.class }; Class[] adapterTypes = new Class[] { OriginalFileStore.class, ImageProvider.class };


@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
@Override @Override
Expand All @@ -36,13 +39,27 @@ public Object getAdapter(Object adaptableObject, Class adapterType) {
return MetsProjectNature.getOriginal(d); 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; return result;
} }


@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
@Override @Override
public Class[] getAdapterList() { public Class[] getAdapterList() {
return null; return adapterTypes;
} }


} }
Original file line number Original file line Diff line number Diff line change
@@ -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();
}

}
Original file line number Original file line Diff line number Diff line change
@@ -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);
}
Original file line number Original file line Diff line number Diff line change
@@ -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();
}
}
Loading

0 comments on commit 6b37c0a

Please sign in to comment.