source: trunk/JFCMonitor/src/de/ugoe/cs/eventbench/jfcmonitor/JFCComponent.java @ 368

Last change on this file since 368 was 368, checked in by sherbold, 12 years ago
  • JFCMonitor now adds hash of the GUI components to the recorded information
  • Property svn:mime-type set to text/plain
File size: 8.6 KB
Line 
1package de.ugoe.cs.eventbench.jfcmonitor;
2
3import java.awt.Component;
4import java.awt.Container;
5import java.io.File;
6import java.lang.reflect.InvocationTargetException;
7import java.lang.reflect.Method;
8import java.security.InvalidParameterException;
9import java.util.HashMap;
10import java.util.LinkedList;
11import java.util.List;
12import java.util.Map;
13
14import javax.accessibility.AccessibleContext;
15
16import de.ugoe.cs.util.StringTools;
17
18/**
19 * <p>
20 * This class manages information about the current GUI. It always contains the
21 * current GUI hierarchy.
22 * </p>
23 *
24 * @author Steffen Herbold
25 * @version 1.0
26 */
27public class JFCComponent {
28
29        /**
30         * <p>
31         * Map of all known GUI components.
32         * </p>
33         */
34        private static Map<Component, JFCComponent> knownComponents = new HashMap<Component, JFCComponent>();
35
36        /**
37         * <p>
38         * Adds a AWT component to the GUI hierarchy. If the component already
39         * exists in the hierarchy, it is not added a second time.
40         * </p>
41         *
42         * @param component
43         *            component that is added
44         */
45        public static void add(Component component) {
46                add(component, find(component.getParent()));
47        }
48
49        /**
50         * <p>
51         * Adds a AWT component to the GUI hierarchy. If the component already
52         * exists in the hierarchy, it is not added a second time.
53         * </p>
54         *
55         * @param component
56         *            component that is added
57         * @param parent
58         *            parent of the component
59         */
60        public static void add(Component component, JFCComponent parent) {
61                if (!knownComponents.containsKey(component)) {
62                        knownComponents.put(component, new JFCComponent(component, parent));
63                }
64        }
65
66        /**
67         * <p>
68         * Finds a component in the GUI hierarchy and returns the corresponding
69         * JFComponent instance. Returns null if the component is not found.
70         * </p>
71         *
72         * @param component
73         *            component that is searched for
74         * @return corresponding JFComponent instance; null if the compenent is not
75         *         found
76         */
77        public static JFCComponent find(Component component) {
78                return knownComponents.get(component);
79        }
80
81        /**
82         * <p>
83         * Removes a component from the GUI hierarchy. In case the component is not
84         * part of the known hierachy, nothing happens.
85         * </p>
86         *
87         * @param component
88         *            component to be removed
89         */
90        public static void remove(Component component) {
91                JFCComponent jfcComponent = knownComponents.remove(component);
92                if (jfcComponent != null) {
93                        jfcComponent.removeFromParent();
94                        jfcComponent.removeChildren();
95                }
96        }
97
98        /**
99         * <p>
100         * Parent of the GUI component. null means, that the component has no
101         * parent.
102         * </p>
103         */
104        private JFCComponent parent = null;
105
106        /**
107         * <p>
108         * Child components of the component.
109         * </p>
110         */
111        private List<JFCComponent> children = new LinkedList<JFCComponent>();
112
113        /**
114         * <p>
115         * Reference to the actual GUI component.
116         * </p>
117         */
118        private Component component;
119
120        /**
121         * <p>
122         * Helper attribute that contains the title of the component. Set by
123         * {@link #setTitle()}.
124         * </p>
125         */
126        private String title = null;
127
128        /**
129         * <p>
130         * Helper attribute that contains the class of the component. Set by
131         * {@link #setClass()}.
132         * </p>
133         */
134        private String componentClass = null;
135
136        /**
137         * <p>
138         * Helper attribute that contains the icon of the component. Set by
139         * {@link #setIcon()}.
140         * </p>
141         */
142        private String icon = null;
143
144        /**
145         * <p>
146         * Helper attribute that contains the icon of the component. Set by
147         * {@link #setIndex()}.
148         * </p>
149         */
150        private int index = -1;
151
152        /**
153         * <p>
154         * Constructor. Creates a new JFCComponent. Only used internally by
155         * {@link #add(Component, JFCComponent)}.
156         * </p>
157         *
158         * @param component
159         *            component associated with the JFCComponent
160         * @param parent
161         *            parent of the component; null if there is no parent
162         */
163        private JFCComponent(Component component, JFCComponent parent) {
164                if (component == null) {
165                        throw new InvalidParameterException(
166                                        "parameter component must not be null");
167                }
168                this.component = component;
169                this.parent = parent;
170                if (parent != null) {
171                        parent.addChild(this);
172                }
173
174                if (component instanceof Container) {
175                        for (Component childComponent : ((Container) component)
176                                        .getComponents()) {
177                                add(childComponent, this);
178                        }
179                }
180        }
181
182        /**
183         * <p>
184         * Adds a child component to the current component.
185         * </p>
186         *
187         * @param child
188         *            child component to be added
189         */
190        private void addChild(JFCComponent child) {
191                children.add(child);
192        }
193
194        /**
195         * <p>
196         * Returns an XML representation of the component.
197         * </p>
198         *
199         * @return XLM snippet
200         */
201        public String getXML() {
202                setClass();
203                setIcon();
204                setIndex();
205                setTitle();
206                StringBuilder builder = new StringBuilder();
207                if (parent != null) {
208                        builder.append(parent.getXML());
209                }
210                builder.append("  <component>" + StringTools.ENDLINE);
211                builder.append("   <param name=\"title\" value=\"" + title + "\" />"
212                                + StringTools.ENDLINE);
213                builder.append("   <param name=\"class\" value=\"" + componentClass
214                                + "\" />" + StringTools.ENDLINE);
215                builder.append("   <param name=\"icon\" value=\"" + icon + "\" />"
216                                + StringTools.ENDLINE);
217                builder.append("   <param name=\"index\" value=\"" + index + "\" />"
218                                + StringTools.ENDLINE);
219                builder.append("   <param name=\"hash\" value=\""
220                                + Integer.toHexString(component.hashCode()) + "\" />"
221                                + StringTools.ENDLINE);
222                builder.append("  </component>" + StringTools.ENDLINE);
223                return builder.toString();
224        }
225
226        /**
227         * <p>
228         * Removes a child component from the current component.
229         * </p>
230         *
231         * @param child
232         *            child component to be removed
233         */
234        private void removeChild(JFCComponent child) {
235                children.remove(child);
236        }
237
238        /**
239         * <p>
240         * Removes the component from the list of children of its parent.
241         * </p>
242         */
243        private void removeFromParent() {
244                if (parent != null) {
245                        parent.removeChild(this);
246                }
247        }
248
249        /**
250         * <p>
251         * Triggers the removals of all child components from the GUI hierarchy,
252         * i.e., calls {@link #remove(Component)} for all child components.
253         * </p>
254         */
255        private void removeChildren() {
256                for (JFCComponent child : children) {
257                        remove(child.component);
258                }
259        }
260
261        /**
262         * <p>
263         * Sets the {@link #title} of the component. The title is defined as follows
264         * (first in the list, that is not null):
265         * <ul>
266         * <li>accessible name of the component if available</li>
267         * <li>{@link #icon} of the component</li>
268         * <li>name of the component</li>
269         * <li>coordinates of the component</li>
270         * </ul>
271         * </p>
272         */
273        private void setTitle() {
274                title = null; // reset title
275
276                AccessibleContext accessibleContext = component.getAccessibleContext();
277                if (accessibleContext != null) {
278                        title = accessibleContext.getAccessibleName();
279                }
280                if (title == null) {
281                        title = icon;
282                }
283                if (title == null) {
284                        title = component.getName();
285                }
286                if (title == null) {
287                        // use coordinates as last resort
288                        title = "Pos(" + component.getX() + "," + component.getY() + ")";
289                }
290        }
291
292        /**
293         * <p>
294         * Sets the {@link #componentClass} of the component.
295         * </p>
296         */
297        private void setClass() {
298                componentClass = component.getClass().getName();
299        }
300
301        /**
302         * <p>
303         * Sets the {@link #icon} of the component.
304         * </p>
305         */
306        private void setIcon() {
307                icon = null; // reset icon
308
309                Method getIconMethod;
310                try {
311                        getIconMethod = component.getClass().getMethod("getIcon",
312                                        new Class[0]);
313                        if (getIconMethod != null) {
314                                Object iconObject = getIconMethod.invoke(component,
315                                                new Object[] {});
316                                if (iconObject != null) {
317                                        String iconPath = iconObject.toString();
318                                        if (!iconPath.contains("@")) {
319                                                System.out.println("iconPath");
320                                                String[] splitResult = iconPath
321                                                                .split(File.separatorChar == '\\' ? "\\\\"
322                                                                                : File.separator);
323                                                icon = splitResult[splitResult.length - 1];
324                                        }
325                                }
326                        }
327                } catch (SecurityException e) {
328                } catch (NoSuchMethodException e) {
329                } catch (IllegalArgumentException e) {
330                } catch (IllegalAccessException e) {
331                } catch (InvocationTargetException e) {
332                        System.err.println("Found method with name " + "getIcon"
333                                        + " but could not access it.");
334                }
335        }
336
337        /**
338         * <p>
339         * Sets the {@link #index} of the component as the index in the parent, if
340         * it is accessible.
341         * </p>
342         */
343        private void setIndex() {
344                index = -1; // reset index
345
346                AccessibleContext accessibleContext = component.getAccessibleContext();
347                if (accessibleContext != null) {
348                        index = accessibleContext.getAccessibleIndexInParent();
349                }
350        }
351
352}
Note: See TracBrowser for help on using the repository browser.