001    package org.LiveGraph.gui;
002    
003    import java.awt.event.ActionEvent;
004    import java.awt.event.ActionListener;
005    import java.io.File;
006    import java.io.FileNotFoundException;
007    
008    import javax.swing.Box;
009    import javax.swing.JCheckBoxMenuItem;
010    import javax.swing.JFileChooser;
011    import javax.swing.JMenu;
012    import javax.swing.JMenuBar;
013    import javax.swing.JMenuItem;
014    import javax.swing.JOptionPane;
015    import javax.swing.filechooser.FileFilter;
016    
017    import org.LiveGraph.LiveGraph;
018    import org.LiveGraph.events.Event;
019    import org.LiveGraph.events.EventListener;
020    import org.LiveGraph.events.EventManager;
021    import org.LiveGraph.events.EventType;
022    import org.LiveGraph.settings.DataFileSettings;
023    import org.LiveGraph.settings.DataSeriesSettings;
024    import org.LiveGraph.settings.GraphSettings;
025    
026    
027    /**
028     * Provides a LiveGraph application menu bar.
029     * 
030     * <p>
031     *   <strong>LiveGraph</strong>
032     *   (<a href="http://www.live-graph.org" target="_blank">http://www.live-graph.org</a>).
033     * </p> 
034     * <p>Copyright (c) 2007-2008 by G. Paperin.</p>
035     * <p>File: MainMenuBar.java</p>
036     * <p style="font-size:smaller;">Redistribution and use in source and binary forms, with or
037     *    without modification, are permitted provided that the following terms and conditions are met:
038     * </p>
039     * <p style="font-size:smaller;">1. Redistributions of source code must retain the above
040     *    acknowledgement of the LiveGraph project and its web-site, the above copyright notice,
041     *    this list of conditions and the following disclaimer.<br />
042     *    2. Redistributions in binary form must reproduce the above acknowledgement of the
043     *    LiveGraph project and its web-site, the above copyright notice, this list of conditions
044     *    and the following disclaimer in the documentation and/or other materials provided with
045     *    the distribution.<br />
046     *    3. All advertising materials mentioning features or use of this software or any derived
047     *    software must display the following acknowledgement:<br />
048     *    <em>This product includes software developed by the LiveGraph project and its
049     *    contributors.<br />(http://www.live-graph.org)</em><br />
050     *    4. All advertising materials distributed in form of HTML pages or any other technology
051     *    permitting active hyper-links that mention features or use of this software or any
052     *    derived software must display the acknowledgment specified in condition 3 of this
053     *    agreement, and in addition, include a visible and working hyper-link to the LiveGraph
054     *    homepage (http://www.live-graph.org).
055     * </p>
056     * <p style="font-size:smaller;">THIS SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY
057     *    OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
058     *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT SHALL
059     *    THE AUTHORS, CONTRIBUTORS OR COPYRIGHT  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
060     *    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  FROM, OUT OF OR
061     *    IN CONNECTION WITH THE SOFTWARE OR THE USE OR  OTHER DEALINGS IN THE SOFTWARE.
062     * </p>
063     * 
064     * @author Greg Paperin (<a href="http://www.paperin.org" target="_blank">http://www.paperin.org</a>)
065     * @version {@value org.LiveGraph.LiveGraph#version}
066     *
067     */
068    /*package*/ class MainMenuBar extends JMenuBar implements EventListener {
069    
070    private JFileChooser dataFileSettingsFileDlg = null;
071    private JFileChooser graphSettingsFileDlg = null;
072    private JFileChooser seriesSettingsFileDlg = null;
073    
074    private JCheckBoxMenuItem dataFileSettingsDisplayMenuItem = null;
075    private JCheckBoxMenuItem graphSettingsDisplayMenuItem = null;
076    private JCheckBoxMenuItem seriesSettingsDisplayMenuItem = null;
077    private JCheckBoxMenuItem messsagesDisplayMenuItem = null;
078    
079    public MainMenuBar() {
080            init();
081    }
082    
083    private void init() {
084            
085            // File Dialogs:
086            
087            try {
088                    dataFileSettingsFileDlg = new JFileChooser("");
089                    dataFileSettingsFileDlg.setFileFilter(new FileFilter() {
090                            @Override public boolean accept(File f) {
091                            if (null == f) return false;
092                            if (f.isDirectory()) return true;
093                            int p = f.getName().lastIndexOf(".");        
094                            return p < 0
095                                            ? false
096                                            : f.getName().substring(p).equalsIgnoreCase(DataFileSettings.preferredFileExtension);
097                        }
098                            @Override public String getDescription() {
099                            return "LiveGraph data file settings (*" + DataFileSettings.preferredFileExtension + ")";
100                    }
101                    });
102                    try {
103                            dataFileSettingsFileDlg.setCurrentDirectory(new File(System.getProperty("user.dir")));
104                    } catch(SecurityException e) {
105                            dataFileSettingsFileDlg.setCurrentDirectory(new File(System.getProperty("user.home")));
106                    }
107            } catch(SecurityException e) {
108                    dataFileSettingsFileDlg = null;
109            }
110            
111            
112            try {
113                    graphSettingsFileDlg = new JFileChooser("");
114                    graphSettingsFileDlg.setFileFilter(new FileFilter() {
115                            @Override public boolean accept(File f) {
116                            if (null == f) return false;
117                            if (f.isDirectory()) return true;
118                            int p = f.getName().lastIndexOf(".");        
119                            return p < 0
120                                            ? false
121                                            : f.getName().substring(p).equalsIgnoreCase(GraphSettings.preferredFileExtension);
122                        }
123                            @Override public String getDescription() {
124                            return "LiveGraph graph settings (*" + GraphSettings.preferredFileExtension + ")";
125                    }
126                    });     
127                    try {
128                            graphSettingsFileDlg.setCurrentDirectory(new File(System.getProperty("user.dir")));
129                    } catch(SecurityException e) {
130                            graphSettingsFileDlg.setCurrentDirectory(new File(System.getProperty("user.home")));
131                    }
132            } catch(SecurityException e) {
133                    graphSettingsFileDlg = null;
134            }
135            
136            
137            try {
138                    seriesSettingsFileDlg = new JFileChooser();
139                    seriesSettingsFileDlg.setFileFilter(new FileFilter() {
140                            @Override public boolean accept(File f) {
141                            if (null == f) return false;
142                            if (f.isDirectory()) return true;
143                            int p = f.getName().lastIndexOf(".");        
144                            return p < 0
145                                            ? false
146                                            : f.getName().substring(p).equalsIgnoreCase(DataSeriesSettings.preferredFileExtension);
147                        }
148                            @Override public String getDescription() {
149                            return "LiveGraph data series settings (*" + DataSeriesSettings.preferredFileExtension + ")";
150                    }
151                    });
152                    try {
153                            seriesSettingsFileDlg.setCurrentDirectory(new File(System.getProperty("user.dir")));
154                    } catch(SecurityException e) {
155                            seriesSettingsFileDlg.setCurrentDirectory(new File(System.getProperty("user.home")));
156                    }
157            } catch(SecurityException e) {
158                    seriesSettingsFileDlg = null;
159            }
160            
161            
162            // Temp variables:
163            JMenu menu = null;
164            JMenuItem mItem = null;
165            
166            
167            // Data file setings menu:
168            
169            menu = new JMenu("Data file");
170            
171            mItem = new JMenuItem("Load data file settings...");
172            mItem.addActionListener(new ActionListener() {
173                    public void actionPerformed(ActionEvent e) { loadDataFileSettings(); }
174            });     
175            menu.add(mItem);
176            mItem.setEnabled(null != dataFileSettingsFileDlg);
177            
178            mItem = new JMenuItem("Save data file settings...");
179            mItem.addActionListener(new ActionListener() {
180                    public void actionPerformed(ActionEvent e) { saveDataFileSettings(); }
181            });
182            menu.add(mItem);
183            mItem.setEnabled(null != dataFileSettingsFileDlg);
184            menu.addSeparator();
185            
186            dataFileSettingsDisplayMenuItem = new JCheckBoxMenuItem("Display data file settings");
187            dataFileSettingsDisplayMenuItem.addActionListener(new ActionListener() {
188                    public void actionPerformed(ActionEvent e) {
189                            visibilityDataFileSettings();
190                    }
191            });
192            menu.add(dataFileSettingsDisplayMenuItem);
193            this.add(menu);
194            
195            
196            // Graph setings menu:
197            
198            menu = new JMenu("Graph settings");
199            
200            mItem = new JMenuItem("Load graph settings...");
201            mItem.addActionListener(new ActionListener() {
202                    public void actionPerformed(ActionEvent e) { loadGraphSettings(); }
203            });
204            menu.add(mItem);
205            mItem.setEnabled(null != graphSettingsFileDlg);
206            
207            mItem = new JMenuItem("Save graph settings...");
208            mItem.addActionListener(new ActionListener() {
209                    public void actionPerformed(ActionEvent e) { saveGraphSettings(); }
210            });
211            menu.add(mItem);
212            mItem.setEnabled(null != graphSettingsFileDlg);
213            menu.addSeparator();
214            
215            graphSettingsDisplayMenuItem = new JCheckBoxMenuItem("Display graph settings");
216            graphSettingsDisplayMenuItem.addActionListener(new ActionListener() {
217                    public void actionPerformed(ActionEvent e) { visibilityGraphSettings(); }
218            });
219            menu.add(graphSettingsDisplayMenuItem);
220            this.add(menu);
221            
222            
223            // Data series settings menu:
224            
225            menu = new JMenu("Data series");
226            
227            mItem = new JMenuItem("Load data series settings...");
228            mItem.addActionListener(new ActionListener() {
229                    public void actionPerformed(ActionEvent e) { loadDataSeriesSettings(); }
230            });
231            menu.add(mItem);
232            mItem.setEnabled(null != seriesSettingsFileDlg);
233            
234            mItem = new JMenuItem("Save data series settings...");
235            mItem.addActionListener(new ActionListener() {
236                    public void actionPerformed(ActionEvent e) { saveDataSeriesSettings(); }
237            });
238            menu.add(mItem);
239            mItem.setEnabled(null != seriesSettingsFileDlg);
240            menu.addSeparator();
241            
242            seriesSettingsDisplayMenuItem = new JCheckBoxMenuItem("Display data series settings");  
243            seriesSettingsDisplayMenuItem.addActionListener(new ActionListener() {
244                    public void actionPerformed(ActionEvent e) { visibilityDataSeriesSettings(); }
245            });
246            menu.add(seriesSettingsDisplayMenuItem);        
247            this.add(menu);
248            
249            
250            // Messages menu:
251            
252            menu = new JMenu("Messages");
253            
254            messsagesDisplayMenuItem = new JCheckBoxMenuItem("Display message window");     
255            messsagesDisplayMenuItem.addActionListener(new ActionListener() {
256                    public void actionPerformed(ActionEvent e) { visibilityMessageWindow(); }
257            });
258            menu.add(messsagesDisplayMenuItem);     
259            this.add(menu);
260            
261            
262            // Plot menu:
263            
264            menu = new JMenu("Plot");
265            mItem = new JMenuItem("Export graph to image...");
266            mItem.addActionListener(new ActionListener() {
267                    public void actionPerformed(ActionEvent e) { exportPlot(); }
268            });
269            menu.add(mItem);
270            this.add(menu);
271    
272            this.add(Box.createHorizontalGlue());
273            
274            
275            // Help menu:
276            
277            menu = new JMenu("Help");       
278            mItem = new JMenuItem("Support...");
279            mItem.addActionListener(new ActionListener() {
280                    public void actionPerformed(ActionEvent e) { showSupportInfo(); }
281            });
282            menu.add(mItem);
283            
284            mItem = new JMenuItem("Software update...");
285            mItem.addActionListener(new ActionListener() {
286                    public void actionPerformed(ActionEvent e) { displayUpdateDialog(); }
287            });
288            menu.add(mItem);
289            mItem.setEnabled(LiveGraph.application().standalone());
290            
291            mItem = new JMenuItem("Info...");
292            mItem.addActionListener(new ActionListener() {
293                    public void actionPerformed(ActionEvent e) { showProgramInfo(); }
294            });
295            menu.add(mItem);
296            this.add(menu);
297    }
298    
299    
300    private void loadDataFileSettings() {
301            
302            if (JFileChooser.APPROVE_OPTION != dataFileSettingsFileDlg.showOpenDialog(this.getParent()))
303                    return;
304            
305            File selFile = dataFileSettingsFileDlg.getSelectedFile();
306            if (!selFile.exists())
307                    return;
308            
309            if (!LiveGraph.application().getDataFileSettings().load(selFile.getAbsolutePath(), false))
310                    LiveGraph.application().guiManager().logErrorLn("Error while loading data file settings from " + selFile.getName() + ".");
311                    
312    }
313    
314    private void saveDataFileSettings() {
315            
316            if (JFileChooser.APPROVE_OPTION != dataFileSettingsFileDlg.showSaveDialog(this.getParent()))
317                    return;
318            
319            File selFile = dataFileSettingsFileDlg.getSelectedFile();
320            if (!selFile.getParentFile().exists())
321                    return;
322            
323            if (!selFile.getName().contains("."))
324                    selFile = new File(selFile.getAbsolutePath() + DataFileSettings.preferredFileExtension);
325            
326            if (!LiveGraph.application().getDataFileSettings().save(selFile.getAbsolutePath()))
327                    LiveGraph.application().guiManager().logErrorLn("Error while saving data file settings to " + selFile.getName() + ".");
328    }
329    
330    private void visibilityDataFileSettings() {
331            LiveGraph.application().guiManager().setDisplayDataFileSettingsWindows(dataFileSettingsDisplayMenuItem.getState());
332            // For testing - remove later:
333            //LiveGraph.application().guiManager().createDataFileSettingsWindow();
334            //LiveGraph.application().guiManager().setDisplayDataFileSettingsWindows(true);
335    }
336    
337    private void loadGraphSettings() {
338            
339            if (JFileChooser.APPROVE_OPTION != graphSettingsFileDlg.showOpenDialog(this.getParent()))
340                    return;
341            
342            File selFile = graphSettingsFileDlg.getSelectedFile();
343            if (!selFile.exists())
344                    return;
345            
346            if (!LiveGraph.application().getGraphSettings().load(selFile.getAbsolutePath()))
347                    LiveGraph.application().guiManager().logErrorLn("Error while loading graph settings from " + selFile.getName() + ".");
348                    
349    }
350    
351    private void saveGraphSettings() {
352            
353            if (JFileChooser.APPROVE_OPTION != graphSettingsFileDlg.showSaveDialog(this.getParent()))
354                    return;
355            
356            File selFile = graphSettingsFileDlg.getSelectedFile();
357            if (!selFile.getParentFile().exists())
358                    return;
359            
360            if (!selFile.getName().contains("."))
361                    selFile = new File(selFile.getAbsolutePath() + GraphSettings.preferredFileExtension);
362            
363            if (!LiveGraph.application().getGraphSettings().save(selFile.getAbsolutePath()))
364                    LiveGraph.application().guiManager().logErrorLn("Error while saving graph settings to " + selFile.getName() + ".");
365    }
366    
367    private void visibilityGraphSettings() {
368        LiveGraph.application().guiManager().setDisplayGraphSettingsWindows(graphSettingsDisplayMenuItem.getState());
369            // For testing - remove later:
370        //LiveGraph.application().guiManager().createGraphSettingsWindow();
371            //LiveGraph.application().guiManager().setDisplayGraphSettingsWindows(true);
372    }
373    
374    private void loadDataSeriesSettings() {
375            
376            if (JFileChooser.APPROVE_OPTION != seriesSettingsFileDlg.showOpenDialog(this.getParent()))
377                    return;
378            
379            File selFile = seriesSettingsFileDlg.getSelectedFile();
380            if (!selFile.exists())
381                    return;
382            
383            if (!LiveGraph.application().getDataSeriesSettings().load(selFile.getAbsolutePath()))
384                    LiveGraph.application().guiManager().logErrorLn("Error while loading data series settings from " + selFile.getName() + ".");
385    }
386    
387    private void saveDataSeriesSettings() {
388            
389            if (JFileChooser.APPROVE_OPTION != seriesSettingsFileDlg.showSaveDialog(this.getParent()))
390                    return;
391            
392            File selFile = seriesSettingsFileDlg.getSelectedFile();
393            if (!selFile.getParentFile().exists())
394                    return;
395            
396            if (!selFile.getName().contains("."))
397                    selFile = new File(selFile.getAbsolutePath() + DataSeriesSettings.preferredFileExtension);
398            
399            if (!LiveGraph.application().getDataSeriesSettings().save(selFile.getAbsolutePath()))
400                    LiveGraph.application().guiManager().logErrorLn("Error while saving data series settings to " + selFile.getName() + ".");
401    }
402    
403    private void visibilityDataSeriesSettings() {
404        LiveGraph.application().guiManager().setDisplaySeriesSettingsWindows(seriesSettingsDisplayMenuItem.getState());
405            // For testing - remove later:
406        //LiveGraph.application().guiManager().createSeriesSettingsWindow();
407            //LiveGraph.application().guiManager().setDisplaySeriesSettingsWindows(true);
408    }
409    
410    private void visibilityMessageWindow() {
411        LiveGraph.application().guiManager().setDisplayMessageWindows(messsagesDisplayMenuItem.getState());
412    }
413    
414    private void exportPlot() {
415            LiveGraph.application().getGraphExporter().exportGraph();
416    }
417    
418    private void showSupportInfo() {
419            JOptionPane.showMessageDialog(this.getParent(),
420                                      "For help using LiveGraph " + LiveGraph.version + " please refer to the user manual at:\n" +
421                                      "http://www.live-graph.org/userManual.html\n\n" +
422                                      "In addition you can visit our support forums at:\n" +
423                                      "http://sourceforge.net/forum/?group_id=191061\n\n" +
424                                      "For further information browse the LiveGraph website at:\n" +
425                                      "http://www.live-graph.org\n ",
426                                      "Help",
427                                      JOptionPane.INFORMATION_MESSAGE);
428    }
429    
430    private void displayUpdateDialog() {
431            LiveGraph.application().upgradeManager().upgradeOptionsDialog();
432    }
433    
434    private void showProgramInfo() {
435            JOptionPane.showMessageDialog(this.getParent(),
436                                      "LiveGraph\nVersion " + LiveGraph.version + "\n" +
437                                      "http://www.live-graph.org\n\n" +
438                                      "Developed by Greg Paperin\n(http://www.paperin.org)\n" +
439                                      "at Monash University\n ",
440                                      "LiveGraph " + LiveGraph.version + " credits",
441                                      JOptionPane.INFORMATION_MESSAGE);
442    }
443    
444    
445    /**
446     * Permits to register as listener with the main LiveGraph event manager and
447     * only with the main LiveGraph event manager.
448     * 
449     * @param manager The {@code EventManager} for the registering attempt.
450     * @return {@code (LiveGraph.application().eventManager() == manager)}.
451     * @see EventListener#permissionRegisterWithEventManager(EventManager)
452     */
453    public boolean permissionRegisterWithEventManager(EventManager manager) {
454            return LiveGraph.application().eventManager() == manager;
455    }
456    
457    /**
458     * Does not permit any unregistering.
459     * 
460     * @param manager The {@code EventManager} for the registering attempt.
461     * @return {@code false}.
462     * @see EventListener#permissionUnregisterWithEventManager(EventManager)
463     */
464    public boolean permissionUnregisterWithEventManager(EventManager manager) {
465            return false;
466    }
467    
468    /**
469     * Does nothing.
470     * 
471     * @param manager The {@code EventManager} with which this {@code EventListener} is now registered.
472     * @see EventListener#completedRegisterWithEventManager(EventManager)
473     */
474    public void completedRegisterWithEventManager(EventManager manager) { }
475    
476    /**
477     * Does nothing.
478     * 
479     * @param manager The {@code EventManager} with which this {@code EventListener} is now unregistered.
480     * @see EventListener#completedUnregisterWithEventManager(EventManager)
481     */
482    public void completedUnregisterWithEventManager(EventManager manager) { }
483    
484    /**
485     * Does nothing.
486     * 
487     * @param event An event in which this {@code EventListener} may be interested.
488     * @return {@code false}.
489     * @see EventListener#checkEventInterest(Event)
490     */
491    public boolean checkEventInterest(Event<? extends EventType> event) {
492            return false;
493    }
494    
495    /**
496     * Does nothing.
497     * 
498     * @param event The event to be validated.
499     * @param soFar Whether {@code event} has been successfuly validated by whichever {@code EventListener}s
500     * (if any) were invoked to validate {@code event} before this {@code EventListener}.
501     * @return {@code true}.
502     * @see EventListener#checkEventValid(Event, boolean)
503     */
504    public boolean checkEventValid(Event<? extends EventType> event, boolean soFar) {
505            return true;
506    }
507    
508    
509    /**
510     * Processes events.
511     * 
512     * @param event Event to process.
513     * @throws FileNotFoundException If could not read new data file.
514     */
515    public void eventRaised(Event<? extends EventType> event) throws FileNotFoundException {
516            
517            if (event.getDomain() == GUIEvent.class) {
518                    processGUIEvent(event.cast(GUIEvent.class));
519                    return;
520            }
521    }
522    
523    /**
524     * Updates local view on GUI events.
525     * 
526     * @param event The GUI event.
527     */
528    private void processGUIEvent(Event<GUIEvent> event) {
529            
530            switch(event.getType()) {
531                    
532                    case GUI_DataFileSettingsDisplayStateChanged:
533                            dataFileSettingsDisplayMenuItem.setState(event.getInfoBoolean());
534                            break;
535                            
536                    case GUI_GraphSettingsDisplayStateChanged:
537                            graphSettingsDisplayMenuItem.setState(event.getInfoBoolean());
538                            break;
539                            
540                    case GUI_DataSeriesSettingsDisplayStateChanged:
541                            seriesSettingsDisplayMenuItem.setState(event.getInfoBoolean());
542                            break;
543    
544                    case GUI_MessagesDisplayStateChanged:
545                            messsagesDisplayMenuItem.setState(event.getInfoBoolean());
546                            break;
547                            
548                    default:
549                            break;
550                            
551            }
552    } // private void processGUIEvent(Event<GUIEvent> event)
553    
554    } // public class MainMenuBar