Mercurial > projects > dwt-addons
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 } |