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

Last change on this file since 32706 was 32706, checked in by ak19, 5 years ago

Committing the non-EDT related changes to GLI. More changes to setNamesRecursively: for GLI GUI buttons (class GLIButton) these are still standalone rather than compound widgets that contain further widgets within them. So want to set names of GLIButtons (and JButtons) to be their container-class.GLIButton.button-membervar-name. 2. Preferences dialog nulls member handles to important widgets whose names I want to set before the widget is even made visible. In testing mode, I want to prevent these from being set to null so I can set their names in order to access them.

File size: 8.5 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, className);
37 //if (DEBUGGING_TEST_MODE) printComponentNames(root, "");
38 }
39
40 private static void setNamesRecursively(String prefix, Component root, String tabSpace, boolean isTrueRoot, String rootClassName) {
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 // if it's a non-member var GLIButton, give it a more sensible name
66 if(JButton.class.isAssignableFrom(root.getClass())) {
67 JButton button = (JButton)root;
68 root.setName(rootClassName + ".GLIButton." + button.getText()); // getLabel() deprecated
69 } else {
70 root.setName(className);
71 }
72 } else if(!isTrueRoot) {
73
74 // GLIButtons are GLI GUI package but they have no member vars so
75 // they would have been processed with their containing classes: their names
76 // are already set.
77 // But their names still have to be displayed if debugging
78 if(JButton.class.isAssignableFrom(root.getClass())) {
79 if (DEBUGGING_TEST_MODE) System.err.println(tabSpace + root.getName());
80 }
81
82 // then the name of this GLI GUI element (i.e. of GLI GUI package) was already set
83 // we've recursively dealt with this GLI element and its children already
84 // Prevents cyclic widget references being processed in a cyclic loop ending
85 // in a StackOverflowError
86 return;
87 }
88 // now we can print out this element's name for debugging
89 if (DEBUGGING_TEST_MODE) System.err.println(tabSpace + root.getName());
90
91 prefix = className;
92
93 // check member vars
94 Field[] memberVars = root.getClass().getDeclaredFields(); // private to public member vars, but not inherited ones
95
96 for(int i = 0; i < memberVars.length; i++) {
97 memberVars[i].setAccessible(true); // make private/protected etc fields accessible
98
99 // https://www.tutorialspoint.com/java/lang/class_isinstance.htm
100 Class jCompClass = Container.class;
101 Class memberVarClass = memberVars[i].getType();
102
103 // memberVarClass is a JComponent (JComponent or subclass)
104 if(jCompClass.isAssignableFrom(memberVarClass)) {
105
106 // get the actual member variable denoted by memberVars[i]
107 // on the current JComponent instance 'root'.
108 // We now know this member var to be a JComponent
109 // Having the actual member variable of the instantiated instance,
110 // we can call setName on it
111 try {
112 Container memberComponent = (Container)memberVars[i].get(root);
113
114 //System.err.println("### Found (null?) member var: " + memberVars[i].getName());
115 if(memberComponent != null) {
116 //System.err.println("@@@ Found member var: " + memberVars[i].getName());
117
118 // member var is a JComponent but not of GLI package, so locally instantiated
119 // or member var can be GLIButtons which are of GLI GUI package
120 // but they contain no Component member vars we care about so
121 // process GLIButtons with their containing classes
122 if(JButton.class.isAssignableFrom(memberVarClass)
123 || !memberVarClass.getPackage().getName().contains("org.greenstone.gatherer.gui"))
124 {
125 String memberprefix = prefix + "." + memberVars[i].getName(); // append member var name
126
127 // now can call setName() on the actual member variable
128 memberComponent.setName(memberprefix);
129 rootClassName = memberprefix; // pass nearest parent GLI GUI class name as param
130 // for namespacing any local JButton members declared in memberVarClass
131 setNamesRecursively(memberprefix, memberComponent, tabSpace+" ", false, rootClassName);
132 }
133
134 //else the member variable is a GLI GUI class, use its className as prefix for child components
135 // Skip this step to avoid circular references to our own member vars
136
137 else { // member variable is a GLI GUI class.
138 // will be using its className as prefix for child components
139
140 //String memberprefix = memberVarClass.getSimpleName();
141 //memberComponent.setName(memberprefix);
142 setNamesRecursively("", memberComponent, tabSpace+" ", false, rootClassName);
143 }
144
145
146 }
147 } catch(Exception e) {
148 e.printStackTrace();
149 }
150 }
151 // else not a JComponent, skip
152 }
153 }
154
155
156 // https://stackoverflow.com/questions/33927349/could-someone-please-explain-note-this-method-should-be-called-under-awt-tree
157 // No worries about AWT tree lock: setNamesRecursively is called by openGUI
158 // which is specifically called by GathererProg on the Event Dispatch Thread (EDT)
159
160
161 Component[] children = ((Container)root).getComponents();
162
163 for(int i = 0; i < children.length; i++) {
164 // if we haven't already set a name for any child JComponents with the above,
165 // then the following will do so now
166 setNamesRecursively(className, children[i], tabSpace+" ", false, rootClassName);
167 }
168
169 }
170
171
172 // For debugging swing Component names assigned with Container's setName()
173 // Wasted a lot of my time debugging why menu bar items' names weren't set by setNamesRecursively().
174 // Turns out they were being set, but that sadly
175 // this method doesn't seem to print all components, e.g. JMenuItems of JMenus of a JMenuBar
176 // Perhaps because those are available only through getSubElements() rather than
177 // through getComponents()?
178 // So have now shifted the printing of elements that we manually set into setNamesRecursively() above.
179 // I'd have preferred this printing method since it prints out the component names in
180 // hierarchical order rather than the sometimes arbitrary order that GUI member vars are
181 // declared in GLI's own GUI classes.
182 public static void printComponentNames(Component root, String tabbing) {
183 if(!TEST_MODE) return;
184
185 System.err.println(tabbing + root.getName());
186 Component[] children = ((Container)root).getComponents();
187 // recursive call
188 for(int i = 0; i < children.length; i++) {
189 printComponentNames(children[i], tabbing + " ");
190 }
191 }
192}
Note: See TracBrowser for help on using the repository browser.