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

Last change on this file since 1434 was 1434, checked in by bln4, 5 years ago

Implementation of ProfileManager. Refactor + additional content for how new profiles are created. The refactoring split out the creation of the default profile from user profiles. Refactoring revealed a long term bug that was causing user profiles to generate with incorrect information. The additional content fixed this bug by introducing the ${USER.NAME} variable, so that the default profile frameset can specify resource locations located in the users resource directory.

org.expeditee.auth.AuthenticatorBrowser
org.expeditee.auth.account.Create
org.expeditee.gui.Browser
org.expeditee.gui.management.ProfileManager
org.expeditee.setting.DirectoryListSetting
org.expeditee.setting.ListSetting
org.expeditee.settings.UserSettings

Implementation of ResourceManager as a core location to get resources from the file system. Also the additional variable ${CURRENT_FRAMESET} to represent the current frameset, so that images can be stored in the directory of the current frameset. This increases portability of framesets.

org.expeditee.gui.FrameIO
org.expeditee.gui.management.ResourceManager
org.expeditee.gui.management.ResourceUtil
Audio:

#NB: Audio used to only operate on a single directory. This has been updated to work in a same way as images. That is: when you ask for a specific resouce, it looks to the user settings to find a sequence of directories to look at in order until it manages to find the desired resource.


There is still need however for a single(ish) source of truth for the .banks and .mastermix file. Therefore these files are now always located in resource-<username>\audio.
org.apollo.agents.MelodySearch
org.apollo.audio.structure.AudioStructureModel
org.apollo.audio.util.MultiTrackPlaybackController
org.apollo.audio.util.SoundDesk
org.apollo.gui.FrameLayoutDaemon
org.apollo.io.AudioPathManager
org.apollo.util.AudioPurger
org.apollo.widgets.FramePlayer
org.apollo.widgets.SampledTrack

Images:

org.expeditee.items.ItemUtils

Frames:

org.expeditee.gui.FrameIO

Fixed a error in the FramePlayer class caused by an incorrect use of toArray().

org.apollo.widgets.FramePlayer


Added several short cut keys to allow for the Play/Pause (Ctrl + P), mute (Ctrl + M) and volume up/down (Ctrl + +/-) when hovering over SampledTrack widgets.

org.apollo.widgets.SampledTrack


Changed the way that Authenticate.login parses the new users profile to be more consistance with other similar places in code.

org.expeditee.auth.account.Authenticate


Encapsulated _body, _surrogateItemsBody and _primaryItemsBody in Frame class. Also changed getBody function to take a boolean flag as to if it should respect the current surrogate mode. If it should then it makes sure that labels have not changed since last time getBody was called.

org.expeditee.gui.Frame

File size: 11.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.ArrayList;
24import java.util.Collection;
25import java.util.HashMap;
26import java.util.Iterator;
27import java.util.LinkedList;
28import java.util.List;
29
30import org.expeditee.gui.AttributeValuePair;
31import org.expeditee.gui.Frame;
32import org.expeditee.gui.FrameCreator;
33import org.expeditee.gui.FrameIO;
34import org.expeditee.gui.MessageBay;
35import org.expeditee.items.Item;
36import org.expeditee.items.ItemParentStateChangedEvent;
37import org.expeditee.items.Text;
38import org.expeditee.items.widgets.Password;
39import org.expeditee.reflection.PackageLoader;
40import org.expeditee.setting.Setting;
41import org.expeditee.setting.VariableSetting;
42
43public abstract class Settings {
44
45 public static final String SETTINGS_PACKAGE_PARENT = "org.expeditee.";
46 public static final String SETTINGS_PACKAGE = SETTINGS_PACKAGE_PARENT + "settings.";
47
48 private static final class PageDescriptor {
49
50 private final HashMap<String, Setting> settings = new HashMap<String, Setting>();
51 private final List<String> orderedEntries = new LinkedList<String>();
52 private final List<VariableSetting> settingsList = new LinkedList<VariableSetting>();
53 private final Method onParsed;
54
55 private PageDescriptor(Class<?> clazz) {
56
57 // populate map of settings
58 for(Field f : clazz.getFields()) {
59 // Only allow classes that inherit from Setting
60 if(!Setting.class.isAssignableFrom(f.getType())) continue;
61
62 try {
63 Setting s = (Setting) f.get(null);
64 settings.put(f.getName().toLowerCase(), s);
65 if (s instanceof VariableSetting) settingsList.add((VariableSetting) s);
66 orderedEntries.add(f.getName());
67 } catch (Exception e) {
68 e.printStackTrace();
69 }
70 }
71
72 Method m = null;
73
74 try {
75 m = clazz.getMethod("onParsed", Text.class);
76 } catch(Exception e) {
77 // System.err.println(clazz.getName() + " has no onParsed(Text t) callback");
78 }
79
80 this.onParsed = m;
81 }
82 }
83
84 private static HashMap<String, PageDescriptor> _pages = new HashMap<String, PageDescriptor>();
85
86 private static boolean _init = false;
87
88 public static void Init()
89 {
90 if(_init) return;
91
92 _init = true;
93
94 try {
95 for(Class<?> clazz : PackageLoader.getClassesNew(SETTINGS_PACKAGE)) {
96 // Ignore this class since it's the controller
97 if(clazz.equals(Settings.class)) continue;
98
99 String settingsPageName = clazz.getPackage().getName().toLowerCase().substring(SETTINGS_PACKAGE_PARENT.length());
100
101 // System.out.println(settingsPage + " : " + clazz.getName());
102 _pages.put(settingsPageName, new PageDescriptor(clazz));
103 }
104
105 } catch (Exception e) {
106 e.printStackTrace();
107 }
108 }
109
110 /** Parses the settings tree, then resets any settings that were not set. */
111 public static void parseSettings(Text text)
112 {
113 List<VariableSetting> set = parseSettings(text, "");
114 List<VariableSetting> toDefault = new LinkedList<VariableSetting>();
115
116 for(PageDescriptor pd : _pages.values()) toDefault.addAll(pd.settingsList);
117
118 toDefault.removeAll(set);
119
120 for(VariableSetting s : toDefault) {
121 try {
122 s.reset();
123 } catch (Exception e) {
124 e.printStackTrace();
125 }
126 }
127 }
128
129 public static void resetAllSettings() {
130 for (PageDescriptor pd : _pages.values()) {
131 for (VariableSetting s : pd.settingsList) {
132 s.reset();
133 }
134 }
135 }
136
137 /**
138 * Sets all the simple settings.
139 *
140 * @param text
141 * @param prefix
142 *
143 * @return List of VariableSettings that were changed
144 */
145 private static List<VariableSetting> parseSettings(Text text, String prefix) {
146
147 List<VariableSetting> set = new LinkedList<VariableSetting>();
148
149 String linkForChild = text.getAbsoluteLink();
150 Frame child = FrameIO.LoadFrame(linkForChild, FrameIO.PROFILE_PATH);
151
152 if(child == null) return set;
153
154 String settingsPage = prefix + text.getText().trim().toLowerCase().replaceAll("^@", "");
155 PageDescriptor pd = _pages.get(settingsPage);
156 if(pd == null) return set;
157
158 try {
159 // set the fields
160 List<Text> items = child.getBodyTextItems(false);
161 List<Text> annotations = new LinkedList<Text>(child.getAnnotationItems());
162 List<Frame> seen = new LinkedList<Frame>(); // to avoid getting stuck in a loop
163 seen.add(child);
164 // find all the frames for this settings page
165 while(!annotations.isEmpty()) {
166 Text annotation = annotations.remove(0);
167 Frame next = annotation.getChild();
168 if(next != null && !seen.contains(next)) {
169 items.addAll(next.getBodyTextItems(false));
170 annotations.addAll(next.getAnnotationItems());
171 seen.add(next);
172 }
173 }
174
175 // parse all the settings items on this page
176 for(Text t : items) {
177 AttributeValuePair avp = new AttributeValuePair(t.getText(), false);
178 try {
179 String settingName = avp.getAttributeOrValue().trim().toLowerCase();
180 // System.out.println(avp.getAttributeOrValue().trim().toLowerCase().replaceAll("^@", ""));
181 Setting s = pd.settings.get(settingName);//.replaceAll("^@", ""));
182 if(s == null) {
183 if(settingName.startsWith("//") || settingName.startsWith("@")) {
184 continue;
185 }
186 // System.out.println("Couldn't find setting \"" + settingName + "\"");
187 List<String> validPages = new LinkedList<String>();
188 // if the setting isn't found on the current page, check all child pages
189 for(String k : _pages.keySet()) {
190 if(k.startsWith(settingsPage) && k.length() > settingsPage.length()) {
191 // System.out.println(k + " is a child of " + settingsPage);
192 PageDescriptor cpd = _pages.get(k);
193 Setting tmp = cpd.settings.get(settingName);
194 if(tmp != null) {
195 // System.out.println("Found setting in subpage: " + k);
196 s = tmp;
197 validPages.add(k);
198 }
199 }
200 }
201
202 if(s == null) {
203 continue;
204 }
205
206 if(validPages.size() > 1) {
207 StringBuffer warnMessage = new StringBuffer("Found multiple matching settings in the following settings subpages: ");
208 String lastPage = "";
209 for(String page : validPages) {
210 warnMessage.append("\"" + page + "\",");
211 lastPage = page;
212 }
213 warnMessage.deleteCharAt(warnMessage.length() - 1);
214 warnMessage.append(" - choosing " + lastPage);
215 MessageBay.warningMessage(warnMessage.toString());
216 }
217 }
218
219 if(s.setSetting(t) && s instanceof VariableSetting) set.add((VariableSetting) s);
220
221 } catch (Exception e) {
222 e.printStackTrace();
223 }
224 }
225
226 // call the onParsed method if one exists
227 if(pd.onParsed != null) {
228 pd.onParsed.invoke(null, text);
229 }
230
231 } catch (Exception e) {
232 e.printStackTrace();
233 return set;
234 }
235
236 // Having parsed this page, we must alter all the items on the frame that they are no longer being shown.
237 // For things such as WidgetCorners, this means that they will be removed from live consideration.
238 Collection<Item> allItems = child.getAllItems();
239 for (Item i: allItems) {
240 i.onParentStateChanged(new ItemParentStateChangedEvent(child, ItemParentStateChangedEvent.EVENT_TYPE_HIDDEN));
241 }
242
243 // if the page was a settings page, check if it has any subpages
244 for(Text t : child.getTextItems()) {
245 set.addAll(parseSettings(t, settingsPage + "."));
246 }
247 return set;
248 }
249
250 public static void generateSettingsTree(Text link) {
251 generateSettingsTree("settings", link);
252 }
253
254 private static void generateSettingsTree(String page, Text text) {
255 Frame parent = text.getParentOrCurrentFrame();
256 FrameCreator frames = new FrameCreator(parent.getFramesetName(), parent.getPath(), page, FrameCreator.ExistingFramesetOptions.AppendSegregatedFrames, false, null);
257 text.setLink(frames.getName());
258
259 // Add subpages of the current page by recursing
260 for (String k: _pages.keySet()) {
261 if (k.startsWith(page.toLowerCase()) && !k.equals(page)) {
262 String name = k.substring(page.length() + 1);
263 if (name.indexOf('.') != -1) {
264 continue;
265 }
266 System.out.println("@Settings: Generating " + name);
267 generateSettingsTree(k, frames.addText(name.substring(0, 1).toUpperCase() + name.substring(1), null, null, null, false));
268 }
269 }
270
271 // Start building current page
272 frames.setLastY(frames.getLastY() + 20);
273 // Add Settings of the current page
274 PageDescriptor pd = _pages.get(page);
275 if (pd == null) {
276 frames.save();
277 return;
278 }
279
280 //Iterator<String> keys = pd.orderedEntries.stream().map(t -> t.toLowerCase()).iterator();
281 Iterator<String> keys = pd.orderedEntries.iterator();
282 while(keys.hasNext()) {
283 String key = keys.next();
284 Setting setting = pd.settings.get(key.toLowerCase());
285 if (setting == null) {
286 continue;
287 }
288
289 // Keep track of were we are placing items on Frames.
290 int x = 0, y = 0;
291
292 Frame currentFrame = frames.getCurrentFrame();
293 if (key.toLowerCase().equals("pass")) {
294 // Special case for Password widgets
295 Text passwordWidgetText = frames.addText("iw: org.expeditee.items.widgets.Passwsord", null, null, null, false);
296 Password pw = new Password(passwordWidgetText, null);
297 pw.setPassword("");
298 currentFrame.removeItem(passwordWidgetText);
299 currentFrame.addAllItems(pw.getItems());
300 x = passwordWidgetText.getX() + passwordWidgetText.getBoundsWidth();
301 y = passwordWidgetText.getY();
302 } else {
303 // Determine the content for a setting label.
304 //String name = key.substring(0, 1).toUpperCase() + key.substring(1);
305 //String name = key;
306
307 // Construct and add text representation for setting.
308 // If a setting has no initialised value then it is not included.
309 String framesetName = currentFrame.getFramesetName();
310 Text template = setting.generateRepresentation(key, framesetName);
311 if (template == null) {
312 continue;
313 }
314 Text settingRepresentation = template.copy();
315 if (settingRepresentation == null || settingRepresentation.getBounds() == null) {
316 continue;
317 }
318 settingRepresentation.setID(currentFrame.getNextItemID());
319 frames.addItem(settingRepresentation, false);
320 x = settingRepresentation.getX() + settingRepresentation.getBoundsWidth();
321 y = settingRepresentation.getY();
322 }
323
324 x = Math.max(250, x + 20);
325 // Add tooltip for setting
326 Text tooltip = currentFrame.addText(x, y, "// " + setting.getTooltip(), null);
327 tooltip.rebuild(true);
328 if (tooltip.getY() + tooltip.getBoundsHeight() > frames.getLastY()) {
329 frames.setLastY(tooltip.getY() + tooltip.getBoundsHeight());
330 }
331 }
332
333 frames.save();
334 }
335}
Note: See TracBrowser for help on using the repository browser.