Subversion Repositories svnkaklik

Rev

Go to most recent revision | Details | Last modification | View Log

Rev Author Line No. Line
157 kaklik 1
/*
2
    AVRcamVIEW: A PC application to test out the functionallity of the
3
     AVRcam real-time image processing engine.
4
    Copyright (C) 2004    Brent A. Taylor
5
 
6
    This program is free software; you can redistribute it and/or
7
    modify it under the terms of the GNU General Public
8
    License as published by the Free Software Foundation; either
9
    version 2 of the License, or (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 GNU
14
    General Public License for more details.
15
 
16
    You should have received a copy of the GNU General Public
17
    License along with this program; if not, write to the Free Software
18
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 
20
   For more information on the AVRcamVIEW, please contact:
21
 
22
   taylorba@comcast.net
23
 
24
   or go to www.jrobot.net for more details regarding the system.
25
*/
26
 
27
package avr.swing;
28
 
29
import java.io.*;
30
import java.util.prefs.*;
31
import javax.comm.*;
32
 
33
import java.awt.*;
34
import java.awt.event.*;
35
import java.lang.reflect.*;
36
import javax.swing.*;
37
import javax.swing.event.*;
38
 
39
import avr.connection.*;
40
import avr.connection.event.*;
41
import avr.device.event.*;
42
import avr.lang.*;
43
import avr.swing.filechooser.*;
44
import avr.util.*;
45
import java.beans.*;
46
 
47
public class JAVRCamFrame extends JFrame {
48
 
49
   public static void main(String[] args) {
50
      /*
51
      try {
52
         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
53
      } catch(Exception e) {
54
      }
55
      */
56
 
57
      try {
58
         if(args.length == 1) {
59
            if(args[0].equals("-r")) {
60
               AVRSystem.PREFS.clear();
61
            }
62
         }
63
      } catch(BackingStoreException bse) {
64
         System.out.println("Could not clear preferences: " + bse.getMessage());
65
      }
66
      SwingUtilities.invokeLater(new Runnable() {
67
         public void run() {
68
            JFrame frame = new JAVRCamFrame();
69
            frame.setVisible(true);
70
         }
71
      });
72
   }
73
 
74
   private static final String COLOR_MAP_BOUNDS_KEY  = "avr.colormap.bounds";
75
   private static final String COLOR_MAP_SHOWING_KEY = "avr.colormap.showing";
76
   private static final String COM_PORT_KEY          = "avr.com.port";
77
   private static final String COM_PARAMS_KEY        = "avr.com.params";
78
   private static final String DEVICE_CONNECTED_KEY  = "avr.device.connected";
79
   private static final String FRAME_BOUNDS_KEY      = "avr.frame.bounds";
80
   private static final String LOG_BOUNDS_KEY        = "avr.log.bounds";
81
   private static final String LOG_SHOWING_KEY       = "avr.log.showing";
82
   private static final String MESSAGE_SHOWING_KEY   = "avr.message.showing";
83
 
84
   private JFrame logF;
85
 
86
   private JSerialPanel serialP;
87
   private JRegisterPanel registersP;
88
   private JMessagePanel messageP;
89
   private JColorMapInterface colorMapP;
90
   private JFrame colorMapF;
91
 
92
   private JMenu windowM;
93
 
94
   private JDesktopPane desktop;
95
   private JTrackingInternalFrame trackingF;
96
 
97
   private CaptureInternalFrameHandler captureInternalFrameHandler;
98
 
99
   private AbstractButton viewLogB;
100
   private AbstractButton viewMessagesB;
101
   private AbstractButton viewColorMapB;
102
   private AbstractButton trackingB;
103
   private AbstractButton passiveTrackingB;
104
 
105
   private ProxyAction connectAction;
106
   private ProxyAction disconnectAction;
107
   private ProxyAction serialParamsAction;
108
   private ProxyAction setRegistersAction;
109
   private ProxyAction pingAction;
110
   private ProxyAction resetAction;
111
   private ProxyAction captureAction;
112
   private ProxyAction trackingAction;
113
   private ProxyAction passiveTrackingAction;
114
 
115
   private ProxyAction cascadeAction;
116
   private ProxyAction tileHorizontalAction;
117
   private ProxyAction tileVerticalAction;
118
   private ProxyAction resetAllAction;
119
   private ProxyAction closeAllAction;
120
 
121
   private ButtonGroup windowBG;
122
 
123
   public JAVRCamFrame() {
124
      super("AVRcamVIEW");
125
 
126
      createActions();
127
      windowBG = new ButtonGroup();
128
      captureInternalFrameHandler = new CaptureInternalFrameHandler();
129
 
130
//      ImageIcon icon = new ImageIcon(getClass().getClassLoader().getResource("avr/resource/AVRcam.gif"));
131
//      if(icon != null) {
132
//         this.setIconImage(icon.getImage());
133
//      }
134
 
135
      serialP = new JSerialPanel();
136
      registersP = new JRegisterPanel();
137
 
138
      messageP = new JMessagePanel();
139
 
140
      String classVersionString = System.getProperty("java.class.version","44.0");
141
      int classVersion = (int)(Double.parseDouble(classVersionString) * 10.0);
142
 
143
      // JDK 5.0 class version is 49.0.  Since the JNewColorMapPanel requires JDK 5.0
144
      // this will check to make sure that the JVM is 5.0 or better, Otherwise, use
145
      // the old color map.
146
      if(System.getProperty("avr.old.color.map") != null || classVersion < 490) {
147
         colorMapP = new JColorMapPanel(messageP);
148
      } else {
149
         try {
150
            // must load the class using reflection so that the 1.4 compiler does not try
151
            // to compile the JNewColorMapPanel class
152
            Constructor constructor = Class.forName("avr.swing.JNewColorMapPanel").getConstructor(new Class[] { JMessagePanel.class });
153
            colorMapP = (JColorMapInterface)constructor.newInstance(new Object[] {messageP});
154
//         colorMapP = new JNewColorMapPanel(messageP);
155
         } catch(Exception ex) {
156
            // we can't load the new color map, so default to the old one.
157
            colorMapP = new JColorMapPanel(messageP);
158
            ex.printStackTrace(System.err);
159
         }
160
      }
161
 
162
      messageP.addComponentListener(new MessagePanelHandler());
163
 
164
      Dimension screen = getToolkit().getScreenSize();
165
      Rectangle bounds = null;
166
 
167
      JLogApplet logA = new JLogApplet();
168
      logA.init(false);
169
      AVRSystem.LOG.addHandler(new LogHandler(logA.getTableModel(), AVRSystem.LOG.getLevel()));
170
 
171
      logF = logA.createFrame();
172
      bounds = getBounds(LOG_BOUNDS_KEY);
173
      if(bounds == null) {
174
         bounds = new Rectangle(0, 0, screen.width * 3 / 4, screen.height / 2);
175
      }
176
      logF.setBounds(bounds);
177
 
178
 
179
      desktop = new JDesktopPane();
180
      desktop.setBackground(new Color(0x005C5C));
181
//      desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
182
 
183
      desktop.addMouseListener(new PopupHandler());
184
 
185
      setJMenuBar(createMenuBar());
186
      getContentPane().add(createToolBar(), BorderLayout.NORTH);
187
      getContentPane().add(desktop, BorderLayout.CENTER);
188
      getContentPane().add(messageP, BorderLayout.EAST);
189
 
190
      bounds = getBounds(FRAME_BOUNDS_KEY);
191
      if(bounds == null) {
192
         bounds = new Rectangle(screen.width / 8, screen.height / 8,
193
                                 screen.width * 3 / 4, screen.height * 3 / 4);
194
      }
195
      setBounds(bounds);
196
 
197
      colorMapF = new JFrame("AVRcamVIEW - Color Map");
198
      colorMapF.addWindowListener(new ColorMapWindowHandler(colorMapF, viewColorMapB));
199
      colorMapF.getContentPane().add(colorMapP, BorderLayout.CENTER);
200
      colorMapF.pack();
201
      colorMapF.setResizable(false);
202
 
203
      bounds = getBounds(COLOR_MAP_BOUNDS_KEY);
204
      if(bounds == null) {
205
         Dimension dim = colorMapF.getSize();
206
         bounds = new Rectangle((screen.width - dim.width) / 2,
207
                                (screen.height - dim.height) / 2,
208
                                dim.width, dim.height);
209
      }
210
 
211
      colorMapF.setLocation(bounds.x, bounds.y);
212
      colorMapF.pack();
213
 
214
      addWindowListener(new WindowHandler(this));
215
      logF.addWindowListener(new LogWindowHandler(viewLogB));
216
 
217
      Action action = new ProxyAction(AVRSystem.DEVICE, "simulateNCK", "Simulate NCK");
218
      registerKeyStrokeAction(
219
         KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK),
220
         action);
221
 
222
      action = new ProxyAction(AVRSystem.DEVICE, "simulateACK", "Simulate ACK");
223
      registerKeyStrokeAction(
224
         KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK),
225
         action);
226
 
227
      resetAction = new ProxyAction(this, "reset", "Reset");
228
//         registerKeyStrokeAction(
229
//            KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_MASK),
230
//            resetAction);
231
 
232
      SwingUtilities.invokeLater(new Startup());
233
 
234
   }
235
 
236
   private void registerKeyStrokeAction(KeyStroke keyStroke, Action action) {
237
      // attach the action to the Ctrl+A key
238
      getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
239
                   .put(keyStroke, action.getValue(Action.NAME));
240
      getRootPane().getActionMap().put(action.getValue(Action.NAME), action);
241
   }
242
 
243
   private void createActions() {
244
      serialParamsAction = new ProxyAction(this, "showSerialDialog", "Configure Serial", 'S');
245
      setRegistersAction = new ProxyAction(this, "showRegisterDialog", "Set Registers", 'R');
246
 
247
      connectAction = new ProxyAction(this, "connect", "Connect", 'C');
248
      disconnectAction = new ProxyAction(this, "disconnect", "Disconnect", 'D');
249
 
250
      pingAction = new ProxyAction(this, "ping", "Ping", 'P');
251
      pingAction.setEnabled(false);
252
 
253
//      resetAction = new ProxyAction(this, "reset", "Reset", 'R');
254
 
255
      captureAction = new ProxyAction(this, "capture", "Capture", 'C');
256
      trackingAction = new ProxyAction(this, "tracking", "Enable Tracking", 'E');
257
 
258
      passiveTrackingAction = new ProxyAction(this, "passiveTracking", "Enable Passive Tracking", 'V');
259
 
260
      cascadeAction = new ProxyAction(this, "cascadeWindows", "Cascade", 'C');
261
      tileHorizontalAction = new ProxyAction(this, "tileHorizontal", "Tile Horizontal", 'H');
262
      tileVerticalAction = new ProxyAction(this, "tileVertical", "Tile Vertical", 'V');
263
      resetAllAction = new ProxyAction(this, "resetAllWindows", "Reset All", 'R');
264
      closeAllAction = new ProxyAction(this, "closeAllWindows", "Close All", 'L');
265
 
266
//      resetAction.setEnabled(false);
267
      setRegistersAction.setEnabled(false);
268
      captureAction.setEnabled(false);
269
      disconnectAction.setEnabled(false);
270
      trackingAction.setEnabled(false);
271
      passiveTrackingAction.setEnabled(false);
272
 
273
      trackingB = new JToggleButton(trackingAction);
274
      passiveTrackingB = new JToggleButton(passiveTrackingAction);
275
 
276
      serialParamsAction.setToolTipText("Modify the Serial Port Parameters");
277
      setRegistersAction.setToolTipText("Modify the AVRcam Register values");
278
      connectAction.setToolTipText("Open the Serial Connection to the AVRcam");
279
      disconnectAction.setToolTipText("Close the Serial Connection to the AVRcam");
280
      pingAction.setToolTipText("Send a Ping ccommand to the AVRcam");
281
      captureAction.setToolTipText("Capture a image from the AVRcam");
282
      trackingAction.setToolTipText("Command the AVRcam to start tracking");
283
      passiveTrackingAction.setToolTipText("Receive tracking packets from the AVRcam");
284
 
285
   }
286
 
287
   private JMenuBar createMenuBar() {
288
      JMenuBar menubar = new JMenuBar();
289
 
290
      JMenu fileM = new JMenu("File");
291
      JMenu viewM = new JMenu("View");
292
      JMenu deviceM = new JMenu("Device");
293
      JMenu helpM = new JMenu("Help");
294
 
295
      windowM = new JMenu("Window");
296
 
297
      fileM.setMnemonic('f');
298
      viewM.setMnemonic('v');
299
      deviceM.setMnemonic('d');
300
      windowM.setMnemonic('w');
301
      helpM.setMnemonic('h');
302
 
303
      fileM.add(new ProxyAction(this, "openBayer", "Open Bayer Image", 'B'));
304
      fileM.add(new ProxyAction(this, "openTracking", "Open Tracking Data", 'T'));
305
      fileM.addSeparator();
306
      fileM.add(serialParamsAction);
307
      fileM.add(setRegistersAction);
308
      fileM.addSeparator();
309
      fileM.add(new ProxyAction(this, "close", "Exit", 'X'));
310
 
311
      viewColorMapB = new JCheckBoxMenuItem(new ProxyAction(this, "viewColorMap", true, "Show Color Map", 'C'));
312
      viewM.add(viewColorMapB);
313
 
314
      viewMessagesB = new JCheckBoxMenuItem(new ProxyAction(this, "viewMessages", true, "Show Messages", 'M'));
315
      viewM.add(viewMessagesB);
316
 
317
      viewLogB = new JCheckBoxMenuItem(new ProxyAction(this, "viewLog", true, "Show Log", 'L'));
318
      viewM.add(viewLogB);
319
 
320
      deviceM.add(connectAction);
321
      deviceM.add(disconnectAction);
322
 
323
      windowM.add(cascadeAction);
324
      windowM.add(tileHorizontalAction);
325
      windowM.add(tileVerticalAction);
326
      windowM.add(resetAllAction);
327
      windowM.add(closeAllAction);
328
      windowM.addSeparator();
329
 
330
      helpM.add(new ProxyAction(this, "about", "About", 'A'));
331
 
332
      menubar.add(fileM);
333
      menubar.add(viewM);
334
      menubar.add(deviceM);
335
      menubar.add(windowM);
336
      menubar.add(helpM);
337
 
338
      return menubar;
339
   }
340
 
341
   private JToolBar createToolBar() {
342
      JToolBar toolbar = new JToolBar();
343
 
344
      toolbar.add(connectAction);
345
      toolbar.add(disconnectAction);
346
      toolbar.addSeparator();
347
      toolbar.add(serialParamsAction);
348
      toolbar.add(setRegistersAction);
349
      toolbar.addSeparator();
350
      toolbar.add(pingAction);
351
//      toolbar.add(resetAction);
352
      toolbar.add(captureAction);
353
      toolbar.add(trackingB);
354
      toolbar.add(passiveTrackingB);
355
 
356
      toolbar.setFloatable(false);
357
 
358
      return toolbar;
359
   }
360
 
361
   private static Rectangle getBounds(String key) {
362
 
363
      byte[] boundsArray = AVRSystem.PREFS.getByteArray(key, null);
364
      Rectangle bounds = null;
365
 
366
      if(boundsArray != null) {
367
 
368
         try {
369
            ObjectInputStream in = new ObjectInputStream(
370
               new ByteArrayInputStream(boundsArray));
371
 
372
            bounds = (Rectangle)in.readObject();
373
 
374
            in.close();
375
         } catch(ClassNotFoundException ex) {
376
         } catch(IOException ex) {
377
         }
378
      }
379
 
380
      return bounds;
381
 
382
   }
383
 
384
   protected JRootPane createRootPane() {
385
      // create a new JRootPane
386
      JRootPane rootPane = new JRootPane() {
387
 
388
         /**
389
          * Create a new Glass Pane Glass Pane that when visible it captures
390
          * all the mouse events, plays a "beep" when the mouse is clicked
391
          * when the Glass Pane is visible, and changes the mouse depending
392
          * on if the Glass Pane is visible or not.
393
          * @return The Glass Pane
394
          */
395
         protected Component createGlassPane() {
396
            JComponent c = new JPanel() {
397
 
398
               /**
399
                * Overridden to change the cursor to a busy cursor when visible
400
                * and a default cursor when not visible.
401
                * @param visible True to show the Glass Pane, false to not
402
                * show the Glass Pane.
403
                */
404
               public void setVisible(boolean visible) {
405
                  super.setVisible(visible);
406
                  if(visible) {
407
                     // this is possible if it this panel has not been added
408
                     // to a JRootPane yet
409
                     if(getRootPane() != null) {
410
                        // change the cursor to a wait/busy cursor (hour glass)
411
                        getRootPane().setCursor(
412
                           Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
413
                        AVRSystem.LOG.finest("Glass Pane SHOWING... ");
414
                     }
415
                  } else {
416
                     // this is possible if it this panel has not been added
417
                     // to a JRootPane yet
418
                     if(getRootPane() != null) {
419
                        // chage the cursor back to the default cursor
420
                        getRootPane().setCursor(Cursor.getDefaultCursor());
421
                        AVRSystem.LOG.finest("Glass Pane HIDDEN... ");
422
                     }
423
                  }
424
               }
425
            };
426
            c.setName(this.getName() + ".glassPane");
427
            c.setVisible(false);
428
            ((JPanel)c).setOpaque(false);
429
            // add a mouse listener to capture all the mouse events and play
430
            // a "beep" when the mouse is pressed.
431
            c.addMouseListener(new MouseAdapter() {
432
               public void mousePressed(MouseEvent me) {
433
                  Toolkit.getDefaultToolkit().beep();
434
               }
435
            });
436
            return c;
437
         }
438
      };
439
      rootPane.setOpaque(true);
440
      return rootPane;
441
   }
442
 
443
   public void openBayer() {
444
 
445
      javax.swing.filechooser.FileFilter[] filters = AVRSystem.FILE_CHOOSER.getChoosableFileFilters();
446
      for(int i = 0; i < filters.length; i++) {
447
         AVRSystem.FILE_CHOOSER.removeChoosableFileFilter(filters[i]);
448
      }
449
 
450
      AVRSystem.FILE_CHOOSER.addChoosableFileFilter(new LogFileFilter("Bayer Image File (*.byr)", ".byr"));
451
 
452
      int option = AVRSystem.FILE_CHOOSER.showOpenDialog(getRootPane());
453
      if(option == JFileChooser.APPROVE_OPTION) {
454
         JInternalFrame iFrame = new JCaptureInternalFrame(messageP, colorMapP, AVRSystem.FILE_CHOOSER.getSelectedFile());
455
         iFrame.pack();
456
         iFrame.setLocation(10, 10);
457
         desktop.add(iFrame);
458
         iFrame.setVisible(true);
459
      }
460
   }
461
 
462
   public void openTracking() {
463
 
464
      javax.swing.filechooser.FileFilter[] filters = AVRSystem.FILE_CHOOSER.getChoosableFileFilters();
465
      for(int i = 0; i < filters.length; i++) {
466
         AVRSystem.FILE_CHOOSER.removeChoosableFileFilter(filters[i]);
467
      }
468
 
469
      AVRSystem.FILE_CHOOSER.addChoosableFileFilter(new LogFileFilter("AVR Tracking File (*.trk)", ".trk"));
470
 
471
      int option = AVRSystem.FILE_CHOOSER.showOpenDialog(getRootPane());
472
      if(option == JFileChooser.APPROVE_OPTION) {
473
         try {
474
            JInternalFrame iFrame = new JTrackingInternalFrame(AVRSystem.FILE_CHOOSER.getSelectedFile());
475
            iFrame.pack();
476
            iFrame.setLocation(10, 10);
477
            desktop.add(iFrame);
478
            iFrame.setVisible(true);
479
         } catch(FileNotFoundException fnfe) {
480
            JOptionPane.showMessageDialog(getRootPane(), "File Not Found", fnfe.getMessage(), JOptionPane.ERROR_MESSAGE);
481
         } catch(IOException ioe) {
482
            JOptionPane.showMessageDialog(getRootPane(), "I/O Exception", ioe.getMessage(), JOptionPane.ERROR_MESSAGE);
483
         }
484
      }
485
   }
486
 
487
   public void showSerialDialog() {
488
      if(AVRSystem.DEVICE.getConnection() != null) {
489
         showSerialDialog(((SerialConnection)AVRSystem.DEVICE.getConnection()).getSerialParams());
490
      } else {
491
         showSerialDialog(null);
492
      }
493
   }
494
 
495
   public void showSerialDialog(SerialParams params) {
496
      int option = serialP.showDialog(this, params);
497
      if(option == JSerialPanel.OK_OPTION) {
498
         try {
499
            if(AVRSystem.DEVICE.isConnected()) {
500
               ((SerialConnection)AVRSystem.DEVICE.getConnection()).setSerialParams(serialP.getSerialParameters());
501
            }
502
            saveConnectionPrefs(null, serialP.getSerialParameters());
503
         } catch(UnsupportedCommOperationException ucoe) {
504
            AVRSystem.LOG.severe(ucoe.getMessage());
505
         }
506
      }
507
   }
508
 
509
   public void showRegisterDialog() {
510
      int option = registersP.showDialog(this);
511
      if(option == JRegisterPanel.OK_OPTION && registersP.getRegisters().size() > 0) {
512
 
513
         DataListener handler = null;
514
         try {
515
            handler = new SetRegistersHandler();
516
            AVRSystem.DEVICE.addDataListener(handler);
517
            getRootPane().getGlassPane().setVisible(true);
518
            AVRSystem.DEVICE.sendSetRegisters(registersP.getRegisters());
519
            messageP.append("Set Registers");
520
         } catch(IOException ioe) {
521
            AVRSystem.DEVICE.removeDataListener(handler);
522
            getRootPane().getGlassPane().setVisible(false);
523
            AVRSystem.LOG.severe(ioe.getMessage());
524
            messageP.append("Set Registers not sent");
525
         }
526
      }
527
   }
528
 
529
   public void close() {
530
 
531
      AVRSystem.PREFS.putBoolean(DEVICE_CONNECTED_KEY, AVRSystem.DEVICE.isConnected());
532
 
533
      if(AVRSystem.DEVICE.isConnected()) {
534
         saveConnectionPrefs((SerialConnection)AVRSystem.DEVICE.getConnection());
535
         disconnect();
536
      }
537
 
538
      AVRSystem.PREFS.putBoolean(LOG_SHOWING_KEY, logF.isVisible());
539
      AVRSystem.PREFS.putBoolean(MESSAGE_SHOWING_KEY, messageP.isVisible());
540
      AVRSystem.PREFS.putBoolean(COLOR_MAP_SHOWING_KEY, colorMapF.isVisible());
541
 
542
      saveBounds(FRAME_BOUNDS_KEY, getBounds());
543
      saveBounds(COLOR_MAP_BOUNDS_KEY, colorMapF.getBounds());
544
      saveBounds(LOG_BOUNDS_KEY, logF.getBounds());
545
 
546
      System.exit(0);
547
   }
548
 
549
   private static void saveConnectionPrefs(SerialConnection con) {
550
      saveConnectionPrefs(con.getComPort(), con.getSerialParams());
551
   }
552
 
553
   private static void saveConnectionPrefs(String comPort, SerialParams params) {
554
      if(comPort != null) {
555
         AVRSystem.PREFS.put(COM_PORT_KEY, comPort);
556
      }
557
      try {
558
         ByteArrayOutputStream out = new ByteArrayOutputStream();
559
         ObjectOutputStream oOut = new ObjectOutputStream(out);
560
 
561
         oOut.writeObject(params);
562
         oOut.close();
563
 
564
         byte[] serialParams = out.toByteArray();
565
 
566
         AVRSystem.PREFS.putByteArray(COM_PARAMS_KEY, serialParams);
567
      } catch(IOException ioe) {
568
         ioe.printStackTrace();
569
         AVRSystem.LOG.warning("Could not save serial parameters: " + ioe.getMessage());
570
      }
571
   }
572
 
573
   private static void saveBounds(String key, Rectangle rect) {
574
 
575
      try {
576
         ByteArrayOutputStream arrayOut = new ByteArrayOutputStream();
577
         ObjectOutputStream out = new ObjectOutputStream(arrayOut);
578
 
579
         out.writeObject(rect);
580
 
581
         out.close();
582
 
583
         AVRSystem.PREFS.putByteArray(key, arrayOut.toByteArray());
584
      } catch(IOException ex) {
585
      }
586
 
587
   }
588
 
589
   public void viewColorMap(ActionEvent ae) {
590
      colorMapF.setVisible(((AbstractButton)ae.getSource()).isSelected());
591
   }
592
 
593
   public void viewLog(ActionEvent ae) {
594
      logF.setVisible(((AbstractButton)ae.getSource()).isSelected());
595
   }
596
 
597
   public void viewMessages(ActionEvent ae) {
598
      messageP.setVisible(((AbstractButton)ae.getSource()).isSelected());
599
   }
600
 
601
   public void connect() {
602
      String[] ports = SerialConnection.getSerialPorts();
603
      if(ports.length > 0) {
604
         Object option = JOptionPane.showInputDialog(this, "Select a COM Port:", "Serial Port",
605
                                                  JOptionPane.QUESTION_MESSAGE,
606
                                                  null,
607
                                                  ports,
608
                                                  AVRSystem.PREFS.get(COM_PORT_KEY, ports[0]));
609
         if(option != null) {
610
            connect(option.toString(), serialP.getSerialParameters());
611
         }
612
      } else {
613
         JOptionPane.showMessageDialog(this, "No Serial Ports Available", "No Serial Ports",
614
                                       JOptionPane.ERROR_MESSAGE);
615
      }
616
   }
617
 
618
   public void connect(String comPort, SerialParams params) {
619
 
620
      SerialConnection con = new SerialConnection(comPort, params);
621
      AVRSystem.DEVICE.setConnection(con);
622
      AVRSystem.DEVICE.addConnectionListener(new ConnectionHandler());
623
      try {
624
         AVRSystem.DEVICE.connect();
625
      } catch(Exception ioe) {
626
         JOptionPane.showMessageDialog(getRootPane(),
627
                                       ioe.getMessage(),
628
                                       "Connect Error",
629
                                       JOptionPane.ERROR_MESSAGE);
630
         AVRSystem.LOG.severe(ioe.getMessage());
631
      }
632
   }
633
 
634
   public void disconnect() {
635
      AVRSystem.DEVICE.disconnect();
636
   }
637
 
638
   public void ping() {
639
      DataListener handler = null;
640
      try {
641
         handler = new PingHandler();
642
         AVRSystem.DEVICE.addDataListener(handler);
643
         getRootPane().getGlassPane().setVisible(true);
644
         AVRSystem.DEVICE.sendPing();
645
         messageP.append("Ping");
646
      } catch(IOException ioe) {
647
         AVRSystem.DEVICE.removeDataListener(handler);
648
         getRootPane().getGlassPane().setVisible(false);
649
         AVRSystem.LOG.severe(ioe.getMessage());
650
         messageP.append("Ping not sent: " + ioe.getMessage());
651
      }
652
   }
653
 
654
   public void reset() {
655
      DataListener handler = null;
656
      try {
657
         handler = new ResetHandler();
658
         AVRSystem.DEVICE.addDataListener(handler);
659
         getRootPane().getGlassPane().setVisible(true);
660
         AVRSystem.DEVICE.sendReset();
661
         messageP.append("Reset");
662
      } catch(IOException ioe) {
663
         AVRSystem.DEVICE.removeDataListener(handler);
664
         getRootPane().getGlassPane().setVisible(false);
665
         AVRSystem.LOG.severe(ioe.getMessage());
666
         messageP.append("Reset not sent");
667
      }
668
   }
669
 
670
   public void capture() {
671
      JCaptureInternalFrame captureF = new JCaptureInternalFrame(messageP, colorMapP);
672
      Insets insets = captureF.getInsets();
673
      captureF.pack();
674
      int frameCount = desktop.getAllFrames().length;
675
      captureF.setLocation(10 * frameCount, 10 * frameCount);
676
 
677
      captureF.addInternalFrameListener(captureInternalFrameHandler);
678
 
679
      desktop.add(captureF);
680
 
681
      captureF.setVisible(true);
682
 
683
   }
684
 
685
   public void tracking() {
686
      if(trackingB.isSelected()) {
687
         enableTracking();
688
      } else {
689
         disableTracking();
690
      }
691
   }
692
 
693
   private void enableTracking() {
694
      DataListener handler = new TrackingHandler();
695
      try {
696
         AVRSystem.DEVICE.addDataListener(handler);
697
         AVRSystem.DEVICE.sendEnableTracking();
698
         messageP.append("Enable Tracking");
699
      } catch(IOException ioe) {
700
         AVRSystem.DEVICE.removeDataListener(handler);
701
         AVRSystem.LOG.severe(ioe.getMessage());
702
         messageP.append("Enable Tracking not sent");
703
      }
704
   }
705
 
706
   private void disableTracking() {
707
      DataListener handler = new TrackingHandler();
708
      try {
709
         AVRSystem.DEVICE.addDataListener(handler);
710
         AVRSystem.DEVICE.sendDisableTracking();
711
         messageP.append("Disable Tracking");
712
      } catch(IOException ioe) {
713
         AVRSystem.DEVICE.removeDataListener(handler);
714
         AVRSystem.LOG.severe(ioe.getMessage());
715
         messageP.append("Disable Tracking not sent");
716
      }
717
   }
718
 
719
   public void passiveTracking() {
720
 
721
      if(passiveTrackingB.isSelected()) {
722
         passiveTrackingB.setText("Disable Passive Tracking");
723
         disconnectAction.setEnabled(false);
724
         serialParamsAction.setEnabled(false);
725
         setRegistersAction.setEnabled(false);
726
         pingAction.setEnabled(false);
727
         resetAction.setEnabled(false);
728
         captureAction.setEnabled(false);
729
         trackingAction.setEnabled(false);
730
 
731
         trackingF = new JTrackingInternalFrame();
732
         Insets insets = trackingF.getInsets();
733
         trackingF.pack();
734
         trackingF.setLocation(10, 10);
735
 
736
         desktop.add(trackingF);
737
 
738
         trackingF.setVisible(true);
739
         trackingF.startTracking();
740
         messageP.append("Enable Passive Tracking");
741
      } else {
742
         passiveTrackingB.setText("Enable Passive Tracking");
743
         disconnectAction.setEnabled(true);
744
         serialParamsAction.setEnabled(true);
745
         setRegistersAction.setEnabled(true);
746
         pingAction.setEnabled(true);
747
         resetAction.setEnabled(true);
748
         captureAction.setEnabled(true);
749
         trackingAction.setEnabled(true);
750
 
751
         trackingF.stopTracking();
752
         desktop.getDesktopManager().closeFrame(trackingF);
753
 
754
         messageP.append("Disable Passive Tracking");
755
      }
756
   }
757
 
758
   public void activateWindow(ActionEvent event) {
759
 
760
      JInternalFrame[] frames = desktop.getAllFrames();
761
      for(int i = 0; i < frames.length; i++) {
762
         if(frames[i].getTitle().equals(event.getActionCommand())) {
763
            desktop.getDesktopManager().activateFrame(frames[i]);
764
            desktop.setSelectedFrame(frames[i]);
765
            frames[i].toFront();
766
            try {
767
               frames[i].setSelected(true);
768
            } catch(PropertyVetoException ex) {
769
               ex.printStackTrace(System.out);
770
               AVRSystem.LOG.severe(ex.getMessage());
771
            }
772
            break;
773
         }
774
      }
775
 
776
   }
777
 
778
   public void cascadeWindows() {
779
 
780
      int x = 0;
781
      int y = 0;
782
 
783
      JInternalFrame[] frames = desktop.getAllFrames();
784
      for(int i = 0; i < frames.length; i++) {
785
         frames[i].setLocation(x, y);
786
         x += 30;
787
         y += 30;
788
      }
789
 
790
   }
791
 
792
   public void tileHorizontal() {
793
 
794
      JInternalFrame[] frames = desktop.getAllFrames();
795
 
796
      int frameCount = frames.length;
797
      int nrows = 1;
798
      int ncols = (frameCount + nrows - 1) / nrows;
799
 
800
      if(frameCount == 0) {
801
         return;
802
      }
803
 
804
      int w = desktop.getWidth();
805
      int h = desktop.getHeight();
806
      w = (w - (ncols - 1)) / ncols;
807
      h = (h - (nrows - 1)) / nrows;
808
 
809
      for(int c = 0, x = 0; c < ncols; c++, x += w) {
810
         for(int r = 0, y = 0; r < nrows; r++, y += h) {
811
            int i = r * ncols + c;
812
            if(i < frameCount) {
813
               frames[i].setBounds(x, y, w, h);
814
            }
815
         }
816
      }
817
 
818
   }
819
 
820
   public void tileVertical() {
821
 
822
      JInternalFrame[] frames = desktop.getAllFrames();
823
 
824
      int frameCount = frames.length;
825
      int ncols = 1;
826
      int nrows = (frameCount + ncols - 1) / ncols;;
827
 
828
      if(frameCount == 0) {
829
         return;
830
      }
831
 
832
      int w = desktop.getWidth();
833
      int h = desktop.getHeight();
834
      w = (w - (ncols - 1)) / ncols;
835
      h = (h - (nrows - 1)) / nrows;
836
 
837
      for(int c = 0, x = 0; c < ncols; c++, x += w) {
838
         for(int r = 0, y = 0; r < nrows; r++, y += h) {
839
            int i = r * ncols + c;
840
            if(i < frameCount) {
841
               frames[i].setBounds(x, y, w, h);
842
            }
843
         }
844
      }
845
 
846
   }
847
 
848
   public void resetAllWindows() {
849
 
850
      JInternalFrame[] frames = desktop.getAllFrames();
851
      for(int i = 0; i < frames.length; i++) {
852
         frames[i].pack();
853
      }
854
 
855
   }
856
 
857
   public void closeAllWindows() {
858
 
859
      JInternalFrame[] frames = desktop.getAllFrames();
860
      for(int i = 0; i < frames.length; i++) {
861
         if(frames[i] != trackingF) {
862
            desktop.getDesktopManager().closeFrame(frames[i]);
863
         }
864
      }
865
 
866
   }
867
 
868
   public void about() {
869
      new JAboutDialog(this, messageP).showDialog();
870
   }
871
 
872
   private final class SetRegistersHandler extends DataAdapter {
873
 
874
      public void ack() {
875
         AVRSystem.DEVICE.removeDataListener(this);
876
         getRootPane().getGlassPane().setVisible(false);
877
      }
878
 
879
      public void nck() {
880
         AVRSystem.DEVICE.removeDataListener(this);
881
         getRootPane().getGlassPane().setVisible(false);
882
         JOptionPane.showMessageDialog(JAVRCamFrame.this, "Set Register NCK Received", "NCK Received", JOptionPane.ERROR_MESSAGE);
883
      }
884
 
885
      public void responseTimerExpired() {
886
         AVRSystem.DEVICE.removeDataListener(this);
887
         getRootPane().getGlassPane().setVisible(false);
888
         JOptionPane.showMessageDialog(JAVRCamFrame.this, "Response Timer Expired", "Timer Expired", JOptionPane.ERROR_MESSAGE);
889
      }
890
 
891
   }
892
 
893
   private final class CaptureInternalFrameHandler implements InternalFrameListener {
894
      public void internalFrameOpened(InternalFrameEvent e) {
895
 
896
         String title = e.getInternalFrame().getTitle();
897
 
898
         JCheckBoxMenuItem windowMI = new JCheckBoxMenuItem(new ProxyAction(JAVRCamFrame.this, "activateWindow", true, title));
899
         windowMI.setActionCommand(title);
900
 
901
         windowBG.add(windowMI);
902
 
903
         windowMI.setSelected(true);
904
 
905
         windowM.add(windowMI);
906
      }
907
 
908
      public void internalFrameClosing(InternalFrameEvent e) {
909
      }
910
 
911
      public void internalFrameClosed(InternalFrameEvent e) {
912
 
913
         String text = null;
914
         String title = e.getInternalFrame().getTitle();
915
 
916
         for(int i = 0; i < windowM.getItemCount(); i++) {
917
            // need to check for the separator
918
            if(windowM.getItem(i) != null) {
919
               text = windowM.getItem(i).getText();
920
               if((text != null) && (title != null) &&
921
                  (text.equals(title))) {
922
                  windowM.remove(i);
923
                  break;
924
               }
925
            }
926
         }
927
      }
928
 
929
      public void internalFrameIconified(InternalFrameEvent e) {
930
      }
931
 
932
      public void internalFrameDeiconified(InternalFrameEvent e) {
933
      }
934
 
935
      public void internalFrameActivated(InternalFrameEvent e) {
936
      }
937
 
938
      public void internalFrameDeactivated(InternalFrameEvent e) {
939
      }
940
 
941
   }
942
 
943
   private final class PingHandler extends DataAdapter {
944
 
945
      public void ack() {
946
         AVRSystem.DEVICE.removeDataListener(this);
947
         getRootPane().getGlassPane().setVisible(false);
948
      }
949
 
950
      public void nck() {
951
         AVRSystem.DEVICE.removeDataListener(this);
952
         getRootPane().getGlassPane().setVisible(false);
953
         JOptionPane.showMessageDialog(JAVRCamFrame.this, "Ping NCK Received", "NCK Received", JOptionPane.ERROR_MESSAGE);
954
      }
955
 
956
      public void responseTimerExpired() {
957
         AVRSystem.DEVICE.removeDataListener(this);
958
         getRootPane().getGlassPane().setVisible(false);
959
         JOptionPane.showMessageDialog(JAVRCamFrame.this, "Response Timer Expired", "Timer Expired", JOptionPane.ERROR_MESSAGE);
960
      }
961
 
962
   }
963
 
964
   private final class ResetHandler extends DataAdapter {
965
 
966
      public void ack() {
967
         AVRSystem.DEVICE.removeDataListener(this);
968
         getRootPane().getGlassPane().setVisible(false);
969
      }
970
 
971
      public void nck() {
972
         AVRSystem.DEVICE.removeDataListener(this);
973
         getRootPane().getGlassPane().setVisible(false);
974
         JOptionPane.showMessageDialog(JAVRCamFrame.this, "Reset NCK Received", "NCK Received", JOptionPane.ERROR_MESSAGE);
975
      }
976
 
977
      public void responseTimerExpired() {
978
         AVRSystem.DEVICE.removeDataListener(this);
979
         getRootPane().getGlassPane().setVisible(false);
980
         JOptionPane.showMessageDialog(JAVRCamFrame.this, "Response Timer Expired", "Timer Expired", JOptionPane.ERROR_MESSAGE);
981
      }
982
 
983
   }
984
 
985
   private final class TrackingHandler extends DataAdapter {
986
      public void ack() {
987
         AVRSystem.DEVICE.removeDataListener(this);
988
         if(trackingB.isSelected()) {
989
            trackingB.setText("Disable Tracking");
990
            disconnectAction.setEnabled(false);
991
            serialParamsAction.setEnabled(false);
992
            setRegistersAction.setEnabled(false);
993
            pingAction.setEnabled(false);
994
            resetAction.setEnabled(false);
995
            captureAction.setEnabled(false);
996
            passiveTrackingAction.setEnabled(false);
997
 
998
            trackingF = new JTrackingInternalFrame();
999
            Insets insets = trackingF.getInsets();
1000
            trackingF.pack();
1001
            trackingF.setLocation(10, 10);
1002
 
1003
            desktop.add(trackingF);
1004
 
1005
            trackingF.setVisible(true);
1006
            trackingF.startTracking();
1007
 
1008
         } else {
1009
            trackingB.setText("Enable Tracking");
1010
            disconnectAction.setEnabled(true);
1011
            serialParamsAction.setEnabled(true);
1012
            setRegistersAction.setEnabled(true);
1013
            pingAction.setEnabled(true);
1014
            resetAction.setEnabled(true);
1015
            captureAction.setEnabled(true);
1016
            passiveTrackingAction.setEnabled(true);
1017
 
1018
            trackingF.stopTracking();
1019
            desktop.getDesktopManager().closeFrame(trackingF);
1020
         }
1021
      }
1022
 
1023
      public void nck() {
1024
         AVRSystem.DEVICE.removeDataListener(this);
1025
         if(trackingB.isSelected()) {
1026
            trackingB.setSelected(false);
1027
         } else {
1028
            trackingB.setSelected(true);
1029
         }
1030
         JOptionPane.showMessageDialog(JAVRCamFrame.this, "Disable Tracking NCK Received", "NCK Received", JOptionPane.ERROR_MESSAGE);
1031
      }
1032
 
1033
      public void responseTimerExpired() {
1034
         AVRSystem.DEVICE.removeDataListener(this);
1035
         getRootPane().getGlassPane().setVisible(false);
1036
         if(trackingB.isSelected()) {
1037
            trackingB.setSelected(false);
1038
         } else {
1039
            trackingB.setSelected(true);
1040
         }
1041
         JOptionPane.showMessageDialog(JAVRCamFrame.this, "Response Timer Expired", "Timer Expired", JOptionPane.ERROR_MESSAGE);
1042
 
1043
      }
1044
 
1045
   }
1046
 
1047
   private final class Startup implements Runnable {
1048
 
1049
      public void run() {
1050
 
1051
         boolean logVisible = AVRSystem.PREFS.getBoolean(LOG_SHOWING_KEY, false);
1052
         logF.setVisible(logVisible);
1053
         viewLogB.setSelected(logVisible);
1054
 
1055
         boolean messagesVisible = AVRSystem.PREFS.getBoolean(MESSAGE_SHOWING_KEY, true);
1056
         messageP.setVisible(messagesVisible);
1057
         viewMessagesB.setSelected(messagesVisible);
1058
 
1059
         boolean colorMapVisible = AVRSystem.PREFS.getBoolean(COLOR_MAP_SHOWING_KEY, false);
1060
         viewColorMapB.setSelected(colorMapVisible);
1061
         if(colorMapVisible) {
1062
            viewColorMap(new ActionEvent(viewColorMapB, ActionEvent.ACTION_PERFORMED, viewColorMapB.getText()));
1063
         }
1064
 
1065
         try {
1066
 
1067
            String comPort = AVRSystem.PREFS.get(COM_PORT_KEY, "COM1");
1068
            byte[] serialParams = AVRSystem.PREFS.getByteArray(COM_PARAMS_KEY, null);
1069
 
1070
            AVRSystem.LOG.config("Prefs Com Port: " + comPort);
1071
            SerialParams params = null;
1072
            if(serialParams != null) {
1073
               ObjectInputStream in = new ObjectInputStream(
1074
                                         new ByteArrayInputStream(serialParams));
1075
               params = (SerialParams)in.readObject();
1076
               in.close();
1077
 
1078
               AVRSystem.LOG.config("Prefs Com Params: " + params);
1079
 
1080
               if(AVRSystem.PREFS.getBoolean(DEVICE_CONNECTED_KEY, false)) {
1081
                  connect(comPort, params);
1082
               }
1083
            }
1084
         } catch(Exception e) {
1085
            e.printStackTrace();
1086
            AVRSystem.LOG.warning("Could not read serial params: " + e.getMessage());
1087
         }
1088
 
1089
      }
1090
 
1091
   }
1092
 
1093
   private final class ConnectionHandler extends DataAdapter implements ConnectionListener {
1094
 
1095
      public void connected(ConnectionEvent ce) {
1096
 
1097
         SerialConnection con = (SerialConnection)ce.getSource();
1098
 
1099
         saveConnectionPrefs(con.getComPort(), con.getSerialParams());
1100
 
1101
         try {
1102
            AVRSystem.DEVICE.addDataListener(this);
1103
            getRootPane().getGlassPane().setVisible(true);
1104
            AVRSystem.DEVICE.sendPing();
1105
            messageP.append("Ping");
1106
         } catch(IOException ioe) {
1107
            AVRSystem.DEVICE.removeDataListener(this);
1108
            getRootPane().getGlassPane().setVisible(false);
1109
            AVRSystem.LOG.severe(ioe.getMessage());
1110
            messageP.append("Ping not sent: " + ioe.getMessage());
1111
         }
1112
      }
1113
 
1114
      public void ack() {
1115
         AVRSystem.DEVICE.removeDataListener(this);
1116
         getRootPane().getGlassPane().setVisible(false);
1117
 
1118
         enableButtons(true);
1119
      }
1120
 
1121
      public void nck() {
1122
         AVRSystem.DEVICE.removeDataListener(this);
1123
         getRootPane().getGlassPane().setVisible(false);
1124
         enableButtons(true);
1125
 
1126
         JOptionPane.showMessageDialog(JAVRCamFrame.this, "Ping NCK Received", "NCK Received", JOptionPane.ERROR_MESSAGE);
1127
      }
1128
 
1129
      public void responseTimerExpired() {
1130
         AVRSystem.DEVICE.removeDataListener(this);
1131
         getRootPane().getGlassPane().setVisible(false);
1132
         disconnect();
1133
         JOptionPane.showMessageDialog(JAVRCamFrame.this, "Response Timer Expired: Please connect the serial port to the computer and make sure the AVRcam is powered.", "Timer Expired", JOptionPane.ERROR_MESSAGE);
1134
      }
1135
 
1136
      public void disconnected(ConnectionEvent ce) {
1137
         AVRSystem.DEVICE.removeConnectionListener(this);
1138
 
1139
         enableButtons(false);
1140
      }
1141
 
1142
      private void enableButtons(boolean enabled) {
1143
         connectAction.setEnabled(!enabled);
1144
         disconnectAction.setEnabled(enabled);
1145
         setRegistersAction.setEnabled(enabled);
1146
         pingAction.setEnabled(enabled);
1147
         resetAction.setEnabled(enabled);
1148
         captureAction.setEnabled(enabled);
1149
         trackingAction.setEnabled(enabled);
1150
         passiveTrackingAction.setEnabled(enabled);
1151
      }
1152
 
1153
   }
1154
 
1155
   private final class MessagePanelHandler extends ComponentAdapter {
1156
 
1157
      public void componentHidden(ComponentEvent e) {
1158
         viewMessagesB.setSelected(false);
1159
      }
1160
 
1161
   }
1162
 
1163
   private final class PopupHandler extends MouseAdapter {
1164
 
1165
      private JPopupMenu popup;
1166
 
1167
      public void mouseReleased(MouseEvent event) {
1168
         if(SwingUtilities.isRightMouseButton(event)) {
1169
            if(popup == null) {
1170
               popup = new JPopupMenu();
1171
               popup.add(cascadeAction);
1172
               popup.add(tileHorizontalAction);
1173
               popup.add(tileVerticalAction);
1174
               popup.add(resetAllAction);
1175
               popup.add(closeAllAction);
1176
               popup.setInvoker(event.getComponent());
1177
            }
1178
            popup.show(event.getComponent(), event.getX(), event.getY());
1179
         }
1180
      }
1181
 
1182
   }
1183
 
1184
   private final static class ColorMapWindowHandler extends WindowAdapter {
1185
 
1186
      private JFrame frame;
1187
      private AbstractButton viewB;
1188
 
1189
      public ColorMapWindowHandler(JFrame frame, AbstractButton viewB) {
1190
         this.frame = frame;
1191
         this.viewB = viewB;
1192
      }
1193
 
1194
      public void windowClosed(WindowEvent we) {
1195
         viewB.setSelected(false);
1196
      }
1197
 
1198
      public void windowClosing(WindowEvent we) {
1199
         frame.dispose();
1200
      }
1201
   }
1202
 
1203
   private final static class WindowHandler extends WindowAdapter {
1204
 
1205
      private JAVRCamFrame frame;
1206
 
1207
      public WindowHandler(JAVRCamFrame frame) {
1208
         this.frame = frame;
1209
      }
1210
 
1211
      public void windowClosing(WindowEvent we) {
1212
         frame.dispose();
1213
      }
1214
 
1215
      public void windowClosed(WindowEvent we) {
1216
         frame.close();
1217
      }
1218
 
1219
   }
1220
 
1221
   private final static class LogWindowHandler extends WindowAdapter {
1222
 
1223
      private AbstractButton button;
1224
 
1225
      public LogWindowHandler(AbstractButton button) {
1226
         this.button = button;
1227
      }
1228
 
1229
      public void windowClosing(WindowEvent we) {
1230
         button.setSelected(false);
1231
      }
1232
 
1233
   }
1234
 
1235
}