comparison java/src/uk/ac/qmul/eecs/ccmi/main/DiagramEditorApp.java @ 0:78b7fc5391a2

first import, outcome of NIME 2014 hackaton
author Fiore Martin <f.martin@qmul.ac.uk>
date Tue, 08 Jul 2014 16:28:59 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:78b7fc5391a2
1 /*
2 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
3
4 Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 package uk.ac.qmul.eecs.ccmi.main;
21
22 import java.io.File;
23 import java.io.FilenameFilter;
24 import java.io.IOException;
25 import java.lang.reflect.InvocationTargetException;
26 import java.text.MessageFormat;
27 import java.util.ResourceBundle;
28
29 import javax.swing.JOptionPane;
30 import javax.swing.SwingUtilities;
31 import javax.swing.UIManager;
32
33 import uk.ac.qmul.eecs.ccmi.gui.Diagram;
34 import uk.ac.qmul.eecs.ccmi.gui.EditorFrame;
35 import uk.ac.qmul.eecs.ccmi.gui.HapticKindle;
36 import uk.ac.qmul.eecs.ccmi.gui.SpeechOptionPane;
37 import uk.ac.qmul.eecs.ccmi.gui.TemplateEditor;
38 import uk.ac.qmul.eecs.ccmi.haptics.Haptics;
39 import uk.ac.qmul.eecs.ccmi.haptics.HapticsFactory;
40 import uk.ac.qmul.eecs.ccmi.simpletemplate.SimpleTemplateEditor;
41 import uk.ac.qmul.eecs.ccmi.sound.SoundFactory;
42 import uk.ac.qmul.eecs.ccmi.speech.NarratorFactory;
43 import uk.ac.qmul.eecs.ccmi.utils.CCmIUncaughtExceptionHandler;
44 import uk.ac.qmul.eecs.ccmi.utils.InteractionLog;
45 import uk.ac.qmul.eecs.ccmi.utils.PreferencesService;
46 import uk.ac.qmul.eecs.ccmi.utils.ResourceFileWriter;
47
48 /**
49 *
50 * The application class with the main method. The main performs
51 * the start up initialization and then displays the graphical user interface.
52 *
53 */
54 public class DiagramEditorApp implements Runnable {
55
56 /* initialize all the non gui resources */
57 private void init() throws IOException {
58 Thread.setDefaultUncaughtExceptionHandler(new CCmIUncaughtExceptionHandler());
59 final ResourceBundle resources = ResourceBundle.getBundle(DiagramEditorApp.class.getName());
60 /* create the home directory if it does not exist and store the path into the preferences */
61 PreferencesService preferences = PreferencesService.getInstance();
62 String homeDirPath = preferences.get("home", null);
63 if(homeDirPath == null){
64 homeDirPath = new StringBuilder(System.getProperty("user.home")).append(System.getProperty("file.separator")).append(resources.getString("dir.home")).toString();
65 preferences.put("home", homeDirPath);
66 }
67 File homeDir = new File(homeDirPath);
68 mkDir(homeDir, resources);
69
70 File backupDir = new File(homeDir,resources.getString("dir.backups"));
71 mkDir(backupDir, resources);
72 backupDirPath = backupDir.getAbsolutePath();
73
74 /* create the templates directory into the home directory */
75 File templateDir = new File(homeDir,resources.getString("dir.templates"));
76 mkDir(templateDir,resources);
77
78 /* create the images directory into the home directory */
79 File imagesDir = new File(homeDir,resources.getString("dir.images"));
80 mkDir(imagesDir,resources);
81 preferences.put("dir.images", imagesDir.getAbsolutePath());
82
83 /* create the diagrams dir into the home directory */
84 File diagramDir = new File(homeDir,resources.getString("dir.diagrams"));
85 mkDir(diagramDir,resources);
86 preferences.put("dir.diagrams", diagramDir.getAbsolutePath());
87
88 /* create the libs directory into he home directory */
89 File libsDir = new File(homeDir,resources.getString("dir.libs"));
90 mkDir(libsDir,resources);
91 preferences.put("dir.libs", libsDir.getAbsolutePath());
92
93 /* write the template files included in the software in the template dir, if they don't exist yet */
94 ResourceFileWriter resourceWriter = new ResourceFileWriter(getClass().getResource("UML Diagram.xml"));
95 resourceWriter.writeOnDisk(templateDir.getAbsolutePath(),"UML Diagram.xml");
96 resourceWriter.setResource(getClass().getResource("Tube.xml"));
97 resourceWriter.writeOnDisk(templateDir.getAbsolutePath(),"Tube.xml");
98 resourceWriter.setResource(getClass().getResource("Organization Chart.xml"));
99 resourceWriter.writeOnDisk(templateDir.getAbsolutePath(),"Organization Chart.xml");
100
101 /* read the template files into an array to pass to the EditorFrame instance */
102 FilenameFilter filter = new FilenameFilter() {
103 @Override
104 public boolean accept(File f, String name) {
105 return (name.endsWith(resources.getString("template.extension")));
106 }
107 };
108 templateFiles = templateDir.listFiles(filter);
109 File logDir = new File(homeDir,resources.getString("dir.log"));
110 mkDir(logDir,resources);
111 preferences.put("dir.log", logDir.getAbsolutePath());
112
113 String enableLog = preferences.get("enable_log", "false");
114 if(Boolean.parseBoolean(enableLog)){
115 try{
116 InteractionLog.enable(logDir.getAbsolutePath());
117 InteractionLog.log("PROGRAM STARTED");
118 }catch(IOException ioe){
119 /* if logging was enabled, the possibility to log is considered inescapable */
120 /* at launch time: do not allow the execution to continue any further */
121 throw new RuntimeException(ioe);
122 }
123 }
124
125 /* create sound, speech engines */
126 NarratorFactory.createInstance();
127 SoundFactory.createInstance();
128 }
129
130 /* loads haptic device. If the user is running the software for the first time *
131 * they're prompted with a dialog to select the device they want to use */
132 private void initHaptics(){
133 final PreferencesService preferences = PreferencesService.getInstance();
134 if(!Boolean.parseBoolean(preferences.get("haptic_device.initialized", "false"))){
135 try {
136 SwingUtilities.invokeAndWait(new Runnable(){
137 @Override
138 public void run() {
139 try {
140 UIManager.setLookAndFeel(
141 UIManager.getSystemLookAndFeelClassName());
142 }catch(Exception e){/* nevermind */}
143
144 String [] hapticDevices = {
145 HapticsFactory.PHANTOM_ID,
146 HapticsFactory.FALCON_ID,
147 HapticsFactory.TABLET_ID};
148 String selection = (String)SpeechOptionPane.showSelectionDialog(null,
149 ResourceBundle.getBundle(DiagramEditorApp.class.getName()).getString("haptics_init.welcome"),
150 hapticDevices,
151 hapticDevices[2]);
152 if(selection == null)
153 System.exit(0);
154 preferences.put("haptic_device", selection);
155 preferences.put("haptic_device.initialized", "true");
156 }
157 });
158 }catch(InvocationTargetException ite){
159 throw new RuntimeException(ite);
160 }catch(InterruptedException ie){
161 throw new RuntimeException(ie);
162 }
163 }
164
165 /* creates the Haptics instance */
166 HapticsFactory.createInstance(new HapticKindle());
167 haptics = HapticsFactory.getInstance();
168 if(haptics.isAlive())
169 NarratorFactory.getInstance().speakWholeText("Haptic device successfully initialized");
170 }
171
172 /* return true if the directory was created, false if it existed before */
173 private boolean mkDir(File dir,ResourceBundle resources) throws IOException{
174 boolean created = dir.mkdir();
175 if(!dir.exists())
176 throw new IOException(MessageFormat.format(
177 resources.getString("dir.error_msg"),
178 dir.getAbsolutePath())
179 );
180 return created;
181 }
182
183 /**
184 * build up the GUI and display it
185 */
186 @Override
187 public void run() {
188 editorFrame = new EditorFrame(haptics,getTemplateFiles(),backupDirPath,getTemplateEditors(),getDiagrams());
189 }
190
191 /**
192 * Provides template editors to create own templates using the diagram editor.
193 *
194 * Subclasses who don't want any template editor to appear in the diagram
195 * can just return an empty array. Returning {@code null} will throw an exception.
196 *
197 * @return an array of template editors
198 */
199 protected TemplateEditor[] getTemplateEditors(){
200 TemplateEditor[] templateEditors = new TemplateEditor[1];
201 templateEditors[0] = new SimpleTemplateEditor();
202 return templateEditors;
203 }
204
205 /**
206 * Returns the template files detected in the ccmi_editor_data/templates directory.
207 *
208 * Returning {@code null} will throw an exception.
209 *
210 * @return an array of (xml) Files containing a template
211 */
212 protected File[] getTemplateFiles(){
213 return templateFiles;
214 }
215
216 /**
217 * Returns an empty list. This method can be overwritten by subclasses to
218 * provide their own custom diagrams. Such diagrams will appear in the menu.
219 *
220 * Returning {@code null} will throw an exception.
221 *
222 * @return an array of diagram templates. The array is empty in this implementation.
223 */
224 protected Diagram[] getDiagrams(){
225 return new Diagram[0];
226 }
227
228 /**
229 * The main function
230 * @param args this software accepts no args from the command line
231 */
232 public static void main(String[] args){
233 DiagramEditorApp application = new DiagramEditorApp();
234 mainImplementation(application);
235 }
236
237
238 /**
239 * Implementation of the main body. It can be used to run the program
240 * using a subclass of {@code DiagramEditorApp}, providing it's own
241 * diagram templates
242 *
243 * @param application the diagram editor application to execute
244 */
245 public final static void mainImplementation(DiagramEditorApp application) {
246 try{
247 application.init();
248 } catch (IOException e) {
249 final String msg = e.getLocalizedMessage();
250 try {
251 SwingUtilities.invokeAndWait(new Runnable(){
252 @Override
253 public void run(){
254 try {
255 UIManager.setLookAndFeel(
256 UIManager.getSystemLookAndFeelClassName());
257 }catch(Exception e){/* nevermind */}
258 JOptionPane.showMessageDialog(null, msg);
259 }
260 });
261 } catch (InterruptedException ex) {
262 throw new RuntimeException(ex);
263 } catch (InvocationTargetException ex) {
264 throw new RuntimeException(ex);
265 }
266 System.exit(-1);
267 }
268
269 application.initHaptics();
270
271 /* start the application */
272 try {
273 SwingUtilities.invokeAndWait(application);
274 } catch (InvocationTargetException ex) {
275 throw new RuntimeException(ex);
276 } catch (InterruptedException ex) {
277 throw new RuntimeException(ex);
278 }
279 }
280
281 /**
282 * Returns the reference to the unique {@code EditorFrame} instance of the program.
283 * The main GUI class.
284 *
285 * @return an reference to {@code EditorFrame}
286 */
287 public static EditorFrame getFrame(){
288 return editorFrame;
289 }
290
291 private static EditorFrame editorFrame;
292 Haptics haptics;
293 File[] templateFiles;
294 TemplateEditor[] templateCreators;
295 String backupDirPath;
296 }
297