Subversion Repositories svn.mios

Rev

Rev 753 | Rev 808 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
628 adamjking 1
/*
2
 * @(#)HexFileUploadGUI.java    beta8   2006/04/23
3
 *
4
 * Copyright (C) 2008   Adam King (adamjking@optusnet.com.au)
5
 *
6
 * This application 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 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This application 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 application; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
 
21
package org.midibox.mios.gui;
22
 
23
import java.awt.BorderLayout;
24
import java.awt.Color;
25
import java.awt.Component;
26
import java.awt.Dimension;
27
import java.awt.FlowLayout;
28
import java.awt.GridBagConstraints;
29
import java.awt.GridBagLayout;
30
import java.awt.Insets;
31
import java.awt.event.ActionEvent;
32
import java.awt.event.ActionListener;
33
import java.io.File;
753 adamjking 34
import java.util.Iterator;
628 adamjking 35
import java.util.Observable;
36
import java.util.Observer;
753 adamjking 37
import java.util.Vector;
628 adamjking 38
 
39
import javax.swing.BorderFactory;
40
import javax.swing.Box;
41
import javax.swing.BoxLayout;
42
import javax.swing.ButtonGroup;
43
import javax.swing.JButton;
44
import javax.swing.JCheckBox;
753 adamjking 45
import javax.swing.JComponent;
628 adamjking 46
import javax.swing.JFileChooser;
47
import javax.swing.JFormattedTextField;
48
import javax.swing.JLabel;
753 adamjking 49
import javax.swing.JMenuItem;
628 adamjking 50
import javax.swing.JOptionPane;
51
import javax.swing.JPanel;
753 adamjking 52
import javax.swing.JPopupMenu;
628 adamjking 53
import javax.swing.JRadioButton;
54
import javax.swing.JScrollPane;
55
import javax.swing.JSpinner;
56
import javax.swing.JTextField;
57
import javax.swing.JTextPane;
58
import javax.swing.SpinnerNumberModel;
59
import javax.swing.event.ChangeEvent;
60
import javax.swing.event.ChangeListener;
753 adamjking 61
import javax.swing.event.PopupMenuEvent;
62
import javax.swing.event.PopupMenuListener;
628 adamjking 63
import javax.swing.text.Style;
64
import javax.swing.text.StyleConstants;
65
import javax.swing.text.StyleContext;
66
import javax.swing.text.StyledDocument;
67
 
68
import org.midibox.mios.HexFileUpload;
69
import org.midibox.utils.gui.HexFormatterFactory;
70
import org.midibox.utils.gui.ImageLoader;
71
import org.midibox.utils.gui.SimpleFileChooserFilter;
753 adamjking 72
import org.midibox.utils.gui.SplitButton;
628 adamjking 73
 
74
public class HexFileUploadGUI extends JPanel implements ActionListener,
75
        ChangeListener, Observer {
76
 
753 adamjking 77
    private JPopupMenu MRUPopupMenu;
78
 
79
    private SplitButton openMRUButton;
80
 
81
    private static int maxMRU = 10;
82
 
628 adamjking 83
    private static String currentDirectory = "";
753 adamjking 84
 
85
    private static Vector MRU = new Vector();
628 adamjking 86
 
87
    private static JFileChooser fc = null;
88
 
89
    private HexFileUpload hexFileUpload;
90
 
91
    // GUI components
92
 
93
    private JButton browseButton;
94
 
95
    private JTextField fileName;
96
 
97
    private JButton startButton;
98
 
99
    private JButton stopButton;
100
 
101
    private JButton queryButton;
102
 
103
    private JTextPane progressMessageTextArea;
104
 
105
    private JLabel deviceIDLabel;
106
 
107
    private JSpinner deviceIDSpinner;
108
 
109
    private JRadioButton smartModeButton;
110
 
111
    private JRadioButton dumbModeButton;
112
 
113
    private ButtonGroup buttonGroup;
114
 
115
    private JCheckBox waitForUploadRequestCheck;
116
 
721 adamjking 117
    private JCheckBox MIOS32Check;
628 adamjking 118
 
119
    private JLabel delayTimeLabel;
120
 
121
    private JSpinner delayTimeSpinner;
122
 
123
    public HexFileUploadGUI(HexFileUpload hexUploadTask) {
124
        super(new BorderLayout());
125
 
126
        this.hexFileUpload = hexUploadTask;
127
        hexUploadTask.addObserver(this);
128
 
753 adamjking 129
        Insets insets = new Insets(2, 2, 2, 2);
130
 
628 adamjking 131
        browseButton = new JButton("Hex File", ImageLoader
132
                .getImageIcon("open.png"));
133
        browseButton.setActionCommand("browse");
134
        browseButton.addActionListener(this);
753 adamjking 135
        browseButton.setMargin(insets);
136
        browseButton.setToolTipText("Open Hex File");
137
 
628 adamjking 138
 
139
        fileName = new JTextField();
140
        fileName.setEditable(false);
738 adamjking 141
 
732 adamjking 142
        File file = hexFileUpload.getFile();
738 adamjking 143
 
732 adamjking 144
        if (file != null) {
738 adamjking 145
 
732 adamjking 146
            fileName.setText(file.getPath());
147
        }
628 adamjking 148
 
149
        startButton = new JButton("Start");
150
        startButton.setActionCommand("start");
151
        startButton.addActionListener(this);
152
        startButton.setEnabled(false);
153
 
154
        stopButton = new JButton("Stop");
155
        stopButton.addActionListener(this);
156
        stopButton.setActionCommand("stop");
157
 
158
        queryButton = new JButton("Query");
159
        queryButton.addActionListener(this);
160
        queryButton.setActionCommand("query");
161
        queryButton.setEnabled(false);
162
 
163
        startButton.setAlignmentX(Component.LEFT_ALIGNMENT);
164
        stopButton.setAlignmentX(Component.LEFT_ALIGNMENT);
165
        queryButton.setAlignmentX(Component.LEFT_ALIGNMENT);
166
 
167
        JPanel fileButtonsPanel = new JPanel(new BorderLayout(2, 0));
753 adamjking 168
 
169
        MRUPopupMenu = new JPopupMenu();
170
        MRUPopupMenu.addPopupMenuListener(new PopupMenuListener() {
171
 
172
            public void popupMenuCanceled(PopupMenuEvent e) {
173
 
174
            }
175
 
176
            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
177
 
178
            }
179
 
180
            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
181
 
182
                HexFileUploadGUI.this.buildMRUMenu(MRUPopupMenu);
183
 
184
            }
185
        });
186
 
187
        openMRUButton = new SplitButton(browseButton, MRUPopupMenu);
188
        openMRUButton.setRollover(true);
189
 
190
        fileButtonsPanel.add(openMRUButton, BorderLayout.WEST);
628 adamjking 191
        fileButtonsPanel.add(fileName, BorderLayout.CENTER);
192
        fileButtonsPanel.setBorder(BorderFactory.createEmptyBorder(7, 7, 5, 7));
193
 
194
        JPanel controlButtonsPanel = new JPanel();
195
        controlButtonsPanel.setLayout(new BoxLayout(controlButtonsPanel,
196
                BoxLayout.LINE_AXIS));
197
        controlButtonsPanel.add(startButton);
198
        controlButtonsPanel.add(Box.createRigidArea(new Dimension(15, 0)));
199
        controlButtonsPanel.add(stopButton);
200
        controlButtonsPanel.add(Box.createHorizontalGlue());
201
        controlButtonsPanel.add(queryButton);
202
        controlButtonsPanel.add(Box.createHorizontalGlue());
203
        controlButtonsPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5,
204
                5));
205
 
206
        JPanel progressMessagePanel = new JPanel();
207
        progressMessagePanel.setLayout(new BoxLayout(progressMessagePanel,
208
                BoxLayout.PAGE_AXIS));
209
 
210
        progressMessageTextArea = new JTextPane();
211
        progressMessageTextArea.setBackground(Color.WHITE);
212
 
213
        StyledDocument doc = progressMessageTextArea.getStyledDocument();
214
 
215
        Style def = StyleContext.getDefaultStyleContext().getStyle(
216
                StyleContext.DEFAULT_STYLE);
217
 
218
        Style regular = doc.addStyle("regular", def);
219
        StyleConstants.setFontFamily(def, "Monospaced");
220
 
221
        Style s = doc.addStyle("ack", regular);
222
        StyleConstants.setForeground(s, new Color(0, 150, 50));
223
 
224
        s = doc.addStyle("error", regular);
225
        StyleConstants.setForeground(s, new Color(150, 0, 50));
226
 
227
        progressMessageTextArea.setEditable(false);
228
        JScrollPane progressMessageTextAreaScrollPane = new JScrollPane(
229
                progressMessageTextArea);
230
        progressMessageTextAreaScrollPane
231
                .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
232
 
233
        // Make preferred width smaller than the other panel's minimum width.
234
        progressMessageTextAreaScrollPane.setPreferredSize(new Dimension(300,
235
                100));
236
 
237
        progressMessagePanel.add(progressMessageTextAreaScrollPane);
238
        progressMessagePanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5,
239
                5));
240
 
241
        JPanel controlPanel = new JPanel();
242
        controlPanel
243
                .setLayout(new BoxLayout(controlPanel, BoxLayout.PAGE_AXIS));
244
        controlPanel.add(controlButtonsPanel);
245
        controlPanel.add(progressMessagePanel);
246
 
247
        controlPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory
248
                .createEmptyBorder(5, 5, 5, 5), BorderFactory
249
                .createTitledBorder("Upload Control")));
250
 
251
        JPanel protocolPanel = new JPanel();
252
 
253
        protocolPanel.setBorder(BorderFactory.createCompoundBorder(
254
                BorderFactory.createEmptyBorder(5, 5, 5, 5), BorderFactory
255
                        .createTitledBorder("Upload Options")));
256
 
257
        protocolPanel.setLayout(new GridBagLayout());
258
 
259
        GridBagConstraints gbc = new GridBagConstraints();
260
        gbc.gridx = 0;
261
        gbc.gridy = 0;
262
        gbc.gridwidth = 1;
263
        gbc.gridheight = 1;
264
        gbc.anchor = GridBagConstraints.WEST;
265
        gbc.insets = new Insets(2, 2, 2, 2);
266
 
267
        deviceIDLabel = new JLabel("Device ID:");
268
        protocolPanel.add(deviceIDLabel, gbc);
269
        gbc.gridx++;
270
 
271
        deviceIDSpinner = new JSpinner(new SpinnerNumberModel(hexFileUpload
272
                .getDeviceID(), 0, 127, 1));
273
        deviceIDSpinner.addChangeListener(this);
274
        JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) deviceIDSpinner
275
                .getEditor();
276
        JFormattedTextField tf = editor.getTextField();
277
        tf.setFormatterFactory(new HexFormatterFactory());
278
        protocolPanel.add(deviceIDSpinner, gbc);
279
        gbc.gridx++;
280
 
281
        gbc.insets = new Insets(2, 15, 2, 2);
282
 
721 adamjking 283
        MIOS32Check = new JCheckBox("MIOS32", hexFileUpload.isMIOS32Mode());
628 adamjking 284
        MIOS32Check.addActionListener(this);
285
        protocolPanel.add(MIOS32Check, gbc);
286
 
287
        gbc.gridx = 0;
288
        gbc.gridy++;
289
 
290
        gbc.gridwidth = 4;
291
        waitForUploadRequestCheck = new JCheckBox(
292
                "Wait for upload request before starting upload", hexFileUpload
293
                        .isWaitForUploadRequest());
294
        waitForUploadRequestCheck.addActionListener(this);
295
        protocolPanel.add(waitForUploadRequestCheck, gbc);
296
        gbc.gridy++;
297
 
298
        smartModeButton = new JRadioButton(
299
                "Smart Mode - Use feedback from core", hexFileUpload
300
                        .getUploadMode() == HexFileUpload.SMART_MODE);
301
        smartModeButton.addActionListener(this);
302
        protocolPanel.add(smartModeButton, gbc);
303
        gbc.gridy++;
304
 
305
        dumbModeButton = new JRadioButton(
306
                "Manual Mode - Don't use feedback from core", hexFileUpload
307
                        .getUploadMode() == HexFileUpload.DUMB_MODE);
308
        dumbModeButton.addActionListener(this);
309
        protocolPanel.add(dumbModeButton, gbc);
310
        gbc.gridy++;
311
 
312
        buttonGroup = new ButtonGroup();
313
        buttonGroup.add(dumbModeButton);
314
        buttonGroup.add(smartModeButton);
315
 
316
        gbc.insets = new Insets(2, 15, 2, 2);
317
 
318
        JPanel timePanel = new JPanel(new FlowLayout(0, 5, 0));
319
 
320
        delayTimeLabel = new JLabel("Delay between SysEx messages (ms):");
321
        timePanel.add(delayTimeLabel);
322
 
323
        delayTimeSpinner = new JSpinner(new SpinnerNumberModel(hexFileUpload
324
                .getDelayTime(), 10, 2000, 1));
325
        delayTimeSpinner.addChangeListener(this);
326
        timePanel.add(delayTimeSpinner);
327
 
328
        protocolPanel.add(timePanel, gbc);
329
 
330
        gbc.gridy++;
331
 
332
        gbc.weighty = 1.0;
333
        protocolPanel.add(new JPanel(), gbc);
334
 
335
        add(fileButtonsPanel, BorderLayout.PAGE_START);
336
        add(controlPanel, BorderLayout.CENTER);
337
        add(protocolPanel, BorderLayout.EAST);
338
 
339
        updateUploadControls();
340
    }
753 adamjking 341
 
342
    private void buildMRUMenu(JComponent menu) {
628 adamjking 343
 
753 adamjking 344
        menu.removeAll();
345
 
346
        Iterator it = MRU.iterator();
347
 
348
        while (it.hasNext()) {
349
 
350
            final JMenuItem menuItem = new JMenuItem((String) it.next());
351
 
352
            menuItem.addActionListener(new ActionListener() {
353
 
354
                public void actionPerformed(ActionEvent ae) {
355
 
356
                    File file = new File(menuItem.getText());
357
 
358
                    openHexFile(file);
359
                }
360
            });
361
 
362
            menu.add(menuItem, 0);
363
        }
364
    }
365
 
366
    public static void saveMRU(String file) {
367
 
368
        MRU.remove(file);
369
 
370
        MRU.add(file);
371
 
372
        for (int i = MRU.size() - maxMRU; i > 0; i--) {
373
 
374
            MRU.removeElementAt(i - 1);
375
        }
376
    }
377
 
628 adamjking 378
    public static String getCurrentDirectory() {
379
        return currentDirectory;
380
    }
381
 
382
    public static void setCurrentDirectory(String currentDirectory) {
383
        HexFileUploadGUI.currentDirectory = currentDirectory;
384
    }
385
 
386
    public HexFileUpload getHexFileUpload() {
387
        return hexFileUpload;
388
    }
389
 
753 adamjking 390
    protected void openHexFile() {
628 adamjking 391
 
392
        if (fc == null) {
393
            fc = new JFileChooser(currentDirectory);
394
            SimpleFileChooserFilter fileFilter = new SimpleFileChooserFilter(
395
                    "Hex files", "hex", "Compliled Hex file");
396
            fc.addChoosableFileFilter(fileFilter);
397
            fc.setAcceptAllFileFilterUsed(false);
398
        }
399
 
400
        File noFile = new File("");
401
        File noFiles[] = { noFile };
402
        fc.setSelectedFile(noFile);
403
        fc.setSelectedFiles(noFiles);
404
 
405
        int nRetVal = fc.showOpenDialog(this);
406
 
407
        if (nRetVal == JFileChooser.APPROVE_OPTION) {
408
            File file = fc.getSelectedFile();
753 adamjking 409
 
410
            openHexFile(file);
411
 
628 adamjking 412
            currentDirectory = fc.getCurrentDirectory().toString();
413
        }
414
    }
753 adamjking 415
 
416
    protected void openHexFile(File file) {
417
 
418
        if (file.exists()) {
419
 
420
            hexFileUpload.setFile(file);
421
 
422
            saveMRU(file.getPath());
423
 
424
        } else {
425
            JOptionPane.showMessageDialog(this,
426
                    "Hex file no longer exists",
427
                    "File does not exist", JOptionPane.ERROR_MESSAGE);
428
        }
429
    }
430
 
431
    public static Vector getMRU() {
432
        return MRU;
433
    }
628 adamjking 434
 
435
    public void updateUploadControls() {
436
 
437
        boolean bUploading = (!hexFileUpload.isCancelled() && !hexFileUpload
438
                .isDone());
439
 
440
        deviceIDLabel.setEnabled(!bUploading);
441
        deviceIDSpinner.setEnabled(!bUploading);
442
 
443
        MIOS32Check.setEnabled(!bUploading);
444
 
721 adamjking 445
        if (hexFileUpload.isMIOS32Mode()) {
628 adamjking 446
            smartModeButton.setEnabled(false);
447
            dumbModeButton.setEnabled(false);
448
            waitForUploadRequestCheck.setEnabled(false);
449
            delayTimeLabel.setEnabled(false);
450
            delayTimeSpinner.setEnabled(false);
451
        } else {
452
            smartModeButton.setEnabled(!bUploading);
453
            dumbModeButton.setEnabled(!bUploading);
454
 
455
            waitForUploadRequestCheck.setEnabled(!bUploading);
456
 
457
            delayTimeLabel
458
                    .setEnabled(!bUploading
459
                            && hexFileUpload.getUploadMode() == HexFileUpload.DUMB_MODE);
460
 
461
            delayTimeSpinner
462
                    .setEnabled(!bUploading
463
                            && hexFileUpload.getUploadMode() == HexFileUpload.DUMB_MODE);
464
        }
465
 
466
        startButton.setEnabled(!bUploading && hexFileUpload.getFile() != null);
467
        stopButton.setEnabled(bUploading);
721 adamjking 468
        queryButton.setEnabled(!bUploading && hexFileUpload.isMIOS32Mode());
628 adamjking 469
    }
470
 
471
    public void stateChanged(ChangeEvent e) {
472
 
473
        Object source = e.getSource();
474
 
475
        if (source == deviceIDSpinner) {
476
            hexFileUpload.setDeviceID(((Integer) deviceIDSpinner.getValue())
477
                    .intValue());
478
 
479
        } else if (source == delayTimeSpinner) {
480
            hexFileUpload.setDelayTime(((Integer) delayTimeSpinner.getValue())
481
                    .intValue());
482
        }
483
    }
484
 
485
    public void actionPerformed(ActionEvent e) {
486
 
487
        String command = e.getActionCommand();
488
        Object source = e.getSource();
489
 
490
        if (command.equals("start")) {
491
            if (hexFileUpload.fileChanged()) {
492
 
493
                int nRet = JOptionPane.showConfirmDialog(null, "The file '"
494
                        + hexFileUpload.getFile().getPath()
495
                        + "' has changed.\n"
496
                        + "Do you wish to reload this file?",
497
                        "File has changed", JOptionPane.YES_NO_OPTION,
498
                        JOptionPane.INFORMATION_MESSAGE, null);
499
 
500
                if (nRet == JOptionPane.YES_OPTION) {
501
                    hexFileUpload.setFile(hexFileUpload.getFile());
502
                }
503
            }
504
 
505
            progressMessageTextArea.setText("");
506
 
507
            Thread t = new Thread() {
508
                public void run() {
509
                    hexFileUpload.createUpload();
510
                }
511
            };
512
 
513
            t.start();
514
 
515
        } else if (command.equals("query")) {
516
            progressMessageTextArea.setText("");
517
 
518
            Thread t = new Thread() {
519
                public void run() {
520
                    hexFileUpload.createQuery();
521
                }
522
            };
523
 
524
            t.start();
525
 
526
        } else if (command.equals("stop")) {
527
            hexFileUpload.cancel();
528
 
529
        } else if (command.equals("browse")) {
753 adamjking 530
            openHexFile();
628 adamjking 531
 
532
        } else if (source == smartModeButton || source == dumbModeButton) {
533
            hexFileUpload
534
                    .setUploadMode(smartModeButton.isSelected() ? HexFileUpload.SMART_MODE
535
                            : HexFileUpload.DUMB_MODE);
536
 
537
        } else if (source == MIOS32Check) {
721 adamjking 538
            hexFileUpload.setMIOS32Mode(MIOS32Check.isSelected());
628 adamjking 539
 
540
        } else if (source == waitForUploadRequestCheck) {
541
            hexFileUpload.setWaitForUploadRequest(waitForUploadRequestCheck
542
                    .isSelected());
543
        }
544
    }
545
 
546
    public void update(Observable observable, Object object) {
547
        if (observable == hexFileUpload) {
548
            if (object == HexFileUpload.MESSAGES
549
                    || object == HexFileUpload.WORKER) {
550
                while (!hexFileUpload.getMessages().isEmpty()) {
551
                    try {
552
                        String message = (String) hexFileUpload.getMessages()
553
                                .removeFirst();
554
                        StyledDocument doc = progressMessageTextArea
555
                                .getStyledDocument();
556
                        String style = "regular";
557
 
558
                        if (message.startsWith("Error")
559
                                || message.startsWith("Received error")
560
                                || message.endsWith("errors")
561
                                || message.endsWith("Error")) {
562
                            style = "error";
563
                        } else if (message.startsWith("Received")) {
564
                            style = "ack";
565
                        }
566
 
567
                        doc.insertString(doc.getLength(), message + "\n", doc
568
                                .getStyle(style));
569
                        progressMessageTextArea.setCaretPosition(doc
570
                                .getLength());
571
                    } catch (Exception e) {
572
 
573
                    }
574
                }
575
            } else if (object == HexFileUpload.FILE) {
576
                fileName.setText(hexFileUpload.getFile().getPath());
577
 
578
            } else if (object == HexFileUpload.DELAY_TIME) {
579
                delayTimeSpinner.setValue(new Integer(hexFileUpload
580
                        .getDelayTime()));
581
 
582
            } else if (object == HexFileUpload.DEVICE_ID) {
583
                deviceIDSpinner.setValue(new Integer(hexFileUpload
584
                        .getDeviceID()));
585
 
586
            } else if (object == HexFileUpload.UPLOAD_MODE) {
587
                smartModeButton
588
                        .setSelected(hexFileUpload.getUploadMode() == HexFileUpload.SMART_MODE);
589
 
590
                dumbModeButton
591
                        .setSelected(hexFileUpload.getUploadMode() == HexFileUpload.DUMB_MODE);
592
 
593
            } else if (object == HexFileUpload.MIOS32_MODE) {
721 adamjking 594
                MIOS32Check.setSelected(hexFileUpload.isMIOS32Mode());
628 adamjking 595
            } else if (object == HexFileUpload.WAIT_FOR_UPLOAD) {
596
                waitForUploadRequestCheck.setSelected(hexFileUpload
597
                        .isWaitForUploadRequest());
598
            }
599
 
600
            updateUploadControls();
601
        }
602
    }
603
}