source: trunk/src/org/expeditee/gui/management/ProfileManager.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: 10.4 KB
Line 
1package org.expeditee.gui.management;
2
3import java.io.File;
4import java.nio.file.Path;
5import java.nio.file.Paths;
6import java.util.ArrayList;
7import java.util.Collection;
8import java.util.List;
9import java.util.Map;
10import java.util.function.Consumer;
11import java.util.stream.Collectors;
12
13import org.expeditee.agents.ExistingFramesetException;
14import org.expeditee.agents.InvalidFramesetNameException;
15import org.expeditee.core.Colour;
16import org.expeditee.core.Point;
17import org.expeditee.gui.Frame;
18import org.expeditee.gui.FrameIO;
19import org.expeditee.gui.MessageBay;
20import org.expeditee.items.Item;
21import org.expeditee.items.ItemUtils;
22import org.expeditee.items.Text;
23import org.expeditee.setting.Setting;
24import org.expeditee.settings.Settings;
25import org.expeditee.settings.UserSettings;
26import org.expeditee.settings.templates.TemplateSettings;
27
28public class ProfileManager {
29
30 private static final String USER_NAME_PATTERN_INTERNAL = "USER.NAME";
31 private static final String DEFAULT = UserSettings.DEFAULT_PROFILE_NAME;
32 private static final String[] startPages = { "exploratorysearch", "webbrowser" };
33 public static final String USER_NAME_PATTERN = "${" + USER_NAME_PATTERN_INTERNAL + "}";
34
35 public static Frame createProfile(String profileFor, Map<String, Setting> specifiedSettings,
36 Map<String, Consumer<Frame>> notifyWhenGenerated) {
37 ensureDefaultProfile();
38 Frame profile = null;
39 Frame profileOne = null;
40 profileFor = FrameIO.ConvertToValidFramesetName(profileFor);
41
42 try {
43 profile = FrameIO.CreateFrameset(profileFor, FrameIO.PROFILE_PATH, true);
44 profileOne = profile;
45 profile.setTitle(profileFor + "'s Profile");
46 Frame defaultFrame = FrameIO.LoadFrame(DEFAULT + "1");
47 MessageBay.suppressMessages(true);
48 UserSettings.UserName.set(profileFor);
49 UserSettings.ProfileName.set(profileFor);
50
51 int lastNumber = FrameIO.getLastNumber(defaultFrame.getFramesetName());
52 for (int i = 1; i <= lastNumber; i++) {
53 // Load in next default, if it doesn't exist continue loop.
54 defaultFrame = FrameIO.LoadFrame(DEFAULT + i);
55 if (defaultFrame == null) { continue; }
56
57 // Create the next next (currently blank) profile frame.
58 // If there is frame gaps in the default (say if there is no 4.exp but there is
59 // a 5.exp) then retain those gaps.
60 // This way copied relative links work.
61 while (profile.getNumber() < defaultFrame.getNumber()) {
62 profile = FrameIO.CreateFrame(profile.getFramesetName(), null, null);
63 }
64 // Ensure we are working from a blank slate.
65 profile.reset();
66 profile.removeAllItems(profile.getAllItems());
67
68 // For each item on defaultFrame:
69 // 1. Set all items to be relatively linked so once copied their links correctly
70 // point to the frame on the created profile rather than the default profile.
71 // 2. Copy item from defaultFrame to the current profile frame being
72 // constructed.
73 // 3. Replace instance of ${USER.NAME} with 'profileFor'
74 // 4. Replace settings values of copied items with those specified in
75 // specifiedSettings (if present)
76 Collection<Item> defaultAllItems = defaultFrame.getAllItems();
77 Collection<Item> allItems = new ArrayList<Item>();
78 for (Item item: defaultAllItems) {
79 Item copyItem = item.copy();
80 allItems.add(copyItem);
81 }
82 profile.addAllItems(allItems);
83
84 for (Item item: profile.getAllItems()) {
85 if (item instanceof Text) {
86 String content = item.getText();
87 item.setText(ResourceUtil.substitute(content, ProfileManager.USER_NAME_PATTERN_INTERNAL, profileFor));
88 }
89 }
90
91 String category = profile.getTitle();
92 List<String> settingsKeys = null;
93 if (specifiedSettings != null) {
94 settingsKeys = specifiedSettings.keySet().stream().filter(key ->
95 key.startsWith(category)).collect(Collectors.toList());
96 }
97 if (settingsKeys != null) {
98 for (String key: settingsKeys) {
99 Setting setting = specifiedSettings.get(key);
100 String name = setting.getName();
101 Text representation = setting.generateRepresentation(name, profile.getFramesetName());
102 Collection<Text> canditates = profile.getTextItems();
103 canditates.removeIf(text -> !text.getText().startsWith(representation.getText().split(" ")[0]));
104 canditates.forEach(text -> {
105 Point backupPos = text.getPosition();
106 Item.DuplicateItem(representation, text);
107 text.setText(representation.getText());
108 text.setPosition(backupPos);
109 });
110 }
111 }
112 if (notifyWhenGenerated != null && notifyWhenGenerated.containsKey(category)) {
113 notifyWhenGenerated.get(category).accept(profile);
114 }
115
116 FrameIO.SaveFrame(profile);
117 }
118 MessageBay.suppressMessages(false);
119 } catch (InvalidFramesetNameException | ExistingFramesetException e) {
120 String preamble = "Failed to create profile for '" + DEFAULT + "'. ";
121 if (e instanceof InvalidFramesetNameException) {
122 String message = preamble + "Profile names must start and end with a letter and must contain only letters and numbers";
123 MessageBay.errorMessage(message);
124 } else if (e instanceof ExistingFramesetException) {
125 String message = preamble + "A frameset with this name already exists in: " + FrameIO.PROFILE_PATH;
126 MessageBay.errorMessage(message);
127 }
128 }
129
130 return profileOne;
131 }
132
133 /**
134 * Checks if the default profile exists, creates it if it does not.
135 */
136 public static void ensureDefaultProfile() {
137 // If we can load in the default profile, we have nothing to do.
138 Frame defaultFrame = FrameIO.LoadProfile(DEFAULT);
139 if (defaultFrame != null) {
140 return;
141 }
142
143 // We do not have a default profile, generate one.
144 createDefaultProfile();
145 }
146
147 /**
148 * Creates the default profile.
149 */
150 private static void createDefaultProfile() {
151 try {
152 Frame profile = FrameIO.CreateFrameset(DEFAULT, FrameIO.PROFILE_PATH, true);
153
154 // Give the first frame in the new profile an appropriate title.
155 Text titleItem = profile.getTitleItem();
156 if (titleItem != null) {
157 titleItem.setText("Default Profile Frame");
158 }
159
160 // initial position for placing items.
161 int xPos = 300;
162 int yPos = 100;
163
164 // Add documentation links
165 Path helpDirectory = Paths.get(FrameIO.HELP_PATH);
166 File[] helpFramesets = helpDirectory.toFile().listFiles();
167 if (helpFramesets != null) {
168 // Add the title for the help index
169 Text helpPagesTitle = profile.addText(xPos, yPos, "@Expeditee Help", null);
170 helpPagesTitle.setSize(25);
171 helpPagesTitle.setFontStyle("Bold");
172 helpPagesTitle.setFamily("SansSerif");
173 helpPagesTitle.setColor(TemplateSettings.ColorWheel.get()[3]);
174
175 xPos += 25;
176 System.out.println("Installing frameset: ");
177
178 boolean first_item = true;
179 for (File helpFrameset : helpFramesets) {
180 String framesetName = helpFrameset.getName();
181 if (!FrameIO.isValidFramesetName(framesetName)) {
182 continue;
183 }
184
185 if (first_item) {
186 System.out.print(" " + framesetName);
187 first_item = false;
188 } else {
189 System.out.print(", " + framesetName);
190 }
191 System.out.flush();
192
193 Frame indexFrame = FrameIO.LoadFrame(framesetName + '1');
194 // Look through the folder for help index pages
195 if (indexFrame != null && ItemUtils.FindTag(indexFrame.getSortedItems(), "@HelpIndex") != null) {
196 // yPos += spacing;
197 yPos += 30;
198 Text helpLink = profile.addText(xPos, yPos, '@' + indexFrame.getFramesetName(), null);
199 helpLink.setLink(indexFrame.getName());
200 helpLink.setColor(Colour.GREY);
201 }
202 }
203 System.out.println();
204 }
205
206 // Reset position
207 xPos = 50;
208 yPos = 100;
209
210 // Add start pages
211 Path framesetDirectory = Paths.get(FrameIO.FRAME_PATH);
212 File[] startPageFramesets = framesetDirectory.toFile().listFiles();
213 if (startPageFramesets != null) {
214 // Add Start Page title
215 Text startPagesTitle = profile.addText(xPos, yPos, "@Start Pages", null);
216 startPagesTitle.setSize(25);
217 startPagesTitle.setFontStyle("Bold");
218 startPagesTitle.setFamily("SansSerif");
219 startPagesTitle.setColor(TemplateSettings.ColorWheel.get()[3]);
220
221 xPos += 25;
222
223 // Start Pages should be the first frame in its own frameset +
224 // frameset name should be present in FrameUtils.startPages[].
225 for (File startpagesFrameset : startPageFramesets) {
226 String framesetName = startpagesFrameset.getName();
227
228 // Only add link if frameset is a startpage
229 for (int i = 0; i < startPages.length; i++) {
230 if (framesetName.equals(startPages[i])) {
231 Frame indexFrame = FrameIO.LoadFrame(framesetName + '1');
232
233 // Add start page link
234 if (indexFrame != null) {
235 yPos += 30;
236 Text startPageLink = profile.addText(xPos, yPos, '@' + indexFrame.getFramesetName(), null);
237 startPageLink.setLink(indexFrame.getName());
238 startPageLink.setColor(Colour.GREY);
239 }
240 }
241 }
242 }
243 }
244
245 // Add 'default' settings frameset
246 Settings.Init();
247 Text settingsLink = profile.addText(550, 100, "@Settings", null);
248 settingsLink.setSize((float) 25.0);
249 settingsLink.setFamily("SansSerif");
250 settingsLink.setFontStyle("Bold");
251 settingsLink.setColor(Colour.GREY);
252 Settings.generateSettingsTree(settingsLink);
253 System.out.println("@Settings: Default settings generation complete.");
254
255 FrameIO.SaveFrame(profile);
256
257 int lastNumber = FrameIO.getLastNumber(profile.getFramesetName());
258 for (int i = 1; i <= lastNumber; i++) {
259 Frame frame = FrameIO.LoadFrame(DEFAULT + i);
260 frame.setOwner(DEFAULT);
261 for(Item item: frame.getAllItems()) {
262 item.setOwner(DEFAULT);
263 item.setRelativeLink();
264 }
265 frame.setChanged(true);
266 FrameIO.SaveFrame(frame);
267 }
268
269 } catch (InvalidFramesetNameException | ExistingFramesetException e) {
270 String preamble = "Failed to create profile for '" + DEFAULT + "'. ";
271 if (e instanceof InvalidFramesetNameException) {
272 String message = preamble + "Profile names must start and end with a letter and must contain only letters and numbers";
273 MessageBay.errorMessage(message);
274 } else if (e instanceof ExistingFramesetException) {
275 String message = preamble + "A frameset with this name already exists in: " + FrameIO.PROFILE_PATH;
276 MessageBay.errorMessage(message);
277 }
278 return;
279 }
280 }
281}
Note: See TracBrowser for help on using the repository browser.