annotate 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
rev   line source
fiore@0 1 /*
fiore@0 2 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
fiore@0 3
fiore@0 4 Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
fiore@0 5
fiore@0 6 This program is free software: you can redistribute it and/or modify
fiore@0 7 it under the terms of the GNU General Public License as published by
fiore@0 8 the Free Software Foundation, either version 3 of the License, or
fiore@0 9 (at your option) any later version.
fiore@0 10
fiore@0 11 This program is distributed in the hope that it will be useful,
fiore@0 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
fiore@0 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
fiore@0 14 GNU General Public License for more details.
fiore@0 15
fiore@0 16 You should have received a copy of the GNU General Public License
fiore@0 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
fiore@0 18 */
fiore@0 19 package uk.ac.qmul.eecs.ccmi.gui;
fiore@0 20
fiore@0 21 import java.awt.geom.Point2D;
fiore@0 22 import java.awt.geom.Rectangle2D;
fiore@0 23
fiore@0 24 import javax.swing.SwingUtilities;
fiore@0 25
fiore@0 26 import uk.ac.qmul.eecs.ccmi.diagrammodel.CollectionModel;
fiore@0 27 import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramElement;
fiore@0 28 import uk.ac.qmul.eecs.ccmi.haptics.HapticListener;
fiore@0 29 import uk.ac.qmul.eecs.ccmi.haptics.HapticListenerCommand;
fiore@0 30 import uk.ac.qmul.eecs.ccmi.sound.SoundFactory;
fiore@0 31 import uk.ac.qmul.eecs.ccmi.sound.SoundEvent;
fiore@0 32 import uk.ac.qmul.eecs.ccmi.speech.NarratorFactory;
fiore@0 33 import uk.ac.qmul.eecs.ccmi.utils.InteractionLog;
fiore@0 34
fiore@0 35 /**
fiore@0 36 *
fiore@0 37 * An instance of HapticListener for the diagram editor. By this class visual diagrams
fiore@0 38 * can be manipulated by an haptic device.
fiore@0 39 *
fiore@0 40 */
fiore@0 41 public class HapticKindle extends HapticListener {
fiore@0 42
fiore@0 43 public HapticKindle(){
fiore@0 44 super();
fiore@0 45 unselectRunnable = new Runnable(){
fiore@0 46 @Override
fiore@0 47 public void run(){
fiore@0 48 frame.selectHapticHighligh(null);
fiore@0 49 }
fiore@0 50 };
fiore@0 51 frameBackupRunnable = new Runnable(){
fiore@0 52 @Override
fiore@0 53 public void run(){
fiore@0 54 frame.backupOpenDiagrams();
fiore@0 55 }
fiore@0 56 };
fiore@0 57 }
fiore@0 58
fiore@0 59 public void setEditorFrame(EditorFrame frame){
fiore@0 60 this.frame = frame;
fiore@0 61 }
fiore@0 62
fiore@0 63 @Override
fiore@0 64 public void executeCommand(HapticListenerCommand cmd, int ID, final double x, final double y, final double startX, final double startY) {
fiore@0 65 if((frame == null)||(frame.getActiveTab() == null))
fiore@0 66 return;
fiore@0 67 CollectionModel<Node,Edge> collectionModel = frame.getActiveTab().getDiagram().getCollectionModel();
fiore@0 68 Object monitor = collectionModel.getMonitor();
fiore@0 69 DiagramElement de = null;
fiore@0 70 switch(cmd){
fiore@0 71 case PLAY_ELEMENT_SOUND :
fiore@0 72 synchronized(monitor){
fiore@0 73 de = Finder.findElementByHashcode(ID, collectionModel.getElements());
fiore@0 74 }
fiore@0 75 /* can be null if the tab has been switched or closed in the meantime */
fiore@0 76 if(de == null)
fiore@0 77 return;
fiore@0 78 SoundFactory.getInstance().play(de.getSound());
fiore@0 79 break;
fiore@0 80 case PLAY_ELEMENT_SPEECH :
fiore@0 81 synchronized(monitor){
fiore@0 82 de = Finder.findElementByHashcode(ID, collectionModel.getElements());
fiore@0 83 }
fiore@0 84 if(de == null)
fiore@0 85 return;
fiore@0 86 SoundFactory.getInstance().play(de.getSound());
fiore@0 87 NarratorFactory.getInstance().speak(de.getName());
fiore@0 88 iLog("touch",((de instanceof Node) ? "node " : "edge ")+de.getName());
fiore@0 89 break;
fiore@0 90 case SELECT :
fiore@0 91 synchronized(monitor){
fiore@0 92 de = Finder.findElementByHashcode(ID, collectionModel.getElements());
fiore@0 93 }
fiore@0 94 if(de == null)
fiore@0 95 return;
fiore@0 96 final DiagramElement selectedElement = de;
fiore@0 97 SwingUtilities.invokeLater(new Runnable(){
fiore@0 98 @Override
fiore@0 99 public void run(){
fiore@0 100 frame.selectHapticHighligh(selectedElement);
fiore@0 101 }
fiore@0 102 });
fiore@0 103 break;
fiore@0 104 case UNSELECT :
fiore@0 105 SwingUtilities.invokeLater(unselectRunnable);
fiore@0 106 break;
fiore@0 107 case MOVE :
fiore@0 108 DiagramPanel dPanel = frame.getActiveTab();
fiore@0 109 if(dPanel == null)
fiore@0 110 return;
fiore@0 111 synchronized(monitor){
fiore@0 112 de = Finder.findElementByHashcode(ID, collectionModel.getElements());
fiore@0 113 }
fiore@0 114 if(de == null)
fiore@0 115 return;
fiore@0 116 final DiagramElement moveSelectedElement = de;
fiore@0 117 final DiagramModelUpdater modelUpdater = dPanel.getDiagram().getModelUpdater();
fiore@0 118 if(!modelUpdater.getLock(moveSelectedElement, Lock.MOVE)){
fiore@0 119 iLog("Could not get lock on element for motion", DiagramElement.toLogString(moveSelectedElement));
fiore@0 120 NarratorFactory.getInstance().speak("Object is being moved by another user");
fiore@0 121 return;
fiore@0 122 }
fiore@0 123
fiore@0 124 try {
fiore@0 125 SwingUtilities.invokeAndWait(new Runnable(){
fiore@0 126 @Override
fiore@0 127 public void run(){
fiore@0 128 if(moveSelectedElement instanceof Node){
fiore@0 129 Node n = (Node)moveSelectedElement;
fiore@0 130 Rectangle2D bounds = n.getBounds();
fiore@0 131 Point2D.Double p = new Point2D.Double(bounds.getCenterX(),bounds.getCenterY());
fiore@0 132 double dx = x - p.getX();
fiore@0 133 double dy = y - p.getY();
fiore@0 134 modelUpdater.translate(n, p, dx, dy);
fiore@0 135 modelUpdater.stopMove(n);
fiore@0 136
fiore@0 137 StringBuilder builder = new StringBuilder();
fiore@0 138 builder.append(DiagramElement.toLogString(n)).append(" ").append(p.getX())
fiore@0 139 .append(' ').append(p.getY());
fiore@0 140 iLog("move node start",builder.toString());
fiore@0 141 builder = new StringBuilder();
fiore@0 142 builder.append(DiagramElement.toLogString(n)).append(' ')
fiore@0 143 .append(x).append(' ').append(y);
fiore@0 144
fiore@0 145 iLog("move node end",builder.toString());
fiore@0 146
fiore@0 147 }else{
fiore@0 148 Edge e = (Edge)moveSelectedElement;
fiore@0 149 modelUpdater.startMove(e, new Point2D.Double(startX,startY));
fiore@0 150 Point2D p = new Point2D.Double(x,y);
fiore@0 151 modelUpdater.bend(e, p);
fiore@0 152 modelUpdater.stopMove(e);
fiore@0 153
fiore@0 154 StringBuilder builder = new StringBuilder();
fiore@0 155 builder.append(DiagramElement.toLogString(e)).append(' ').append(startX)
fiore@0 156 .append(' ').append(startY);
fiore@0 157 iLog("bend edge start",builder.toString());
fiore@0 158 builder = new StringBuilder();
fiore@0 159 builder.append(DiagramElement.toLogString(e)).append(' ')
fiore@0 160 .append(x).append(' ').append(y);
fiore@0 161 iLog("bend edge end",builder.toString());
fiore@0 162
fiore@0 163 }
fiore@0 164 }
fiore@0 165 });
fiore@0 166 } catch (Exception e) {
fiore@0 167 throw new RuntimeException(e);
fiore@0 168 }
fiore@0 169 SoundFactory.getInstance().play(SoundEvent.HOOK_OFF);
fiore@0 170 modelUpdater.yieldLock(moveSelectedElement, Lock.MOVE);
fiore@0 171 break;
fiore@0 172 case INFO :
fiore@0 173 synchronized(monitor){
fiore@0 174 de = Finder.findElementByHashcode(ID, collectionModel.getElements());
fiore@0 175 }
fiore@0 176 if(de == null)
fiore@0 177 return;
fiore@0 178 SoundFactory.getInstance().stop();
fiore@0 179 NarratorFactory.getInstance().speak(de.detailedSpokenText());
fiore@0 180 iLog("request detailed info",((de instanceof Node) ? "node " : "edge ")+de.getName());
fiore@0 181 break;
fiore@0 182 case PLAY_SOUND :
fiore@0 183 switch(HapticListenerCommand.Sound.fromInt(ID) ){
fiore@0 184 case MAGNET_OFF :
fiore@0 185 SoundFactory.getInstance().play(SoundEvent.MAGNET_OFF);
fiore@0 186 iLog("sticky mode off","");
fiore@0 187 break;
fiore@0 188 case MAGNET_ON :
fiore@0 189 SoundFactory.getInstance().play(SoundEvent.MAGNET_ON);
fiore@0 190 iLog("sticky mode on","");
fiore@0 191 break;
fiore@0 192 case HOOK_ON :
fiore@0 193 SoundFactory.getInstance().play(SoundEvent.HOOK_ON);
fiore@0 194 iLog("hook on","");
fiore@0 195 break;
fiore@0 196 case DRAG : SoundFactory.getInstance().play(SoundEvent.DRAG);
fiore@0 197 break;
fiore@0 198 }
fiore@0 199 break;
fiore@0 200 case ERROR :
fiore@0 201 /* no synchronization necessary as the XMLManager looks after it*/
fiore@0 202 SwingUtilities.invokeLater(frameBackupRunnable);
fiore@0 203 NarratorFactory.getInstance().speak("Haptic device crashed. " +
fiore@0 204 "Unsaved diagrams saved in backup directory");
fiore@0 205 break;
fiore@0 206 }
fiore@0 207 }
fiore@0 208
fiore@0 209 private void iLog(String action, String args){
fiore@0 210 InteractionLog.log(INTERACTION_LOG_SOURCE,action,args);
fiore@0 211 }
fiore@0 212
fiore@0 213 private Runnable unselectRunnable;
fiore@0 214 private Runnable frameBackupRunnable;
fiore@0 215 private static String INTERACTION_LOG_SOURCE = "HAPTIC";
fiore@0 216 private EditorFrame frame;
fiore@0 217 }