source: main/trunk/gli/src/org/greenstone/gatherer/gui/TestingPreparation.java@ 32700

Last change on this file since 32700 was 32700, checked in by ak19, 5 years ago
  1. I'm hoping that setNamesRecursively now properly deals with cyclical references to GUI components (especially GLI's custom GUI components) by skipping those whose names are already set. The code should have set the entire subbranch (all descendants) of an already named GUI component, so skipping should be fine. 2. printComponentNames() sadly wasn't printing all components: submenu items of a menubar were missed out. This seems to have to do with how getComponents() is implemented on a MenuBar? Rather than calling the getSubElements() in the case of MenuBars and Menu(Item)s, I'm now just printing Component names out from within setNamesRecursively() instead as soon as a name has been set (or is known to have been set).
File size: 7.2 KB
Line 
1package org.greenstone.gatherer.gui;
2
3import java.awt.*;
4import javax.swing.*;
5import java.lang.reflect.*;
6
7public class TestingPreparation {
8 public static boolean TEST_MODE = true; // TODO: set to true for debugging. Reset to false when committing to svn
9 public static boolean DEBUGGING_TEST_MODE = true;
10
11 /*
12 For GUI swing testing of GLI, it's very handy for components to have names
13 I use the GLI classname as name or if it's not a GLI class, then:
14 - if a member var of a GLI class, then GLIclassName.memberVarName
15 - else GLIClassName.swingComponentName
16 Google: "Java swing automatically setName"
17 -> https://stackoverflow.com/questions/3628218/strategy-for-naming-swing-components
18 https://stackoverflow.com/questions/1782598/with-java-reflection-how-to-instantiate-a-new-object-then-call-a-method-on-it
19 - https://stackoverflow.com/questions/4163500/how-to-automatic-set-name-attr-of-gui-components/4164479#4164479
20 - https://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.wb.swing.doc.user%2Fhtml%2Fwizards%2Fswing%2Fautomatic_databinding.html
21 - https://stackoverflow.com/questions/28639294/in-java-how-to-get-name-of-component-which-is-clicked
22 */
23 public static void setNamesRecursively(Component root) {
24 if(!TEST_MODE) return;
25
26 // setNamesRecursively won't assign a name if one is already set
27 // But GUIManager for instance g_man has a name "frame0" assigned automatically
28 // Setting explicitly since GUIManager is preferred for its name
29
30 // Workaround to force replacement of non-informative names like frame0 for GUIManager
31 // and dialog0 for OpenCollectioNDialog
32 // Workaround is to not check if name already set for root, but to set it ourselves
33 String className = root.getClass().getSimpleName();
34 root.setName(className);
35
36 setNamesRecursively("", root, "", true);
37 //if (DEBUGGING_TEST_MODE) printComponentNames(root, "");
38 }
39
40 private static void setNamesRecursively(String prefix, Component root, String tabSpace, boolean isTrueRoot) {
41 if(!TEST_MODE) return;
42
43 // root starts off as GLI's JFrame, so we know that all its GUI children are specifically JComponents
44
45 // https://docs.oracle.com/javase/7/docs/api/index.html?java/lang/reflect/package-summary.html
46 String className = root.getClass().getSimpleName();
47
48 String packageName = root.getClass().getPackage().getName();
49 if(!packageName.contains("org.greenstone.gatherer.gui")) {
50 if(root.getName() == null || root.getName().equals("")) { // if name not already set
51 if(!prefix.equals("")){
52 // TODO: set this to something more meaningful?
53 root.setName(prefix + "." + className);
54 }
55 else {
56 root.setName(className);
57 }
58 } // else swing Component name already set
59
60 // now we can print out this element's name for debugging
61 if (DEBUGGING_TEST_MODE) System.err.println(tabSpace + root.getName());
62 } else { // root is in GLI GUI package, use its classname for name
63
64 if(root.getName() == null || root.getName().equals("")) {
65 root.setName(className);
66 } else if(!isTrueRoot) {
67 // then the name of this GLI GUI element (i.e. of GLI GUI package) was already set
68 // we've recursively dealt with this GLI element and its children already
69 // Prevents cyclic widget references being processed in a cyclic loop ending
70 // in a StackOverflowError
71 return;
72 }
73 // now we can print out this element's name for debugging
74 if (DEBUGGING_TEST_MODE) System.err.println(tabSpace + root.getName());
75
76 prefix = className;
77
78 // check member vars
79 Field[] memberVars = root.getClass().getDeclaredFields(); // private to public member vars, but not inherited ones
80
81 for(int i = 0; i < memberVars.length; i++) {
82 memberVars[i].setAccessible(true); // make private/protected etc fields accessible
83
84 // https://www.tutorialspoint.com/java/lang/class_isinstance.htm
85 Class jCompClass = Container.class;
86 Class memberVarClass = memberVars[i].getType();
87
88 // memberVarClass is a JComponent (JComponent or subclass)
89 if(jCompClass.isAssignableFrom(memberVarClass)) {
90
91 // get the actual member variable denoted by memberVars[i]
92 // on the current JComponent instance 'root'.
93 // We now know this member var to be a JComponent
94 // Having the actual member variable of the instantiated instance,
95 // we can call setName on it
96 try {
97 Container memberComponent = (Container)memberVars[i].get(root);
98
99 if(memberComponent != null) {
100
101 // member var is a JComponent but not of GLI package, so locally instantiated
102 if(!memberVarClass.getPackage().getName().contains("org.greenstone.gatherer.gui")) {
103 String memberprefix = prefix + "." + memberVars[i].getName(); // append member var name
104
105 // now can call setName() on the actual member variable
106 memberComponent.setName(memberprefix);
107 setNamesRecursively(memberprefix, memberComponent, tabSpace+" ", false);
108 }
109
110 //else the member variable is a GLI GUI class, use its className as prefix for child components
111 // Skip this step to avoid circular references to our own member vars
112
113 else { // member variable is a GLI GUI class.
114 // will be using its className as prefix for child components
115
116 //String memberprefix = memberVarClass.getSimpleName();
117 //memberComponent.setName(memberprefix);
118 setNamesRecursively("", memberComponent, tabSpace+" ", false);
119 }
120
121
122 }
123 } catch(Exception e) {
124 e.printStackTrace();
125 }
126 }
127 // else not a JComponent, skip
128 }
129 }
130
131
132 // https://stackoverflow.com/questions/33927349/could-someone-please-explain-note-this-method-should-be-called-under-awt-tree
133 // No worries about AWT tree lock: setNamesRecursively is called by openGUI
134 // which is specifically called by GathererProg on the Event Dispatch Thread (EDT)
135
136
137 Component[] children = ((Container)root).getComponents();
138
139 for(int i = 0; i < children.length; i++) {
140 // if we haven't already set a name for any child JComponents with the above,
141 // then the following will do so now
142 setNamesRecursively(className, children[i], tabSpace+" ", false);
143 }
144
145 }
146
147
148 // For debugging swing Component names assigned with Container's setName()
149 // Wasted a lot of my time debugging why menu bar items' names weren't set by setNamesRecursively().
150 // Turns out they were being set, but that sadly
151 // this method doesn't seem to print all components, e.g. JMenuItems of JMenus of a JMenuBar
152 // Perhaps because those are available only through getSubElements() rather than
153 // through getComponents()?
154 // So have now shifted the printing of elements that we manually set into setNamesRecursively() above.
155 // I'd have preferred this printing method since it prints out the component names in
156 // hierarchical order rather than the sometimes arbitrary order that GUI member vars are
157 // declared in GLI's own GUI classes.
158 public static void printComponentNames(Component root, String tabbing) {
159 if(!TEST_MODE) return;
160
161 System.err.println(tabbing + root.getName());
162 Component[] children = ((Container)root).getComponents();
163 // recursive call
164 for(int i = 0; i < children.length; i++) {
165 printComponentNames(children[i], tabbing + " ");
166 }
167 }
168}
Note: See TracBrowser for help on using the repository browser.