view org.eclipse.draw2d/src/org/eclipse/draw2d/parts/ScrollableThumbnail.d @ 16:dbfb303e8fb0

first complete successful compile (win-only)
author Frank Benoit <benoit@tionex.de>
date Wed, 18 Mar 2009 08:56:47 +0100
parents bc29606a740c
children
line wrap: on
line source

/*******************************************************************************
 * Copyright (c) 2000, 2005 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
 * Port to the D programming language:
 *     Frank Benoit <benoit@tionex.de>
 *******************************************************************************/
module org.eclipse.draw2d.parts.ScrollableThumbnail;

import java.lang.all;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;

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;
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;

/**
 * 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
    : Thumbnail
{

private class ClickScrollerAndDragTransferrer
    : MouseMotionListener.Stub
    , MouseListener
{
    private bool dragTransfer;
    public void mouseDoubleClicked(MouseEvent me) { }
    public void mouseDragged(MouseEvent me) {
        if (dragTransfer)
            syncher.mouseDragged(me);
    }
    public void mousePressed(MouseEvent me) {
        if (!(this.outer.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
    : MouseMotionListener.Stub
    , MouseListener
{
    private Point startLocation;
    private Point viewLocation;

    public void mouseDoubleClicked(MouseEvent me) { }

    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
    : Figure
{
    this(){
        iBounds = new Rectangle(0, 0, 1, 1);
        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;

    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;
private void initFigureListener(){
    figureListener = new class() FigureListener {
        public void figureMoved(IFigure source) {
            reconfigureSelectorBounds();
        }
    };
}
private KeyListener keyListener;
private void initKeyListener(){
    keyListener = new class() KeyListenerStub {
        public void keyPressed(KeyEvent ke) {
            int moveX = viewport.getClientArea().width / 4;
            int moveY = viewport.getClientArea().height / 4;
            if (ke.keycode is SWT.HOME || (isMirrored() ? ke.keycode is SWT.ARROW_RIGHT
                    : ke.keycode is SWT.ARROW_LEFT))
                viewport.setViewLocation(viewport.getViewLocation().translate(-moveX, 0));
            else if (ke.keycode is SWT.END || (isMirrored() ? ke.keycode is SWT.ARROW_LEFT
                    : ke.keycode is SWT.ARROW_RIGHT))
                viewport.setViewLocation(viewport.getViewLocation().translate(moveX, 0));
            else if (ke.keycode is SWT.ARROW_UP || ke.keycode is SWT.PAGE_UP)
                viewport.setViewLocation(viewport.getViewLocation().translate(0, -moveY));
            else if (ke.keycode is SWT.ARROW_DOWN  || ke.keycode is SWT.PAGE_DOWN)
                viewport.setViewLocation(viewport.getViewLocation().translate(0, moveY));
        }
    };
}

private PropertyChangeListener propListener;
private void initPropListener(){
    propListener = new class() PropertyChangeListener {
        public void propertyChange(PropertyChangeEvent evt) {
            reconfigureSelectorBounds();
        }
    };
}

private SelectorFigure selector;

private ScrollSynchronizer syncher;
private Viewport viewport;

/**
 * Creates a new ScrollableThumbnail.
 */
public this() {
    super();
    initFigureListener();
    initKeyListener();
    initPropListener();
    initialize();
}

/**
 * Creates a new ScrollableThumbnail that synchs with the given Viewport.
 * @param port The Viewport
 */
public this(Viewport port) {
    super();
    initFigureListener();
    initKeyListener();
    initPropListener();
    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 cast(double)targetSize.width / viewport.getContents().getBounds().width;
}

private double getViewportScaleY() {
    return cast(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 is getScaleX() && scaleY is 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;
}

}