Mercurial > projects > dwt-addons
diff dwtx/draw2d/FocusTraverseManager.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/FocusTraverseManager.d Sun Aug 03 00:52:14 2008 +0200 @@ -0,0 +1,195 @@ +/******************************************************************************* + * 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 dwtx.draw2d.FocusTraverseManager; + +import dwt.dwthelper.utils; +import dwtx.dwtxhelper.Collection; +import dwtx.draw2d.IFigure; + +/** + * This class is a helper to the {@link SWTEventDispatcher}. It handles the task of + * determining which Figure will gain focus upon a tab/shift-tab. It also keeps track of + * the Figure with current focus. + * <p> + * Note: When a Canvas with a {@link LightweightSystem} gains focus, it gives focus to the + * child Figure who had focus when this Canvas lost focus. If the canvas is gaining focus + * for the first time, focus is given to its first child Figure. + */ +public class FocusTraverseManager { + +IFigure currentFocusOwner; + +/** + * Default constructor. + */ +public this() { } + +private IFigure findDeepestRightmostChildOf(IFigure fig) { + while (fig.getChildren().size() !is 0) { + fig = cast(IFigure)fig.getChildren().get(fig.getChildren().size() - 1); + } + return fig; +} + +/** + * Returns the IFigure that will receive focus upon a 'tab' traverse event. + * + * @param root the {@link LightweightSystem LightweightSystem's} root figure + * @param prevFocus the IFigure who currently owns focus + * @return the next focusable figure + */ +public IFigure getNextFocusableFigure(IFigure root, IFigure prevFocus) { + bool found = false; + IFigure nextFocus = prevFocus; + + /* + * If no Figure currently has focus, apply focus to root's first focusable child. + */ + if (prevFocus is null) { + if (root.getChildren().size() !is 0) { + nextFocus = (cast(IFigure)root.getChildren().get(0)); + if (isFocusEligible(nextFocus)) + return nextFocus; + } else + return null; + } + + int siblingPos = nextFocus.getParent().getChildren().indexOf(cast(Object)nextFocus); + while (!found) { + IFigure parent = nextFocus.getParent(); + + /* + * Figure traversal is implemented using the pre-order left to right + * tree traversal algorithm. + * + * If the focused sibling has children, traverse to its leftmost child. + * If the focused sibling has no children, traverse to the sibling + * to its right. + * If there is no sibling to the right, go up the tree until a node + * with un-traversed siblings is found. + */ + List siblings = parent.getChildren(); + + if (nextFocus.getChildren().size() !is 0) { + nextFocus = cast(IFigure)nextFocus.getChildren().get(0); + siblingPos = 0; + if (isFocusEligible(nextFocus)) + found = true; + } else if (siblingPos < siblings.size() - 1) { + nextFocus = (cast(IFigure)(siblings.get(++siblingPos))); + if (isFocusEligible(nextFocus)) + found = true; + } else { + bool untraversedSiblingFound = false; + while (!untraversedSiblingFound) { + IFigure p = nextFocus.getParent(); + IFigure gp = p.getParent(); + + if (gp !is null) { + int parentSiblingCount = gp.getChildren().size(); + int parentIndex = gp.getChildren().indexOf(cast(Object)p); + if (parentIndex < parentSiblingCount - 1) { + nextFocus = (cast(IFigure)p.getParent() + .getChildren().get(parentIndex + 1)); + siblingPos = parentIndex + 1; + untraversedSiblingFound = true; + if (isFocusEligible(nextFocus)) + found = true; + } else + nextFocus = p; + } else { + nextFocus = null; + untraversedSiblingFound = true; + found = true; + } + } + } + } + return nextFocus; +} + +/** + * Returns the IFigure that will receive focus upon a 'shift-tab' traverse event. + * + * @param root The {@link LightweightSystem LightweightSystem's} root figure + * @param prevFocus The IFigure who currently owns focus + * @return the previous focusable figure + */ +public IFigure getPreviousFocusableFigure(IFigure root, IFigure prevFocus) { + if (prevFocus is null) + return null; + + bool found = false; + IFigure nextFocus = prevFocus; + while (!found) { + IFigure parent = nextFocus.getParent(); + + /* + * At root, return null to indicate traversal + * is complete. + */ + if (parent is null) + return null; + + List siblings = parent.getChildren(); + int siblingPos = siblings.indexOf(cast(Object)nextFocus); + + /* + * Figure traversal is implemented using the post-order right to left + * tree traversal algorithm. + * + * Find the rightmost child. + * If this child is focusable, return it + * If not focusable, traverse to its sibling and repeat. + * If there is no sibling, traverse its parent. + */ + if (siblingPos !is 0) { + IFigure child = + findDeepestRightmostChildOf(cast(IFigure)siblings.get(siblingPos - 1)); + if (isFocusEligible(child)) { + found = true; + nextFocus = child; + } else if ((cast(Object)child).opEquals(cast(Object)nextFocus)) { + if (isFocusEligible(nextFocus)) + found = true; + } else + nextFocus = child; + } else { + nextFocus = parent; + if (isFocusEligible(nextFocus)) + found = true; + } + } + return nextFocus; +} + +/** + * @return the figure that currently has focus + */ +public IFigure getCurrentFocusOwner() { + return currentFocusOwner; +} + +private bool isFocusEligible(IFigure fig) { + return (fig !is null && fig.isFocusTraversable() && fig.isShowing()); +} + +/** + * Sets the currently focused figure. + * @param fig the figure to get focus + */ +public void setCurrentFocusOwner(IFigure fig) { + currentFocusOwner = fig; +} + +}