source: trunk/quest-jfcmonitor/src/main/java/de/ugoe/cs/quest/jfcmonitor/JFCComponent.java @ 842

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