source: trunk/autoquest-plugin-jfc/src/main/java/de/ugoe/cs/autoquest/plugin/jfc/guimodel/JFCGUIElement.java

Last change on this file 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:executable set to *
File size: 11.4 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.jfc.guimodel;
16
17import de.ugoe.cs.autoquest.eventcore.IEventTargetSpec;
18import de.ugoe.cs.autoquest.eventcore.guimodel.AbstractDefaultGUIElement;
19import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement;
20import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIView;
21
22/**
23 * <p>
24 * Base class for all JFC GUI elements.
25 * </p>
26 *
27 * @version 1.0
28 * @author Patrick Harms
29 */
30public class JFCGUIElement extends AbstractDefaultGUIElement {
31
32    /**
33     * <p>
34     * Id for object serialization.
35     * </p>
36     */
37    private static final long serialVersionUID = 1L;
38
39    /**
40     * <p>
41     * the default distance value for different applications
42     * </p>
43     */
44    protected static final double DISTANCE_DISTINCT_APPLICATION = 1.0;
45
46    /**
47     * <p>
48     * the default distance value for same application but different views, i.e., dialogs, frames,
49     * or tabbed panes
50     * </p>
51     */
52    protected static final double DISTANCE_SAME_APPLICATION = 0.75;
53
54    /**
55     * <p>
56     * the default distance value for same view but different panels
57     * </p>
58     */
59    protected static final double DISTANCE_SAME_VIEW = 0.5;
60
61    /**
62     * <p>
63     * the default distance value for same parent panel but different GUI elements
64     * </p>
65     */
66    protected static final double DISTANCE_SAME_PANEL = 0.2;
67
68    /**
69     * <p>
70     * the default distance value for identical GUI elements
71     * </p>
72     */
73    protected static final double DISTANCE_NONE = 0.0;
74
75    /**
76     * <p>
77     * Specification of the GUI Element
78     * </p>
79     */
80    private JFCGUIElementSpec specification;
81
82    /**
83     * <p>
84     * Constructor. Creates a new JFCGUIElement.
85     * </p>
86     *
87     * @param specification
88     *            specification of created GUI element
89     * @param parent
90     *            parent of the created GUI element; null means that the element is a top-level
91     *            window
92     */
93    public JFCGUIElement(JFCGUIElementSpec specification, JFCGUIElement parent) {
94        super(specification, parent);
95        this.specification = specification;
96    }
97
98    /*
99     * (non-Javadoc)
100     *
101     * @see de.ugoe.cs.autoquest.eventcore.IEventTarget#getPlatform()
102     */
103    @Override
104    public String getPlatform() {
105        return "JFC";
106    }
107
108    /**
109     * <p>
110     * Returns the type of the GUI element, i.e., the name of its Java class.
111     * </p>
112     *
113     * @return the Java class name
114     */
115    public String getJavaType() {
116        return specification.getType();
117    }
118
119    /**
120     * <p>
121     * Returns the name of the GUI element.
122     * </p>
123     *
124     * @return the name
125     */
126    public String getName() {
127        return specification.getName();
128    }
129
130    /**
131     * <p>
132     * Returns the icon of the GUI element.
133     * </p>
134     *
135     * @return the icon
136     */
137    String getIcon() {
138        return specification.getIcon();
139    }
140
141    /**
142     * <p>
143     * Returns the index of the GUI element.
144     * </p>
145     *
146     * @return the index
147     */
148    int getIndex() {
149        return specification.getIndex();
150    }
151
152    /**
153     * <p>
154     * Returns the object hash of the GUI element.
155     * </p>
156     *
157     * @return the object hash
158     */
159    int getElementHash() {
160        return specification.getElementHash();
161    }
162
163    /*
164     * (non-Javadoc)
165     *
166     * @see
167     * de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#updateSpecification(de.ugoe.cs.autoquest
168     * .eventcore .guimodel.IGUIElementSpec)
169     */
170    @Override
171    public void updateSpecification(IEventTargetSpec updateSpecification) {
172        if (updateSpecification instanceof JFCGUIElementSpec) {
173            specification.update(((JFCGUIElementSpec) updateSpecification));
174        }
175    }
176
177    /*
178     * (non-Javadoc)
179     *
180     * @see java.lang.Object#toString()
181     */
182    @Override
183    public String getStringIdentifier() {
184        String str = this.toString();
185        if (getParent() != null) {
186            return str + "<-" + getParent().getStringIdentifier();
187        }
188        return str;
189    }
190
191    public String getJacaretoHierarchy() {
192        String str;
193
194        // get the Java classname, ignore the package hierarchy if present
195        String[] parts = getSpecification().getType().split("\\.");
196
197        // find the correct Jacareto index
198        // jacareto indices start at 1
199        int jacIndex = ((JFCGUIElementSpec) getSpecification()).getAltIndex() + 1;
200        str = parts[parts.length - 1] + "_(" + jacIndex + ")";
201
202        if (getParent() != null) {
203            return ((JFCGUIElement) getParent()).getJacaretoHierarchy() + "." + str;
204        }
205        return str;
206    }
207
208    public String getJacaretoRoot() {
209        return getJacaretoHierarchy().split("\\.")[0];
210    }
211
212    /*
213     * (non-Javadoc)
214     *
215     * @see java.lang.Object#toString()
216     */
217    @Override
218    public String toString() {
219        String str =
220            getElementDescriptor() + "(" + getName() + "," + getElementHash() + "," + getIcon() +
221                "," + getIndex() + ")";
222        return str;
223    }
224
225    /* (non-Javadoc)
226     * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#getView()
227     */
228    @Override
229    public IGUIView getView() {
230        JFCGUIElement element = this;
231       
232        while ((element != null) && (!(element instanceof JFCFrame)) &&
233               (!(element instanceof JFCDialog)))
234        {
235            if (!(element.getParent() instanceof JFCTabbedPane)) {
236                element = (JFCGUIElement) element.getParent();
237            }
238            else {
239                // break, as all children of a tabbed pane are always views
240                break;
241            }
242        }
243       
244        return new JFCView(element);
245    }
246
247    /*
248     * (non-Javadoc)
249     *
250     * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#getDistanceTo(IGUIElement)
251     */
252    @Override
253    public double getDistanceTo(IGUIElement otherElement) {
254        if (otherElement instanceof JFCGUIElement) {
255            if (equals(otherElement)) {
256                return DISTANCE_NONE;
257            }
258           
259            if (!areInSameView(this, otherElement)) {
260                IGUIElement root1 = this;
261               
262                while (root1.getParent() != null) {
263                    root1 = root1.getParent();
264                }
265               
266                IGUIElement root2 = otherElement;
267               
268                while (root2.getParent() != null) {
269                    root2 = root2.getParent();
270                }
271               
272                if (!root1.equals(root2)) {
273                    return DISTANCE_DISTINCT_APPLICATION;
274                }
275                else {
276                    return DISTANCE_SAME_APPLICATION;
277                }
278            }
279            else {
280                // check if they have the same parent panel. If so, they are very close.
281                // If not, they may be structured completely differently
282                IGUIElement parentPanel1 = this;
283               
284                while (parentPanel1 != null) {
285                    if ((parentPanel1 instanceof JFCPanel) ||
286                        (parentPanel1 instanceof JFCFrame) ||
287                        (parentPanel1 instanceof JFCDialog) ||
288                        (parentPanel1 instanceof JFCCanvas) ||
289                        (parentPanel1 instanceof JFCMenu) ||
290                        (parentPanel1 instanceof JFCScrollPane) ||
291                        (parentPanel1 instanceof JFCSplitPane) ||
292                        (parentPanel1 instanceof JFCTabbedPane))
293                    {
294                        break;
295                    }
296                    else {
297                        parentPanel1 = parentPanel1.getParent();
298                    }
299                }
300               
301                IGUIElement parentPanel2 = otherElement;
302               
303                while (parentPanel2 != null) {
304                    if ((parentPanel2 instanceof JFCPanel) ||
305                        (parentPanel2 instanceof JFCFrame) ||
306                        (parentPanel2 instanceof JFCDialog) ||
307                        (parentPanel2 instanceof JFCCanvas) ||
308                        (parentPanel2 instanceof JFCMenu) ||
309                        (parentPanel2 instanceof JFCScrollPane) ||
310                        (parentPanel2 instanceof JFCSplitPane) ||
311                        (parentPanel2 instanceof JFCTabbedPane))
312                    {
313                        break;
314                    }
315                    else {
316                        parentPanel2 = parentPanel2.getParent();
317                    }
318                }
319               
320                // a check for the identity of the objects is sufficient. That they resist on the
321                // same document was checked beforehand. So even a condense of the GUI model should
322                // not cause an invalid result here.
323                if ((parentPanel1 == parentPanel2) ||
324                    ((parentPanel1 != null) && (parentPanel1.equals(parentPanel2))))
325                {
326                    return DISTANCE_SAME_PANEL;
327                }
328                else {
329                    return DISTANCE_SAME_VIEW;
330                }
331            }
332        }
333       
334        return DISTANCE_DISTINCT_APPLICATION;
335    }
336
337    /**
338     * <p>
339     * A short string describing the GUI element, e.g., Button, Canvas, or ScrollBar.
340     * </p>
341     *
342     * @return short element descriptor
343     */
344    protected String getElementDescriptor() {
345        return "Default";
346    }
347
348    /**
349     * <p>
350     * convenience method to check if two GUI elements are in the same view. In contrast to other
351     * technologies, JFC GUI views may have other views as children. Hence, it is not sufficient to
352     * check, if the direct parent views are identical.
353     * </p>
354     */
355    private boolean areInSameView(IGUIElement guiElement1, IGUIElement guiElement2) {
356        IGUIView view1 = guiElement1.getView();
357        IGUIElement other = guiElement2;
358       
359        while (other != null) {
360            if (view1.equals(other.getView())) {
361                return true;
362            }
363           
364            other = other.getParent();
365        }
366       
367        // the parent views of the other gui element are checked. But not the ones of this. Hence,
368        // check also them.
369        if ((view1 instanceof JFCView) && (((JFCView) view1).getParent() != null)) {
370            return areInSameView(((JFCView) view1).getParent(), guiElement2);
371        }
372        else {
373            return false;
374        }
375    }
376}
Note: See TracBrowser for help on using the repository browser.