001package jmri.jmrix.loconet.soundloader;
002
003import java.awt.Color;
004import java.awt.FlowLayout;
005import java.io.FileNotFoundException;
006import java.io.IOException;
007
008import javax.swing.AbstractAction;
009import javax.swing.BoxLayout;
010import javax.swing.JButton;
011import javax.swing.JFileChooser;
012import javax.swing.JLabel;
013import javax.swing.JPanel;
014import javax.swing.JProgressBar;
015import javax.swing.JSeparator;
016import javax.swing.JTextField;
017
018import jmri.jmrix.loconet.spjfile.SpjFile;
019import jmri.util.FileUtil;
020import jmri.util.swing.JmriJOptionPane;
021
022/**
023 * Pane for downloading .hex files
024 *
025 * @author Bob Jacobsen Copyright (C) 2005
026 */
027public class LoaderPane extends jmri.jmrix.loconet.swing.LnPanel {
028
029    // GUI member declarations
030    JLabel inputFileName = new JLabel("");
031
032    JButton readButton;
033    JButton loadButton;
034
035    JTextField comment = new JTextField(32);
036
037    JProgressBar bar;
038    JLabel status = new JLabel("");
039    String statusText = "";
040
041    SpjFile file;
042    LoaderEngine engine;
043
044    @Override
045    public String getHelpTarget() {
046        return "package.jmri.jmrix.loconet.soundloader.LoaderFrame"; // NOI18N
047    }
048
049    @Override
050    public String getTitle() {
051        return getTitle(Bundle.getMessage("MenuItemSoundload"));
052    }
053
054    public LoaderPane() {
055        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
056
057        {
058            JPanel p = new JPanel();
059            p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
060            JButton b = new JButton(Bundle.getMessage("ButtonSelect")); // is in jmri.NBBundle
061            b.addActionListener(new AbstractAction() {
062                @Override
063                public void actionPerformed(java.awt.event.ActionEvent e) {
064                    selectInputFile();
065                }
066            });
067            p.add(b);
068            p.add(new JLabel(Bundle.getMessage("LabelInpFile")));
069            p.add(inputFileName);
070
071            add(p);
072        }
073
074        add(new JSeparator());
075
076        {
077            JPanel p = new JPanel();
078            p.setLayout(new FlowLayout());
079
080            readButton = new JButton(Bundle.getMessage("ButtonRead"));
081            readButton.setEnabled(false);
082            readButton.setToolTipText(Bundle.getMessage("TipReadDisabled"));
083            p.add(readButton);
084            readButton.addActionListener(new AbstractAction() {
085                @Override
086                public void actionPerformed(java.awt.event.ActionEvent e) {
087                    doRead();
088                }
089            });
090
091            add(p);
092        }
093
094        {
095            JPanel p = new JPanel();
096            p.setLayout(new FlowLayout());
097
098            p.add(new JLabel(Bundle.getMessage("LabelFileComment")));
099            comment.setEditable(false);
100            p.add(comment);
101            add(p);
102        }
103
104        add(new JSeparator());
105
106        {
107            JPanel p = new JPanel();
108            p.setLayout(new FlowLayout());
109
110            loadButton = new JButton(Bundle.getMessage("ButtonDownload"));
111            loadButton.setEnabled(false);
112            loadButton.setToolTipText(Bundle.getMessage("TipLoadDisabled"));
113            p.add(loadButton);
114            loadButton.addActionListener(new AbstractAction() {
115                @Override
116                public void actionPerformed(java.awt.event.ActionEvent e) {
117                    doLoad();
118                }
119            });
120
121            add(p);
122
123            add(new JSeparator());
124
125            bar = new JProgressBar();
126            add(bar);
127
128            add(new JSeparator());
129
130            {
131                p = new JPanel();
132                p.setLayout(new FlowLayout());
133                status.setText(Bundle.getMessage("StatusSelectFile"));
134                // layout
135                status.setAlignmentX(JLabel.LEFT_ALIGNMENT);
136                status.setFont(status.getFont().deriveFont(0.9f * inputFileName.getFont().getSize())); // a bit smaller
137                status.setForeground(Color.gray);
138                p.add(status);
139                add(p);
140            }
141        }
142    }
143
144    JFileChooser chooser;
145
146    void selectInputFile() {
147        String name = inputFileName.getText();
148        if (name.equals("")) {
149            name = FileUtil.getUserFilesPath();
150        }
151        if (chooser == null) {
152            chooser = new jmri.util.swing.JmriJFileChooser(name);
153        }
154        inputFileName.setText("");  // clear out in case of failure
155        int retVal = chooser.showOpenDialog(this);
156        if (retVal != JFileChooser.APPROVE_OPTION) {
157            return;  // give up if no file selected
158        }
159        inputFileName.setText(chooser.getSelectedFile().getName());
160
161        readButton.setEnabled(true);
162        readButton.setToolTipText(Bundle.getMessage("TipReadEnabled"));
163        loadButton.setEnabled(false);
164        loadButton.setToolTipText(Bundle.getMessage("TipLoadDisabled"));
165        status.setText(Bundle.getMessage("StatusReadFile"));
166    }
167
168    void doRead() {
169        if (inputFileName.getText().equals("")) {
170            JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("ErrorNoInputFile"),
171                    Bundle.getMessage("ErrorTitle"),
172                    JmriJOptionPane.ERROR_MESSAGE);
173            return;
174        }
175
176        // force load, verify disabled in case read fails
177        loadButton.setEnabled(false);
178        loadButton.setToolTipText(Bundle.getMessage("TipLoadDisabled"));
179
180        try {
181            file = new SpjFile(chooser.getSelectedFile());
182            file.read();
183        } catch (FileNotFoundException f) {
184            JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("ErrorFileNotFound"),
185                    Bundle.getMessage("ErrorTitle"),
186                    JmriJOptionPane.ERROR_MESSAGE);
187            return;
188        } catch (IOException f) {
189            JmriJOptionPane.showMessageDialog(this, Bundle.getMessage("ErrorIOError"),
190                    Bundle.getMessage("ErrorTitle"),
191                    JmriJOptionPane.ERROR_MESSAGE);
192            return;
193        }
194
195        // display contents
196        comment.setText(file.getComment());
197
198        // set up for next step
199        loadButton.setEnabled(true);
200        loadButton.setToolTipText(Bundle.getMessage("TipLoadEnabled"));
201        status.setText(Bundle.getMessage("StatusDoDownload"));
202
203    }
204
205    void doLoad() {
206        status.setText(Bundle.getMessage("StatusDownloading"));
207        readButton.setEnabled(false);
208        readButton.setToolTipText(Bundle.getMessage("TipDisabledDownload"));
209        loadButton.setEnabled(false);
210        loadButton.setToolTipText(Bundle.getMessage("TipDisabledDownload"));
211
212        // Create a loader to run in a separate thread
213        // Override notify() method to do a swing-thread update of status field
214        if (engine == null) {
215            engine = new LoaderEngine(memo) {
216                @Override
217                public void notify(String s) {
218                    javax.swing.SwingUtilities.invokeLater(new Notifier(s));
219                }
220            };
221        }
222
223        // start the download itself
224        new Thread() {
225            @Override
226            public void run() {
227                engine.runDownload(file);
228            }
229        }.start();
230
231    }
232
233    /**
234     * Define objects to update status JLabel in pane
235     */
236    private class Notifier implements Runnable {
237
238        public Notifier(String msg) {
239            this.msg = msg;
240        }
241        String msg;
242
243        @Override
244        public void run() {
245            status.setText(msg);
246        }
247    }
248
249    /**
250     * Get rid of any held resources
251     */
252    @Override
253    public void dispose() {
254        if (file != null) {
255            file.dispose();
256        }
257        file = null;  // not for GC, this flags need to reinit
258
259        if (engine != null) {
260            engine.dispose();
261        }
262        engine = null;  // not for GC, this flags need to reinit
263    }
264
265}