Mercurial > hg > ccmieditor
diff java/src/uk/ac/qmul/eecs/ccmi/gui/HapticKindle.java @ 3:9e67171477bc
PHANTOM Omni Heptic device release
author | Fiore Martin <fiore@eecs.qmul.ac.uk> |
---|---|
date | Wed, 25 Apr 2012 17:09:09 +0100 |
parents | 9418ab7b7f3f |
children | d66dd5880081 |
line wrap: on
line diff
--- a/java/src/uk/ac/qmul/eecs/ccmi/gui/HapticKindle.java Mon Feb 06 12:54:06 2012 +0000 +++ b/java/src/uk/ac/qmul/eecs/ccmi/gui/HapticKindle.java Wed Apr 25 17:09:09 2012 +0100 @@ -20,6 +20,7 @@ import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; +import java.util.ResourceBundle; import javax.swing.SwingUtilities; @@ -27,8 +28,11 @@ import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramElement; import uk.ac.qmul.eecs.ccmi.haptics.HapticListener; import uk.ac.qmul.eecs.ccmi.haptics.HapticListenerCommand; +import uk.ac.qmul.eecs.ccmi.main.DiagramEditorApp; +import uk.ac.qmul.eecs.ccmi.network.Command; +import uk.ac.qmul.eecs.ccmi.network.DiagramEventActionSource; +import uk.ac.qmul.eecs.ccmi.sound.SoundEvent; import uk.ac.qmul.eecs.ccmi.sound.SoundFactory; -import uk.ac.qmul.eecs.ccmi.sound.SoundEvent; import uk.ac.qmul.eecs.ccmi.speech.NarratorFactory; import uk.ac.qmul.eecs.ccmi.utils.InteractionLog; @@ -45,94 +49,94 @@ unselectRunnable = new Runnable(){ @Override public void run(){ + EditorFrame frame = DiagramEditorApp.getFrame(); + if((frame == null)||(frame.getActiveTab() == null)) + return; frame.selectHapticHighligh(null); } }; - frameBackupRunnable = new Runnable(){ - @Override - public void run(){ - frame.backupOpenDiagrams(); - } - }; } - public void setEditorFrame(EditorFrame frame){ - this.frame = frame; - } - + /** + * Implementation of the {@code executeCommand} method. All the commands that involve the + * diagram model, are executed in the Event Dispatching Thread through {@code SwingUtilities} invoke + * methods. This prevents race conditions on the model and on diagram elements. + * + * @see HapticListener#executeCommand(HapticListenerCommand, int, double, double, double, double) + */ @Override - public void executeCommand(HapticListenerCommand cmd, int ID, final double x, final double y, final double startX, final double startY) { - if((frame == null)||(frame.getActiveTab() == null)) - return; - CollectionModel<Node,Edge> collectionModel = frame.getActiveTab().getDiagram().getCollectionModel(); - Object monitor = collectionModel.getMonitor(); - DiagramElement de = null; + public void executeCommand(HapticListenerCommand cmd, final int ID, final double x, final double y, final double startX, final double startY) { + final EditorFrame frame = DiagramEditorApp.getFrame(); switch(cmd){ - case PLAY_ELEMENT_SOUND : - synchronized(monitor){ - de = Finder.findElementByHashcode(ID, collectionModel.getElements()); - } - /* can be null if the tab has been switched or closed in the meantime */ - if(de == null) - return; - SoundFactory.getInstance().play(de.getSound()); + case PLAY_ELEMENT_SOUND : + SwingUtilities.invokeLater(new Runnable(){ + public void run(){ + if((frame == null)||(frame.getActiveTab() == null)) + return; + CollectionModel<Node,Edge> collectionModel = frame.getActiveTab().getDiagram().getCollectionModel(); + DiagramElement de = Finder.findElementByHashcode(ID, collectionModel.getElements()); + /* can be null if the tab has been switched or closed in the meantime */ + if(de == null) + return; + SoundFactory.getInstance().play(de.getSound()); + } + }); break; case PLAY_ELEMENT_SPEECH : - synchronized(monitor){ - de = Finder.findElementByHashcode(ID, collectionModel.getElements()); - } - if(de == null) - return; - SoundFactory.getInstance().play(de.getSound()); - NarratorFactory.getInstance().speak(de.getName()); - iLog("touch",((de instanceof Node) ? "node " : "edge ")+de.getName()); + SwingUtilities.invokeLater(new Runnable(){ + public void run(){ + if((frame == null)||(frame.getActiveTab() == null)) + return; + CollectionModel<Node,Edge> collectionModel = frame.getActiveTab().getDiagram().getCollectionModel(); + DiagramElement de = Finder.findElementByHashcode(ID, collectionModel.getElements()); + if(de == null) + return; + SoundFactory.getInstance().play(de.getSound()); + NarratorFactory.getInstance().speak(de.getName()); + iLog("touch",((de instanceof Node) ? "node " : "edge ")+de.getName()); + } + }); break; case SELECT : - synchronized(monitor){ - de = Finder.findElementByHashcode(ID, collectionModel.getElements()); - } - if(de == null) - return; - final DiagramElement selectedElement = de; SwingUtilities.invokeLater(new Runnable(){ - @Override public void run(){ - frame.selectHapticHighligh(selectedElement); + if((frame == null)||(frame.getActiveTab() == null)) + return; + CollectionModel<Node,Edge> collectionModel = frame.getActiveTab().getDiagram().getCollectionModel(); + DiagramElement de = Finder.findElementByHashcode(ID, collectionModel.getElements()); + if(de == null) + return; + frame.selectHapticHighligh(de); } }); break; case UNSELECT : SwingUtilities.invokeLater(unselectRunnable); break; - case MOVE : - DiagramPanel dPanel = frame.getActiveTab(); - if(dPanel == null) - return; - synchronized(monitor){ - de = Finder.findElementByHashcode(ID, collectionModel.getElements()); - } - if(de == null) - return; - final DiagramElement moveSelectedElement = de; - final DiagramModelUpdater modelUpdater = dPanel.getDiagram().getModelUpdater(); - if(!modelUpdater.getLock(moveSelectedElement, Lock.MOVE)){ - iLog("Could not get lock on element for motion", DiagramElement.toLogString(moveSelectedElement)); - NarratorFactory.getInstance().speak("Object is being moved by another user"); - return; - } - + case MOVE : { + /* when this block is executed we already have the lock * + * on the element from the PICK_UP command execution */ try { SwingUtilities.invokeAndWait(new Runnable(){ @Override public void run(){ - if(moveSelectedElement instanceof Node){ - Node n = (Node)moveSelectedElement; + if((frame == null)||(frame.getActiveTab() == null)) + return; + CollectionModel<Node,Edge> collectionModel = frame.getActiveTab().getDiagram().getCollectionModel(); + DiagramElement de = Finder.findElementByHashcode(ID, collectionModel.getElements()); + if(de == null) + return; + DiagramModelUpdater modelUpdater = frame.getActiveTab().getDiagram().getModelUpdater(); + if(de instanceof Node){ + Node n = (Node)de; Rectangle2D bounds = n.getBounds(); Point2D.Double p = new Point2D.Double(bounds.getCenterX(),bounds.getCenterY()); double dx = x - p.getX(); double dy = y - p.getY(); - modelUpdater.translate(n, p, dx, dy); - modelUpdater.stopMove(n); + n.getMonitor().lock(); + modelUpdater.translate(n, p, dx, dy,DiagramEventSource.HAPT); + modelUpdater.stopMove(n,DiagramEventSource.HAPT); + n.getMonitor().unlock(); StringBuilder builder = new StringBuilder(); builder.append(DiagramElement.toLogString(n)).append(" ").append(p.getX()) @@ -141,16 +145,16 @@ builder = new StringBuilder(); builder.append(DiagramElement.toLogString(n)).append(' ') .append(x).append(' ').append(y); - iLog("move node end",builder.toString()); + }else{ + Edge e = (Edge)de; + modelUpdater.startMove(e, new Point2D.Double(startX,startY),DiagramEventSource.HAPT); + Point2D p = new Point2D.Double(x,y); + e.getMonitor().lock(); + modelUpdater.bend(e, p,DiagramEventSource.HAPT); + modelUpdater.stopMove(e,DiagramEventSource.HAPT); + e.getMonitor().unlock(); - }else{ - Edge e = (Edge)moveSelectedElement; - modelUpdater.startMove(e, new Point2D.Double(startX,startY)); - Point2D p = new Point2D.Double(x,y); - modelUpdater.bend(e, p); - modelUpdater.stopMove(e); - StringBuilder builder = new StringBuilder(); builder.append(DiagramElement.toLogString(e)).append(' ').append(startX) .append(' ').append(startY); @@ -159,25 +163,37 @@ builder.append(DiagramElement.toLogString(e)).append(' ') .append(x).append(' ').append(y); iLog("bend edge end",builder.toString()); - } - } + modelUpdater.yieldLock(de, + Lock.MOVE, + new DiagramEventActionSource( + DiagramEventSource.HAPT, + de instanceof Node ? Command.Name.STOP_NODE_MOVE : Command.Name.STOP_EDGE_MOVE, + de.getId(), + de.getName() + )); + } // run() }); } catch (Exception e) { throw new RuntimeException(e); } SoundFactory.getInstance().play(SoundEvent.HOOK_OFF); - modelUpdater.yieldLock(moveSelectedElement, Lock.MOVE); + } break; - case INFO : - synchronized(monitor){ - de = Finder.findElementByHashcode(ID, collectionModel.getElements()); - } - if(de == null) - return; - SoundFactory.getInstance().stop(); - NarratorFactory.getInstance().speak(de.detailedSpokenText()); - iLog("request detailed info",((de instanceof Node) ? "node " : "edge ")+de.getName()); + case INFO : + SwingUtilities.invokeLater(new Runnable(){ + public void run(){ + if((frame == null)||(frame.getActiveTab() == null)) + return; + CollectionModel<Node,Edge> collectionModel = frame.getActiveTab().getDiagram().getCollectionModel(); + DiagramElement de = Finder.findElementByHashcode(ID, collectionModel.getElements()); + if(de == null) + return; + SoundFactory.getInstance().stop(); + NarratorFactory.getInstance().speak(de.detailedSpokenText()); + iLog("request detailed info",((de instanceof Node) ? "node " : "edge ")+de.getName()); + } + }); break; case PLAY_SOUND : switch(HapticListenerCommand.Sound.fromInt(ID) ){ @@ -189,19 +205,50 @@ SoundFactory.getInstance().play(SoundEvent.MAGNET_ON); iLog("sticky mode on",""); break; - case HOOK_ON : - SoundFactory.getInstance().play(SoundEvent.HOOK_ON); - iLog("hook on",""); - break; case DRAG : SoundFactory.getInstance().play(SoundEvent.DRAG); break; } break; + case PICK_UP : + try { + SwingUtilities.invokeAndWait(new Runnable (){ + @Override + public void run(){ + if((frame == null)||(frame.getActiveTab() == null)) + return; + CollectionModel<Node,Edge> collectionModel = frame.getActiveTab().getDiagram().getCollectionModel(); + DiagramElement de = Finder.findElementByHashcode(ID, collectionModel.getElements()); + if(de == null) + return; + DiagramModelUpdater modelUpdater = frame.getActiveTab().getDiagram().getModelUpdater(); + if(!modelUpdater.getLock(de, + Lock.MOVE, + new DiagramEventActionSource(DiagramEventSource.HAPT, de instanceof Edge ? Command.Name.TRANSLATE_EDGE : Command.Name.TRANSLATE_NODE ,de.getId(),de.getName()))){ + iLog("Could not get lock on element for motion", DiagramElement.toLogString(de)); + NarratorFactory.getInstance().speak("Object is being moved by another user"); + return; + } + frame.hPickUp(de); + SoundFactory.getInstance().play(SoundEvent.HOOK_ON); + iLog("hook on",""); + } + }); + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(); + } + break; case ERROR : /* no synchronization necessary as the XMLManager looks after it*/ - SwingUtilities.invokeLater(frameBackupRunnable); - NarratorFactory.getInstance().speak("Haptic device crashed. " + - "Unsaved diagrams saved in backup directory"); + SwingUtilities.invokeLater(new Runnable(){ + @Override + public void run(){ + if((frame == null)||(frame.getActiveTab() == null)) + return; + frame.backupOpenDiagrams(); + } + }); + NarratorFactory.getInstance().speak(ResourceBundle.getBundle(EditorFrame.class.getName()).getString("speech.haptic_device_crashed")); break; } } @@ -211,7 +258,6 @@ } private Runnable unselectRunnable; - private Runnable frameBackupRunnable; private static String INTERACTION_LOG_SOURCE = "HAPTIC"; - private EditorFrame frame; + //private EditorFrame frame; }