⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swtimagecanvas.java

📁 dump3 morpheus 0.2.9 src
💻 JAVA
字号:
/***************************************************************************************************************************************************************
 * Copyright (c) 2004 Chengdong Li : cdli@ccs.uky.edu All rights reserved. This program and the accompanying materials are made available under the terms of the
 * Common Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/cpl-v10.html
 **************************************************************************************************************************************************************/
package net.za.grasser.duplicate.gui.display.image;

import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.ScrollBar;

/**
 * A scrollable image canvas that extends org.eclipse.swt.graphics.Canvas. <br>
 * It requires Eclipse (version >= 2.1) on Win32/win32; Linux/gtk; MacOSX/carbon. <br>
 * 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
 */
public class SWTImageCanvas extends Canvas {
  /* zooming rates in x and y direction are equal. */
  /** zoomin rate */
  final float ZOOMIN_RATE = 1.1f;
  /** zoomout rate */
  final float ZOOMOUT_RATE = 0.9f;
  /** original image */
  private Image sourceImage;
  /** screen image */
  private Image screenImage;
  /**
   * <code>transform</code> SWTImageCanvas -
   */
  private AffineTransform transform = new AffineTransform();

  /**
   * Constructor
   * 
   * @param parent
   */
  public SWTImageCanvas(final Composite parent) {
    this(parent, SWT.NULL);
  }

  /**
   * Constructor for ScrollableCanvas.
   * 
   * @param parent the parent of this control.
   * @param style the style of this control.
   */
  public SWTImageCanvas(final Composite parent, final int style) {
    super(parent, style | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.NO_BACKGROUND);
    addControlListener(new ControlAdapter() { /* resize listener. */
      @Override
      public void controlResized(final ControlEvent event) {
        syncScrollBars();
      }
    });
    addPaintListener(new PaintListener() { /* paint listener. */
      public void paintControl(final PaintEvent event) {
        paint(event.gc);
      }
    });
    initScrollBars();
  }

  /**
   * Dispose the garbage here
   */
  @Override
  public void dispose() {
    if (sourceImage != null && !sourceImage.isDisposed()) {
      sourceImage.dispose();
    }
    if (screenImage != null && !screenImage.isDisposed()) {
      screenImage.dispose();
    }
  }

  /**
   * This method unloads the image that was loaded
   */
  public void unloadImage() {
    if (sourceImage != null && !sourceImage.isDisposed()) {
      sourceImage.dispose();
      sourceImage = null;
    }
    if (screenImage != null && !screenImage.isDisposed()) {
      screenImage.dispose();
      screenImage = null;
    }
  }

  /**
   * Paint function
   * 
   * @param gc
   */
  void paint(final GC gc) {
    final Rectangle clientRect = getClientArea(); /* Canvas' painting area */
    if (sourceImage != null) {
      Rectangle imageRect = SWT2Dutil.inverseTransformRect(transform, clientRect);
      final int gap = 2; /* find a better start point to render */
      imageRect.x -= gap;
      imageRect.y -= gap;
      imageRect.width += 2 * gap;
      imageRect.height += 2 * gap;
      final Rectangle imageBound = sourceImage.getBounds();
      imageRect = imageRect.intersection(imageBound);
      final Rectangle destRect = SWT2Dutil.transformRect(transform, imageRect);
      if (screenImage != null) {
        screenImage.dispose();
      }
      screenImage = new Image(getDisplay(), clientRect.width, clientRect.height);
      final GC newGC = new GC(screenImage);
      newGC.setClipping(clientRect);
      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() {
    final ScrollBar horizontal = getHorizontalBar();
    horizontal.setEnabled(false);
    horizontal.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(final SelectionEvent event) {
        scrollHorizontally((ScrollBar)event.widget, true);
      }
    });
    final ScrollBar vertical = getVerticalBar();
    vertical.setEnabled(false);
    vertical.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(final SelectionEvent event) {
        scrollVertically((ScrollBar)event.widget, true);
      }
    });
  }

  /**
   * Scroll horizontally
   * 
   * @param scrollBar
   * @param synch
   */
  void scrollHorizontally(final ScrollBar scrollBar, final boolean synch) {
    if (sourceImage == null) {
      return;
    }
    final AffineTransform af = transform;
    final double tx = af.getTranslateX();
    final double select = -scrollBar.getSelection();
    af.preConcatenate(AffineTransform.getTranslateInstance(select - tx, 0));
    transform = af;
    syncScrollBars();
    if (synch) {
      ((DoubleImageDisplay)super.getParent()).scrollX(this, scrollBar.getMinimum(), scrollBar.getSelection(), scrollBar.getMaximum());
    }
  }

  /**
   * Scroll vertically
   * 
   * @param scrollBar
   * @param synch
   */
  void scrollVertically(final ScrollBar scrollBar, final boolean synch) {
    if (sourceImage == null) {
      return;
    }
    final AffineTransform af = transform;
    final double ty = af.getTranslateY();
    final double select = -scrollBar.getSelection();
    af.preConcatenate(AffineTransform.getTranslateInstance(0, select - ty));
    transform = af;
    syncScrollBars();
    if (synch) {
      ((DoubleImageDisplay)super.getParent()).scrollY(this, scrollBar.getMinimum(), scrollBar.getSelection(), scrollBar.getMaximum());
    }
  }

  /**
   * 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;
    final double sx = af.getScaleX(), sy = af.getScaleY();
    double tx = af.getTranslateX(), ty = af.getTranslateY();
    if (tx > 0) {
      tx = 0;
    }
    if (ty > 0) {
      ty = 0;
    }
    final ScrollBar horizontal = getHorizontalBar();
    horizontal.setIncrement(getClientArea().width / 100);
    horizontal.setPageIncrement(getClientArea().width);
    final Rectangle imageBound = sourceImage.getBounds();
    final 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(getClientArea().width);
    final ScrollBar vertical = getVerticalBar();
    vertical.setIncrement(getClientArea().height / 100);
    vertical.setPageIncrement(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(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(final String filename) {
    if (sourceImage != null && !sourceImage.isDisposed()) {
      sourceImage.dispose();
      sourceImage = null;
    }
    try {
      final File f = new File(filename);
      final BufferedImage im = ImageIO.read(f);
      final ImageData id = SWT2Dutil.convertToSWT(im);
      sourceImage = new Image(getDisplay(), id);
      showOriginal();
      return sourceImage;
    } catch (final IOException e1) {
      return null;
    }
  }

  /**
   * Get the image data. (for future use only)
   * 
   * @return image data of canvas
   */
  public ImageData getImageData() {
    return sourceImage.getImageData();
  }

  /**
   * Reset the image data and update the image
   * 
   * @param data image data to be set
   */
  public void setImageData(final ImageData data) {
    if (sourceImage != null) {
      sourceImage.dispose();
    }
    if (data != null) {
      sourceImage = new Image(getDisplay(), data);
    }
    syncScrollBars();
  }

  /**
   * Fit the image onto the canvas
   */
  public void fitCanvas() {
    if (sourceImage == null) {
      return;
    }
    final Rectangle imageBound = sourceImage.getBounds();
    final Rectangle destRect = getClientArea();
    final double sx = (double)destRect.width / (double)imageBound.width;
    final double sy = (double)destRect.height / (double)imageBound.height;
    final double s = Math.min(sx, sy);
    final double dx = 0.5 * destRect.width;
    final double dy = 0.5 * destRect.height;
    centerZoom(dx, dy, s, new AffineTransform());
  }

  /**
   * Show the image with the original size
   */
  public void showOriginal() {
    if (sourceImage == null) {
      return;
    }
    transform = new AffineTransform();
    syncScrollBars();
  }

  /**
   * Perform a zooming operation centered on the given point (dx, dy) and using the given scale factor. The given AffineTransform instance is preconcatenated.
   * 
   * @param dx center x
   * @param dy center y
   * @param scale zoom rate
   * @param af original affinetransform
   */
  public void centerZoom(double dx, double dy, final double scale, final AffineTransform af) {
    af.preConcatenate(AffineTransform.getTranslateInstance(-dx, -dy));
    af.preConcatenate(AffineTransform.getScaleInstance(scale, scale));
    af.preConcatenate(AffineTransform.getTranslateInstance(dx, dy));
    transform = af;
    syncScrollBars();
  }

  /**
   * Zoom in around the center of client Area.
   */
  public void zoomIn() {
    if (sourceImage == null) {
      return;
    }
    final Rectangle rect = getClientArea();
    final int w = rect.width, h = rect.height;
    final double dx = (double)w / 2;
    final double dy = (double)h / 2;
    centerZoom(dx, dy, ZOOMIN_RATE, transform);
  }

  /**
   * Zoom out around the center of client Area.
   */
  public void zoomOut() {
    if (sourceImage == null) {
      return;
    }
    final Rectangle rect = getClientArea();
    final int w = rect.width, h = rect.height;
    final double dx = (double)w / 2;
    final double dy = (double)h / 2;
    centerZoom(dx, dy, ZOOMOUT_RATE, transform);
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -