Subversion Repositories svn.mios

Rev

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