comparison 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
comparison
equal deleted inserted replaced
96:b492ba44e44d 98:95307ad235d9
1 /*******************************************************************************
2 * Copyright (c) 2000, 2005 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module dwtx.draw2d.FocusTraverseManager;
14
15 import dwt.dwthelper.utils;
16 import dwtx.dwtxhelper.Collection;
17 import dwtx.draw2d.IFigure;
18
19 /**
20 * This class is a helper to the {@link SWTEventDispatcher}. It handles the task of
21 * determining which Figure will gain focus upon a tab/shift-tab. It also keeps track of
22 * the Figure with current focus.
23 * <p>
24 * Note: When a Canvas with a {@link LightweightSystem} gains focus, it gives focus to the
25 * child Figure who had focus when this Canvas lost focus. If the canvas is gaining focus
26 * for the first time, focus is given to its first child Figure.
27 */
28 public class FocusTraverseManager {
29
30 IFigure currentFocusOwner;
31
32 /**
33 * Default constructor.
34 */
35 public this() { }
36
37 private IFigure findDeepestRightmostChildOf(IFigure fig) {
38 while (fig.getChildren().size() !is 0) {
39 fig = cast(IFigure)fig.getChildren().get(fig.getChildren().size() - 1);
40 }
41 return fig;
42 }
43
44 /**
45 * Returns the IFigure that will receive focus upon a 'tab' traverse event.
46 *
47 * @param root the {@link LightweightSystem LightweightSystem's} root figure
48 * @param prevFocus the IFigure who currently owns focus
49 * @return the next focusable figure
50 */
51 public IFigure getNextFocusableFigure(IFigure root, IFigure prevFocus) {
52 bool found = false;
53 IFigure nextFocus = prevFocus;
54
55 /*
56 * If no Figure currently has focus, apply focus to root's first focusable child.
57 */
58 if (prevFocus is null) {
59 if (root.getChildren().size() !is 0) {
60 nextFocus = (cast(IFigure)root.getChildren().get(0));
61 if (isFocusEligible(nextFocus))
62 return nextFocus;
63 } else
64 return null;
65 }
66
67 int siblingPos = nextFocus.getParent().getChildren().indexOf(cast(Object)nextFocus);
68 while (!found) {
69 IFigure parent = nextFocus.getParent();
70
71 /*
72 * Figure traversal is implemented using the pre-order left to right
73 * tree traversal algorithm.
74 *
75 * If the focused sibling has children, traverse to its leftmost child.
76 * If the focused sibling has no children, traverse to the sibling
77 * to its right.
78 * If there is no sibling to the right, go up the tree until a node
79 * with un-traversed siblings is found.
80 */
81 List siblings = parent.getChildren();
82
83 if (nextFocus.getChildren().size() !is 0) {
84 nextFocus = cast(IFigure)nextFocus.getChildren().get(0);
85 siblingPos = 0;
86 if (isFocusEligible(nextFocus))
87 found = true;
88 } else if (siblingPos < siblings.size() - 1) {
89 nextFocus = (cast(IFigure)(siblings.get(++siblingPos)));
90 if (isFocusEligible(nextFocus))
91 found = true;
92 } else {
93 bool untraversedSiblingFound = false;
94 while (!untraversedSiblingFound) {
95 IFigure p = nextFocus.getParent();
96 IFigure gp = p.getParent();
97
98 if (gp !is null) {
99 int parentSiblingCount = gp.getChildren().size();
100 int parentIndex = gp.getChildren().indexOf(cast(Object)p);
101 if (parentIndex < parentSiblingCount - 1) {
102 nextFocus = (cast(IFigure)p.getParent()
103 .getChildren().get(parentIndex + 1));
104 siblingPos = parentIndex + 1;
105 untraversedSiblingFound = true;
106 if (isFocusEligible(nextFocus))
107 found = true;
108 } else
109 nextFocus = p;
110 } else {
111 nextFocus = null;
112 untraversedSiblingFound = true;
113 found = true;
114 }
115 }
116 }
117 }
118 return nextFocus;
119 }
120
121 /**
122 * Returns the IFigure that will receive focus upon a 'shift-tab' traverse event.
123 *
124 * @param root The {@link LightweightSystem LightweightSystem's} root figure
125 * @param prevFocus The IFigure who currently owns focus
126 * @return the previous focusable figure
127 */
128 public IFigure getPreviousFocusableFigure(IFigure root, IFigure prevFocus) {
129 if (prevFocus is null)
130 return null;
131
132 bool found = false;
133 IFigure nextFocus = prevFocus;
134 while (!found) {
135 IFigure parent = nextFocus.getParent();
136
137 /*
138 * At root, return null to indicate traversal
139 * is complete.
140 */
141 if (parent is null)
142 return null;
143
144 List siblings = parent.getChildren();
145 int siblingPos = siblings.indexOf(cast(Object)nextFocus);
146
147 /*
148 * Figure traversal is implemented using the post-order right to left
149 * tree traversal algorithm.
150 *
151 * Find the rightmost child.
152 * If this child is focusable, return it
153 * If not focusable, traverse to its sibling and repeat.
154 * If there is no sibling, traverse its parent.
155 */
156 if (siblingPos !is 0) {
157 IFigure child =
158 findDeepestRightmostChildOf(cast(IFigure)siblings.get(siblingPos - 1));
159 if (isFocusEligible(child)) {
160 found = true;
161 nextFocus = child;
162 } else if ((cast(Object)child).opEquals(cast(Object)nextFocus)) {
163 if (isFocusEligible(nextFocus))
164 found = true;
165 } else
166 nextFocus = child;
167 } else {
168 nextFocus = parent;
169 if (isFocusEligible(nextFocus))
170 found = true;
171 }
172 }
173 return nextFocus;
174 }
175
176 /**
177 * @return the figure that currently has focus
178 */
179 public IFigure getCurrentFocusOwner() {
180 return currentFocusOwner;
181 }
182
183 private bool isFocusEligible(IFigure fig) {
184 return (fig !is null && fig.isFocusTraversable() && fig.isShowing());
185 }
186
187 /**
188 * Sets the currently focused figure.
189 * @param fig the figure to get focus
190 */
191 public void setCurrentFocusOwner(IFigure fig) {
192 currentFocusOwner = fig;
193 }
194
195 }