Mercurial > projects > dwt-addons
diff dwtx/draw2d/SWTEventDispatcher.d @ 98:95307ad235d9
Added Draw2d code, still work in progress
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sun, 03 Aug 2008 00:52:14 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/draw2d/SWTEventDispatcher.d Sun Aug 03 00:52:14 2008 +0200 @@ -0,0 +1,575 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 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 dwtx.draw2d.SWTEventDispatcher; + +import dwt.dwthelper.utils; + +import dwt.DWT; +import dwt.accessibility.AccessibleControlEvent; +import dwt.accessibility.AccessibleControlListener; +import dwt.accessibility.AccessibleEvent; +import dwt.accessibility.AccessibleListener; +import dwt.events.DisposeEvent; +import dwt.events.TraverseEvent; +import dwt.graphics.Cursor; +import dwt.widgets.Control; +import dwtx.draw2d.EventDispatcher; +import dwtx.draw2d.IFigure; +import dwtx.draw2d.Figure; +import dwtx.draw2d.MouseEvent; +import dwtx.draw2d.FocusEvent; +import dwtx.draw2d.KeyEvent; +import dwtx.draw2d.ToolTipHelper; +static import dwt.widgets.Control; +import dwtx.draw2d.FocusTraverseManager; +static import dwt.events.FocusEvent; +static import dwt.events.KeyEvent; +static import dwt.events.MouseEvent; + +/** + * The SWTEventDispatcher provides draw2d with the ability to dispatch DWT Events. The + * {@link dwtx.draw2d.LightweightSystem} adds DWT event listeners on its Canvas. + * When the Canvas receives an DWT event, it calls the appropriate dispatcher method in + * SWTEventDispatcher. + */ +public class SWTEventDispatcher + : EventDispatcher +{ + +/** + * Used to tell if any button is pressed without regard to the specific button. + * @deprecated Use {@link DWT#BUTTON_MASK} instead. + */ +protected static const int ANY_BUTTON = DWT.BUTTON_MASK; + +private bool figureTraverse = true; + +private bool captured; +private IFigure root; +private IFigure mouseTarget; +private IFigure cursorTarget; +private IFigure focusOwner; +private IFigure hoverSource; + +private MouseEvent currentEvent; +private Cursor cursor; +/** The control this dispatcher is listening to. */ +protected dwt.widgets.Control.Control control; + +private ToolTipHelper toolTipHelper; +private FocusTraverseManager focusManager; + +/** + * Implements {@link EventDispatcher.AccessibilityDispatcher} but + * does nothing in the implementation. + */ +protected class FigureAccessibilityDispatcher + : AccessibilityDispatcher +{ + /** @see AccessibleControlListener#getChildAtPoint(AccessibleControlEvent) */ + public void getChildAtPoint(AccessibleControlEvent e) { } + /** @see AccessibleControlListener#getChildCount(AccessibleControlEvent) */ + public void getChildCount(AccessibleControlEvent e) { } + /** @see AccessibleControlListener#getChildren(AccessibleControlEvent) */ + public void getChildren(AccessibleControlEvent e) { } + /** @see AccessibleControlListener#getDefaultAction(AccessibleControlEvent) */ + public void getDefaultAction(AccessibleControlEvent e) { } + /** @see AccessibleListener#getDescription(AccessibleEvent) */ + public void getDescription(AccessibleEvent e) { } + /** @see AccessibleControlListener#getFocus(AccessibleControlEvent) */ + public void getFocus(AccessibleControlEvent e) { } + /** @see AccessibleListener#getHelp(AccessibleEvent) */ + public void getHelp(AccessibleEvent e) { } + /** @see AccessibleListener#getKeyboardShortcut(AccessibleEvent) */ + public void getKeyboardShortcut(AccessibleEvent e) { } + /** @see AccessibleControlListener#getLocation(AccessibleControlEvent) */ + public void getLocation(AccessibleControlEvent e) { } + /** @see AccessibleListener#getName(AccessibleEvent) */ + public void getName(AccessibleEvent e) { } + /** @see AccessibleControlListener#getRole(AccessibleControlEvent) */ + public void getRole(AccessibleControlEvent e) { } + /** @see AccessibleControlListener#getSelection(AccessibleControlEvent) */ + public void getSelection(AccessibleControlEvent e) { } + /** @see AccessibleControlListener#getState(AccessibleControlEvent) */ + public void getState(AccessibleControlEvent e) { } + /** @see AccessibleControlListener#getValue(AccessibleControlEvent) */ + public void getValue(AccessibleControlEvent e) { } +} + +public this(){ + focusManager = new FocusTraverseManager(); +} + +/** + * @see EventDispatcher#dispatchFocusGained(dwt.events.FocusEvent) + */ +public void dispatchFocusGained(dwt.events.FocusEvent.FocusEvent e) { + IFigure currentFocusOwner = getFocusTraverseManager().getCurrentFocusOwner(); + + /* + * Upon focus gained, if there is no current focus owner, + * set focus on first focusable child. + */ + if (currentFocusOwner is null) + currentFocusOwner = + getFocusTraverseManager().getNextFocusableFigure(root, focusOwner); + setFocus(currentFocusOwner); +} + +/** + * @see EventDispatcher#dispatchFocusLost(dwt.events.FocusEvent) + */ +public void dispatchFocusLost(dwt.events.FocusEvent.FocusEvent e) { + setFocus(null); +} + +/** + * @see EventDispatcher#dispatchKeyPressed(dwt.events.KeyEvent) + */ +public void dispatchKeyPressed(dwt.events.KeyEvent.KeyEvent e) { + if (focusOwner !is null) { + KeyEvent event = new KeyEvent(this, focusOwner, e); + focusOwner.handleKeyPressed(event); + } +} + +/** + * @see EventDispatcher#dispatchKeyReleased(dwt.events.KeyEvent) + */ +public void dispatchKeyReleased(dwt.events.KeyEvent.KeyEvent e) { + if (focusOwner !is null) { + KeyEvent event = new KeyEvent(this, focusOwner, e); + focusOwner.handleKeyReleased(event); + } +} + +/** + * @see EventDispatcher#dispatchKeyTraversed(TraverseEvent) + */ +public void dispatchKeyTraversed(TraverseEvent e) { + if (!figureTraverse) + return; + IFigure nextFigure = null; + + if (e.detail is DWT.TRAVERSE_TAB_NEXT) + nextFigure = getFocusTraverseManager().getNextFocusableFigure(root, focusOwner); + else if (e.detail is DWT.TRAVERSE_TAB_PREVIOUS) + nextFigure = + getFocusTraverseManager().getPreviousFocusableFigure(root, focusOwner); + + if (nextFigure !is null) { + e.doit = false; + setFocus(nextFigure); + } +} + +/** + * @see EventDispatcher#dispatchMouseHover(dwt.events.MouseEvent) + */ +public void dispatchMouseHover(dwt.events.MouseEvent.MouseEvent me) { + receive(me); + if (mouseTarget !is null) + mouseTarget.handleMouseHover(currentEvent); + /* + * Check Tooltip source. + * Get Tooltip source's Figure. + * Set that tooltip as the lws contents on the helper. + */ + if (hoverSource !is null) { + toolTipHelper = getToolTipHelper(); + IFigure tip = hoverSource.getToolTip(); + Control control = cast(Control)me.getSource(); + dwt.graphics.Point.Point absolute; + absolute = control.toDisplay(new dwt.graphics.Point.Point(me.x, me.y)); + toolTipHelper.displayToolTipNear(hoverSource, tip, absolute.x, absolute.y); + } +} + +/** + * @see EventDispatcher#dispatchMouseDoubleClicked(dwt.events.MouseEvent) + */ +public void dispatchMouseDoubleClicked(dwt.events.MouseEvent.MouseEvent me) { + receive(me); + if (mouseTarget !is null) + mouseTarget.handleMouseDoubleClicked(currentEvent); +} + +/** + * @see EventDispatcher#dispatchMouseEntered(dwt.events.MouseEvent) + */ +public void dispatchMouseEntered(dwt.events.MouseEvent.MouseEvent me) { + receive(me); +} + +/** + * @see EventDispatcher#dispatchMouseExited(dwt.events.MouseEvent) + */ +public void dispatchMouseExited(dwt.events.MouseEvent.MouseEvent me) { + setHoverSource(null, me); + if (mouseTarget !is null) { + currentEvent = + new MouseEvent(me.x, me.y, this, mouseTarget, me.button, me.stateMask); + mouseTarget.handleMouseExited(currentEvent); + releaseCapture(); + mouseTarget = null; + } +} + +/** + * @see EventDispatcher#dispatchMousePressed(dwt.events.MouseEvent) + */ +public void dispatchMousePressed(dwt.events.MouseEvent.MouseEvent me) { + receive(me); + if (mouseTarget !is null) { + mouseTarget.handleMousePressed(currentEvent); + if (currentEvent.isConsumed()) + setCapture(mouseTarget); + } +} + +/** + * @see EventDispatcher#dispatchMouseMoved(dwt.events.MouseEvent) + */ +public void dispatchMouseMoved(dwt.events.MouseEvent.MouseEvent me) { + receive(me); + if (mouseTarget !is null) { + if ((me.stateMask & DWT.BUTTON_MASK) !is 0) + mouseTarget.handleMouseDragged(currentEvent); + else + mouseTarget.handleMouseMoved(currentEvent); + } +} + +/** + * @see EventDispatcher#dispatchMouseReleased(dwt.events.MouseEvent) + */ +public void dispatchMouseReleased(dwt.events.MouseEvent.MouseEvent me) { + receive(me); + if (mouseTarget !is null) { + mouseTarget.handleMouseReleased(currentEvent); + } + releaseCapture(); + receive(me); +} + +/** + * @see EventDispatcher#getAccessibilityDispatcher() + */ +protected AccessibilityDispatcher getAccessibilityDispatcher() { + return null; +} + +/** + * Returns the current mouse event. + * @return the current mouse event; can be <code>null</code> + */ +protected MouseEvent getCurrentEvent() { + return currentEvent; +} + +private IFigure getCurrentToolTip() { + if (hoverSource !is null) + return hoverSource.getToolTip(); + else + return null; +} + +/** + * Returns the figure that the cursor is over. + * @return the cursor target + */ +protected IFigure getCursorTarget() { + return cursorTarget; +} + +/** + * Returns the ToolTipHelper used to display tooltips on hover events. + * @return the ToolTipHelper + */ +protected ToolTipHelper getToolTipHelper() { + if (toolTipHelper is null) + toolTipHelper = new ToolTipHelper(control); + return toolTipHelper; +} + +/** + * Returns the FocusTraverseManager which is used to determine which figure will get focus + * when a TAB or ALT+TAB key sequence occurs. + * @return the FocusTraverseManager + */ +protected final FocusTraverseManager getFocusTraverseManager() { + if (focusManager is null) { + focusManager = new FocusTraverseManager(); + } + return focusManager; +} + +/** + * @see EventDispatcher#getFocusOwner() + */ +/*package*/ IFigure getFocusOwner() { + return focusOwner; +} + +/** + * Returns the figure that is the target of mouse events. This may not be the figure + * beneath the cursor because another figure may have captured the mouse and will continue + * to get mouse events until capture is released. + * @return the mouse target + */ +protected IFigure getMouseTarget() { + return mouseTarget; +} + +/** + * Returns the root figure for this dispatcher. + * @return the root figure + */ +protected IFigure getRoot() { + return root; +} + +/** + * @see EventDispatcher#isCaptured() + */ +public bool isCaptured() { + return captured; +} + +private void receive(dwt.events.MouseEvent.MouseEvent me) { + currentEvent = null; + updateFigureUnderCursor(me); + int state = me.stateMask; + if (captured) { + if (mouseTarget !is null) + currentEvent = new MouseEvent(me.x, me.y, this, mouseTarget, me.button, state); + } else { + IFigure f = root.findMouseEventTargetAt(me.x, me.y); + if (f is mouseTarget) { + if (mouseTarget !is null) + currentEvent = + new MouseEvent(me.x, me.y, this, mouseTarget, me.button, state); + return; + } + if (mouseTarget !is null) { + currentEvent = new MouseEvent(me.x, me.y, this, mouseTarget, me.button, state); + mouseTarget.handleMouseExited(currentEvent); + } + setMouseTarget(f); + if (mouseTarget !is null) { + currentEvent = new MouseEvent(me.x, me.y, this, mouseTarget, me.button, state); + mouseTarget.handleMouseEntered(currentEvent); + } + } +} + +/** + * @see EventDispatcher#releaseCapture() + */ +protected void releaseCapture() { + captured = false; +} + +/** + * @see EventDispatcher#requestFocus(IFigure) + */ +public void requestFocus(IFigure fig) { + setFocus(fig); +} + +/** + * @see EventDispatcher#requestRemoveFocus(IFigure) + */ +public void requestRemoveFocus(IFigure fig) { + if (getFocusOwner() is fig) + setFocus(null); + if (mouseTarget is fig) + mouseTarget = null; + if (cursorTarget is fig) + cursorTarget = null; + if (hoverSource is fig) + hoverSource = null; + getFocusTraverseManager().setCurrentFocusOwner(null); +} + +/** + * @see EventDispatcher#setCapture(IFigure) + */ +protected void setCapture(IFigure figure) { + captured = true; + mouseTarget = figure; +} + +/** + * @see EventDispatcher#setControl(Control) + */ +public void setControl(Control c) { + if (c is control) + return; + if (control !is null && !control.isDisposed()) + throw new RuntimeException( + "Can not set control again once it has been set"); //$NON-NLS-1$ + if (c !is null) + c.addDisposeListener(new class() dwt.events.DisposeListener.DisposeListener { + public void widgetDisposed(DisposeEvent e) { + if (toolTipHelper !is null) + toolTipHelper.dispose(); + } + }); + control = c; +} + +/** + * Sets the mouse cursor. + * @param c the new cursor + */ +protected void setCursor(Cursor c) { + if (c is null && cursor is null) { + return; + } else if ((c !is cursor) || (!c.opEquals(cursor))) { + cursor = c; + if (control !is null && !control.isDisposed()) + control.setCursor(c); + } +} + +/** + * Enables key traversal via TAB and ALT+TAB if <i>traverse</i> is <code>true</code>. + * Disables it otherwise. + * @param traverse whether key traversal should be enabled + */ +public void setEnableKeyTraversal(bool traverse) { + figureTraverse = traverse; +} + +/** + * Sets the figure under the mouse cursor. + * @param f the new figure under the cursor + */ +protected void setFigureUnderCursor(IFigure f) { + if (cursorTarget is f) + return; + cursorTarget = f; + updateCursor(); +} + +/** + * Sets the focus figure. If the figure currently with focus is not <code>null</code>, + * {@link IFigure#handleFocusLost(FocusEvent)} is called on the current focused figure. If + * the new focus figure is not <code>null</code>, this will call + * {@link IFigure#handleFocusGained(FocusEvent)} on the new focused figure. + * @param fig the new focus figure + */ +protected void setFocus(IFigure fig) { + if (fig is focusOwner) + return; + FocusEvent fe = new FocusEvent(focusOwner, fig); + IFigure oldOwner = focusOwner; + focusOwner = fig; + if (oldOwner !is null) + oldOwner.handleFocusLost(fe); + if (fig !is null) + getFocusTraverseManager().setCurrentFocusOwner(fig); + if (focusOwner !is null) + focusOwner.handleFocusGained(fe); +} + +/** + * Sets the figure that the mouse cursor is hovering over. + * @param figure the new hover source + * @param me the mouse event + */ +protected void setHoverSource(Figure figure, dwt.events.MouseEvent.MouseEvent me) { + hoverSource = figure; + if (figure !is null) { + Control control = cast(Control)me.getSource(); + dwt.graphics.Point.Point absolute; + absolute = control.toDisplay(new dwt.graphics.Point.Point(me.x, me.y)); + toolTipHelper = getToolTipHelper(); + toolTipHelper.updateToolTip( + hoverSource, getCurrentToolTip(), absolute.x, absolute.y); + } else if (toolTipHelper !is null) { + // Update with null to clear hoverSource in ToolTipHelper + toolTipHelper.updateToolTip(hoverSource, getCurrentToolTip(), me.x, me.y); + } +} + +/** + * Sets the given figure to be the target of future mouse events. + * @param figure the new mouse target + */ +protected void setMouseTarget(IFigure figure) { + mouseTarget = figure; +} + +/** + * @see EventDispatcher#setRoot(IFigure) + */ +public void setRoot(IFigure figure) { + root = figure; +} + +/** + * @see EventDispatcher#updateCursor() + */ +protected void updateCursor() { + Cursor newCursor = null; + if (cursorTarget !is null) + newCursor = cursorTarget.getCursor(); + setCursor(newCursor); +} + +/** + * Updates the figure under the cursor, unless the mouse is captured, in which case all + * mouse events will be routed to the figure that captured the mouse. + * @param me the mouse event + */ +protected void updateFigureUnderCursor(dwt.events.MouseEvent.MouseEvent me) { + if (!captured) { + IFigure f = root.findFigureAt(me.x, me.y); + setFigureUnderCursor(f); + if (cast(Figure)cursorTarget !is hoverSource) + updateHoverSource(me); + } +} + +/** + * Updates the figure that will receive hover events. The hover source must have a + * tooltip. If the figure under the mouse doesn't have a tooltip set, this method will + * walk up the ancestor hierarchy until either a figure with a tooltip is found or it + * gets to the root figure. + * @param me the mouse event + */ +protected void updateHoverSource(dwt.events.MouseEvent.MouseEvent me) { + /* + * Derive source from figure under cursor. + * Set the source in setHoverSource(); + * If figure.getToolTip() is null, get parent's toolTip + * Continue parent traversal until a toolTip is found or root is reached. + */ + if (cursorTarget !is null) { + bool sourceFound = false; + Figure source = cast(Figure)cursorTarget; + while (!sourceFound && source.getParent() !is null) { + if (source.getToolTip() !is null) + sourceFound = true; + else + source = cast(Figure)source.getParent(); + } + setHoverSource(source, me); + } else { + setHoverSource(null, me); + } +} + +}