annotate src/uk/ac/qmul/eecs/depic/jhapticgui/examples/XYPad.java @ 1:46671fc7d649 tip

fixed "window" message bug and brought the message outside the haptic device monitor
author Fiore Martin <f.martin@qmul.ac.uk>
date Fri, 13 Mar 2015 13:02:16 +0000
parents 011caca7515a
children
rev   line source
f@0 1 /*
f@0 2 XYPad - a haptic xy-pad that uses the jHapticGUI library
f@0 3
f@0 4 Copyright (C) 2015 Queen Mary University of London (http://depic.eecs.qmul.ac.uk/)
f@0 5
f@0 6 This program is free software: you can redistribute it and/or modify
f@0 7 it under the terms of the GNU General Public License as published by
f@0 8 the Free Software Foundation, either version 3 of the License, or
f@0 9 (at your option) any later version.
f@0 10
f@0 11 This program is distributed in the hope that it will be useful,
f@0 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
f@0 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f@0 14 GNU General Public License for more details.
f@0 15
f@0 16 You should have received a copy of the GNU General Public License
f@0 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
f@0 18 */
f@0 19 package uk.ac.qmul.eecs.depic.jhapticgui.examples;
f@0 20
f@0 21 import java.awt.BorderLayout;
f@0 22 import java.awt.Color;
f@0 23 import java.awt.Dimension;
f@0 24 import java.awt.EventQueue;
f@0 25 import java.awt.event.ActionEvent;
f@0 26 import java.awt.event.ActionListener;
f@0 27 import java.io.InputStream;
f@0 28
f@0 29 import javax.swing.JButton;
f@0 30 import javax.swing.JFrame;
f@0 31 import javax.swing.JPanel;
f@0 32 import javax.swing.JScrollPane;
f@0 33 import javax.swing.JTextArea;
f@0 34 import javax.swing.SwingUtilities;
f@0 35 import javax.swing.UIManager;
f@0 36 import javax.swing.border.EmptyBorder;
f@0 37 import javax.swing.border.LineBorder;
f@0 38 import javax.swing.text.DefaultCaret;
f@0 39
f@0 40 import uk.ac.qmul.eecs.depic.jhapticgui.HapticDevice;
f@0 41 import uk.ac.qmul.eecs.depic.jhapticgui.HapticDeviceWinFactory;
f@0 42 import uk.ac.qmul.eecs.depic.jhapticgui.HapticListener;
f@0 43 import uk.ac.qmul.eecs.depic.jhapticgui.HapticsException;
f@0 44
f@0 45 /**
f@0 46 * A haptic XYPad.
f@0 47 *
f@0 48 * Provides two buttons for starting the haptic device and change
f@0 49 * the shape of the haptic pad, a text area to display notification messages
f@0 50 * (also from the haptic device) and an XYPanel displaying a cursor that
f@0 51 * can be manipulated using the haptic device.
f@0 52 *
f@0 53 *
f@0 54 * @author Fiore Martin
f@0 55 *
f@0 56 */
f@0 57 public class XYPad extends JFrame implements ActionListener{
f@0 58 private static final long serialVersionUID = 1L;
f@0 59 private XYPanel xyPanel;
f@0 60 private JButton startButton;
f@0 61 private JButton changeButton;
f@0 62 private HapticDevice hapticDevice;
f@0 63 private JTextArea textArea;
f@0 64
f@0 65 /**
f@0 66 * Launch the application.
f@0 67 */
f@0 68 public static void main(String[] args) {
f@0 69 try {
f@0 70 // Set System L&F
f@0 71 UIManager.setLookAndFeel(
f@0 72 UIManager.getSystemLookAndFeelClassName());
f@0 73 }catch(Exception e){}
f@0 74
f@0 75 EventQueue.invokeLater(new Runnable() {
f@0 76 public void run() {
f@0 77 try {
f@0 78 XYPad frame = new XYPad();
f@0 79 frame.setVisible(true);
f@0 80 } catch (Exception e) {
f@0 81 e.printStackTrace();
f@0 82 }
f@0 83 }
f@0 84 });
f@0 85 }
f@0 86
f@0 87 /**
f@0 88 * Creates the frame.
f@0 89 */
f@0 90 public XYPad() {
f@0 91 super("XY Pad");
f@0 92 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f@0 93 setBounds(100, 100, 450, 542);
f@0 94 JPanel contentPane = new JPanel();
f@0 95 contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
f@0 96 contentPane.setLayout(new BorderLayout(0, 0));
f@0 97 setContentPane(contentPane);
f@0 98
f@0 99 xyPanel = new XYPanel();
f@0 100 xyPanel.setBackground(Color.LIGHT_GRAY);
f@0 101 xyPanel.setBorder(new LineBorder(Color.GRAY));
f@0 102 xyPanel.setBackground(Color.BLACK);
f@0 103 contentPane.add(xyPanel, BorderLayout.CENTER);
f@0 104
f@0 105 JPanel buttonsPanel = new JPanel();
f@0 106 contentPane.add(buttonsPanel, BorderLayout.SOUTH);
f@0 107 buttonsPanel.setLayout(new BorderLayout(0, 0));
f@0 108
f@0 109 JPanel panel_1 = new JPanel();
f@0 110 buttonsPanel.add(panel_1, BorderLayout.SOUTH);
f@0 111 buttonsPanel.setPreferredSize(new Dimension(buttonsPanel.getWidth(), 100));
f@0 112
f@0 113 startButton = new JButton("Start Haptics");
f@0 114 panel_1.add(startButton);
f@0 115
f@0 116 changeButton = new JButton("Change to Square");
f@0 117 panel_1.add(changeButton);
f@0 118 changeButton.setEnabled(false);
f@0 119
f@0 120 textArea = new JTextArea();
f@0 121 /* this makes the scroll pane to always be at the bottom */
f@0 122 ((DefaultCaret) textArea.getCaret()).setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
f@0 123 textArea.setEditable(false);
f@0 124 buttonsPanel.add(new JScrollPane(textArea), BorderLayout.CENTER);
f@0 125
f@0 126 /* install listener to buttons */
f@0 127 startButton.addActionListener(this);
f@0 128 changeButton.addActionListener(this);
f@0 129 }
f@0 130
f@0 131 /**
f@0 132 * The action performed by the two buttons of this XYPad.
f@0 133 *
f@0 134 * The first button starts the haptic device, whereas the second button
f@0 135 * sends a message to the haptic device to change the shape of the haptic
f@0 136 * xy pad shape.
f@0 137 *
f@0 138 */
f@0 139 @Override
f@0 140 public void actionPerformed(ActionEvent evt) {
f@0 141 if(evt.getSource().equals(startButton)){
f@0 142
f@0 143 textArea.append("Starting haptic device...\n");
f@0 144
f@0 145 /**
f@0 146 * creates a new haptic listener that updates the xy panel upon receiving "position"
f@0 147 * messages. Moreover it prints on the text area when the haptic proxy touches
f@0 148 * and untouches the haptic xy pad
f@0 149 *
f@0 150 *
f@0 151 */
f@0 152 class XYHapticListener extends HapticListener {
f@0 153
f@0 154 @Override
f@0 155 public void messageReceived(String command, final String args, int id) {
f@0 156
f@0 157 switch(command){
f@0 158 case "position" : {
f@0 159
f@0 160 /* The coordinates are passed as a string representing two floats (x and y). *
f@0 161 * so the string needs to be unpacked and parsed. */
f@0 162 String[] coord = args.split(" ");
f@0 163 final float x = Float.parseFloat(coord[0]);
f@0 164 final float y = Float.parseFloat(coord[1]);
f@0 165
f@0 166 /* The haptic listener runs on its own thread, therefore changes *
f@0 167 * to the GUI must be queued for the event dispatching thread. */
f@0 168 SwingUtilities.invokeLater(new Runnable(){
f@0 169 @Override
f@0 170 public void run(){
f@0 171 xyPanel.setXY(x, y);
f@0 172 }
f@0 173 });
f@0 174 } break;
f@0 175
f@0 176 case "touch" : {
f@0 177 /* The haptic listener runs on its own thread, therefore changes *
f@0 178 * to the GUI must be queued for the event dispatching thread. */
f@0 179 SwingUtilities.invokeLater(new Runnable(){
f@0 180 @Override
f@0 181 public void run(){
f@0 182
f@0 183 /* uses message argument to discriminate between touch and untouch */
f@0 184 if("yes".equals(args)){
f@0 185 textArea.append("haptic xy touched\n");
f@0 186 }else if("no".equals(args)){
f@0 187 textArea.append("haptic xy untouched\n");
f@0 188 }
f@0 189 }
f@0 190 });
f@0 191 } break;
f@0 192
f@0 193 case HapticListener.WINDOW_MSG : {
f@0 194 SwingUtilities.invokeLater(new Runnable(){
f@0 195 @Override
f@0 196 public void run(){
f@0 197 requestFocus();
f@0 198 }
f@0 199 });
f@0 200 } break;
f@0 201 }
f@0 202 }
f@0 203 };
f@0 204
f@0 205 InputStream dll = this.getClass().getResourceAsStream("XYPad.dll");
f@0 206 try {
f@0 207 hapticDevice = new HapticDeviceWinFactory().getHapticDevice(dll, new XYHapticListener(), new Dimension (getWidth(), getWidth() ));
f@0 208
f@0 209 changeButton.setEnabled(true);
f@0 210 startButton.setEnabled(false);
f@0 211
f@0 212 textArea.append("haptic device started\n");
f@0 213 } catch (HapticsException e) {
f@0 214 e.printStackTrace();
f@0 215 textArea.append(e.getMessage());
f@0 216 }
f@0 217
f@0 218 }else if(evt.getSource().equals(changeButton)){
f@0 219 /* Changes the shape of the haptics object use message args to tell *
f@0 220 * the haptics which shape to display ID is left to 0 as there is *
f@0 221 * only one haptic shape and no need to refer to a specific haptic shape. */
f@0 222 if("Change to Square".equals(changeButton.getText())){
f@0 223 changeButton.setText("Change to Circle");
f@0 224
f@0 225 hapticDevice.sendMessage("change", "square", 0);
f@0 226
f@0 227 textArea.append("shape changed to square\n");
f@0 228 }else if("Change to Circle".equals(changeButton.getText())){ // change to circle
f@0 229 changeButton.setText("Change to Square");
f@0 230
f@0 231 hapticDevice.sendMessage("change", "circle", 0);
f@0 232
f@0 233 textArea.append("shape changed to circle\n");
f@0 234 }
f@0 235
f@0 236 }
f@0 237
f@0 238 }
f@0 239
f@0 240 }