Mercurial > hg > haptic-xypad
view 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 |
line wrap: on
line source
/* XYPad - a haptic xy-pad that uses the jHapticGUI library Copyright (C) 2015 Queen Mary University of London (http://depic.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.depic.jhapticgui.examples; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.InputStream; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.border.EmptyBorder; import javax.swing.border.LineBorder; import javax.swing.text.DefaultCaret; import uk.ac.qmul.eecs.depic.jhapticgui.HapticDevice; import uk.ac.qmul.eecs.depic.jhapticgui.HapticDeviceWinFactory; import uk.ac.qmul.eecs.depic.jhapticgui.HapticListener; import uk.ac.qmul.eecs.depic.jhapticgui.HapticsException; /** * A haptic XYPad. * * Provides two buttons for starting the haptic device and change * the shape of the haptic pad, a text area to display notification messages * (also from the haptic device) and an XYPanel displaying a cursor that * can be manipulated using the haptic device. * * * @author Fiore Martin * */ public class XYPad extends JFrame implements ActionListener{ private static final long serialVersionUID = 1L; private XYPanel xyPanel; private JButton startButton; private JButton changeButton; private HapticDevice hapticDevice; private JTextArea textArea; /** * Launch the application. */ public static void main(String[] args) { try { // Set System L&F UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName()); }catch(Exception e){} EventQueue.invokeLater(new Runnable() { public void run() { try { XYPad frame = new XYPad(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Creates the frame. */ public XYPad() { super("XY Pad"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 450, 542); JPanel contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); contentPane.setLayout(new BorderLayout(0, 0)); setContentPane(contentPane); xyPanel = new XYPanel(); xyPanel.setBackground(Color.LIGHT_GRAY); xyPanel.setBorder(new LineBorder(Color.GRAY)); xyPanel.setBackground(Color.BLACK); contentPane.add(xyPanel, BorderLayout.CENTER); JPanel buttonsPanel = new JPanel(); contentPane.add(buttonsPanel, BorderLayout.SOUTH); buttonsPanel.setLayout(new BorderLayout(0, 0)); JPanel panel_1 = new JPanel(); buttonsPanel.add(panel_1, BorderLayout.SOUTH); buttonsPanel.setPreferredSize(new Dimension(buttonsPanel.getWidth(), 100)); startButton = new JButton("Start Haptics"); panel_1.add(startButton); changeButton = new JButton("Change to Square"); panel_1.add(changeButton); changeButton.setEnabled(false); textArea = new JTextArea(); /* this makes the scroll pane to always be at the bottom */ ((DefaultCaret) textArea.getCaret()).setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE); textArea.setEditable(false); buttonsPanel.add(new JScrollPane(textArea), BorderLayout.CENTER); /* install listener to buttons */ startButton.addActionListener(this); changeButton.addActionListener(this); } /** * The action performed by the two buttons of this XYPad. * * The first button starts the haptic device, whereas the second button * sends a message to the haptic device to change the shape of the haptic * xy pad shape. * */ @Override public void actionPerformed(ActionEvent evt) { if(evt.getSource().equals(startButton)){ textArea.append("Starting haptic device...\n"); /** * creates a new haptic listener that updates the xy panel upon receiving "position" * messages. Moreover it prints on the text area when the haptic proxy touches * and untouches the haptic xy pad * * */ class XYHapticListener extends HapticListener { @Override public void messageReceived(String command, final String args, int id) { switch(command){ case "position" : { /* The coordinates are passed as a string representing two floats (x and y). * * so the string needs to be unpacked and parsed. */ String[] coord = args.split(" "); final float x = Float.parseFloat(coord[0]); final float y = Float.parseFloat(coord[1]); /* The haptic listener runs on its own thread, therefore changes * * to the GUI must be queued for the event dispatching thread. */ SwingUtilities.invokeLater(new Runnable(){ @Override public void run(){ xyPanel.setXY(x, y); } }); } break; case "touch" : { /* The haptic listener runs on its own thread, therefore changes * * to the GUI must be queued for the event dispatching thread. */ SwingUtilities.invokeLater(new Runnable(){ @Override public void run(){ /* uses message argument to discriminate between touch and untouch */ if("yes".equals(args)){ textArea.append("haptic xy touched\n"); }else if("no".equals(args)){ textArea.append("haptic xy untouched\n"); } } }); } break; case HapticListener.WINDOW_MSG : { SwingUtilities.invokeLater(new Runnable(){ @Override public void run(){ requestFocus(); } }); } break; } } }; InputStream dll = this.getClass().getResourceAsStream("XYPad.dll"); try { hapticDevice = new HapticDeviceWinFactory().getHapticDevice(dll, new XYHapticListener(), new Dimension (getWidth(), getWidth() )); changeButton.setEnabled(true); startButton.setEnabled(false); textArea.append("haptic device started\n"); } catch (HapticsException e) { e.printStackTrace(); textArea.append(e.getMessage()); } }else if(evt.getSource().equals(changeButton)){ /* Changes the shape of the haptics object use message args to tell * * the haptics which shape to display ID is left to 0 as there is * * only one haptic shape and no need to refer to a specific haptic shape. */ if("Change to Square".equals(changeButton.getText())){ changeButton.setText("Change to Circle"); hapticDevice.sendMessage("change", "square", 0); textArea.append("shape changed to square\n"); }else if("Change to Circle".equals(changeButton.getText())){ // change to circle changeButton.setText("Change to Square"); hapticDevice.sendMessage("change", "circle", 0); textArea.append("shape changed to circle\n"); } } } }