/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * Copyright (C) 2004 * & Matthias Schubert (schubert@dbs.ifi.lmu.de) * & Zhanna Melnikova-Albrecht (melnikov@cip.ifi.lmu.de) * & Rainer Holzmann (holzmann@cip.ifi.lmu.de) */ package weka.clusterers.forOPTICSAndDBScan.OPTICS_GUI; import weka.core.FastVector; import weka.core.RevisionHandler; import weka.core.RevisionUtils; import weka.gui.LookAndFeel; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.table.DefaultTableColumnModel; import javax.swing.table.TableColumn; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.Calendar; import java.util.GregorianCalendar; /** * Start the OPTICS Visualizer from command-line: <br/> * <code>java weka.clusterers.forOPTICSAndDBScan.OPTICS_GUI.OPTICS_Visualizer [file.ser]</code> * <br/> * * <p> * OPTICS_Visualizer.java <br/> * Authors: Rainer Holzmann, Zhanna Melnikova-Albrecht <br/> * Date: Sep 12, 2004 <br/> * Time: 8:01:13 PM <br/> * $ Revision 1.4 $ <br/> * </p> * * @author Zhanna Melnikova-Albrecht (melnikov@cip.ifi.lmu.de) * @author Rainer Holzmann (holzmann@cip.ifi.lmu.de) * @version $Revision: 4791 $ */ public class OPTICS_Visualizer implements RevisionHandler { /** * Holds the OPTICS clustering results */ private SERObject serObject; /** * Main Window of the OPTICS-Visualizer */ private JFrame frame; /** * Statistic-frame */ private JFrame statisticsFrame; /** * Help-frame */ private JFrame helpFrame; /** * Listener for menu- and toolBar actions */ private FrameListener frameListener; /** * Holds the toolBar and its components */ private JToolBar toolBar; private JButton toolBarButton_open; private JButton toolBarButton_save; private JButton toolBarButton_parameters; private JButton toolBarButton_help; private JButton toolBarButton_about; /** * Holds the default-menu and its components */ private JMenuBar defaultMenuBar; private JMenuItem open; private JMenuItem save; private JMenuItem exit; private JMenuItem parameters; private JMenuItem help; private JMenuItem about; /** * Holds the tabbedPane and its components */ private JTabbedPane tabbedPane; private JTable resultVectorTable; private GraphPanel graphPanel; private JScrollPane graphPanelScrollPane; /** * Holds the settingsPanel and its components */ private JPanel settingsPanel; private JCheckBox showCoreDistances; private JCheckBox showReachabilityDistances; private int verValue = 30; private JSlider verticalSlider; private JButton coreDistanceColorButton; private JButton reachDistanceColorButton; private JButton graphBackgroundColorButton; private JButton resetColorButton; /** * FileChooser for saving- and open-actions */ private JFileChooser jFileChooser; private String lastPath; // ***************************************************************************************************************** // constructors // ***************************************************************************************************************** public OPTICS_Visualizer(SERObject serObject, String title) { this.serObject = serObject; LookAndFeel.setLookAndFeel(); frame = new JFrame(title); frame.addWindowListener(new WindowAdapter() { /** * Invoked when a window is in the process of being closed. * The close operation can be overridden at this point. */ public void windowClosing(WindowEvent e) { frame.dispose(); } }); frame.getContentPane().setLayout(new BorderLayout()); frame.setSize(new Dimension(800, 600)); Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); Rectangle windowRectangle = frame.getBounds(); frame.setLocation((screenDimension.width - windowRectangle.width) / 2, (screenDimension.height - windowRectangle.height) / 2); frameListener = new FrameListener(); jFileChooser = new JFileChooser(); jFileChooser.setFileFilter(new SERFileFilter("ser", "Java Serialized Object File (*.ser)")); createGUI(); frame.setVisible(true); frame.toFront(); } // ***************************************************************************************************************** // methods // ***************************************************************************************************************** /** * Constructs the main-layout for the OPTICS-Visualizer */ private void createGUI() { setMenuBar(constructDefaultMenuBar()); frame.getContentPane().add(createToolBar(), BorderLayout.NORTH); frame.getContentPane().add(createTabbedPane(), BorderLayout.CENTER); frame.getContentPane().add(createSettingsPanel(), BorderLayout.SOUTH); disableSettingsPanel(); } /** * Creates the settings-panel * @return Settings-panel */ private JComponent createSettingsPanel() { settingsPanel = new JPanel(new GridBagLayout()); SettingsPanelListener panelListener = new SettingsPanelListener(); JPanel setPanelLeft = new JPanel(new GridBagLayout()); setPanelLeft.setBorder(BorderFactory.createTitledBorder(" General Settings ")); JPanel checkBoxesPanel = new JPanel(new GridLayout(1, 2)); showCoreDistances = new JCheckBox("Show Core-Distances"); showCoreDistances.setSelected(true); showReachabilityDistances = new JCheckBox("Show Reachability-Distances"); showReachabilityDistances.setSelected(true); showCoreDistances.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) { graphPanel.setShowCoreDistances(true); graphPanel.adjustSize(serObject); graphPanel.repaint(); } else if (e.getStateChange() == ItemEvent.DESELECTED) { graphPanel.setShowCoreDistances(false); graphPanel.adjustSize(serObject); graphPanel.repaint(); } } }); showReachabilityDistances.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) { graphPanel.setShowReachabilityDistances(true); graphPanel.adjustSize(serObject); graphPanel.repaint(); } else if (e.getStateChange() == ItemEvent.DESELECTED) { graphPanel.setShowReachabilityDistances(false); graphPanel.adjustSize(serObject); graphPanel.repaint(); } } }); checkBoxesPanel.add(showCoreDistances); checkBoxesPanel.add(showReachabilityDistances); JPanel verticalAdPanel = new JPanel(new BorderLayout()); final JLabel verValueLabel = new JLabel("Vertical Adjustment: " + verValue); verticalAdPanel.add(verValueLabel, BorderLayout.NORTH); verticalSlider = new JSlider(JSlider.HORIZONTAL, 0, frame.getHeight(), verValue); verticalSlider.setMajorTickSpacing(100); verticalSlider.setMinorTickSpacing(10); verticalSlider.setPaintTicks(true); verticalSlider.setPaintLabels(true); verticalSlider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { if (!verticalSlider.getValueIsAdjusting()) { verValue = verticalSlider.getValue(); verValueLabel.setText("Vertical Adjustment: " + verValue); graphPanel.setVerticalAdjustment(verValue); graphPanel.repaint(); } } }); verticalAdPanel.add(verticalSlider, BorderLayout.CENTER); setPanelLeft.add(checkBoxesPanel, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); setPanelLeft.add(verticalAdPanel, new GridBagConstraints(0, 1, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); settingsPanel.add(setPanelLeft, new GridBagConstraints(0, 0, 1, 1, 3, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 0), 0, 0)); JPanel setPanelRight = new JPanel(new GridBagLayout()); setPanelRight.setBorder(BorderFactory.createTitledBorder(" Colors ")); JPanel colorsPanel = new JPanel(new GridLayout(4, 2, 10, 10)); colorsPanel.add(new JLabel("Core-Distance: ")); coreDistanceColorButton = new JButton(); coreDistanceColorButton.setBackground(new Color(100, 100, 100)); coreDistanceColorButton.addActionListener(panelListener); colorsPanel.add(coreDistanceColorButton); colorsPanel.add(new JLabel("Reachability-Distance: ")); reachDistanceColorButton = new JButton(); reachDistanceColorButton.setBackground(Color.orange); reachDistanceColorButton.addActionListener(panelListener); colorsPanel.add(reachDistanceColorButton); colorsPanel.add(new JLabel("Graph Background: ")); graphBackgroundColorButton = new JButton(); graphBackgroundColorButton.setBackground(new Color(255, 255, 179)); graphBackgroundColorButton.addActionListener(panelListener); colorsPanel.add(graphBackgroundColorButton); colorsPanel.add(new JLabel()); resetColorButton = new JButton("Reset"); resetColorButton.addActionListener(panelListener); colorsPanel.add(resetColorButton); setPanelRight.add(colorsPanel, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); settingsPanel.add(setPanelRight, new GridBagConstraints(1, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0)); return settingsPanel; } /** * Disables all components from the settingsPanel */ private void disableSettingsPanel() { verticalSlider.setEnabled(false); coreDistanceColorButton.setEnabled(false); reachDistanceColorButton.setEnabled(false); graphBackgroundColorButton.setEnabled(false); resetColorButton.setEnabled(false); settingsPanel.setVisible(false); } /** * Enables all components from the settingsPanel */ private void enableSettingsPanel() { verticalSlider.setEnabled(true); coreDistanceColorButton.setEnabled(true); reachDistanceColorButton.setEnabled(true); graphBackgroundColorButton.setEnabled(true); resetColorButton.setEnabled(true); settingsPanel.setVisible(true); } /** * Creates the TabbedPane * @return TabbedPane */ private JComponent createTabbedPane() { tabbedPane = new JTabbedPane(); tabbedPane.addTab("Table", new ImageIcon(Toolkit.getDefaultToolkit(). getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Table16.gif"))), clusteringResultsTable(), "Show table of DataObjects, Core- and Reachability-Distances"); if (serObject != null) tabbedPane.addTab("Graph - Epsilon: " + serObject.getEpsilon() + ", MinPoints: " + serObject.getMinPoints() , new ImageIcon(Toolkit.getDefaultToolkit(). getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Graph16.gif"))), graphPanel(), "Show Plot of Core- and Reachability-Distances"); else tabbedPane.addTab( "Graph - Epsilon: --, MinPoints: --", new ImageIcon( Toolkit.getDefaultToolkit().getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Graph16.gif"))), graphPanel(), "Show Plot of Core- and Reachability-Distances"); tabbedPane.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { int c = tabbedPane.getSelectedIndex(); if (c == 0) disableSettingsPanel(); else enableSettingsPanel(); } }); return tabbedPane; } /** * Creates the ToolBar * @return ToolBar */ private JComponent createToolBar() { toolBar = new JToolBar(); toolBar.setName("OPTICS Visualizer ToolBar"); toolBar.setFloatable(false); toolBarButton_open = new JButton(new ImageIcon(Toolkit.getDefaultToolkit(). getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Open16.gif")))); toolBarButton_open.setToolTipText("Open OPTICS-Session"); toolBarButton_open.addActionListener(frameListener); toolBar.add(toolBarButton_open); toolBarButton_save = new JButton(new ImageIcon(Toolkit.getDefaultToolkit(). getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Save16.gif")))); toolBarButton_save.setToolTipText("Save OPTICS-Session"); toolBarButton_save.addActionListener(frameListener); toolBar.add(toolBarButton_save); toolBar.addSeparator(new Dimension(10, 25)); toolBarButton_parameters = new JButton(new ImageIcon(Toolkit.getDefaultToolkit(). getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Parameters16.gif")))); toolBarButton_parameters.setToolTipText("Show epsilon, MinPoints..."); toolBarButton_parameters.addActionListener(frameListener); toolBar.add(toolBarButton_parameters); toolBar.addSeparator(new Dimension(10, 25)); toolBarButton_help = new JButton(new ImageIcon(Toolkit.getDefaultToolkit(). getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Help16.gif")))); toolBarButton_help.setToolTipText("Help topics"); toolBarButton_help.addActionListener(frameListener); toolBar.add(toolBarButton_help); toolBarButton_about = new JButton(new ImageIcon(Toolkit.getDefaultToolkit(). getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Information16.gif")))); toolBarButton_about.setToolTipText("About"); toolBarButton_about.addActionListener(frameListener); toolBar.add(toolBarButton_about); return toolBar; } /** * Creates the OPTICS clustering results table * @return Table */ private JComponent clusteringResultsTable() { resultVectorTable = new JTable(); String[] resultVectorTableColumnNames = {"Key", "DataObject", "Core-Distance", "Reachability-Distance"}; DefaultTableColumnModel resultVectorTableColumnModel = new DefaultTableColumnModel(); for (int i = 0; i < resultVectorTableColumnNames.length; i++) { TableColumn tc = new TableColumn(i); tc.setHeaderValue(resultVectorTableColumnNames[i]); resultVectorTableColumnModel.addColumn(tc); } ResultVectorTableModel resultVectorTableModel; if (serObject != null) resultVectorTableModel = new ResultVectorTableModel(serObject.getResultVector()); else resultVectorTableModel = new ResultVectorTableModel(null); resultVectorTable = new JTable(resultVectorTableModel, resultVectorTableColumnModel); resultVectorTable.getColumnModel().getColumn(0).setPreferredWidth(70); resultVectorTable.getColumnModel().getColumn(1).setPreferredWidth(400); resultVectorTable.getColumnModel().getColumn(2).setPreferredWidth(150); resultVectorTable.getColumnModel().getColumn(3).setPreferredWidth(150); resultVectorTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); JScrollPane resultVectorTableScrollPane = new JScrollPane(resultVectorTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); return resultVectorTableScrollPane; } /** * Creates the OPTICS Plot * @return JComponent with the PLOT */ private JComponent graphPanel() { if (serObject == null) { graphPanel = new GraphPanel(new FastVector(), verValue, true, true); } else { graphPanel = new GraphPanel(serObject.getResultVector(), verValue, true, true); graphPanel.setPreferredSize(new Dimension((10 * serObject.getDatabaseSize()) + serObject.getDatabaseSize(), graphPanel.getHeight())); } graphPanel.setBackground(new Color(255, 255, 179)); graphPanel.setOpaque(true); graphPanelScrollPane = new JScrollPane(graphPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); return (graphPanelScrollPane); } /** * Constructs the default MenuBar * @return MenuBar */ private JMenuBar constructDefaultMenuBar() { defaultMenuBar = new JMenuBar(); JMenu fileMenu = new JMenu("File"); fileMenu.setMnemonic('F'); open = new JMenuItem("Open...", new ImageIcon(Toolkit.getDefaultToolkit(). getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Open16.gif")))); open.setMnemonic('O'); open.setAccelerator(KeyStroke.getKeyStroke('O', Event.CTRL_MASK)); open.addActionListener(frameListener); fileMenu.add(open); save = new JMenuItem("Save...", new ImageIcon(Toolkit.getDefaultToolkit(). getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Save16.gif")))); save.setMnemonic('S'); save.setAccelerator(KeyStroke.getKeyStroke('S', Event.CTRL_MASK)); save.addActionListener(frameListener); fileMenu.add(save); fileMenu.addSeparator(); exit = new JMenuItem("Exit", 'X'); exit.addActionListener(frameListener); fileMenu.add(exit); defaultMenuBar.add(fileMenu); JMenu toolsMenu = new JMenu("View"); toolsMenu.setMnemonic('V'); parameters = new JMenuItem("Parameters...", new ImageIcon(Toolkit.getDefaultToolkit(). getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Parameters16.gif")))); parameters.setMnemonic('P'); parameters.setAccelerator(KeyStroke.getKeyStroke('P', Event.CTRL_MASK)); parameters.addActionListener(frameListener); toolsMenu.add(parameters); defaultMenuBar.add(toolsMenu); JMenu miscMenu = new JMenu("Help"); miscMenu.setMnemonic('H'); help = new JMenuItem("Help Topics", new ImageIcon(Toolkit.getDefaultToolkit(). getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Help16.gif")))); help.setMnemonic('H'); help.setAccelerator(KeyStroke.getKeyStroke('H', Event.CTRL_MASK)); help.addActionListener(frameListener); miscMenu.add(help); about = new JMenuItem("About...", new ImageIcon(Toolkit.getDefaultToolkit(). getImage(ClassLoader.getSystemResource("weka/clusterers/forOPTICSAndDBScan/OPTICS_GUI/Graphics/Information16.gif")))); about.setMnemonic('A'); about.setAccelerator(KeyStroke.getKeyStroke('A', Event.CTRL_MASK)); about.addActionListener(frameListener); miscMenu.add(about); defaultMenuBar.add(miscMenu); return defaultMenuBar; } /** * Sets a MenuBar for the this frame * @param menuBar New MenuBar */ private void setMenuBar(JMenuBar menuBar) { frame.setJMenuBar(menuBar); } /** * Shows a little frame with statistic information about the OPTICS-results */ private void loadStatisticsFrame() { statisticsFrame = new JFrame("Parameters"); statisticsFrame.getContentPane().setLayout(new BorderLayout()); JPanel statPanel_Labels = new JPanel(new GridBagLayout()); JPanel statPanel_Labels_Left = new JPanel(new GridLayout(9, 1)); JPanel statPanel_Labels_Right = new JPanel(new GridLayout(9, 1)); statPanel_Labels_Left.add(new JLabel("Number of clustered DataObjects: ")); statPanel_Labels_Right.add(new JLabel(Integer.toString(serObject.getDatabaseSize()))); statPanel_Labels_Left.add(new JLabel("Number of attributes: ")); statPanel_Labels_Right.add(new JLabel(Integer.toString(serObject.getNumberOfAttributes()))); statPanel_Labels_Left.add(new JLabel("Epsilon: ")); statPanel_Labels_Right.add(new JLabel(Double.toString(serObject.getEpsilon()))); statPanel_Labels_Left.add(new JLabel("MinPoints: ")); statPanel_Labels_Right.add(new JLabel(Integer.toString(serObject.getMinPoints()))); statPanel_Labels_Left.add(new JLabel("Write results to file: ")); statPanel_Labels_Right.add(new JLabel(serObject.isOpticsOutputs() ? "yes" : "no")); statPanel_Labels_Left.add(new JLabel("Index: ")); statPanel_Labels_Right.add(new JLabel(serObject.getDatabase_Type())); statPanel_Labels_Left.add(new JLabel("Distance-Type: ")); statPanel_Labels_Right.add(new JLabel(serObject.getDatabase_distanceType())); statPanel_Labels_Left.add(new JLabel("Number of generated clusters: ")); statPanel_Labels_Right.add(new JLabel(Integer.toString(serObject.getNumberOfGeneratedClusters()))); statPanel_Labels_Left.add(new JLabel("Elapsed-time: ")); statPanel_Labels_Right.add(new JLabel(serObject.getElapsedTime())); statPanel_Labels.setBorder(BorderFactory.createTitledBorder(" OPTICS parameters ")); statPanel_Labels.add(statPanel_Labels_Left, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 2, 0), 0, 0)); statPanel_Labels.add(statPanel_Labels_Right, new GridBagConstraints(1, 0, 1, 1, 3, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 2, 5), 0, 0)); statisticsFrame.getContentPane().add(statPanel_Labels, BorderLayout.CENTER); statisticsFrame.addWindowListener(new WindowAdapter() { /** * Invoked when a window is in the process of being closed. * The close operation can be overridden at this point. */ public void windowClosing(WindowEvent e) { statisticsFrame.dispose(); } }); JPanel okButtonPanel = new JPanel(new GridBagLayout()); JButton okButton = new JButton("OK"); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("OK")) { statisticsFrame.dispose(); } } }); okButtonPanel.add(okButton, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 0, 5, 0), 0, 0)); statisticsFrame.getContentPane().add(okButtonPanel, BorderLayout.SOUTH); statisticsFrame.setSize(new Dimension(500, 300)); Rectangle frameDimension = frame.getBounds(); Point p = frame.getLocation(); Rectangle statisticsFrameDimension = statisticsFrame.getBounds(); statisticsFrame.setLocation(((frameDimension.width - statisticsFrameDimension.width) / 2) + (int) p.getX(), ((frameDimension.height - statisticsFrameDimension.height) / 2) + (int) p.getY()); statisticsFrame.setVisible(true); statisticsFrame.toFront(); } /** * Shows a little frame with information about handling the OPTICS Visualizer */ private void loadHelpFrame() { helpFrame = new JFrame("Help Topics"); helpFrame.getContentPane().setLayout(new BorderLayout()); JPanel helpPanel = new JPanel(new GridBagLayout()); JTextArea helpTextArea = new JTextArea(); helpTextArea.setEditable(false); helpTextArea.append( "OPTICS Visualizer Help\n" + "===========================================================\n\n" + "Open\n" + " - Open OPTICS-Session\n" + " [Ctrl-O], File | Open\n\n" + "Save\n" + " - Save OPTICS-Session\n" + " [Ctrl-S], File | Save\n\n" + "Exit\n" + " - Exit OPTICS Visualizer\n" + " [Alt-F4], File | Exit\n\n" + "Parameters\n" + " - Show epsilon, MinPoints...\n" + " [Ctrl-P], View | Parameters\n\n" + "Help Topics\n" + " - Show this frame\n" + " [Ctrl-H], Help | Help Topics\n\n" + "About\n" + " - Copyright-Information\n" + " [Ctrl-A], Help | About\n\n\n" + "Table-Pane:\n" + "-----------------------------------------------------------\n" + "The table represents the calculated clustering-order.\n" + "To save the table please select File | Save from the\n" + "menubar. Restart OPTICS with the -F option to obtain\n" + "an ASCII-formatted file of the clustering-order.\n\n" + "Graph-Pane:\n" + "-----------------------------------------------------------\n" + "The graph draws the plot of core- and reachability-\n" + "distances. By (de-)activating core- and reachability-\n" + "distances in the 'General Settings'-Panel you can\n" + "influence the visualization in detail. Simply use the\n" + "'Vertical Adjustment'-Slider to emphasize the plot of\n" + "distances. The 'Colors'-Panel lets you define different\n" + "colors of the graph background, core- and reachability-\n" + "distances. Click the 'Reset'-Button to restore the\n" + "defaults.\n" ); final JScrollPane helpTextAreaScrollPane = new JScrollPane(helpTextArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); helpTextAreaScrollPane.setBorder(BorderFactory.createEtchedBorder()); helpPanel.add(helpTextAreaScrollPane, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 7, 5), 0, 0)); helpFrame.getContentPane().add(helpPanel, BorderLayout.CENTER); helpFrame.addWindowListener(new WindowAdapter() { /** * Invoked when a window is in the process of being closed. * The close operation can be overridden at this point. */ public void windowClosing(WindowEvent e) { helpFrame.dispose(); } /** * Invoked when a window has been opened. */ public void windowOpened(WindowEvent e) { helpTextAreaScrollPane.getVerticalScrollBar().setValue(0); } }); JPanel closeButtonPanel = new JPanel(new GridBagLayout()); JButton closeButton = new JButton("Close"); closeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("Close")) { helpFrame.dispose(); } } }); closeButtonPanel.add(closeButton, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 5, 0), 0, 0)); helpFrame.getContentPane().add(closeButtonPanel, BorderLayout.SOUTH); helpFrame.setSize(new Dimension(480, 400)); Rectangle frameDimension = frame.getBounds(); Point p = frame.getLocation(); Rectangle helpFrameDimension = helpFrame.getBounds(); helpFrame.setLocation(((frameDimension.width - helpFrameDimension.width) / 2) + (int) p.getX(), ((frameDimension.height - helpFrameDimension.height) / 2) + (int) p.getY()); helpFrame.setVisible(true); helpFrame.toFront(); } /** * Returns the revision string. * * @return the revision */ public String getRevision() { return RevisionUtils.extract("$Revision: 4791 $"); } /** * Displays the GUI. If an optics file is provided as first parameter, * this will be loaded and displayed automatically. * * @param args the commandline parameters * @throws Exception if something goes wrong */ public static void main(String[] args) throws Exception { SERObject serObject = null; if (args.length == 1) { System.out.println("Attempting to load: " + args[0]); ObjectInputStream is = null; try { FileInputStream fs = new FileInputStream(args[0]); is = new ObjectInputStream(fs); serObject = (SERObject) is.readObject(); } catch (Exception e) { serObject = null; JOptionPane.showMessageDialog( null, "Error loading file:\n" + e, "Error", JOptionPane.ERROR_MESSAGE); } finally { try { is.close(); } catch (Exception e) { // ignored } } } // open GUI new OPTICS_Visualizer(serObject, "OPTICS Visualizer - Main Window"); } // ***************************************************************************************************************** // inner classes // ***************************************************************************************************************** private class FrameListener implements ActionListener, RevisionHandler { /** * Invoked when an action occurs. */ public void actionPerformed(ActionEvent e) { if (e.getSource() == parameters || e.getSource() == toolBarButton_parameters) { loadStatisticsFrame(); } if (e.getSource() == about || e.getSource() == toolBarButton_about) { JOptionPane.showMessageDialog(frame, "OPTICS Visualizer\n$ Rev 1.4 $\n\nCopyright (C) 2004 " + "Rainer Holzmann, Zhanna Melnikova-Albrecht", "About", JOptionPane.INFORMATION_MESSAGE); } if (e.getSource() == help || e.getSource() == toolBarButton_help) { loadHelpFrame(); } if (e.getSource() == exit) { frame.dispose(); } if (e.getSource() == open || e.getSource() == toolBarButton_open) { jFileChooser.setDialogTitle("Open OPTICS-Session"); if (lastPath == null) { lastPath = System.getProperty("user.dir"); } jFileChooser.setCurrentDirectory(new File(lastPath)); int ret = jFileChooser.showOpenDialog(frame); SERObject serObject_1 = null; if (ret == JFileChooser.APPROVE_OPTION) { File f = jFileChooser.getSelectedFile(); try { FileInputStream fs = new FileInputStream(f.getAbsolutePath()); ObjectInputStream is = new ObjectInputStream(fs); serObject_1 = (SERObject) is.readObject(); is.close(); } catch (FileNotFoundException e1) { JOptionPane.showMessageDialog(frame, "File not found.", "Error", JOptionPane.ERROR_MESSAGE); } catch (ClassNotFoundException e1) { JOptionPane.showMessageDialog(frame, "OPTICS-Session could not be read.", "Error", JOptionPane.ERROR_MESSAGE); } catch (IOException e1) { JOptionPane.showMessageDialog(frame, "This file does not contain a valid OPTICS-Session.", "Error", JOptionPane.ERROR_MESSAGE); } if (serObject_1 != null) { int ret_1 = JOptionPane.showConfirmDialog(frame, "Open OPTICS-Session in a new window?", "Open", 1); switch (ret_1) { case 0: new OPTICS_Visualizer(serObject_1, "OPTICS Visualizer - " + f.getName()); break; case 1: serObject = serObject_1; resultVectorTable.setModel(new ResultVectorTableModel(serObject.getResultVector())); tabbedPane.setTitleAt(1, "Graph - Epsilon: " + serObject.getEpsilon() + ", MinPoints: " + serObject.getMinPoints()); graphPanel.setResultVector(serObject.getResultVector()); graphPanel.adjustSize(serObject); graphPanel.repaint(); break; default: break; } } } } if (e.getSource() == save || e.getSource() == toolBarButton_save) { jFileChooser.setDialogTitle("Save OPTICS-Session"); GregorianCalendar gregorianCalendar = new GregorianCalendar(); String timeStamp = gregorianCalendar.get(Calendar.DAY_OF_MONTH) + "-" + (gregorianCalendar.get(Calendar.MONTH) + 1) + "-" + gregorianCalendar.get(Calendar.YEAR) + "--" + gregorianCalendar.get(Calendar.HOUR_OF_DAY) + "-" + gregorianCalendar.get(Calendar.MINUTE) + "-" + gregorianCalendar.get(Calendar.SECOND); String filename = "OPTICS_" + timeStamp + ".ser"; File file = new File(filename); jFileChooser.setSelectedFile(file); if (lastPath == null) { lastPath = System.getProperty("user.dir"); } jFileChooser.setCurrentDirectory(new File(lastPath)); int ret = jFileChooser.showSaveDialog(frame); if (ret == JFileChooser.APPROVE_OPTION) { file = jFileChooser.getSelectedFile(); try { FileOutputStream fs = new FileOutputStream(file.getAbsolutePath()); ObjectOutputStream os = new ObjectOutputStream(fs); os.writeObject(serObject); os.flush(); os.close(); } catch (IOException e1) { JOptionPane.showMessageDialog(frame, "OPTICS-Session could not be saved.", "Error", JOptionPane.ERROR_MESSAGE); } } } } /** * Returns the revision string. * * @return the revision */ public String getRevision() { return RevisionUtils.extract("$Revision: 4791 $"); } } private class SettingsPanelListener implements ActionListener, RevisionHandler { /** * Invoked when an action occurs. */ public void actionPerformed(ActionEvent e) { if (e.getSource() == coreDistanceColorButton) { Color c = getSelectedColor("Select 'Core-Distance' color"); if (c != null) { coreDistanceColorButton.setBackground(c); graphPanel.setCoreDistanceColor(c); } } if (e.getSource() == reachDistanceColorButton) { Color c = getSelectedColor("Select 'Reachability-Distance' color"); if (c != null) { reachDistanceColorButton.setBackground(c); graphPanel.setReachabilityDistanceColor(c); } } if (e.getSource() == graphBackgroundColorButton) { Color c = getSelectedColor("Select 'Graph Background' color"); if (c != null) { graphBackgroundColorButton.setBackground(c); graphPanel.setBackground(c); } } if (e.getSource() == resetColorButton) { coreDistanceColorButton.setBackground(new Color(100, 100, 100)); graphPanel.setCoreDistanceColor(new Color(100, 100, 100)); reachDistanceColorButton.setBackground(Color.orange); graphPanel.setReachabilityDistanceColor(Color.orange); graphBackgroundColorButton.setBackground(new Color(255, 255, 179)); graphPanel.setBackground(new Color(255, 255, 179)); graphPanel.repaint(); } } private Color getSelectedColor(String title) { Color c = JColorChooser.showDialog(frame, title, Color.black); return c; } /** * Returns the revision string. * * @return the revision */ public String getRevision() { return RevisionUtils.extract("$Revision: 4791 $"); } } }