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

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