source: trunk/src/org/expeditee/settings/Settings.java@ 1102

Last change on this file since 1102 was 1102, checked in by davidb, 6 years ago

Reworking of the code-base to separate logic from graphics. This version of Expeditee now supports a JFX graphics as an alternative to SWING

File size: 10.2 KB
Line 
1/**
2 * Settings.java
3 * Copyright (C) 2010 New Zealand Digital Library, http://expeditee.org
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package org.expeditee.settings;
20
21import java.lang.reflect.Field;
22import java.lang.reflect.Method;
23import java.util.HashMap;
24import java.util.LinkedList;
25import java.util.List;
26
27import org.expeditee.gui.AttributeValuePair;
28import org.expeditee.gui.Frame;
29import org.expeditee.gui.FrameCreator;
30import org.expeditee.gui.FrameIO;
31import org.expeditee.gui.FrameUtils;
32import org.expeditee.gui.MessageBay;
33import org.expeditee.items.Text;
34import org.expeditee.items.widgets.Password;
35import org.expeditee.reflection.PackageLoader;
36import org.expeditee.setting.GenericSetting;
37import org.expeditee.setting.Setting;
38import org.expeditee.setting.VariableSetting;
39
40public abstract class Settings {
41
42 public static final String SETTINGS_PACKAGE_PARENT = "org.expeditee.";
43 public static final String SETTINGS_PACKAGE = SETTINGS_PACKAGE_PARENT + "settings.";
44
45 private static final class PageDescriptor {
46
47 private final HashMap<String, Setting> settings = new HashMap<String, Setting>();
48 private final List<String> orderedEntries = new LinkedList<String>();
49 private final List<VariableSetting> settingsList = new LinkedList<VariableSetting>();
50 private final Method onParsed;
51
52 private PageDescriptor(Class<?> clazz) {
53
54 // populate map of settings
55 for(Field f : clazz.getFields()) {
56 // Only allow classes that inherit from Setting
57 if(!Setting.class.isAssignableFrom(f.getType())) continue;
58
59 try {
60 Setting s = (Setting) f.get(null);
61 settings.put(f.getName().toLowerCase(), s);
62 if (s instanceof VariableSetting) settingsList.add((VariableSetting) s);
63 orderedEntries.add(f.getName());
64 } catch (Exception e) {
65 e.printStackTrace();
66 }
67 }
68
69 Method m = null;
70
71 try {
72 m = clazz.getMethod("onParsed", Text.class);
73 } catch(Exception e) {
74 // System.err.println(clazz.getName() + " has no onParsed(Text t) callback");
75 }
76
77 this.onParsed = m;
78 }
79 }
80
81 private static HashMap<String, PageDescriptor> _pages = new HashMap<String, PageDescriptor>();
82
83 private static boolean _init = false;
84
85 public static void Init()
86 {
87 if(_init) return;
88
89 _init = true;
90
91 try {
92 for(Class<?> clazz : PackageLoader.getClassesNew(SETTINGS_PACKAGE)) {
93 // Ignore this class since it's the controller
94 if(clazz.equals(Settings.class)) continue;
95
96 String settingsPageName = clazz.getPackage().getName().toLowerCase().substring(SETTINGS_PACKAGE_PARENT.length());
97 // System.out.println(settingsPage + " : " + clazz.getName());
98 _pages.put(settingsPageName, new PageDescriptor(clazz));
99 }
100
101 } catch (Exception e) {
102 e.printStackTrace();
103 }
104 }
105
106 /** Parses the settings tree, then resets any settings that were not set. */
107 public static void parseSettings(Text text)
108 {
109 List<VariableSetting> set = parseSettings(text, "");
110 List<VariableSetting> toDefault = new LinkedList<VariableSetting>();
111
112 for(PageDescriptor pd : _pages.values()) toDefault.addAll(pd.settingsList);
113
114 toDefault.removeAll(set);
115
116 for(VariableSetting s : toDefault) {
117 try {
118 s.reset();
119 } catch (Exception e) {
120 e.printStackTrace();
121 }
122 }
123 }
124
125 /**
126 * Sets all the simple settings.
127 *
128 * @param text
129 * @param prefix
130 *
131 * @return List of VariableSettings that were changed
132 */
133 private static List<VariableSetting> parseSettings(Text text, String prefix) {
134
135 List<VariableSetting> set = new LinkedList<VariableSetting>();
136
137 Frame child = text.getChild();
138
139 if(child == null) return set;
140
141 String settingsPage = prefix + text.getText().trim().toLowerCase().replaceAll("^@", "");
142 PageDescriptor pd = _pages.get(settingsPage);
143 if(pd == null) return set;
144
145 try {
146 // set the fields
147 List<Text> items = child.getBodyTextItems(false);
148 List<Text> annotations = new LinkedList<Text>(child.getAnnotationItems());
149 List<Frame> seen = new LinkedList<Frame>(); // to avoid getting stuck in a loop
150 seen.add(child);
151 // find all the frames for this settings page
152 while(!annotations.isEmpty()) {
153 Text annotation = annotations.remove(0);
154 Frame next = annotation.getChild();
155 if(next != null && !seen.contains(next)) {
156 items.addAll(next.getBodyTextItems(false));
157 annotations.addAll(next.getAnnotationItems());
158 seen.add(next);
159 }
160 }
161
162 // parse all the settings items on this page
163 for(Text t : items) {
164 AttributeValuePair avp = new AttributeValuePair(t.getText(), false);
165 try {
166 String settingName = avp.getAttributeOrValue().trim().toLowerCase();
167 // System.out.println(avp.getAttributeOrValue().trim().toLowerCase().replaceAll("^@", ""));
168 Setting s = pd.settings.get(settingName);//.replaceAll("^@", ""));
169 if(s == null) {
170 if(settingName.startsWith("//") || settingName.startsWith("@")) {
171 continue;
172 }
173 // System.out.println("Couldn't find setting \"" + settingName + "\"");
174 List<String> validPages = new LinkedList<String>();
175 // if the setting isn't found on the current page, check all child pages
176 for(String k : _pages.keySet()) {
177 if(k.startsWith(settingsPage) && k.length() > settingsPage.length()) {
178 // System.out.println(k + " is a child of " + settingsPage);
179 PageDescriptor cpd = _pages.get(k);
180 Setting tmp = cpd.settings.get(settingName);
181 if(tmp != null) {
182 // System.out.println("Found setting in subpage: " + k);
183 s = tmp;
184 validPages.add(k);
185 }
186 }
187 }
188
189 if(s == null) continue;
190
191 if(validPages.size() > 1) {
192 StringBuffer warnMessage = new StringBuffer("Found multiple matching settings in the following settings subpages: ");
193 String lastPage = "";
194 for(String page : validPages) {
195 warnMessage.append("\"" + page + "\",");
196 lastPage = page;
197 }
198 warnMessage.deleteCharAt(warnMessage.length() - 1);
199 warnMessage.append(" - choosing " + lastPage);
200 MessageBay.warningMessage(warnMessage.toString());
201 }
202 }
203
204 if(s.setSetting(t) && s instanceof VariableSetting) set.add((VariableSetting) s);
205
206 } catch (Exception e) {
207 e.printStackTrace();
208 }
209 }
210
211 // call the onParsed method if one exists
212 if(pd.onParsed != null) {
213 pd.onParsed.invoke(null, text);
214 }
215
216 } catch (Exception e) {
217 e.printStackTrace();
218 return set;
219 }
220
221 // if the page was a settings page, check if it has any subpages
222 for(Text t : child.getTextItems()) {
223 set.addAll(parseSettings(t, settingsPage + "."));
224 }
225 return set;
226 }
227
228 public static void generateSettingsTree(Text link)
229 {
230 generateSettingsTree("settings", link);
231 }
232
233 /** Generates settings tree */
234 private static void generateSettingsTree(String page, Text text)
235 {
236 FrameCreator frames = new FrameCreator(text.getParentOrCurrentFrame().getFramesetName(), text.getParentOrCurrentFrame().getPath(), page, false, false);
237 // Frame frame = FrameIO.CreateFrame(text.getParentOrCurrentFrame().getFramesetName(), page, null);
238 text.setLink(frames.getName());
239
240 // add subpages of the current page
241 for(String k : _pages.keySet()) {
242 if(k.startsWith(page.toLowerCase()) && !k.equals(page)) {
243 String name = k.substring(page.length() + 1);
244 if(name.indexOf('.') != -1) {
245 continue;
246 }
247 System.out.println("Generating " + name);
248 generateSettingsTree(k, frames.addText(name.substring(0, 1).toUpperCase() + name.substring(1), null, null, null, false));
249 }
250 }
251
252 frames.setLastY(frames.getLastY() + 20);
253
254 // add settings of the current page
255 PageDescriptor pd = _pages.get(page);
256 if(pd != null) {
257 for(String str : pd.orderedEntries) {
258 String key = str.toLowerCase();
259 Setting s = pd.settings.get(key);
260 if(s == null) {
261 continue;
262 }
263 String name = str.substring(0, 1).toUpperCase() + str.substring(1);
264 String value = "";
265 if(s instanceof GenericSetting && ((GenericSetting<?>) s).isPrimitive()) {
266 if(((GenericSetting<?>) s).get() != null) {
267 value = ": " + ((GenericSetting<?>) s).get();
268 } else {
269 value = ": ";
270 }
271 }
272 int x = 0, y = 0;
273 Text t;
274 if(key.equals("pass")) {
275 t = frames.addText("iw: org.expeditee.items.widgets.Password", null, null, null, false);
276 Password pw = new Password(t, null);
277 pw.setPassword((String) value);
278 frames.getCurrentFrame().removeItem(t);
279 frames.getCurrentFrame().addAllItems(pw.getItems());
280 x = pw.getX() + pw.getWidth();
281 y = pw.getY();
282 } else {
283 if(s instanceof GenericSetting && ((GenericSetting<?>) s).getType().equals(Text.class)) {
284 t = (Text) ((GenericSetting<?>)s).get();
285 if(t == null) {
286 System.err.println("Failed to get Text setting \"" + str + "\"");
287 continue;
288 }
289 t = t.copy();
290 t.setID(frames.getCurrentFrame().getNextItemID());
291 t.setText(name);
292 frames.addItem(t, false);
293 } else {
294 t = frames.addText(name + value, null, null, null, false);
295 }
296 x = t.getX() + t.getBoundsWidth();
297 y = t.getY();
298 }
299 x = Math.max(250, x + 20);
300 Text tt = frames.getCurrentFrame().addText(x, y, "// " + s.getTooltip(), null);
301 // rebuild to get the correct height since setWidth() doesn't immediately rebuild
302 tt.rebuild(true);
303 if(tt.getY() + tt.getBoundsHeight() > frames.getLastY()) {
304 frames.setLastY(tt.getY() + tt.getBoundsHeight());
305 }
306 }
307 }
308
309 frames.save();
310 //FrameIO.SaveFrame(frame);
311 }
312}
Note: See TracBrowser for help on using the repository browser.