blob: f2930b2a5a2d06995783599065bd81e3e007806d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2008 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
* SAP AG - Changed for initial API, implementation and documentation of Graphiti:
* changed mouseDragged to check for existing startLocation
* changed deactivate to handle subsequent calls
* added override tags
*******************************************************************************/
package org.eclipse.graphiti.ui.internal.fixed;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
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.parts.Thumbnail;
import org.eclipse.swt.SWT;
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;
/**
* The Class FixedScrollableThumbnail.
*
* @noinstantiate This class is not intended to be instantiated by clients.
* @noextend This class is not intended to be subclassed by clients.
*/
public final class FixedScrollableThumbnail extends FixedThumbnail {
private class ClickScrollerAndDragTransferrer extends MouseMotionListener.Stub implements MouseListener {
private boolean dragTransfer;
public void mouseDoubleClicked(MouseEvent me) {
}
@Override
public void mouseDragged(MouseEvent me) {
if (dragTransfer)
syncher.mouseDragged(me);
}
public void mousePressed(MouseEvent me) {
if (!(FixedScrollableThumbnail.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) {
}
@Override
public void mouseDragged(MouseEvent me) {
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();
}
@Override
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() {
@Override
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 FixedScrollableThumbnail() {
super();
initialize();
}
/**
* Creates a new ScrollableThumbnail that synchs with the given Viewport.
*
* @param port
* The Viewport
*/
public FixedScrollableThumbnail(Viewport port) {
super();
setViewport(port);
initialize();
}
/**
* Deactivate.
*
* @see Thumbnail#deactivate()
*/
@Override
public void deactivate() {
viewport.removePropertyChangeListener(Viewport.PROPERTY_VIEW_LOCATION, propListener);
viewport.removeFigureListener(figureListener);
if (selector.getParent() == this) { // if this method was called before,
// the selector might already be
// removed
remove(selector);
}
disposeSelector();
super.deactivate();
}
public void disposeSelector() {
selector.dispose();
}
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)
*/
@Override
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;
}
}