Mercurial > hg > accesspd
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java/src/uk/ac/qmul/eecs/ccmi/main/DiagramEditorApp.java Tue Jul 08 16:28:59 2014 +0100 @@ -0,0 +1,297 @@ +/* + CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool + + Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +package uk.ac.qmul.eecs.ccmi.main; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.text.MessageFormat; +import java.util.ResourceBundle; + +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +import uk.ac.qmul.eecs.ccmi.gui.Diagram; +import uk.ac.qmul.eecs.ccmi.gui.EditorFrame; +import uk.ac.qmul.eecs.ccmi.gui.HapticKindle; +import uk.ac.qmul.eecs.ccmi.gui.SpeechOptionPane; +import uk.ac.qmul.eecs.ccmi.gui.TemplateEditor; +import uk.ac.qmul.eecs.ccmi.haptics.Haptics; +import uk.ac.qmul.eecs.ccmi.haptics.HapticsFactory; +import uk.ac.qmul.eecs.ccmi.simpletemplate.SimpleTemplateEditor; +import uk.ac.qmul.eecs.ccmi.sound.SoundFactory; +import uk.ac.qmul.eecs.ccmi.speech.NarratorFactory; +import uk.ac.qmul.eecs.ccmi.utils.CCmIUncaughtExceptionHandler; +import uk.ac.qmul.eecs.ccmi.utils.InteractionLog; +import uk.ac.qmul.eecs.ccmi.utils.PreferencesService; +import uk.ac.qmul.eecs.ccmi.utils.ResourceFileWriter; + +/** + * + * The application class with the main method. The main performs + * the start up initialization and then displays the graphical user interface. + * + */ +public class DiagramEditorApp implements Runnable { + + /* initialize all the non gui resources */ + private void init() throws IOException { + Thread.setDefaultUncaughtExceptionHandler(new CCmIUncaughtExceptionHandler()); + final ResourceBundle resources = ResourceBundle.getBundle(DiagramEditorApp.class.getName()); + /* create the home directory if it does not exist and store the path into the preferences */ + PreferencesService preferences = PreferencesService.getInstance(); + String homeDirPath = preferences.get("home", null); + if(homeDirPath == null){ + homeDirPath = new StringBuilder(System.getProperty("user.home")).append(System.getProperty("file.separator")).append(resources.getString("dir.home")).toString(); + preferences.put("home", homeDirPath); + } + File homeDir = new File(homeDirPath); + mkDir(homeDir, resources); + + File backupDir = new File(homeDir,resources.getString("dir.backups")); + mkDir(backupDir, resources); + backupDirPath = backupDir.getAbsolutePath(); + + /* create the templates directory into the home directory */ + File templateDir = new File(homeDir,resources.getString("dir.templates")); + mkDir(templateDir,resources); + + /* create the images directory into the home directory */ + File imagesDir = new File(homeDir,resources.getString("dir.images")); + mkDir(imagesDir,resources); + preferences.put("dir.images", imagesDir.getAbsolutePath()); + + /* create the diagrams dir into the home directory */ + File diagramDir = new File(homeDir,resources.getString("dir.diagrams")); + mkDir(diagramDir,resources); + preferences.put("dir.diagrams", diagramDir.getAbsolutePath()); + + /* create the libs directory into he home directory */ + File libsDir = new File(homeDir,resources.getString("dir.libs")); + mkDir(libsDir,resources); + preferences.put("dir.libs", libsDir.getAbsolutePath()); + + /* write the template files included in the software in the template dir, if they don't exist yet */ + ResourceFileWriter resourceWriter = new ResourceFileWriter(getClass().getResource("UML Diagram.xml")); + resourceWriter.writeOnDisk(templateDir.getAbsolutePath(),"UML Diagram.xml"); + resourceWriter.setResource(getClass().getResource("Tube.xml")); + resourceWriter.writeOnDisk(templateDir.getAbsolutePath(),"Tube.xml"); + resourceWriter.setResource(getClass().getResource("Organization Chart.xml")); + resourceWriter.writeOnDisk(templateDir.getAbsolutePath(),"Organization Chart.xml"); + + /* read the template files into an array to pass to the EditorFrame instance */ + FilenameFilter filter = new FilenameFilter() { + @Override + public boolean accept(File f, String name) { + return (name.endsWith(resources.getString("template.extension"))); + } + }; + templateFiles = templateDir.listFiles(filter); + File logDir = new File(homeDir,resources.getString("dir.log")); + mkDir(logDir,resources); + preferences.put("dir.log", logDir.getAbsolutePath()); + + String enableLog = preferences.get("enable_log", "false"); + if(Boolean.parseBoolean(enableLog)){ + try{ + InteractionLog.enable(logDir.getAbsolutePath()); + InteractionLog.log("PROGRAM STARTED"); + }catch(IOException ioe){ + /* if logging was enabled, the possibility to log is considered inescapable */ + /* at launch time: do not allow the execution to continue any further */ + throw new RuntimeException(ioe); + } + } + + /* create sound, speech engines */ + NarratorFactory.createInstance(); + SoundFactory.createInstance(); + } + + /* loads haptic device. If the user is running the software for the first time * + * they're prompted with a dialog to select the device they want to use */ + private void initHaptics(){ + final PreferencesService preferences = PreferencesService.getInstance(); + if(!Boolean.parseBoolean(preferences.get("haptic_device.initialized", "false"))){ + try { + SwingUtilities.invokeAndWait(new Runnable(){ + @Override + public void run() { + try { + UIManager.setLookAndFeel( + UIManager.getSystemLookAndFeelClassName()); + }catch(Exception e){/* nevermind */} + + String [] hapticDevices = { + HapticsFactory.PHANTOM_ID, + HapticsFactory.FALCON_ID, + HapticsFactory.TABLET_ID}; + String selection = (String)SpeechOptionPane.showSelectionDialog(null, + ResourceBundle.getBundle(DiagramEditorApp.class.getName()).getString("haptics_init.welcome"), + hapticDevices, + hapticDevices[2]); + if(selection == null) + System.exit(0); + preferences.put("haptic_device", selection); + preferences.put("haptic_device.initialized", "true"); + } + }); + }catch(InvocationTargetException ite){ + throw new RuntimeException(ite); + }catch(InterruptedException ie){ + throw new RuntimeException(ie); + } + } + + /* creates the Haptics instance */ + HapticsFactory.createInstance(new HapticKindle()); + haptics = HapticsFactory.getInstance(); + if(haptics.isAlive()) + NarratorFactory.getInstance().speakWholeText("Haptic device successfully initialized"); + } + + /* return true if the directory was created, false if it existed before */ + private boolean mkDir(File dir,ResourceBundle resources) throws IOException{ + boolean created = dir.mkdir(); + if(!dir.exists()) + throw new IOException(MessageFormat.format( + resources.getString("dir.error_msg"), + dir.getAbsolutePath()) + ); + return created; + } + + /** + * build up the GUI and display it + */ + @Override + public void run() { + editorFrame = new EditorFrame(haptics,getTemplateFiles(),backupDirPath,getTemplateEditors(),getDiagrams()); + } + + /** + * Provides template editors to create own templates using the diagram editor. + * + * Subclasses who don't want any template editor to appear in the diagram + * can just return an empty array. Returning {@code null} will throw an exception. + * + * @return an array of template editors + */ + protected TemplateEditor[] getTemplateEditors(){ + TemplateEditor[] templateEditors = new TemplateEditor[1]; + templateEditors[0] = new SimpleTemplateEditor(); + return templateEditors; + } + + /** + * Returns the template files detected in the ccmi_editor_data/templates directory. + * + * Returning {@code null} will throw an exception. + * + * @return an array of (xml) Files containing a template + */ + protected File[] getTemplateFiles(){ + return templateFiles; + } + + /** + * Returns an empty list. This method can be overwritten by subclasses to + * provide their own custom diagrams. Such diagrams will appear in the menu. + * + * Returning {@code null} will throw an exception. + * + * @return an array of diagram templates. The array is empty in this implementation. + */ + protected Diagram[] getDiagrams(){ + return new Diagram[0]; + } + + /** + * The main function + * @param args this software accepts no args from the command line + */ + public static void main(String[] args){ + DiagramEditorApp application = new DiagramEditorApp(); + mainImplementation(application); + } + + + /** + * Implementation of the main body. It can be used to run the program + * using a subclass of {@code DiagramEditorApp}, providing it's own + * diagram templates + * + * @param application the diagram editor application to execute + */ + public final static void mainImplementation(DiagramEditorApp application) { + try{ + application.init(); + } catch (IOException e) { + final String msg = e.getLocalizedMessage(); + try { + SwingUtilities.invokeAndWait(new Runnable(){ + @Override + public void run(){ + try { + UIManager.setLookAndFeel( + UIManager.getSystemLookAndFeelClassName()); + }catch(Exception e){/* nevermind */} + JOptionPane.showMessageDialog(null, msg); + } + }); + } catch (InterruptedException ex) { + throw new RuntimeException(ex); + } catch (InvocationTargetException ex) { + throw new RuntimeException(ex); + } + System.exit(-1); + } + + application.initHaptics(); + + /* start the application */ + try { + SwingUtilities.invokeAndWait(application); + } catch (InvocationTargetException ex) { + throw new RuntimeException(ex); + } catch (InterruptedException ex) { + throw new RuntimeException(ex); + } + } + + /** + * Returns the reference to the unique {@code EditorFrame} instance of the program. + * The main GUI class. + * + * @return an reference to {@code EditorFrame} + */ + public static EditorFrame getFrame(){ + return editorFrame; + } + + private static EditorFrame editorFrame; + Haptics haptics; + File[] templateFiles; + TemplateEditor[] templateCreators; + String backupDirPath; +} +