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

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