source: trunk/autoquest-core-events/src/main/java/de/ugoe/cs/autoquest/eventcore/guimodel/GUIElementTree.java @ 2146

Last change on this file since 2146 was 2146, checked in by pharms, 7 years ago
  • refactored GUI model so that hierarchical event target structures can also be used and created by plugins not being strictly for GUIs
  • Property svn:mime-type set to text/plain
File size: 8.8 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.eventcore.guimodel;
16
17import java.util.ArrayList;
18import java.util.HashMap;
19import java.util.List;
20import java.util.Map;
21
22import de.ugoe.cs.autoquest.eventcore.EventTargetModelException;
23import de.ugoe.cs.autoquest.eventcore.IEventTargetFactory;
24import de.ugoe.cs.autoquest.eventcore.guimodel.GUIElementFactory;
25import de.ugoe.cs.autoquest.eventcore.guimodel.GUIModel;
26
27/**
28 * <p>
29 * This class provides the interfaces for GUI element trees.
30 * </p>
31 * <p>
32 * The GUIElementTree represents the hierarchical structure of the GUI elements "as it is"
33 * currently during a session. It may change during the session due to creation and destruction
34 * of GUI elements. The parameter T represents the id type of the GUI elements that are handled
35 * internally.
36 * </p>
37 *
38 * @author Fabian Glaser
39 * @author Steffen Herbold
40 * @version 1.0
41 */
42public class GUIElementTree<T> {
43    /**
44     * <p>
45     * Map of all GUI elements that are part of the tree for efficient searching. The keys of the
46     * map are the ids of the GUI elements.
47     * </p>
48     */
49    private Map<T, IGUIElement> guiElements;
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 ids of the GUI elements.
55     * </p>
56     */
57    private Map<T, IGUIElementSpec> 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     * ids of the parent GUI elements.
63     * </p>
64     */
65    private Map<T, List<T>> 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     * ids of the child GUI elements.
71     * </p>
72     */
73    private Map<T, T> parentRelations;
74
75    /**
76     * <p>
77     * the internally created GUI model
78     * </p>
79     */
80    private GUIModel guiModel;
81
82    /**
83     * <p>
84     * the GUI element factory used in the model
85     * </p>
86     */
87    private IEventTargetFactory guiElementFactory = GUIElementFactory.getInstance();
88
89    /**
90     * <p>
91     * Creates a new GUIElementTree.
92     * </p>
93     */
94    public GUIElementTree() {
95        guiElementSpecs = new HashMap<T, IGUIElementSpec>();
96        childRelations = new HashMap<T, List<T>>();
97        parentRelations = new HashMap<T, T>();
98        guiElements = new HashMap<T, IGUIElement>();
99        guiModel = new GUIModel();
100    }
101   
102    /**
103     * <p>
104     * Creates a GUIElementTree with an already existing guiModel
105     * @param guiModel
106     * </p>
107     */
108    public GUIElementTree(GUIModel guiModel){
109        guiElementSpecs = new HashMap<T, IGUIElementSpec>();
110        childRelations = new HashMap<T, List<T>>();
111        parentRelations = new HashMap<T, T>();
112        guiElements = new HashMap<T, IGUIElement>();
113        this.guiModel = guiModel;
114    }
115
116    /**
117     * <p>
118     * Adds a new GUI element to the tree.
119     * </p>
120     *
121     * @param guiElementID
122     *            id of the GUI element to be created
123     * @param parentID
124     *            id of the parent GUI element
125     * @param guiElementSpec
126     *            the GUI element specification
127     *           
128     * @throws EventTargetModelException if the GUI element can not be added to the underlying GUI model
129     */
130    public void add(T guiElementID,
131                    T parentID,
132                    IGUIElementSpec guiElementSpec)
133        throws EventTargetModelException
134    {
135        IGUIElement guiElement = guiElements.get(guiElementID);
136       
137        if (guiElement == null) {
138            IGUIElementSpec parent = guiElementSpecs.get(parentID);
139            if (parent != null) {
140                List<T> otherChildren = childRelations.get(parentID);
141
142                if (otherChildren == null) {
143                    otherChildren = new ArrayList<T>();
144                    childRelations.put(parentID, otherChildren);
145                }
146
147                otherChildren.add(guiElementID);
148
149                parentRelations.put(guiElementID, parentID);
150            }
151            guiElementSpecs.put(guiElementID, guiElementSpec);
152           
153            List<IGUIElementSpec> guiElementPath = new ArrayList<IGUIElementSpec>();
154
155            T currentElementID = guiElementID;
156            while (guiElementSpec != null) {
157                guiElementPath.add(0, guiElementSpec);
158                currentElementID = parentRelations.get(currentElementID);
159                guiElementSpec = guiElementSpecs.get(currentElementID);
160            }
161
162            guiElement = (IGUIElement) guiModel.integratePath(guiElementPath, guiElementFactory);
163            guiElements.put(guiElementID, guiElement);
164        }
165    }
166
167    /**
168     * <p>
169     * Searches the tree for a GUI element with the specified id and returns its
170     * {@link IGUIElement} .
171     * </p>
172     *
173     * @param id
174     *            id that is looked for
175     * @return {@link IGUIElementSpec} of the GUI element with the given id if found, null otherwise
176     */
177    public IGUIElement find(T id) {
178        return guiElements.get(id);
179    }
180
181    /**
182     * <p>
183     * Returns the id of the provided {@link IGUIElement}. The comparison is performed using the
184     * equals method of the GUI element.
185     * </p>
186     *
187     * @param guiElement
188     *            guiElement that is looked for
189     * @return the id of the GUI element, null if the GUI element can not be found
190     */
191    public T find(IGUIElement guiElement) {
192        for (Map.Entry<T, IGUIElement> entry : guiElements.entrySet()) {
193            if (guiElement.equals(entry.getValue())) {
194                return entry.getKey();
195            }
196        }
197       
198        return null;
199    }
200
201    /**
202     * <p>
203     * Removes a GUI element (defined by its id) from the tree. All children of the GUI element will be
204     * removed recursively.
205     * </p>
206     *
207     * @param id
208     *            id of the GUI element to be removed
209     * @return number of GUI elements that were removed
210     */
211    public int remove(T id) {
212        int removedCounter = 0;
213        IGUIElementSpec node = guiElementSpecs.remove(id);
214
215        if (node != null) {
216            removedCounter++;
217            List<T> nodesToBeRemoved = childRelations.remove(id);
218
219            // remove all children and sub-children, if any
220            if (nodesToBeRemoved != null) {
221                for (int i = 0; i < nodesToBeRemoved.size(); i++) {
222                    T nodeToBeRemoved = nodesToBeRemoved.get(i);
223                    List<T> children =
224                        childRelations.remove(nodeToBeRemoved);
225
226                    if (children != null) {
227                        nodesToBeRemoved.addAll(children);
228                    }
229
230                    guiElementSpecs.remove(nodeToBeRemoved);
231                    parentRelations.remove(nodeToBeRemoved);
232                    removedCounter++;
233                }
234            }
235
236            /* the node may be a child node of a parent. So search for it in the child relations
237            of the parent and remove it */
238            T parent = parentRelations.remove(id);
239            if (parent != null) {
240                List<T> children = childRelations.get(parent);
241
242                if (children != null) {
243                    for (int i = 0; i < children.size(); i++) {
244                        if (children.get(i) == id) {
245                            children.remove(i);
246                            break;
247                        }
248                    }
249
250                    if (children.size() <= 0) {
251                        childRelations.remove(parent);
252                    }
253                }
254            }
255        }
256        return removedCounter;
257    }
258
259    /**
260     * @return the guiModel
261     */
262    public GUIModel getGUIModel() {
263        return guiModel;
264    }
265
266    /**
267     * <p>
268     * Returns the number of nodes contained in the JFCComponentTree.
269     * </p>
270     *
271     * @return number of nodes
272     */
273    public int size() {
274        return guiElementSpecs.size();
275    }
276
277}
Note: See TracBrowser for help on using the repository browser.