/******************************************************************************* * 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 org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.SWTEventDispatcher; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Widget; /** * A dispatcher that dispatches events to tools that understand widgets. ToolEventDispatchers * can be set onto the LightweightSystem of a draw2d-based visualization. An * IWidgetFinder is provided in order to translate between figures in the * visualization and widgets inside the visualization. Once a ToolEventDispatcher * is set on the draw2d based visualization, the viewer should provide a method of * changing the tool that is used within it (provided that it supports more than one * tool). Two tools (ZoomTool and ZoomToTool) are provided which will work on any draw2d based viewer, just so * long as it conforms to contracts outlined in the documentation of those views. * * Currently, tools only work with mouse events that occur within the lightweight system. * Mouse events are handled in the following fashion: * 1) The figure that is under the mouse is found, and the mouse event is dispatched * to it first. This ensures that any actions that must be performed regardless of * the tool get performed (e.g. dragging scroll bars). * 2) The provided IWidgetFinder is used to find the widget that is under the mouse. * 3) The current tool is queried to find out if it understands the mouse event given * the context of the event (the viewer that it occurred on, the widget that it * occurred on (may be null), and the IFigure that it occurred on). * 4) If the tool understands the event, the tool is asked to perform an operation * based on the event. * @author Del Myers */ public class ToolEventDispatcher extends SWTEventDispatcher { private IWidgetFinder widgetFinder; private Widget widgetUnderCursor; private IWidgetTool currentTool; private Cursor currentCursor; private boolean wasCaptured = false; /** * The control on which the event dispatcher is running. */ private Composite control; /** * Constructs an event dispatcher that uses the given widget finder to * dispatch to based on widgets. * @param finder */ public ToolEventDispatcher(IWidgetFinder finder, Composite control) { this.widgetFinder = finder; this.control = control; } public void setTool(IWidgetTool tool) { this.currentTool = tool; this.currentCursor = tool.getDefaultCursor(); tool.setCurrentControl(getControl()); } public Composite getControl() { return control; } /* (non-Javadoc) * @see org.eclipse.draw2d.EventDispatcher#dispatchMouseDoubleClicked(org.eclipse.swt.events.MouseEvent) */ @Override public void dispatchMouseDoubleClicked(MouseEvent me) { super.dispatchMouseDoubleClicked(me); recieve(me); if (getCurrentEvent() != null && getCurrentEvent().isConsumed()) { if (currentTool != null && currentTool.understandsEvent(me, widgetUnderCursor, getCursorTarget())) { currentTool.handleMouseDoubleClicked(me, widgetUnderCursor, getCursorTarget()); } } } /* (non-Javadoc) * @see org.eclipse.draw2d.EventDispatcher#dispatchMouseHover(org.eclipse.swt.events.MouseEvent) */ @Override public void dispatchMouseHover(MouseEvent me) { super.dispatchMouseHover(me); recieve(me); if (getCurrentEvent() != null && getCurrentEvent().isConsumed()) { if (currentTool != null && currentTool.understandsEvent(me, widgetUnderCursor, getCursorTarget())) { currentTool.handleMouseHover(me, widgetUnderCursor, getCursorTarget()); } } } /* (non-Javadoc) * @see org.eclipse.draw2d.EventDispatcher#dispatchMouseMoved(org.eclipse.swt.events.MouseEvent) */ @Override public void dispatchMouseMoved(MouseEvent me) { super.dispatchMouseMoved(me); recieve(me); if (!isCaptured()) { if (currentTool != null && currentTool.understandsEvent(me, widgetUnderCursor, getCursorTarget())) { currentTool.handleMouseMoved(me, widgetUnderCursor, getCursorTarget()); } } } /* (non-Javadoc) * @see org.eclipse.draw2d.EventDispatcher#dispatchMousePressed(org.eclipse.swt.events.MouseEvent) */ @Override public void dispatchMousePressed(MouseEvent me) { super.dispatchMousePressed(me); recieve(me); wasCaptured = isCaptured(); if (!isCaptured()) { if (currentTool != null && currentTool.understandsEvent(me, widgetUnderCursor, getCursorTarget())) { currentTool.handleMousePressed(me, widgetUnderCursor, getCursorTarget()); } } } /* (non-Javadoc) * @see org.eclipse.draw2d.EventDispatcher#dispatchMouseReleased(org.eclipse.swt.events.MouseEvent) */ @Override public void dispatchMouseReleased(MouseEvent me) { super.dispatchMouseReleased(me); recieve(me); if (!wasCaptured) { if (currentTool != null && currentTool.understandsEvent(me, widgetUnderCursor, getCursorTarget())) { currentTool.handleMouseReleased(me, widgetUnderCursor, getCursorTarget()); } } wasCaptured = isCaptured(); } /** * Updates the widget under the mouse event. * @param me */ private void recieve(MouseEvent me) { IFigure cursorTarget = getCursorTarget(); this.widgetUnderCursor = widgetFinder.getWidget(cursorTarget); if (cursorTarget != null && cursorTarget.getCursor() == null) { this.currentCursor = currentTool.getCursor(widgetUnderCursor != null ? widgetUnderCursor : me.widget, cursorTarget); if (me.widget instanceof Composite) { ((Composite)me.widget).setCursor(this.currentCursor); } } } /* (non-Javadoc) * @see org.eclipse.draw2d.SWTEventDispatcher#setFocus(org.eclipse.draw2d.IFigure) */ @Override protected void setFocus(IFigure fig) { super.setFocus(fig); Widget newWidget = widgetFinder.getWidget(fig); if (newWidget instanceof Composite) { ((Composite)newWidget).setFocus(); } } /* (non-Javadoc) * @see org.eclipse.draw2d.EventDispatcher#dispatchMouseWheelScrolled(org.eclipse.swt.widgets.Event) */ @Override public void dispatchMouseWheelScrolled(Event event) { if (currentTool != null) { currentTool.handleMouseWheelScrolled(event, getCursorTarget()); } super.dispatchMouseWheelScrolled(event); } /** * @return the current tool applied on the dispatcher. */ public IWidgetTool getTool() { return currentTool; } }