/*******************************************************************************
* Copyright (c) 2009 the CHISEL group and contributors.
* 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:
* Del Myers -- initial API and implementation
*******************************************************************************/
package org.eclipse.zest.custom.sequence.tools;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Viewport;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.zest.custom.sequence.figures.RectangleZoomManager;
import org.eclipse.zest.custom.sequence.figures.internal.ZoomManager;
/**
* Tool for zooming in and out on a Zest viewer. The viewer is required to follow the
* following contract in order for this tool to understand mouse events:
* viewer.getData("ZoomManager") returns an instanceof ZoomManager. The returned
* zoom manager will be used to perform the zooming.
*
* Zooming is done in the following manner: on a left-mouse click, the viewport is
* zoomed over the cursor position. on a right-mouse click, or a MOD1+click, the
* viewport is zoomed out over the cursor position.
* @author Del Myers
*/
public class ZoomTool implements IWidgetTool {
Cursor cursor;
private Listener cursorDisposer = new Listener() {
public void handleEvent(Event event) {
synchronized (ZoomTool.this) {
if (cursor != null && !cursor.isDisposed()) {
cursor.dispose();
cursor = null;
}
}
}
};
private Control currentControl;
/* (non-Javadoc)
* @see org.eclipse.mylar.zest.custom.sequence.tools.IWidgetTool#getCursor(org.eclipse.swt.widgets.Widget, org.eclipse.draw2d.IFigure)
*/
public Cursor getCursor(Widget widget, IFigure cursorTarget) {
Widget viewer = getCurrentControl();
if ((viewer instanceof Control)) {
ZoomManager manager = getZoomManager((Control)viewer);
if (manager instanceof RectangleZoomManager) {
//check to see if the target is a child of the scalable figure.
IFigure figure = cursorTarget;
while (figure != null) {
if (figure == manager.getViewport()) {
return getCursor(viewer);
}
figure =figure.getParent();
}
}
}
if (cursorTarget != null) {
Cursor c = cursorTarget.getCursor();
if (c != null) {
return c;
}
}
return getDefaultCursor();
}
/**
* Loads a cursor for the given display.
* @param display
* @return
*/
private synchronized Cursor getCursor(Widget viewer) {
if (cursor == null || !cursor.getDevice().equals(viewer.getDisplay())) {
if (cursor != null) {
((Display)cursor.getDevice()).removeListener(SWT.Dispose, cursorDisposer);
cursor.dispose();
}
try {
cursor = loadCursor(viewer.getDisplay());
viewer.addListener(SWT.Dispose, cursorDisposer);
} catch (IOException e) {
return viewer.getDisplay().getSystemCursor(SWT.CURSOR_ARROW);
}
}
return cursor;
}
protected Cursor loadCursor(Display display) throws IOException {
InputStream stream = getClass().getClassLoader().getResourceAsStream("cursors/magnify.png");
ImageData source = new ImageData(stream);
stream.close();
stream = getClass().getClassLoader().getResourceAsStream("cursors/magnifymask.png");
ImageData mask = new ImageData(stream);
stream.close();
return new Cursor(display, source, mask, source.width/2, source.height/2);
}
/* (non-Javadoc)
* @see org.eclipse.mylar.zest.custom.sequence.tools.IWidgetTool#getDefaultCursor()
*/
public Cursor getDefaultCursor() {
if (Display.getCurrent() != null) {
return Display.getCurrent().getSystemCursor(SWT.CURSOR_ARROW);
} else {
return Display.getDefault().getSystemCursor(SWT.CURSOR_ARROW);
}
}
/* (non-Javadoc)
* @see org.eclipse.mylar.zest.custom.sequence.tools.IWidgetTool#handleMouseDoubleClicked(org.eclipse.swt.events.MouseEvent, org.eclipse.swt.widgets.Widget, org.eclipse.draw2d.IFigure)
*/
public void handleMouseDoubleClicked(MouseEvent me, Widget widget,
IFigure cursorTarget) {
}
/* (non-Javadoc)
* @see org.eclipse.mylar.zest.custom.sequence.tools.IWidgetTool#handleMouseHover(org.eclipse.swt.events.MouseEvent, org.eclipse.swt.widgets.Widget, org.eclipse.draw2d.IFigure)
*/
public void handleMouseHover(MouseEvent me, Widget widget,
IFigure cursorTarget) {
}
/* (non-Javadoc)
* @see org.eclipse.mylar.zest.custom.sequence.tools.IWidgetTool#handleMouseMoved(org.eclipse.swt.events.MouseEvent, org.eclipse.swt.widgets.Widget, org.eclipse.draw2d.IFigure)
*/
public void handleMouseMoved(MouseEvent me, Widget widget,
IFigure cursorTarget) {
}
/* (non-Javadoc)
* @see org.eclipse.mylar.zest.custom.sequence.tools.IWidgetTool#handleMousePressed(org.eclipse.swt.events.MouseEvent, org.eclipse.swt.widgets.Widget, org.eclipse.draw2d.IFigure)
*/
public void handleMousePressed(MouseEvent me, Widget widget,
IFigure cursorTarget) {
}
/* (non-Javadoc)
* @see org.eclipse.mylar.zest.custom.sequence.tools.IWidgetTool#handleMouseReleased(org.eclipse.swt.events.MouseEvent, org.eclipse.swt.widgets.Widget, org.eclipse.draw2d.IFigure)
*/
public void handleMouseReleased(MouseEvent me, Widget widget,
IFigure cursorTarget) {
Widget parent = me.widget;
if (!(parent instanceof Control)) return;
ZoomManager manager = getZoomManager((Control) parent);
if (manager != null) {
setViewLocation(manager, new Point(me.x, me.y));
if (me.button == 1) {
if ((me.stateMask & SWT.MOD1) != 0) {
manager.zoomOut();
} else {
manager.zoomIn();
}
} else if (me.button == 3) {
manager.zoomOut();
}
}
}
/* (non-Javadoc)
* @see org.eclipse.mylar.zest.custom.sequence.tools.IWidgetTool#handleMouseWheelScrolled(org.eclipse.swt.widgets.Event, org.eclipse.draw2d.IFigure)
*/
public void handleMouseWheelScrolled(Event event, IFigure mouseTarget) {
if (!(event.widget instanceof Control)) {
return;
}
ZoomManager manager = getZoomManager((Control) event.widget);
if (manager != null) {
setViewLocation(manager, new Point(event.x, event.y));
if (event.count > 0) manager.zoomIn();
else if (event.count < 0) manager.zoomOut();
}
}
/* (non-Javadoc)
* @see org.eclipse.mylar.zest.custom.sequence.tools.IWidgetTool#understandsEvent(org.eclipse.swt.events.MouseEvent, org.eclipse.swt.widgets.Widget, org.eclipse.draw2d.IFigure)
*/
public boolean understandsEvent(MouseEvent me, Widget widget,
IFigure cursorTarget) {
if (!(me.widget instanceof Control)) {
return false;
}
Object manager = getZoomManager((Control) me.widget);
if ((me.button == 1 || me.button == 3) &&
manager instanceof ZoomManager) {
// make sure that the cursor target is a child of the zoom manager's
//viewport
ZoomManager zoomManager = (ZoomManager) manager;
Viewport port = zoomManager.getViewport();
IFigure figure = cursorTarget;
while (figure != null) {
if (figure == port)
return true;
figure = figure.getParent();
}
}
return false;
}
private void setViewLocation(ZoomManager zoomManager, Point p) {
Viewport port = zoomManager.getViewport();
port.getContents().translateToRelative(p);
//center on the point
Dimension d = port.getSize();
port.setViewLocation(p.x - d.width/2, p.y - d.height/2);
}
protected ZoomManager getZoomManager(Widget viewer) {
Object m = viewer.getData("ZoomManager");
if (viewer instanceof Control) {
viewer = ((Control)viewer).getParent();
}
while (viewer instanceof Control && m == null) {
m = viewer.getData("ZoomManager");
if (m instanceof ZoomManager) {
return (ZoomManager) m;
}
viewer = ((Control)viewer).getParent();
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.zest.custom.sequence.tools.IWidgetTool#getCurrentControl()
*/
public Control getCurrentControl() {
return currentControl;
}
/* (non-Javadoc)
* @see org.eclipse.zest.custom.sequence.tools.IWidgetTool#setCurrentControl(org.eclipse.swt.widgets.Control)
*/
public void setCurrentControl(Control currentControl) {
this.currentControl = currentControl;
}
}