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