001    package org.LiveGraph.gui;
002    
003    import java.awt.BorderLayout;
004    import java.awt.Dimension;
005    import java.awt.Toolkit;
006    
007    import javax.swing.Box;
008    import javax.swing.JFileChooser;
009    import javax.swing.JFrame;
010    import javax.swing.JOptionPane;
011    import javax.swing.JScrollBar;
012    import javax.swing.JTextArea;
013    import javax.swing.JMenu;
014    import javax.swing.JMenuBar;
015    import javax.swing.JMenuItem;
016    import javax.swing.WindowConstants;
017    import javax.swing.JScrollPane;
018    import javax.swing.JCheckBoxMenuItem;
019    import javax.swing.filechooser.FileFilter;
020    
021    import org.LiveGraph.LiveGraph;
022    import org.LiveGraph.settings.DataFileSettings;
023    import org.LiveGraph.settings.DataSeriesSettings;
024    import org.LiveGraph.settings.ErrorWhileSettingHasChangedProcessingException;
025    import org.LiveGraph.settings.GraphSettings;
026    
027    
028    import java.awt.Font;
029    import java.awt.event.ActionEvent;
030    import java.awt.event.ActionListener;
031    import java.awt.event.WindowAdapter;
032    import java.awt.event.WindowEvent;
033    import java.io.File;
034    import java.text.DateFormat;
035    import java.text.SimpleDateFormat;
036    import java.util.Date;
037    
038    /**
039     * This is the main window of the application.
040     * 
041     * <p style="font-size:smaller;">This product includes software developed by the
042     *    <strong>LiveGraph</strong> project and its contributors.<br />
043     *    (<a href="http://www.live-graph.org" target="_blank">http://www.live-graph.org</a>)<br />
044     *    Copyright (c) 2007 G. Paperin.<br />
045     *    All rights reserved.
046     * </p>
047     * <p style="font-size:smaller;">File: MainWindow.java</p> 
048     * <p style="font-size:smaller;">Redistribution and use in source and binary forms, with or
049     *    without modification, are permitted provided that the following terms and conditions are met:
050     * </p>
051     * <p style="font-size:smaller;">1. Redistributions of source code must retain the above
052     *    acknowledgement of the LiveGraph project and its web-site, the above copyright notice,
053     *    this list of conditions and the following disclaimer.<br />
054     *    2. Redistributions in binary form must reproduce the above acknowledgement of the
055     *    LiveGraph project and its web-site, the above copyright notice, this list of conditions
056     *    and the following disclaimer in the documentation and/or other materials provided with
057     *    the distribution.<br />
058     *    3. All advertising materials mentioning features or use of this software or any derived
059     *    software must display the following acknowledgement:<br />
060     *    <em>This product includes software developed by the LiveGraph project and its
061     *    contributors.<br />(http://www.live-graph.org)</em><br />
062     *    4. All advertising materials distributed in form of HTML pages or any other technology
063     *    permitting active hyper-links that mention features or use of this software or any
064     *    derived software must display the acknowledgment specified in condition 3 of this
065     *    agreement, and in addition, include a visible and working hyper-link to the LiveGraph
066     *    homepage (http://www.live-graph.org).
067     * </p>
068     * <p style="font-size:smaller;">THIS SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY
069     *    OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
070     *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT SHALL
071     *    THE AUTHORS, CONTRIBUTORS OR COPYRIGHT  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
072     *    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  FROM, OUT OF OR
073     *    IN CONNECTION WITH THE SOFTWARE OR THE USE OR  OTHER DEALINGS IN THE SOFTWARE.
074     * </p>
075     * 
076     * @author Greg Paperin (<a href="http://www.paperin.org" target="_blank">http://www.paperin.org</a>)
077     * @version {@value org.LiveGraph.LiveGraph#version}
078     */
079    public class MainWindow extends JFrame {
080    
081    private static final DateFormat logTimestampFormat = new SimpleDateFormat("HH:mm:ss");
082    
083    private JTextArea messageArea = null;
084    private JCheckBoxMenuItem dataFileSettingsDisplayMenuItem = null;
085    private JCheckBoxMenuItem graphSettingsDisplayMenuItem = null;
086    private JCheckBoxMenuItem seriesSettingsDisplayMenuItem = null;
087    private JCheckBoxMenuItem plotDisplayMenuItem = null;
088    
089    /**
090     * This is the default constructor. 
091     */
092    public MainWindow() {
093            super();
094            initialize();
095    }
096    
097    
098    /**
099     * This method initializes the main window.
100     */
101    private void initialize() {
102            
103            // Main window size and position:
104            final int WIN_WIDTH = 600;
105            final int WIN_HEIGHT = 200;
106            Dimension scr = Toolkit.getDefaultToolkit().getScreenSize();
107            this.setBounds((scr.width - WIN_WIDTH) / 2, (scr.height - WIN_HEIGHT) / 2, WIN_WIDTH, WIN_HEIGHT);
108            
109            // Other main settings:
110            final MainWindow MAIN_WIN = this;
111            this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);     
112            this.setTitle("LiveGraph");     
113            getContentPane().setLayout(new BorderLayout());
114            
115            // CLosing handler:
116            this.addWindowListener(new WindowAdapter() {
117                    @Override public void windowClosing(WindowEvent e) {
118                            LiveGraph.application().disposeGUIAndExit();
119                    }
120            });
121            
122            // Message area in the centre:
123            JScrollPane centreScrollPane = new JScrollPane();       
124            getContentPane().add(centreScrollPane, BorderLayout.CENTER);
125            messageArea = new JTextArea();
126            messageArea.setEditable(false);
127            messageArea.setFont(new Font("Courier New", Font.PLAIN, 12));
128            centreScrollPane.setViewportView(messageArea);
129            
130            // Menu:
131            JMenuBar menuBar = new JMenuBar();
132            this.setJMenuBar(menuBar);
133            JMenu menu = null;
134            JMenuItem mItem = null;
135            
136            menu = new JMenu("Data file");
137            final JFileChooser dataFileSettingsFileDlg = new JFileChooser();
138            dataFileSettingsFileDlg.setFileFilter(new FileFilter() {
139                    @Override public boolean accept(File f) {
140                    if (null == f) return false;
141                    if (f.isDirectory()) return true;
142                    int p = f.getName().lastIndexOf(".");        
143                    return p < 0
144                                    ? false
145                                    : f.getName().substring(p).equalsIgnoreCase(DataFileSettings.preferredFileExtension);
146                }
147                    @Override public String getDescription() {
148                    return "LiveGraph data file settings (*" + DataFileSettings.preferredFileExtension + ")";
149            }
150            });     
151            dataFileSettingsFileDlg.setCurrentDirectory(new File(System.getProperty("user.dir")));
152            mItem = new JMenuItem("Load data file settings...");
153            mItem.addActionListener(new ActionListener() {
154                    public void actionPerformed(ActionEvent e) {
155                            if (JFileChooser.APPROVE_OPTION != dataFileSettingsFileDlg.showOpenDialog(MAIN_WIN))
156                                    return;
157                            File selFile = dataFileSettingsFileDlg.getSelectedFile();
158                            if (!selFile.exists())
159                                    return;
160                            
161                            try {                           
162                                    if (LiveGraph.application().getDataFileSettings().load(selFile.getAbsolutePath()))
163                                            LiveGraph.application().logSuccessLn("Data file settings loaded from " + selFile.getName() + ".");
164                                    else
165                                            LiveGraph.application().logErrorLn("Error while loading data file settings from " + selFile.getName() + ".");
166                                    
167                            } catch (ErrorWhileSettingHasChangedProcessingException ex) {
168                                    logErrorLn("There was a problem while loading data file settings: \n"
169                                                     + "    " + (null != ex.getCause() ? ex.getCause().getMessage() : ex.getMessage()) + ".");
170                            }
171                    }
172            });
173            menu.add(mItem);
174            mItem = new JMenuItem("Save data file settings...");
175            menu.add(mItem);
176            mItem.addActionListener(new ActionListener() {
177                    public void actionPerformed(ActionEvent e) {
178                            if (JFileChooser.APPROVE_OPTION != dataFileSettingsFileDlg.showSaveDialog(MAIN_WIN))
179                                    return;
180                            File selFile = dataFileSettingsFileDlg.getSelectedFile();
181                            if (!selFile.getParentFile().exists())
182                                    return;
183                            if (!selFile.getName().contains("."))
184                                    selFile = new File(selFile.getAbsolutePath() + DataFileSettings.preferredFileExtension);  
185                            if (LiveGraph.application().getDataFileSettings().save(selFile.getAbsolutePath()))
186                                    LiveGraph.application().logSuccessLn("Data file settings saved to " + selFile.getName() + ".");
187                            else
188                                    LiveGraph.application().logErrorLn("Error while saving data file settings to " + selFile.getName() + ".");                      
189                    }
190            });
191            menu.addSeparator();
192            dataFileSettingsDisplayMenuItem = new JCheckBoxMenuItem("Display data file settings");
193            dataFileSettingsDisplayMenuItem.addActionListener(new ActionListener() {
194                    public void actionPerformed(ActionEvent e) {
195                            LiveGraph.application().setDisplayDataFileSettingsWindow(dataFileSettingsDisplayMenuItem.getState());
196                    }
197            });
198            menu.add(dataFileSettingsDisplayMenuItem);      
199            menuBar.add(menu);
200            
201            menu = new JMenu("Graph settings");
202            final JFileChooser graphSettingsFileDlg = new JFileChooser();
203            graphSettingsFileDlg.setFileFilter(new FileFilter() {
204                    @Override public boolean accept(File f) {
205                    if (null == f) return false;
206                    if (f.isDirectory()) return true;
207                    int p = f.getName().lastIndexOf(".");        
208                    return p < 0
209                                    ? false
210                                    : f.getName().substring(p).equalsIgnoreCase(GraphSettings.preferredFileExtension);
211                }
212                    @Override public String getDescription() {
213                    return "LiveGraph graph settings (*" + GraphSettings.preferredFileExtension + ")";
214            }
215            });     
216            graphSettingsFileDlg.setCurrentDirectory(new File(System.getProperty("user.dir")));
217            mItem = new JMenuItem("Load graph settings...");
218            mItem.addActionListener(new ActionListener() {
219                    public void actionPerformed(ActionEvent e) {
220                            if (JFileChooser.APPROVE_OPTION != graphSettingsFileDlg.showOpenDialog(MAIN_WIN))
221                                    return;
222                            File selFile = graphSettingsFileDlg.getSelectedFile();
223                            if (!selFile.exists())
224                                    return;
225                            
226                            try {                           
227                                    if (LiveGraph.application().getGraphSettings().load(selFile.getAbsolutePath()))
228                                            LiveGraph.application().logSuccessLn("Graph settings loaded from " + selFile.getName() + ".");
229                                    else
230                                            LiveGraph.application().logErrorLn("Error while loading graph settings from " + selFile.getName() + ".");
231                                    
232                            } catch (ErrorWhileSettingHasChangedProcessingException ex) {
233                                    logErrorLn("There was a problem while loading graph settings: \n"
234                                                     + "    " + (null != ex.getCause() ? ex.getCause().getMessage() : ex.getMessage()) + ".");
235                            }
236                    }
237            });
238            menu.add(mItem);
239            mItem = new JMenuItem("Save graph settings...");
240            mItem.addActionListener(new ActionListener() {
241                    public void actionPerformed(ActionEvent e) {
242                            if (JFileChooser.APPROVE_OPTION != graphSettingsFileDlg.showSaveDialog(MAIN_WIN))
243                                    return;
244                            File selFile = graphSettingsFileDlg.getSelectedFile();
245                            if (!selFile.getParentFile().exists())
246                                    return;
247                            if (!selFile.getName().contains("."))
248                                    selFile = new File(selFile.getAbsolutePath() + GraphSettings.preferredFileExtension);  
249                            if (LiveGraph.application().getGraphSettings().save(selFile.getAbsolutePath()))
250                                    LiveGraph.application().logSuccessLn("Graph settings saved to " + selFile.getName() + ".");
251                            else
252                                    LiveGraph.application().logErrorLn("Error while saving graph settings to " + selFile.getName() + ".");                  
253                    }
254            });
255            menu.add(mItem);
256            menu.addSeparator();
257            graphSettingsDisplayMenuItem = new JCheckBoxMenuItem("Display graph settings");
258            graphSettingsDisplayMenuItem.addActionListener(new ActionListener() {
259                    public void actionPerformed(ActionEvent e) {
260                            LiveGraph.application().setDisplayGraphSettingsWindow(graphSettingsDisplayMenuItem.getState());
261                    }
262            });
263            menu.add(graphSettingsDisplayMenuItem); 
264            menuBar.add(menu);
265            
266            menu = new JMenu("Data series");
267            final JFileChooser seriesSettingsFileDlg = new JFileChooser();
268            seriesSettingsFileDlg.setFileFilter(new FileFilter() {
269                    @Override public boolean accept(File f) {
270                    if (null == f) return false;
271                    if (f.isDirectory()) return true;
272                    int p = f.getName().lastIndexOf(".");        
273                    return p < 0
274                                    ? false
275                                    : f.getName().substring(p).equalsIgnoreCase(DataSeriesSettings.preferredFileExtension);
276                }
277                    @Override public String getDescription() {
278                    return "LiveGraph data series settings (*" + DataSeriesSettings.preferredFileExtension + ")";
279            }
280            });
281            seriesSettingsFileDlg.setCurrentDirectory(new File(System.getProperty("user.dir")));
282            mItem = new JMenuItem("Load data series settings...");
283            mItem.addActionListener(new ActionListener() {
284                    public void actionPerformed(ActionEvent e) {
285                            if (JFileChooser.APPROVE_OPTION != seriesSettingsFileDlg.showOpenDialog(MAIN_WIN))
286                                    return;
287                            File selFile = seriesSettingsFileDlg.getSelectedFile();
288                            if (!selFile.exists())
289                                    return;
290                            
291                            try {
292                                    if (LiveGraph.application().getDataSeriesSettings().load(selFile.getAbsolutePath()))
293                                            LiveGraph.application().logSuccessLn("Data series settings loaded from " + selFile.getName() + ".");
294                                    else
295                                            LiveGraph.application().logErrorLn("Error while loading data series settings from " + selFile.getName() + ".");
296                            
297                            } catch (ErrorWhileSettingHasChangedProcessingException ex) {
298                                    logErrorLn("There was a problem while loading data series settings: \n"
299                                                     + "    " + (null != ex.getCause() ? ex.getCause().getMessage() : ex.getMessage()) + ".");
300                            }
301                    }
302            });
303            menu.add(mItem);
304            mItem = new JMenuItem("Save data series settings...");
305            mItem.addActionListener(new ActionListener() {
306                    public void actionPerformed(ActionEvent e) {
307                            if (JFileChooser.APPROVE_OPTION != seriesSettingsFileDlg.showSaveDialog(MAIN_WIN))
308                                    return;
309                            File selFile = seriesSettingsFileDlg.getSelectedFile();
310                            if (!selFile.getParentFile().exists())
311                                    return;
312                            if (!selFile.getName().contains("."))
313                                    selFile = new File(selFile.getAbsolutePath() + DataSeriesSettings.preferredFileExtension);  
314                            if (LiveGraph.application().getDataSeriesSettings().save(selFile.getAbsolutePath()))
315                                    LiveGraph.application().logSuccessLn("Data series settings saved to " + selFile.getName() + ".");
316                            else
317                                    LiveGraph.application().logErrorLn("Error while saving data series settings to " + selFile.getName() + ".");                    
318                    }
319            });
320            menu.add(mItem);
321            menu.addSeparator();
322            seriesSettingsDisplayMenuItem = new JCheckBoxMenuItem("Display data series settings");  
323            seriesSettingsDisplayMenuItem.addActionListener(new ActionListener() {
324                    public void actionPerformed(ActionEvent e) {
325                            LiveGraph.application().setDisplaySeriesSettingsWindow(seriesSettingsDisplayMenuItem.getState());
326                    }
327            });
328            menu.add(seriesSettingsDisplayMenuItem);        
329            menuBar.add(menu);
330            
331            menu = new JMenu("Plot");
332            mItem = new JMenuItem("Export graph to image...");
333            mItem.addActionListener(new ActionListener() {
334                    public void actionPerformed(ActionEvent e) {
335                            LiveGraph.application().getGraphExporter().exportGraph();                       
336                    }
337            });
338            menu.add(mItem);
339            menu.addSeparator();
340            plotDisplayMenuItem = new JCheckBoxMenuItem("Display plot window");
341            plotDisplayMenuItem.addActionListener(new ActionListener() {
342                    public void actionPerformed(ActionEvent e) {
343                            LiveGraph.application().setDisplayPlotWindow(plotDisplayMenuItem.getState());
344                    }
345            });
346            menu.add(plotDisplayMenuItem);  
347            menuBar.add(menu);
348    
349            menuBar.add(Box.createHorizontalGlue());
350            menu = new JMenu("Help");       
351            mItem = new JMenuItem("Support...");
352            mItem.addActionListener(new ActionListener() {
353                    public void actionPerformed(ActionEvent e) {
354                            JOptionPane.showMessageDialog(MAIN_WIN,
355                                                                                      "For help using LiveGraph " + LiveGraph.version + " please refer to the user manual at:\n" +
356                                                                                      "http://www.live-graph.org/userManual.html\n\n" +
357                                                                                      "In addition you can visit our support forums at:\n" +
358                                                                                      "http://sourceforge.net/forum/?group_id=191061\n\n" +
359                                                                                      "For further information browse the LiveGraph website at:\n" +
360                                                                                      "http://www.live-graph.org\n ",
361                                                                                      "Help",
362                                                                                      JOptionPane.INFORMATION_MESSAGE);
363                    }
364            });
365            menu.add(mItem);
366            mItem = new JMenuItem("Info...");
367            mItem.addActionListener(new ActionListener() {
368                    public void actionPerformed(ActionEvent e) {
369                            JOptionPane.showMessageDialog(MAIN_WIN,
370                                                                                      "LiveGraph\nVersion " + LiveGraph.version + "\n" +
371                                                                                      "http://www.live-graph.org\n\n" +
372                                                                                      "Developed by Greg Paperin\n(http://www.paperin.org)\n" +
373                                                                                      "at Monash University\n ",
374                                                                                      "LiveGraph " + LiveGraph.version + " credits",
375                                                                                      JOptionPane.INFORMATION_MESSAGE);
376                    }
377            });
378            menu.add(mItem);
379            menuBar.add(menu);
380    }
381    
382    /**
383     * Displays a log message.
384     * @param s A message.
385     */
386    private void logLn(String s) {
387            messageArea.append(s);
388            JScrollBar sb = ((JScrollPane) messageArea.getParent().getParent()).getVerticalScrollBar();
389            if (null != sb)
390                    sb.setValue(sb.getMaximum());
391            messageArea.append("\n");
392    }
393    
394    /**
395     * Displays an info message.
396     * @param s A message
397     */
398    public void logInfoLn(String s) {
399            StringBuffer b = new StringBuffer();
400            b.append("[INFO](");
401            b.append(logTimestampFormat.format(new Date()));
402            b.append("): ");
403            b.append(s);
404            logLn(b.toString());
405    }
406    
407    /**
408     * Displays an error message.
409     * @param s A message
410     */
411    public void logErrorLn(String s) {
412            StringBuffer b = new StringBuffer();
413            b.append("[ERR ](");
414            b.append(logTimestampFormat.format(new Date()));
415            b.append("): ");
416            b.append(s);
417            logLn(b.toString());
418    }
419    
420    /**
421     * Displays an success message.
422     * @param s A message
423     */
424    public void logSuccessLn(String s) {
425            StringBuffer b = new StringBuffer();
426            b.append("[SUCC](");
427            b.append(logTimestampFormat.format(new Date()));
428            b.append("): ");
429            b.append(s);
430            logLn(b.toString());
431    }
432    
433    /**
434     * Update the menu state of {@link #dataFileSettingsDisplayMenuItem}.
435     * @param state New state.
436     */
437    public void fileSettingsDisplayStateChanged(boolean state) {
438            dataFileSettingsDisplayMenuItem.setState(state);
439    }
440    
441    /**
442     * Update the menu state of {@link #graphSettingsDisplayMenuItem}.
443     * @param state New state.
444     */
445    public void graphSettingsDisplayStateChanged(boolean state) {
446            graphSettingsDisplayMenuItem.setState(state);
447    }
448    
449    /**
450     * Update the menu state of {@link #seriesSettingsDisplayMenuItem}.
451     * @param state New state.
452     */
453    public void seriesSettingsDisplayStateChanged(boolean state) {
454            seriesSettingsDisplayMenuItem.setState(state);
455    }
456    
457    /**
458     * Update the menu state of {@link #plotDisplayMenuItem}.
459     * @param state New state.
460     */
461    public void plotDisplayStateChanged(boolean state) {
462            plotDisplayMenuItem.setState(state);
463    }
464    
465    }