source: trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/WindowTree.java @ 619

Last change on this file since 619 was 619, checked in by pharms, 12 years ago
  • adapted implementation to now generate a full GUI model as well as concrete GUI interaction events
File size: 9.0 KB
Line 
1
2package de.ugoe.cs.quest.plugin.mfc.guimodel;
3
4import java.util.ArrayList;
5import java.util.HashMap;
6import java.util.HashSet;
7import java.util.List;
8import java.util.Map;
9import java.util.Set;
10
11import de.ugoe.cs.quest.eventcore.guimodel.GUIElementFactory;
12import de.ugoe.cs.quest.eventcore.guimodel.GUIModel;
13import de.ugoe.cs.quest.eventcore.guimodel.GUIModelException;
14import de.ugoe.cs.quest.eventcore.guimodel.IGUIElementFactory;
15
16
17/**
18 * <p>
19 * This class provides an the interfaces for window trees.
20 * </p>
21 * <p>
22 * The window tree represents the hierarchical structure of the windows "as it is" currently during
23 * a session. It may change during the session due to creation and destruction of windows.
24 * </p>
25 *
26 * @author Steffen Herbold
27 * @version 1.0
28 */
29public class WindowTree {
30
31    /**
32     * <p>
33     * Maintains a set of all the targets of all widgets that were at some point part of the
34     * window tree.
35     * </p>
36     */
37    private Set<MFCGUIElementSpec> targets;
38
39    /**
40     * <p>
41     * Map of all GUI element specifications that are part of the tree for efficient searching.
42     * The keys of the map are the hwnd's of the GUI elements.
43     * </p>
44     */
45    private Map<Long, MFCGUIElementSpec> guiElementSpecs;
46
47    /**
48     * <p>
49     * Map of all children of GUI elements that are part of the tree. The keys of the map are
50     * the hwnd's of the parent GUI elements.
51     * </p>
52     */
53    private Map<Long, List<MFCGUIElementSpec>> childRelations;
54
55    /**
56     * <p>
57     * Map of all parents of GUI elements that are part of the tree. The keys of the map are
58     * the hwnd's of the child GUI elements.
59     * </p>
60     */
61    private Map<Long, MFCGUIElementSpec> parentRelations;
62
63    /**
64     * <p>
65     * the internally created GUI model
66     * </p>
67     */
68    private GUIModel guiModel = new GUIModel();
69   
70    /**
71     * <p>
72     * the GUI element factory used in the model
73     * </p>
74     */
75    private IGUIElementFactory guiElementFactory = GUIElementFactory.getInstance();
76
77    /**
78     * <p>
79     * Map of all GUI elements that are part of the tree for efficient searching. The keys of the
80     * map are the hwnd's of the GUI elements.
81     * </p>
82     */
83    private Map<Long, MFCGUIElement> guiElements;
84
85    /**
86     * <p>
87     * Creates a new WindowTree.
88     * </p>
89     * <p>
90     * Private, as the class is a singleton.
91     * </p>
92     */
93    public WindowTree() {
94        guiElementSpecs = new HashMap<Long, MFCGUIElementSpec>();
95        targets = new HashSet<MFCGUIElementSpec>();
96        childRelations = new HashMap<Long, List<MFCGUIElementSpec>>();
97        parentRelations = new HashMap<Long, MFCGUIElementSpec>();
98        guiElements = new HashMap<Long, MFCGUIElement>();
99    }
100
101    /**
102     * <p>
103     * Adds a new window to the tree.
104     * </p>
105     *
106     * @param parentHwnd
107     *            hwnd of the parent window
108     * @param childHwnd
109     *            hwnd of the window to be created
110     * @param childWindowName
111     *            resource id of the window to be created
112     * @param resourceId
113     *            resource id of the window to be created
114     * @param className
115     *            class name of the window to be created
116     */
117    public void add(long    parentHwnd,
118                    long    childHwnd,
119                    String  childWindowName,
120                    int     resourceId,
121                    String  className,
122                    boolean isModal)
123    {
124        MFCGUIElementSpec parent = guiElementSpecs.get(parentHwnd);
125        MFCGUIElementSpec child = guiElementSpecs.get(childHwnd);
126        if (child == null) {
127            child =
128                new MFCGUIElementSpec(childHwnd, childWindowName, resourceId, className, isModal);
129            if (parent != null) {
130                List<MFCGUIElementSpec> otherChildren = childRelations.get(parentHwnd);
131               
132                if (otherChildren == null) {
133                    otherChildren = new ArrayList<MFCGUIElementSpec>();
134                    childRelations.put(parentHwnd, otherChildren);
135                }
136               
137                otherChildren.add(child);
138               
139                parentRelations.put(childHwnd, parent);
140            }
141            guiElementSpecs.put(childHwnd, child);
142            targets.add(child);
143        }
144    }
145
146    /**
147     * <p>
148     * Searches the tree for a window with the specified hwnd and returns its {@link MFCGUIElementSpec}
149     * .
150     * </p>
151     *
152     * @param hwnd
153     *            hwnd that is looked for
154     * @return {@link MFCGUIElementSpec} of the window with the given hwnd if found, null otherwise
155     */
156    public MFCGUIElement find(long hwnd) {
157        MFCGUIElement guiElement = guiElements.get(hwnd);
158        if (guiElement == null) {
159            List<MFCGUIElementSpec> guiElementPath = new ArrayList<MFCGUIElementSpec>();
160           
161            MFCGUIElementSpec child = guiElementSpecs.get(hwnd);
162           
163            if (child == null) {
164                throw new RuntimeException("no GUI element found with id " + hwnd);
165            }
166           
167            while (child != null) {
168                guiElementPath.add(0, child);
169                child = parentRelations.get(child.getHwnd());
170            }
171           
172            try {
173                guiElement = (MFCGUIElement)
174                    guiModel.integratePath(guiElementPath, guiElementFactory);
175            }
176            catch (GUIModelException e) {
177                throw new RuntimeException("could not instantiate GUI element with id " + hwnd, e);
178            }
179            guiElements.put(hwnd, guiElement);
180        }
181        return guiElement;
182    }
183
184    /**
185     * <p>
186     * TODO: comment
187     * </p>
188     *
189     * @param hwnd
190     * @param windowName
191     */
192    public void setName(long hwnd, String windowName) {
193        MFCGUIElementSpec child = guiElementSpecs.get(hwnd);
194        if (child != null) {
195            child.setName(windowName);
196
197            MFCGUIElement guiElement = guiElements.remove(hwnd);
198            if (guiElement == null) {
199                // we need to update the GUI model as well
200                find(hwnd);
201            }
202        }
203    }
204   
205    /**
206     * <p>
207     * Removes a window (defined by its hwnd) from the tree. All children of the window will be
208     * removed recursively.
209     * </p>
210     *
211     * @param hwnd
212     *            hwnd of the window to be removed
213     * @return number of windows that were removed
214     */
215    public int remove(long hwnd) {
216        MFCGUIElementSpec node = guiElementSpecs.remove(hwnd);
217        int removedCounter = 1;
218       
219        if (node != null) {
220            List<MFCGUIElementSpec> nodesToBeRemoved = childRelations.remove(hwnd);
221           
222            // remove all children and sub-children, if any
223            if (nodesToBeRemoved != null) {
224                for (int i = 0; i < nodesToBeRemoved.size(); i++) {
225                    MFCGUIElementSpec nodeToBeRemoved = nodesToBeRemoved.get(i);
226                    List<MFCGUIElementSpec> children =
227                        childRelations.remove(nodeToBeRemoved.getHwnd());
228                   
229                    if (children != null) {
230                        nodesToBeRemoved.addAll(children);
231                    }
232                   
233                    guiElementSpecs.remove(nodeToBeRemoved.getHwnd());
234                    parentRelations.remove(nodeToBeRemoved.getHwnd());
235                    removedCounter++;
236                }
237            }
238
239            // the node may be a child node of a parent. So search for it and remove it
240            MFCGUIElementSpec parent = parentRelations.remove(hwnd);
241            if (parent != null) {
242                List<MFCGUIElementSpec> children = childRelations.get(parent.getHwnd());
243
244                if (children != null) {
245                    for (int i = 0; i < children.size(); i++) {
246                        if (children.get(i).getHwnd() == hwnd) {
247                            children.remove(i);
248                            break;
249                        }
250                    }
251                   
252                    if (children.size() <= 0) {
253                        childRelations.remove(parent.getHwnd());
254                    }
255                }
256            }
257        }
258        return removedCounter;
259    }
260
261    /**
262     * @return the guiModel
263     */
264    public GUIModel getGUIModel() {
265        return guiModel;
266    }
267
268    /**
269     * <p>
270     * Returns the number of nodes contained in the WindowTree.
271     * </p>
272     *
273     * @return number of nodes
274     */
275    public int size() {
276        return guiElementSpecs.size();
277    }
278
279    /**
280     * <p>
281     * Returns a sorted set of all targets that existed any time in the window tree.
282     * </p>
283     *
284     * @return set of targets
285     */
286    public Set<MFCGUIElementSpec> getTargets() {
287        return targets;
288    }
289
290}
Note: See TracBrowser for help on using the repository browser.