annotate java/src/uk/ac/qmul/eecs/ccmi/main/DiagramEditorApp.java @ 1:e3935c01cde2 tip

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