Mercurial > hg > ccmieditor
diff java/src/uk/ac/qmul/eecs/ccmi/gui/HapticKindle.java @ 0:9418ab7b7f3f
Initial import
author | Fiore Martin <fiore@eecs.qmul.ac.uk> |
---|---|
date | Fri, 16 Dec 2011 17:35:51 +0000 |
parents | |
children | 9e67171477bc |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java/src/uk/ac/qmul/eecs/ccmi/gui/HapticKindle.java Fri Dec 16 17:35:51 2011 +0000 @@ -0,0 +1,217 @@ +/* + 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.gui; + +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import javax.swing.SwingUtilities; + +import uk.ac.qmul.eecs.ccmi.diagrammodel.CollectionModel; +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.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; + +/** + * + * An instance of HapticListener for the diagram editor. By this class visual diagrams + * can be manipulated by an haptic device. + * + */ +public class HapticKindle extends HapticListener { + + public HapticKindle(){ + super(); + unselectRunnable = new Runnable(){ + @Override + public void run(){ + frame.selectHapticHighligh(null); + } + }; + frameBackupRunnable = new Runnable(){ + @Override + public void run(){ + frame.backupOpenDiagrams(); + } + }; + } + + public void setEditorFrame(EditorFrame frame){ + this.frame = frame; + } + + @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; + 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()); + 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()); + 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); + } + }); + 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; + } + + try { + SwingUtilities.invokeAndWait(new Runnable(){ + @Override + public void run(){ + if(moveSelectedElement instanceof Node){ + Node n = (Node)moveSelectedElement; + 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); + + StringBuilder builder = new StringBuilder(); + builder.append(DiagramElement.toLogString(n)).append(" ").append(p.getX()) + .append(' ').append(p.getY()); + iLog("move node start",builder.toString()); + builder = new StringBuilder(); + builder.append(DiagramElement.toLogString(n)).append(' ') + .append(x).append(' ').append(y); + + iLog("move node end",builder.toString()); + + }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); + iLog("bend edge start",builder.toString()); + builder = new StringBuilder(); + builder.append(DiagramElement.toLogString(e)).append(' ') + .append(x).append(' ').append(y); + iLog("bend edge end",builder.toString()); + + } + } + }); + } 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()); + break; + case PLAY_SOUND : + switch(HapticListenerCommand.Sound.fromInt(ID) ){ + case MAGNET_OFF : + SoundFactory.getInstance().play(SoundEvent.MAGNET_OFF); + iLog("sticky mode off",""); + break; + case MAGNET_ON : + 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 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"); + break; + } + } + + private void iLog(String action, String args){ + InteractionLog.log(INTERACTION_LOG_SOURCE,action,args); + } + + private Runnable unselectRunnable; + private Runnable frameBackupRunnable; + private static String INTERACTION_LOG_SOURCE = "HAPTIC"; + private EditorFrame frame; +}