67,512
社区成员
发帖
与我相关
我的任务
分享
/**
* A scrollable image canvas that extends org.eclipse.swt.graphics.Canvas.
* <p/>
* It requires Eclipse (version >= 2.1) on Win32/win32; Linux/gtk; MacOSX/carbon.
* <p/>
* This implementation using the pure SWT, no UI AWT package is used. For
* convenience, I put everything into one class. However, the best way to
* implement this is to use inheritance to create multiple hierarchies.
*
* @author Chengdong Li: cli4@uky.edu
* @author Christian Clausner: Added panning by mouse dragging
*/
public class SWTImageCanvas extends Canvas implements MouseWheelListener, MouseListener, MouseMoveListener {
/* zooming rates in x and y direction are equal.*/
final float ZOOMIN_RATE = 1.1f; /* zoomin rate */
final float ZOOMOUT_RATE = 0.9f; /* zoomout rate */
private Image sourceImage; /* original image */
private Image screenImage; /* screen image */
private AffineTransform transform = new AffineTransform(); //支持滚动和缩放
private Point mouseReferencePoint = null;
private Color grey;
private String currentDir=""; /* remembering file open directory */
public SWTImageCanvas(final Composite parent) {
this(parent, SWT.NULL);
grey = new Color(parent.getDisplay(), 85, 85, 85);
}
/**
* Constructor for ScrollableCanvas.
* @param parent the parent of this control.
* @param style the style of this control.
*/
public SWTImageCanvas(final Composite parent, int style) {
super( parent, style|SWT.BORDER|SWT.V_SCROLL|SWT.H_SCROLL
| SWT.NO_BACKGROUND);
grey = new Color(parent.getDisplay(), 85, 85, 85);
addControlListener(new ControlAdapter() { /* resize listener. */
public void controlResized(ControlEvent event) {
syncScrollBars();
}
});
addPaintListener(new PaintListener() { /* paint listener. */
public void paintControl(final PaintEvent event) {
paint(event.gc);
}
});
initScrollBars();
addMouseListener(this);
addMouseMoveListener(this);
}
/**
* Dispose the garbage here
*/
public void dispose() {
if (sourceImage != null && !sourceImage.isDisposed()) {
sourceImage.dispose();
}
if (screenImage != null && !screenImage.isDisposed()) {
screenImage.dispose();
}
grey.dispose();
}
/* Paint function */
private void paint(GC gc) {
Rectangle clientRect = getClientArea(); /* Canvas' painting area */
if (sourceImage != null) {
Rectangle imageRect =
SWT2Dutil.inverseTransformRect(transform, clientRect);
int gap = 2; /* find a better start point to render */
imageRect.x -= gap; imageRect.y -= gap;
imageRect.width += 2 * gap; imageRect.height += 2 * gap;
Rectangle imageBound = sourceImage.getBounds();
imageRect = imageRect.intersection(imageBound);
Rectangle destRect = SWT2Dutil.transformRect(transform, imageRect);
if (screenImage != null)
screenImage.dispose();
screenImage =
new Image(getDisplay(), clientRect.width, clientRect.height);
GC newGC = new GC(screenImage);
newGC.setClipping(clientRect);
//Background
newGC.setBackground(grey);
newGC.fillRectangle(0, 0, destRect.x, clientRect.height);
newGC.fillRectangle(clientRect.width-destRect.x, 0, destRect.x, clientRect.height);
newGC.fillRectangle(0, 0, clientRect.width, destRect.y);
newGC.fillRectangle(0, clientRect.height-destRect.y, clientRect.width, destRect.y);
//Document image
newGC.drawImage(
sourceImage,
imageRect.x,
imageRect.y,
imageRect.width,
imageRect.height,
destRect.x,
destRect.y,
destRect.width,
destRect.height);
newGC.dispose();
gc.drawImage(screenImage, 0, 0);
} else {
gc.setClipping(clientRect);
gc.fillRectangle(clientRect);
initScrollBars();
}
}
/* Initalize the scrollbar and register listeners. */
private void initScrollBars() {
ScrollBar horizontal = getHorizontalBar();
horizontal.setEnabled(false);
horizontal.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
scrollHorizontally((ScrollBar) event.widget);
}
});
ScrollBar vertical = getVerticalBar();
vertical.setEnabled(false);
vertical.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
scrollVertically((ScrollBar) event.widget);
}
});
}
/* Scroll horizontally */
private void scrollHorizontally(ScrollBar scrollBar) {
if (sourceImage == null)
return;
AffineTransform af = transform;
double tx = af.getTranslateX();
double select = -scrollBar.getSelection();
af.preConcatenate(AffineTransform.getTranslateInstance(select - tx, 0));
transform = af;
syncScrollBars();
}
/* Scroll vertically */
private void scrollVertically(ScrollBar scrollBar) {
if (sourceImage == null)
return;
AffineTransform af = transform;
double ty = af.getTranslateY();
double select = -scrollBar.getSelection();
af.preConcatenate(AffineTransform.getTranslateInstance(0, select - ty));
transform = af;
syncScrollBars();
}
/**
* Source image getter.
* @return sourceImage.
*/
public Image getSourceImage() {
return sourceImage;
}
/**
* Synchronize the scrollbar with the image. If the transform is out
* of range, it will correct it. This function considers only following
* factors :<b> transform, image size, client area</b>.
*/
public void syncScrollBars() {
if (sourceImage == null) {
redraw();
return;
}
AffineTransform af = transform;
double sx = af.getScaleX(), sy = af.getScaleY();
double tx = af.getTranslateX(), ty = af.getTranslateY();
if (tx > 0) tx = 0;
if (ty > 0) ty = 0;
ScrollBar horizontal = getHorizontalBar();
horizontal.setIncrement((int) (getClientArea().width / 100));
horizontal.setPageIncrement(getClientArea().width);
Rectangle imageBound = sourceImage.getBounds();
int cw = getClientArea().width, ch = getClientArea().height;
if (imageBound.width * sx > cw) { /* image is wider than client area */
horizontal.setMaximum((int) (imageBound.width * sx));
horizontal.setEnabled(true);
if (((int) - tx) > horizontal.getMaximum() - cw)
tx = -horizontal.getMaximum() + cw;
} else { /* image is narrower than client area */
horizontal.setEnabled(false);
tx = (cw - imageBound.width * sx) / 2; //center if too small.
}
horizontal.setSelection((int) (-tx));
horizontal.setThumb((int) (getClientArea().width));
ScrollBar vertical = getVerticalBar();
vertical.setIncrement((int) (getClientArea().height / 100));
vertical.setPageIncrement((int) (getClientArea().height));
if (imageBound.height * sy > ch) { /* image is higher than client area */
vertical.setMaximum((int) (imageBound.height * sy));
vertical.setEnabled(true);
if (((int) - ty) > vertical.getMaximum() - ch)
ty = -vertical.getMaximum() + ch;
} else { /* image is less higher than client area */
vertical.setEnabled(false);
ty = (ch - imageBound.height * sy) / 2; //center if too small.
}
vertical.setSelection((int) (-ty));
vertical.setThumb((int) (getClientArea().height));
/* update transform. */
af = AffineTransform.getScaleInstance(sx, sy);
af.preConcatenate(AffineTransform.getTranslateInstance(tx, ty));
transform = af;
redraw();
}
/**
* Reload image from a file
* @param filename image file
* @return swt image created from image file
*/
public Image loadImage(String filename) {
if (sourceImage != null && !sourceImage.isDisposed()) {
sourceImage.dispose();
sourceImage = null;
}
sourceImage = new Image(getDisplay(), filename);
showOriginal();
return sourceImage;
}
/**
* Call back funtion of button "open". Will open a file dialog, and choose
* the image file. It supports image formats supported by Eclipse.
*/
public void onFileOpen() {
FileDialog fileChooser = new FileDialog(getShell(), SWT.OPEN);
fileChooser.setText("Open image file");
fileChooser.setFilterPath(currentDir);
fileChooser.setFilterExtensions(
new String[] { "*.gif; *.jpg; *.png; *.ico; *.bmp" });
fileChooser.setFilterNames(
new String[] { "SWT image" + " (gif, jpeg, png, ico, bmp)" });
String filename = fileChooser.open();
if (filename != null){
loadImage(filename);
currentDir = fileChooser.getFilterPath();
}
}
public void setSourceImage(Image image) {
setSourceImage(image, true);
}
public void setSourceImage(Image image, boolean resetZoomAndScrollbars)
{
if (sourceImage != null && !sourceImage.isDisposed()) {
sourceImage.dispose();
sourceImage = null;
}
sourceImage = image;
if (resetZoomAndScrollbars)
showOriginal();
else
syncScrollBars();
}
以上是SWTImageCanvas源码