source: branches/MetisMQI/src/main/java/weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/OPTICS_Visualizer.java

Last change on this file was 29, checked in by gnappo, 15 years ago

Taggata versione per la demo e aggiunto branch.

File size: 40.8 KB
Line 
1/*
2 *    This program is free software; you can redistribute it and/or modify
3 *    it under the terms of the GNU General Public License as published by
4 *    the Free Software Foundation; either version 2 of the License, or
5 *    (at your option) any later version.
6 *
7 *    This program is distributed in the hope that it will be useful,
8 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 *    GNU General Public License for more details.
11 *
12 *    You should have received a copy of the GNU General Public License
13 *    along with this program; if not, write to the Free Software
14 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17/*
18 *    Copyright (C) 2004
19 *    & Matthias Schubert (schubert@dbs.ifi.lmu.de)
20 *    & Zhanna Melnikova-Albrecht (melnikov@cip.ifi.lmu.de)
21 *    & Rainer Holzmann (holzmann@cip.ifi.lmu.de)
22 */
23
24package weka.clusterers.forOPTICSAndDBScan.OPTICS_GUI;
25
26import weka.core.FastVector;
27import weka.core.RevisionHandler;
28import weka.core.RevisionUtils;
29import weka.gui.LookAndFeel;
30
31import java.awt.BorderLayout;
32import java.awt.Color;
33import java.awt.Dimension;
34import java.awt.Event;
35import java.awt.GridBagConstraints;
36import java.awt.GridBagLayout;
37import java.awt.GridLayout;
38import java.awt.Insets;
39import java.awt.Point;
40import java.awt.Rectangle;
41import java.awt.Toolkit;
42import java.awt.event.ActionEvent;
43import java.awt.event.ActionListener;
44import java.awt.event.ItemEvent;
45import java.awt.event.ItemListener;
46import java.awt.event.WindowAdapter;
47import java.awt.event.WindowEvent;
48import java.io.File;
49import java.io.FileInputStream;
50import java.io.FileNotFoundException;
51import java.io.FileOutputStream;
52import java.io.IOException;
53import java.io.ObjectInputStream;
54import java.io.ObjectOutputStream;
55import java.util.Calendar;
56import java.util.GregorianCalendar;
57
58import javax.swing.BorderFactory;
59import javax.swing.ImageIcon;
60import javax.swing.JButton;
61import javax.swing.JCheckBox;
62import javax.swing.JColorChooser;
63import javax.swing.JComponent;
64import javax.swing.JFileChooser;
65import javax.swing.JFrame;
66import javax.swing.JLabel;
67import javax.swing.JMenu;
68import javax.swing.JMenuBar;
69import javax.swing.JMenuItem;
70import javax.swing.JOptionPane;
71import javax.swing.JPanel;
72import javax.swing.JScrollPane;
73import javax.swing.JSlider;
74import javax.swing.JTabbedPane;
75import javax.swing.JTable;
76import javax.swing.JTextArea;
77import javax.swing.JToolBar;
78import javax.swing.KeyStroke;
79import javax.swing.event.ChangeEvent;
80import javax.swing.event.ChangeListener;
81import javax.swing.table.DefaultTableColumnModel;
82import javax.swing.table.TableColumn;
83
84/**
85 * Start the OPTICS Visualizer from command-line: <br/>
86 * <code>java weka.clusterers.forOPTICSAndDBScan.OPTICS_GUI.OPTICS_Visualizer [file.ser]</code>
87 * <br/>
88 *
89 * <p>
90 * OPTICS_Visualizer.java <br/>
91 * Authors: Rainer Holzmann, Zhanna Melnikova-Albrecht <br/>
92 * Date: Sep 12, 2004 <br/>
93 * Time: 8:01:13 PM <br/>
94 * $ Revision 1.4 $ <br/>
95 * </p>
96 *
97 * @author Zhanna Melnikova-Albrecht (melnikov@cip.ifi.lmu.de)
98 * @author Rainer Holzmann (holzmann@cip.ifi.lmu.de)
99 * @version $Revision: 4791 $
100 */
101public class OPTICS_Visualizer
102    implements RevisionHandler {
103
104    /**
105     * Holds the OPTICS clustering results
106     */
107    private SERObject serObject;
108
109    /**
110     * Main Window of the OPTICS-Visualizer
111     */
112    private JFrame frame;
113
114    /**
115     * Statistic-frame
116     */
117    private JFrame statisticsFrame;
118
119    /**
120     * Help-frame
121     */
122    private JFrame helpFrame;
123
124    /**
125     * Listener for menu- and toolBar actions
126     */
127    private FrameListener frameListener;
128
129    /**
130     * Holds the toolBar and its components
131     */
132    private JToolBar toolBar;
133    private JButton toolBarButton_open;
134    private JButton toolBarButton_save;
135    private JButton toolBarButton_parameters;
136    private JButton toolBarButton_help;
137    private JButton toolBarButton_about;
138
139    /**
140     * Holds the default-menu and its components
141     */
142    private JMenuBar defaultMenuBar;
143    private JMenuItem open;
144    private JMenuItem save;
145    private JMenuItem exit;
146    private JMenuItem parameters;
147    private JMenuItem help;
148    private JMenuItem about;
149
150    /**
151     * Holds the tabbedPane and its components
152     */
153    private JTabbedPane tabbedPane;
154    private JTable resultVectorTable;
155    private GraphPanel graphPanel;
156    private JScrollPane graphPanelScrollPane;
157
158    /**
159     * Holds the settingsPanel and its components
160     */
161    private JPanel settingsPanel;
162    private JCheckBox showCoreDistances;
163    private JCheckBox showReachabilityDistances;
164    private int verValue = 30;
165    private JSlider verticalSlider;
166    private JButton coreDistanceColorButton;
167    private JButton reachDistanceColorButton;
168    private JButton graphBackgroundColorButton;
169    private JButton resetColorButton;
170
171    /**
172     * FileChooser for saving- and open-actions
173     */
174    private JFileChooser jFileChooser;
175    private String lastPath;
176
177    // *****************************************************************************************************************
178    // constructors
179    // *****************************************************************************************************************
180
181    public OPTICS_Visualizer(SERObject serObject, String title) {
182        this.serObject = serObject;
183
184        LookAndFeel.setLookAndFeel();
185   
186        frame = new JFrame(title);
187
188        frame.addWindowListener(new WindowAdapter() {
189            /**
190             * Invoked when a window is in the process of being closed.
191             * The close operation can be overridden at this point.
192             */
193            public void windowClosing(WindowEvent e) {
194                frame.dispose();
195            }
196        });
197
198        frame.getContentPane().setLayout(new BorderLayout());
199        frame.setSize(new Dimension(800, 600));
200        Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
201        Rectangle windowRectangle = frame.getBounds();
202        frame.setLocation((screenDimension.width - windowRectangle.width) / 2,
203                (screenDimension.height - windowRectangle.height) / 2);
204
205        frameListener = new FrameListener();
206        jFileChooser = new JFileChooser();
207        jFileChooser.setFileFilter(new SERFileFilter("ser", "Java Serialized Object File (*.ser)"));
208
209        createGUI();
210        frame.setVisible(true);
211        frame.toFront();
212
213    }
214
215    // *****************************************************************************************************************
216    // methods
217    // *****************************************************************************************************************
218
219    /**
220     * Constructs the main-layout for the OPTICS-Visualizer
221     */
222    private void createGUI() {
223        setMenuBar(constructDefaultMenuBar());
224
225        frame.getContentPane().add(createToolBar(), BorderLayout.NORTH);
226        frame.getContentPane().add(createTabbedPane(), BorderLayout.CENTER);
227        frame.getContentPane().add(createSettingsPanel(), BorderLayout.SOUTH);
228        disableSettingsPanel();
229    }
230
231    /**
232     * Creates the settings-panel
233     * @return Settings-panel
234     */
235    private JComponent createSettingsPanel() {
236        settingsPanel = new JPanel(new GridBagLayout());
237
238        SettingsPanelListener panelListener = new SettingsPanelListener();
239
240        JPanel setPanelLeft = new JPanel(new GridBagLayout());
241        setPanelLeft.setBorder(BorderFactory.createTitledBorder(" General Settings "));
242
243        JPanel checkBoxesPanel = new JPanel(new GridLayout(1, 2));
244        showCoreDistances = new JCheckBox("Show Core-Distances");
245        showCoreDistances.setSelected(true);
246        showReachabilityDistances = new JCheckBox("Show Reachability-Distances");
247        showReachabilityDistances.setSelected(true);
248        showCoreDistances.addItemListener(new ItemListener() {
249            public void itemStateChanged(ItemEvent e) {
250                if (e.getStateChange() == ItemEvent.SELECTED) {
251                    graphPanel.setShowCoreDistances(true);
252                    graphPanel.adjustSize(serObject);
253                    graphPanel.repaint();
254                } else if (e.getStateChange() == ItemEvent.DESELECTED) {
255                    graphPanel.setShowCoreDistances(false);
256                    graphPanel.adjustSize(serObject);
257                    graphPanel.repaint();
258                }
259            }
260        });
261        showReachabilityDistances.addItemListener(new ItemListener() {
262            public void itemStateChanged(ItemEvent e) {
263                if (e.getStateChange() == ItemEvent.SELECTED) {
264                    graphPanel.setShowReachabilityDistances(true);
265                    graphPanel.adjustSize(serObject);
266                    graphPanel.repaint();
267                } else if (e.getStateChange() == ItemEvent.DESELECTED) {
268                    graphPanel.setShowReachabilityDistances(false);
269                    graphPanel.adjustSize(serObject);
270                    graphPanel.repaint();
271                }
272            }
273        });
274
275        checkBoxesPanel.add(showCoreDistances);
276        checkBoxesPanel.add(showReachabilityDistances);
277
278        JPanel verticalAdPanel = new JPanel(new BorderLayout());
279        final JLabel verValueLabel = new JLabel("Vertical Adjustment: " + verValue);
280        verticalAdPanel.add(verValueLabel, BorderLayout.NORTH);
281        verticalSlider = new JSlider(JSlider.HORIZONTAL, 0, frame.getHeight(), verValue);
282        verticalSlider.setMajorTickSpacing(100);
283        verticalSlider.setMinorTickSpacing(10);
284        verticalSlider.setPaintTicks(true);
285        verticalSlider.setPaintLabels(true);
286        verticalSlider.addChangeListener(new ChangeListener() {
287            public void stateChanged(ChangeEvent e) {
288                if (!verticalSlider.getValueIsAdjusting()) {
289                    verValue = verticalSlider.getValue();
290                    verValueLabel.setText("Vertical Adjustment: " + verValue);
291                    graphPanel.setVerticalAdjustment(verValue);
292                    graphPanel.repaint();
293                }
294            }
295        });
296        verticalAdPanel.add(verticalSlider, BorderLayout.CENTER);
297
298        setPanelLeft.add(checkBoxesPanel,
299                new GridBagConstraints(0, 0, 1, 1, 1, 1,
300                        GridBagConstraints.CENTER,
301                        GridBagConstraints.BOTH,
302                        new Insets(5, 5, 5, 5), 0, 0));
303        setPanelLeft.add(verticalAdPanel,
304                new GridBagConstraints(0, 1, 1, 1, 1, 1,
305                        GridBagConstraints.CENTER,
306                        GridBagConstraints.BOTH,
307                        new Insets(5, 5, 5, 5), 0, 0));
308
309        settingsPanel.add(setPanelLeft,
310                new GridBagConstraints(0, 0, 1, 1, 3, 1,
311                        GridBagConstraints.CENTER,
312                        GridBagConstraints.BOTH,
313                        new Insets(5, 5, 5, 0), 0, 0));
314
315        JPanel setPanelRight = new JPanel(new GridBagLayout());
316        setPanelRight.setBorder(BorderFactory.createTitledBorder(" Colors "));
317
318        JPanel colorsPanel = new JPanel(new GridLayout(4, 2, 10, 10));
319
320        colorsPanel.add(new JLabel("Core-Distance: "));
321        coreDistanceColorButton = new JButton();
322        coreDistanceColorButton.setBackground(new Color(100, 100, 100));
323        coreDistanceColorButton.addActionListener(panelListener);
324        colorsPanel.add(coreDistanceColorButton);
325
326        colorsPanel.add(new JLabel("Reachability-Distance: "));
327        reachDistanceColorButton = new JButton();
328        reachDistanceColorButton.setBackground(Color.orange);
329        reachDistanceColorButton.addActionListener(panelListener);
330        colorsPanel.add(reachDistanceColorButton);
331
332        colorsPanel.add(new JLabel("Graph Background: "));
333        graphBackgroundColorButton = new JButton();
334        graphBackgroundColorButton.setBackground(new Color(255, 255, 179));
335        graphBackgroundColorButton.addActionListener(panelListener);
336        colorsPanel.add(graphBackgroundColorButton);
337
338        colorsPanel.add(new JLabel());
339        resetColorButton = new JButton("Reset");
340        resetColorButton.addActionListener(panelListener);
341        colorsPanel.add(resetColorButton);
342
343        setPanelRight.add(colorsPanel,
344                new GridBagConstraints(0, 0, 1, 1, 1, 1,
345                        GridBagConstraints.CENTER,
346                        GridBagConstraints.BOTH,
347                        new Insets(5, 5, 5, 5), 0, 0));
348
349        settingsPanel.add(setPanelRight,
350                new GridBagConstraints(1, 0, 1, 1, 1, 1,
351                        GridBagConstraints.CENTER,
352                        GridBagConstraints.BOTH,
353                        new Insets(5, 5, 5, 5), 0, 0));
354
355        return settingsPanel;
356    }
357
358    /**
359     * Disables all components from the settingsPanel
360     */
361    private void disableSettingsPanel() {
362
363        verticalSlider.setEnabled(false);
364        coreDistanceColorButton.setEnabled(false);
365        reachDistanceColorButton.setEnabled(false);
366        graphBackgroundColorButton.setEnabled(false);
367        resetColorButton.setEnabled(false);
368        settingsPanel.setVisible(false);
369    }
370
371    /**
372     * Enables all components from the settingsPanel
373     */
374    private void enableSettingsPanel() {
375        verticalSlider.setEnabled(true);
376        coreDistanceColorButton.setEnabled(true);
377        reachDistanceColorButton.setEnabled(true);
378        graphBackgroundColorButton.setEnabled(true);
379        resetColorButton.setEnabled(true);
380        settingsPanel.setVisible(true);
381    }
382
383    /**
384     * Creates the TabbedPane
385     * @return TabbedPane
386     */
387    private JComponent createTabbedPane() {
388        tabbedPane = new JTabbedPane();
389        tabbedPane.addTab("Table", new ImageIcon(Toolkit.getDefaultToolkit().
390            getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Table16.gif"))),
391            clusteringResultsTable(),
392        "Show table of DataObjects, Core- and Reachability-Distances");
393        if (serObject != null)
394          tabbedPane.addTab("Graph - Epsilon: " + serObject.getEpsilon() + ", MinPoints: " + serObject.getMinPoints()
395              , new ImageIcon(Toolkit.getDefaultToolkit().
396                  getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Graph16.gif"))),
397                  graphPanel(),
398          "Show Plot of Core- and Reachability-Distances");
399        else
400          tabbedPane.addTab(
401              "Graph - Epsilon: --, MinPoints: --", 
402              new ImageIcon(
403                  Toolkit.getDefaultToolkit().getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Graph16.gif"))),
404                  graphPanel(),
405          "Show Plot of Core- and Reachability-Distances");
406
407        tabbedPane.addChangeListener(new ChangeListener() {
408            public void stateChanged(ChangeEvent e) {
409                int c = tabbedPane.getSelectedIndex();
410                if (c == 0)
411                    disableSettingsPanel();
412                else
413                    enableSettingsPanel();
414            }
415        });
416
417        return tabbedPane;
418    }
419
420    /**
421     * Creates the ToolBar
422     * @return ToolBar
423     */
424    private JComponent createToolBar() {
425        toolBar = new JToolBar();
426        toolBar.setName("OPTICS Visualizer ToolBar");
427        toolBar.setFloatable(false);
428        toolBarButton_open = new JButton(new ImageIcon(Toolkit.getDefaultToolkit().
429                getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Open16.gif"))));
430        toolBarButton_open.setToolTipText("Open OPTICS-Session");
431        toolBarButton_open.addActionListener(frameListener);
432        toolBar.add(toolBarButton_open);
433
434        toolBarButton_save = new JButton(new ImageIcon(Toolkit.getDefaultToolkit().
435                getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Save16.gif"))));
436        toolBarButton_save.setToolTipText("Save OPTICS-Session");
437        toolBarButton_save.addActionListener(frameListener);
438        toolBar.add(toolBarButton_save);
439        toolBar.addSeparator(new Dimension(10, 25));
440
441        toolBarButton_parameters = new JButton(new ImageIcon(Toolkit.getDefaultToolkit().
442                getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Parameters16.gif"))));
443        toolBarButton_parameters.setToolTipText("Show epsilon, MinPoints...");
444        toolBarButton_parameters.addActionListener(frameListener);
445        toolBar.add(toolBarButton_parameters);
446
447        toolBar.addSeparator(new Dimension(10, 25));
448
449        toolBarButton_help = new JButton(new ImageIcon(Toolkit.getDefaultToolkit().
450                getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Help16.gif"))));
451        toolBarButton_help.setToolTipText("Help topics");
452        toolBarButton_help.addActionListener(frameListener);
453        toolBar.add(toolBarButton_help);
454
455        toolBarButton_about = new JButton(new ImageIcon(Toolkit.getDefaultToolkit().
456                getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Information16.gif"))));
457        toolBarButton_about.setToolTipText("About");
458        toolBarButton_about.addActionListener(frameListener);
459        toolBar.add(toolBarButton_about);
460
461        return toolBar;
462    }
463
464    /**
465     * Creates the OPTICS clustering results table
466     * @return Table
467     */
468    private JComponent clusteringResultsTable() {
469        resultVectorTable = new JTable();
470        String[] resultVectorTableColumnNames = {"Key",
471                                                 "DataObject",
472                                                 "Core-Distance",
473                                                 "Reachability-Distance"};
474
475        DefaultTableColumnModel resultVectorTableColumnModel = new DefaultTableColumnModel();
476        for (int i = 0; i < resultVectorTableColumnNames.length; i++) {
477            TableColumn tc = new TableColumn(i);
478            tc.setHeaderValue(resultVectorTableColumnNames[i]);
479            resultVectorTableColumnModel.addColumn(tc);
480        }
481
482        ResultVectorTableModel resultVectorTableModel;
483        if (serObject != null)
484          resultVectorTableModel = new ResultVectorTableModel(serObject.getResultVector());
485        else
486          resultVectorTableModel = new ResultVectorTableModel(null);
487        resultVectorTable = new JTable(resultVectorTableModel, resultVectorTableColumnModel);
488        resultVectorTable.getColumnModel().getColumn(0).setPreferredWidth(70);
489        resultVectorTable.getColumnModel().getColumn(1).setPreferredWidth(400);
490        resultVectorTable.getColumnModel().getColumn(2).setPreferredWidth(150);
491        resultVectorTable.getColumnModel().getColumn(3).setPreferredWidth(150);
492        resultVectorTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
493
494        JScrollPane resultVectorTableScrollPane = new JScrollPane(resultVectorTable,
495                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
496                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
497
498        return resultVectorTableScrollPane;
499    }
500
501    /**
502     * Creates the OPTICS Plot
503     * @return JComponent with the PLOT
504     */
505    private JComponent graphPanel() {
506
507        if (serObject == null) {
508          graphPanel = new GraphPanel(new FastVector(), verValue, true, true);
509        }
510        else {
511          graphPanel = new GraphPanel(serObject.getResultVector(), verValue, true, true);
512          graphPanel.setPreferredSize(new Dimension((10 * serObject.getDatabaseSize()) +
513              serObject.getDatabaseSize(), graphPanel.getHeight()));
514        }
515        graphPanel.setBackground(new Color(255, 255, 179));
516        graphPanel.setOpaque(true);
517
518        graphPanelScrollPane = new JScrollPane(graphPanel,
519                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
520
521        return (graphPanelScrollPane);
522    }
523
524    /**
525     * Constructs the default MenuBar
526     * @return MenuBar
527     */
528    private JMenuBar constructDefaultMenuBar() {
529        defaultMenuBar = new JMenuBar();
530
531        JMenu fileMenu = new JMenu("File");
532        fileMenu.setMnemonic('F');
533        open = new JMenuItem("Open...", new ImageIcon(Toolkit.getDefaultToolkit().
534                getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Open16.gif"))));
535        open.setMnemonic('O');
536        open.setAccelerator(KeyStroke.getKeyStroke('O', Event.CTRL_MASK));
537        open.addActionListener(frameListener);
538        fileMenu.add(open);
539
540        save = new JMenuItem("Save...", new ImageIcon(Toolkit.getDefaultToolkit().
541                getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Save16.gif"))));
542        save.setMnemonic('S');
543        save.setAccelerator(KeyStroke.getKeyStroke('S', Event.CTRL_MASK));
544        save.addActionListener(frameListener);
545        fileMenu.add(save);
546
547        fileMenu.addSeparator();
548
549        exit = new JMenuItem("Exit", 'X');
550        exit.addActionListener(frameListener);
551        fileMenu.add(exit);
552
553        defaultMenuBar.add(fileMenu);
554
555        JMenu toolsMenu = new JMenu("View");
556        toolsMenu.setMnemonic('V');
557        parameters = new JMenuItem("Parameters...", new ImageIcon(Toolkit.getDefaultToolkit().
558                getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Parameters16.gif"))));
559        parameters.setMnemonic('P');
560        parameters.setAccelerator(KeyStroke.getKeyStroke('P', Event.CTRL_MASK));
561        parameters.addActionListener(frameListener);
562        toolsMenu.add(parameters);
563
564        defaultMenuBar.add(toolsMenu);
565
566        JMenu miscMenu = new JMenu("Help");
567        miscMenu.setMnemonic('H');
568        help = new JMenuItem("Help Topics", new ImageIcon(Toolkit.getDefaultToolkit().
569                getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Help16.gif"))));
570        help.setMnemonic('H');
571        help.setAccelerator(KeyStroke.getKeyStroke('H', Event.CTRL_MASK));
572        help.addActionListener(frameListener);
573        miscMenu.add(help);
574
575        about = new JMenuItem("About...", new ImageIcon(Toolkit.getDefaultToolkit().
576                getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Information16.gif"))));
577        about.setMnemonic('A');
578        about.setAccelerator(KeyStroke.getKeyStroke('A', Event.CTRL_MASK));
579        about.addActionListener(frameListener);
580        miscMenu.add(about);
581        defaultMenuBar.add(miscMenu);
582
583        return defaultMenuBar;
584    }
585
586    /**
587     * Sets a MenuBar for the this frame
588     * @param menuBar New MenuBar
589     */
590    private void setMenuBar(JMenuBar menuBar) {
591        frame.setJMenuBar(menuBar);
592    }
593
594    /**
595     * Shows a little frame with statistic information about the OPTICS-results
596     */
597    private void loadStatisticsFrame() {
598        statisticsFrame = new JFrame("Parameters");
599        statisticsFrame.getContentPane().setLayout(new BorderLayout());
600
601        JPanel statPanel_Labels = new JPanel(new GridBagLayout());
602        JPanel statPanel_Labels_Left = new JPanel(new GridLayout(9, 1));
603        JPanel statPanel_Labels_Right = new JPanel(new GridLayout(9, 1));
604
605        statPanel_Labels_Left.add(new JLabel("Number of clustered DataObjects: "));
606        statPanel_Labels_Right.add(new JLabel(Integer.toString(serObject.getDatabaseSize())));
607        statPanel_Labels_Left.add(new JLabel("Number of attributes: "));
608        statPanel_Labels_Right.add(new JLabel(Integer.toString(serObject.getNumberOfAttributes())));
609        statPanel_Labels_Left.add(new JLabel("Epsilon: "));
610        statPanel_Labels_Right.add(new JLabel(Double.toString(serObject.getEpsilon())));
611        statPanel_Labels_Left.add(new JLabel("MinPoints: "));
612        statPanel_Labels_Right.add(new JLabel(Integer.toString(serObject.getMinPoints())));
613        statPanel_Labels_Left.add(new JLabel("Write results to file: "));
614        statPanel_Labels_Right.add(new JLabel(serObject.isOpticsOutputs() ? "yes" : "no"));
615        statPanel_Labels_Left.add(new JLabel("Index: "));
616        statPanel_Labels_Right.add(new JLabel(serObject.getDatabase_Type()));
617        statPanel_Labels_Left.add(new JLabel("Distance-Type: "));
618        statPanel_Labels_Right.add(new JLabel(serObject.getDatabase_distanceType()));
619        statPanel_Labels_Left.add(new JLabel("Number of generated clusters: "));
620        statPanel_Labels_Right.add(new JLabel(Integer.toString(serObject.getNumberOfGeneratedClusters())));
621        statPanel_Labels_Left.add(new JLabel("Elapsed-time: "));
622        statPanel_Labels_Right.add(new JLabel(serObject.getElapsedTime()));
623        statPanel_Labels.setBorder(BorderFactory.createTitledBorder(" OPTICS parameters "));
624
625        statPanel_Labels.add(statPanel_Labels_Left,
626                new GridBagConstraints(0, 0, 1, 1, 1, 1,
627                        GridBagConstraints.CENTER,
628                        GridBagConstraints.BOTH,
629                        new Insets(0, 5, 2, 0), 0, 0));
630
631        statPanel_Labels.add(statPanel_Labels_Right,
632                new GridBagConstraints(1, 0, 1, 1, 3, 1,
633                        GridBagConstraints.CENTER,
634                        GridBagConstraints.BOTH,
635                        new Insets(0, 5, 2, 5), 0, 0));
636
637        statisticsFrame.getContentPane().add(statPanel_Labels, BorderLayout.CENTER);
638
639        statisticsFrame.addWindowListener(new WindowAdapter() {
640            /**
641             * Invoked when a window is in the process of being closed.
642             * The close operation can be overridden at this point.
643             */
644            public void windowClosing(WindowEvent e) {
645                statisticsFrame.dispose();
646            }
647        });
648
649        JPanel okButtonPanel = new JPanel(new GridBagLayout());
650
651        JButton okButton = new JButton("OK");
652        okButton.addActionListener(new ActionListener() {
653            public void actionPerformed(ActionEvent e) {
654                if (e.getActionCommand().equals("OK")) {
655                    statisticsFrame.dispose();
656                }
657            }
658        });
659        okButtonPanel.add(okButton,
660                new GridBagConstraints(0, 0, 1, 1, 1, 1,
661                        GridBagConstraints.CENTER,
662                        GridBagConstraints.NONE,
663                        new Insets(5, 0, 5, 0), 0, 0));
664
665        statisticsFrame.getContentPane().add(okButtonPanel, BorderLayout.SOUTH);
666        statisticsFrame.setSize(new Dimension(500, 300));
667        Rectangle frameDimension = frame.getBounds();
668        Point p = frame.getLocation();
669        Rectangle statisticsFrameDimension = statisticsFrame.getBounds();
670        statisticsFrame.setLocation(((frameDimension.width - statisticsFrameDimension.width) / 2) + (int) p.getX(),
671                ((frameDimension.height - statisticsFrameDimension.height) / 2) + (int) p.getY());
672        statisticsFrame.setVisible(true);
673        statisticsFrame.toFront();
674    }
675
676    /**
677     * Shows a little frame with information about handling the OPTICS Visualizer
678     */
679    private void loadHelpFrame() {
680        helpFrame = new JFrame("Help Topics");
681        helpFrame.getContentPane().setLayout(new BorderLayout());
682
683        JPanel helpPanel = new JPanel(new GridBagLayout());
684        JTextArea helpTextArea = new JTextArea();
685        helpTextArea.setEditable(false);
686        helpTextArea.append(
687                "OPTICS Visualizer Help\n"
688                + "===========================================================\n\n"
689                + "Open\n"
690                + " - Open OPTICS-Session\n"
691                + "   [Ctrl-O], File | Open\n\n"
692                + "Save\n"
693                + " - Save OPTICS-Session\n"
694                + "   [Ctrl-S], File | Save\n\n"
695                + "Exit\n"
696                + " - Exit OPTICS Visualizer\n"
697                + "   [Alt-F4], File | Exit\n\n"
698                + "Parameters\n"
699                + " - Show epsilon, MinPoints...\n"
700                + "   [Ctrl-P], View | Parameters\n\n"
701                + "Help Topics\n"
702                + " - Show this frame\n"
703                + "   [Ctrl-H], Help | Help Topics\n\n"
704                + "About\n"
705                + " - Copyright-Information\n"
706                + "   [Ctrl-A], Help | About\n\n\n"
707                + "Table-Pane:\n"
708                + "-----------------------------------------------------------\n"
709                + "The table represents the calculated clustering-order.\n"
710                + "To save the table please select File | Save from the\n"
711                + "menubar. Restart OPTICS with the -F option to obtain\n"
712                + "an ASCII-formatted file of the clustering-order.\n\n"
713                + "Graph-Pane:\n"
714                + "-----------------------------------------------------------\n"
715                + "The graph draws the plot of core- and reachability-\n"
716                + "distances. By (de-)activating core- and reachability-\n"
717                + "distances in the 'General Settings'-Panel you can\n"
718                + "influence the visualization in detail. Simply use the\n"
719                + "'Vertical Adjustment'-Slider to emphasize the plot of\n"
720                + "distances. The 'Colors'-Panel lets you define different\n"
721                + "colors of the graph background, core- and reachability-\n"
722                + "distances. Click the 'Reset'-Button to restore the\n"
723                + "defaults.\n"
724        );
725        final JScrollPane helpTextAreaScrollPane = new JScrollPane(helpTextArea,
726                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
727                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
728        helpTextAreaScrollPane.setBorder(BorderFactory.createEtchedBorder());
729        helpPanel.add(helpTextAreaScrollPane,
730                new GridBagConstraints(0, 0, 1, 1, 1, 1,
731                        GridBagConstraints.CENTER,
732                        GridBagConstraints.BOTH,
733                        new Insets(5, 5, 7, 5), 0, 0));
734
735        helpFrame.getContentPane().add(helpPanel, BorderLayout.CENTER);
736
737        helpFrame.addWindowListener(new WindowAdapter() {
738            /**
739             * Invoked when a window is in the process of being closed.
740             * The close operation can be overridden at this point.
741             */
742            public void windowClosing(WindowEvent e) {
743                helpFrame.dispose();
744            }
745
746            /**
747             * Invoked when a window has been opened.
748             */
749            public void windowOpened(WindowEvent e) {
750                helpTextAreaScrollPane.getVerticalScrollBar().setValue(0);
751            }
752        });
753
754        JPanel closeButtonPanel = new JPanel(new GridBagLayout());
755
756        JButton closeButton = new JButton("Close");
757        closeButton.addActionListener(new ActionListener() {
758            public void actionPerformed(ActionEvent e) {
759                if (e.getActionCommand().equals("Close")) {
760                    helpFrame.dispose();
761                }
762            }
763        });
764        closeButtonPanel.add(closeButton,
765                new GridBagConstraints(0, 0, 1, 1, 1, 1,
766                        GridBagConstraints.CENTER,
767                        GridBagConstraints.NONE,
768                        new Insets(0, 0, 5, 0), 0, 0));
769
770        helpFrame.getContentPane().add(closeButtonPanel, BorderLayout.SOUTH);
771        helpFrame.setSize(new Dimension(480, 400));
772        Rectangle frameDimension = frame.getBounds();
773        Point p = frame.getLocation();
774        Rectangle helpFrameDimension = helpFrame.getBounds();
775        helpFrame.setLocation(((frameDimension.width - helpFrameDimension.width) / 2) + (int) p.getX(),
776                ((frameDimension.height - helpFrameDimension.height) / 2) + (int) p.getY());
777        helpFrame.setVisible(true);
778        helpFrame.toFront();
779    }
780   
781    /**
782     * Returns the revision string.
783     *
784     * @return          the revision
785     */
786    public String getRevision() {
787      return RevisionUtils.extract("$Revision: 4791 $");
788    }
789   
790    /**
791     * Displays the GUI. If an optics file is provided as first parameter,
792     * this will be loaded and displayed automatically.
793     *
794     * @param args              the commandline parameters
795     * @throws Exception        if something goes wrong
796     */
797    public static void main(String[] args) throws Exception {
798      SERObject serObject = null;
799      if (args.length == 1) {
800        System.out.println("Attempting to load: " + args[0]);
801        ObjectInputStream is = null;
802        try {
803          FileInputStream fs = new FileInputStream(args[0]);
804          is = new ObjectInputStream(fs);
805          serObject = (SERObject) is.readObject();
806        }
807        catch (Exception e) {
808          serObject = null;
809          JOptionPane.showMessageDialog(
810              null,
811              "Error loading file:\n" + e,
812              "Error", JOptionPane.ERROR_MESSAGE);
813        }
814        finally {
815          try {
816            is.close();
817          }
818          catch (Exception e) {
819            // ignored
820          }
821        }
822      }
823     
824      // open GUI
825      new OPTICS_Visualizer(serObject, "OPTICS Visualizer - Main Window");
826    }
827
828    // *****************************************************************************************************************
829    // inner classes
830    // *****************************************************************************************************************
831
832    private class FrameListener
833        implements ActionListener, RevisionHandler {
834     
835        /**
836         * Invoked when an action occurs.
837         */
838        public void actionPerformed(ActionEvent e) {
839            if (e.getSource() == parameters || e.getSource() == toolBarButton_parameters) {
840                loadStatisticsFrame();
841            }
842
843            if (e.getSource() == about || e.getSource() == toolBarButton_about) {
844                JOptionPane.showMessageDialog(frame,
845                        "OPTICS Visualizer\n$ Rev 1.4 $\n\nCopyright (C) 2004 " +
846                        "Rainer Holzmann, Zhanna Melnikova-Albrecht",
847                        "About", JOptionPane.INFORMATION_MESSAGE);
848            }
849
850            if (e.getSource() == help || e.getSource() == toolBarButton_help) {
851                loadHelpFrame();
852            }
853
854            if (e.getSource() == exit) {
855                frame.dispose();
856            }
857
858            if (e.getSource() == open || e.getSource() == toolBarButton_open) {
859                jFileChooser.setDialogTitle("Open OPTICS-Session");
860                if (lastPath == null) {
861                    lastPath = System.getProperty("user.dir");
862                }
863                jFileChooser.setCurrentDirectory(new File(lastPath));
864                int ret = jFileChooser.showOpenDialog(frame);
865                SERObject serObject_1 = null;
866                if (ret == JFileChooser.APPROVE_OPTION) {
867                    File f = jFileChooser.getSelectedFile();
868                    try {
869                        FileInputStream fs = new FileInputStream(f.getAbsolutePath());
870                        ObjectInputStream is = new ObjectInputStream(fs);
871                        serObject_1 = (SERObject) is.readObject();
872                        is.close();
873                    } catch (FileNotFoundException e1) {
874                        JOptionPane.showMessageDialog(frame,
875                                "File not found.",
876                                "Error", JOptionPane.ERROR_MESSAGE);
877                    } catch (ClassNotFoundException e1) {
878                        JOptionPane.showMessageDialog(frame,
879                                "OPTICS-Session could not be read.",
880                                "Error", JOptionPane.ERROR_MESSAGE);
881                    } catch (IOException e1) {
882                        JOptionPane.showMessageDialog(frame,
883                                "This file does not contain a valid OPTICS-Session.",
884                                "Error", JOptionPane.ERROR_MESSAGE);
885                    }
886                    if (serObject_1 != null) {
887                        int ret_1 = JOptionPane.showConfirmDialog(frame,
888                                "Open OPTICS-Session in a new window?",
889                                "Open", 1);
890                        switch (ret_1) {
891                            case 0:
892                                new OPTICS_Visualizer(serObject_1, "OPTICS Visualizer - " + f.getName());
893                                break;
894                            case 1:
895                                serObject = serObject_1;
896                                resultVectorTable.setModel(new ResultVectorTableModel(serObject.getResultVector()));
897                                tabbedPane.setTitleAt(1,
898                                        "Graph - Epsilon: " + serObject.getEpsilon() +
899                                        ", MinPoints: " + serObject.getMinPoints());
900                                graphPanel.setResultVector(serObject.getResultVector());
901                                graphPanel.adjustSize(serObject);
902                                graphPanel.repaint();
903                                break;
904                            default:
905                                break;
906                        }
907                    }
908                }
909            }
910
911            if (e.getSource() == save || e.getSource() == toolBarButton_save) {
912                jFileChooser.setDialogTitle("Save OPTICS-Session");
913
914                GregorianCalendar gregorianCalendar = new GregorianCalendar();
915                String timeStamp = gregorianCalendar.get(Calendar.DAY_OF_MONTH) + "-" +
916                        (gregorianCalendar.get(Calendar.MONTH) + 1) +
917                        "-" + gregorianCalendar.get(Calendar.YEAR) +
918                        "--" + gregorianCalendar.get(Calendar.HOUR_OF_DAY) +
919                        "-" + gregorianCalendar.get(Calendar.MINUTE) +
920                        "-" + gregorianCalendar.get(Calendar.SECOND);
921                String filename = "OPTICS_" + timeStamp + ".ser";
922
923                File file = new File(filename);
924                jFileChooser.setSelectedFile(file);
925                if (lastPath == null) {
926                    lastPath = System.getProperty("user.dir");
927                }
928                jFileChooser.setCurrentDirectory(new File(lastPath));
929
930                int ret = jFileChooser.showSaveDialog(frame);
931                if (ret == JFileChooser.APPROVE_OPTION) {
932                    file = jFileChooser.getSelectedFile();
933                    try {
934                        FileOutputStream fs = new FileOutputStream(file.getAbsolutePath());
935                        ObjectOutputStream os = new ObjectOutputStream(fs);
936                        os.writeObject(serObject);
937                        os.flush();
938                        os.close();
939                    } catch (IOException e1) {
940                        JOptionPane.showMessageDialog(frame,
941                                "OPTICS-Session could not be saved.",
942                                "Error", JOptionPane.ERROR_MESSAGE);
943                    }
944                }
945            }
946        }
947       
948        /**
949         * Returns the revision string.
950         *
951         * @return              the revision
952         */
953        public String getRevision() {
954          return RevisionUtils.extract("$Revision: 4791 $");
955        }
956    }
957
958    private class SettingsPanelListener
959        implements ActionListener, RevisionHandler {
960     
961        /**
962         * Invoked when an action occurs.
963         */
964        public void actionPerformed(ActionEvent e) {
965            if (e.getSource() == coreDistanceColorButton) {
966                Color c = getSelectedColor("Select 'Core-Distance' color");
967                if (c != null) {
968                    coreDistanceColorButton.setBackground(c);
969                    graphPanel.setCoreDistanceColor(c);
970                }
971            }
972            if (e.getSource() == reachDistanceColorButton) {
973                Color c = getSelectedColor("Select 'Reachability-Distance' color");
974                if (c != null) {
975                    reachDistanceColorButton.setBackground(c);
976                    graphPanel.setReachabilityDistanceColor(c);
977                }
978            }
979            if (e.getSource() == graphBackgroundColorButton) {
980                Color c = getSelectedColor("Select 'Graph Background' color");
981                if (c != null) {
982                    graphBackgroundColorButton.setBackground(c);
983                    graphPanel.setBackground(c);
984                }
985            }
986            if (e.getSource() == resetColorButton) {
987                coreDistanceColorButton.setBackground(new Color(100, 100, 100));
988                graphPanel.setCoreDistanceColor(new Color(100, 100, 100));
989                reachDistanceColorButton.setBackground(Color.orange);
990                graphPanel.setReachabilityDistanceColor(Color.orange);
991                graphBackgroundColorButton.setBackground(new Color(255, 255, 179));
992                graphPanel.setBackground(new Color(255, 255, 179));
993                graphPanel.repaint();
994            }
995        }
996
997        private Color getSelectedColor(String title) {
998            Color c = JColorChooser.showDialog(frame, title, Color.black);
999            return c;
1000        }
1001       
1002        /**
1003         * Returns the revision string.
1004         *
1005         * @return              the revision
1006         */
1007        public String getRevision() {
1008          return RevisionUtils.extract("$Revision: 4791 $");
1009        }
1010    }
1011}
Note: See TracBrowser for help on using the repository browser.