| /******************************************************************************* |
| * Copyright (c) 2000, 2010 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.draw2d.parts; |
| |
| import java.beans.PropertyChangeEvent; |
| import java.beans.PropertyChangeListener; |
| |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.ImageData; |
| import org.eclipse.swt.graphics.PaletteData; |
| import org.eclipse.swt.graphics.RGB; |
| import org.eclipse.swt.widgets.Display; |
| |
| import org.eclipse.draw2d.ColorConstants; |
| import org.eclipse.draw2d.Figure; |
| import org.eclipse.draw2d.FigureListener; |
| import org.eclipse.draw2d.Graphics; |
| import org.eclipse.draw2d.IFigure; |
| import org.eclipse.draw2d.KeyEvent; |
| import org.eclipse.draw2d.KeyListener; |
| import org.eclipse.draw2d.MouseEvent; |
| import org.eclipse.draw2d.MouseListener; |
| import org.eclipse.draw2d.MouseMotionListener; |
| import org.eclipse.draw2d.Viewport; |
| import org.eclipse.draw2d.geometry.Dimension; |
| import org.eclipse.draw2d.geometry.Point; |
| import org.eclipse.draw2d.geometry.Rectangle; |
| import org.eclipse.draw2d.rap.swt.SWT; |
| |
| /** |
| * A scaled image representation of a Figure. If the source Figure is not |
| * completely visible, a SelectorFigure is placed over the thumbnail |
| * representing the viewable area and can be dragged around to scroll the source |
| * figure. |
| */ |
| public final class ScrollableThumbnail extends Thumbnail { |
| |
| private class ClickScrollerAndDragTransferrer extends |
| MouseMotionListener.Stub implements MouseListener { |
| private boolean dragTransfer; |
| |
| public void mouseDoubleClicked(MouseEvent me) { |
| } |
| |
| public void mouseDragged(MouseEvent me) { |
| if (dragTransfer) |
| syncher.mouseDragged(me); |
| } |
| |
| public void mousePressed(MouseEvent me) { |
| if (!(ScrollableThumbnail.this.getClientArea().contains(me |
| .getLocation()))) |
| return; |
| Dimension selectorCenter = selector.getBounds().getSize() |
| .scale(0.5f); |
| Point scrollPoint = me |
| .getLocation() |
| .getTranslated(getLocation().getNegated()) |
| .translate(selectorCenter.negate()) |
| .scale(1.0f / getViewportScaleX(), |
| 1.0f / getViewportScaleY()) |
| .translate(viewport.getHorizontalRangeModel().getMinimum(), |
| viewport.getVerticalRangeModel().getMinimum()); |
| viewport.setViewLocation(scrollPoint); |
| syncher.mousePressed(me); |
| dragTransfer = true; |
| } |
| |
| public void mouseReleased(MouseEvent me) { |
| syncher.mouseReleased(me); |
| dragTransfer = false; |
| } |
| } |
| |
| private class ScrollSynchronizer extends MouseMotionListener.Stub implements |
| MouseListener { |
| private Point startLocation; |
| private Point viewLocation; |
| |
| public void mouseDoubleClicked(MouseEvent me) { |
| } |
| |
| public void mouseDragged(MouseEvent me) { |
| if (startLocation != null) { |
| Dimension d = me.getLocation().getDifference(startLocation); |
| d.scale(1.0f / getViewportScaleX(), 1.0f / getViewportScaleY()); |
| viewport.setViewLocation(viewLocation.getTranslated(d)); |
| me.consume(); |
| } |
| } |
| |
| public void mousePressed(MouseEvent me) { |
| startLocation = me.getLocation(); |
| viewLocation = viewport.getViewLocation(); |
| me.consume(); |
| } |
| |
| public void mouseReleased(MouseEvent me) { |
| } |
| } |
| |
| private class SelectorFigure extends Figure { |
| { |
| Display display = Display.getCurrent(); |
| PaletteData pData = new PaletteData(0xFF, 0xFF00, 0xFF0000); |
| RGB rgb = ColorConstants.menuBackgroundSelected.getRGB(); |
| int fillColor = pData.getPixel(rgb); |
| ImageData iData = new ImageData(1, 1, 24, pData); |
| iData.setPixel(0, 0, fillColor); |
| iData.setAlpha(0, 0, 55); |
| image = new Image(display, iData); |
| } |
| private Rectangle iBounds = new Rectangle(0, 0, 1, 1); |
| |
| private Image image; |
| |
| protected void dispose() { |
| image.dispose(); |
| } |
| |
| public void paintFigure(Graphics g) { |
| Rectangle bounds = getBounds().getCopy(); |
| |
| // Avoid drawing images that are 0 in dimension |
| if (bounds.width < 5 || bounds.height < 5) |
| return; |
| |
| // Don't paint the selector figure if the entire source is visible. |
| Dimension thumbnailSize = new Dimension(getThumbnailImage()); |
| // expand to compensate for rounding errors in calculating bounds |
| Dimension size = getSize().getExpanded(1, 1); |
| if (size.contains(thumbnailSize)) |
| return; |
| |
| bounds.height--; |
| bounds.width--; |
| g.drawImage(image, iBounds, bounds); |
| |
| g.setForegroundColor(ColorConstants.menuBackgroundSelected); |
| g.drawRectangle(bounds); |
| } |
| |
| } |
| |
| private FigureListener figureListener = new FigureListener() { |
| public void figureMoved(IFigure source) { |
| reconfigureSelectorBounds(); |
| } |
| }; |
| private KeyListener keyListener = new KeyListener.Stub() { |
| public void keyPressed(KeyEvent ke) { |
| int moveX = viewport.getClientArea().width / 4; |
| int moveY = viewport.getClientArea().height / 4; |
| if (ke.keycode == SWT.HOME |
| || (isMirrored() ? ke.keycode == SWT.ARROW_RIGHT |
| : ke.keycode == SWT.ARROW_LEFT)) |
| viewport.setViewLocation(viewport.getViewLocation().translate( |
| -moveX, 0)); |
| else if (ke.keycode == SWT.END |
| || (isMirrored() ? ke.keycode == SWT.ARROW_LEFT |
| : ke.keycode == SWT.ARROW_RIGHT)) |
| viewport.setViewLocation(viewport.getViewLocation().translate( |
| moveX, 0)); |
| else if (ke.keycode == SWT.ARROW_UP || ke.keycode == SWT.PAGE_UP) |
| viewport.setViewLocation(viewport.getViewLocation().translate( |
| 0, -moveY)); |
| else if (ke.keycode == SWT.ARROW_DOWN |
| || ke.keycode == SWT.PAGE_DOWN) |
| viewport.setViewLocation(viewport.getViewLocation().translate( |
| 0, moveY)); |
| } |
| }; |
| |
| private PropertyChangeListener propListener = new PropertyChangeListener() { |
| public void propertyChange(PropertyChangeEvent evt) { |
| reconfigureSelectorBounds(); |
| } |
| }; |
| |
| private SelectorFigure selector; |
| |
| private ScrollSynchronizer syncher; |
| private Viewport viewport; |
| |
| /** |
| * Creates a new ScrollableThumbnail. |
| */ |
| public ScrollableThumbnail() { |
| super(); |
| initialize(); |
| } |
| |
| /** |
| * Creates a new ScrollableThumbnail that synchs with the given Viewport. |
| * |
| * @param port |
| * The Viewport |
| */ |
| public ScrollableThumbnail(Viewport port) { |
| super(); |
| setViewport(port); |
| initialize(); |
| } |
| |
| /** |
| * @see Thumbnail#deactivate() |
| */ |
| public void deactivate() { |
| viewport.removePropertyChangeListener(Viewport.PROPERTY_VIEW_LOCATION, |
| propListener); |
| viewport.removeFigureListener(figureListener); |
| remove(selector); |
| selector.dispose(); |
| super.deactivate(); |
| } |
| |
| private double getViewportScaleX() { |
| return (double) targetSize.width |
| / viewport.getContents().getBounds().width; |
| } |
| |
| private double getViewportScaleY() { |
| return (double) targetSize.height |
| / viewport.getContents().getBounds().height; |
| } |
| |
| private void initialize() { |
| selector = new SelectorFigure(); |
| selector.addMouseListener(syncher = new ScrollSynchronizer()); |
| selector.addMouseMotionListener(syncher); |
| selector.setFocusTraversable(true); |
| selector.addKeyListener(keyListener); |
| add(selector); |
| ClickScrollerAndDragTransferrer transferrer = new ClickScrollerAndDragTransferrer(); |
| addMouseListener(transferrer); |
| addMouseMotionListener(transferrer); |
| } |
| |
| private void reconfigureSelectorBounds() { |
| Rectangle rect = new Rectangle(); |
| Point offset = viewport.getViewLocation(); |
| offset.x -= viewport.getHorizontalRangeModel().getMinimum(); |
| offset.y -= viewport.getVerticalRangeModel().getMinimum(); |
| rect.setLocation(offset); |
| rect.setSize(viewport.getClientArea().getSize()); |
| rect.scale(getViewportScaleX(), getViewportScaleY()); |
| rect.translate(getClientArea().getLocation()); |
| selector.setBounds(rect); |
| } |
| |
| /** |
| * Reconfigures the SelectorFigure's bounds if the scales have changed. |
| * |
| * @param scaleX |
| * The X scale |
| * @param scaleY |
| * The Y scale |
| * @see org.eclipse.draw2d.parts.Thumbnail#setScales(float, float) |
| */ |
| protected void setScales(float scaleX, float scaleY) { |
| if (scaleX == getScaleX() && scaleY == getScaleY()) |
| return; |
| |
| super.setScales(scaleX, scaleY); |
| reconfigureSelectorBounds(); |
| } |
| |
| /** |
| * Sets the Viewport that this ScrollableThumbnail will synch with. |
| * |
| * @param port |
| * The Viewport |
| */ |
| public void setViewport(Viewport port) { |
| port.addPropertyChangeListener(Viewport.PROPERTY_VIEW_LOCATION, |
| propListener); |
| port.addFigureListener(figureListener); |
| viewport = port; |
| } |
| |
| } |