/* * RapidMiner * * Copyright (C) 2001-2008 by Rapid-I and the contributors * * Complete list of developers available at our web site: * * http://rapid-i.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.gui.plotter; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Font; import java.awt.Graphics; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSlider; import javax.swing.ListCellRenderer; import javax.swing.ListSelectionModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.freehep.util.export.ExportDialog; import com.rapidminer.datatable.DataTable; import com.rapidminer.gui.MainFrame; import com.rapidminer.gui.plotter.charts.BarChart2DPlotter; import com.rapidminer.gui.plotter.charts.BarChart3DPlotter; import com.rapidminer.gui.plotter.charts.BubbleChartPlotter; import com.rapidminer.gui.plotter.charts.DeviationChartPlotter; import com.rapidminer.gui.plotter.charts.PieChart2DPlotter; import com.rapidminer.gui.plotter.charts.PieChart3DPlotter; import com.rapidminer.gui.plotter.charts.RingChartPlotter; import com.rapidminer.gui.plotter.charts.SeriesChartPlotter; import com.rapidminer.gui.plotter.conditions.PlotterCondition; import com.rapidminer.gui.plotter.mathplot.BoxPlot2D; import com.rapidminer.gui.plotter.mathplot.BoxPlot3D; import com.rapidminer.gui.plotter.mathplot.ScatterPlot3D; import com.rapidminer.gui.plotter.mathplot.ScatterPlot3DColor; import com.rapidminer.gui.plotter.mathplot.SticksPlot2D; import com.rapidminer.gui.plotter.mathplot.SticksPlot3D; import com.rapidminer.gui.plotter.mathplot.SurfacePlot3D; import com.rapidminer.gui.plotter.som.SOMPlotter; import com.rapidminer.gui.tools.ExtendedJComboBox; import com.rapidminer.gui.tools.ExtendedJList; import com.rapidminer.gui.tools.ExtendedJScrollPane; import com.rapidminer.gui.tools.ExtendedListModel; import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.operator.visualization.SOMModelPlotter; import com.rapidminer.report.Renderable; import com.rapidminer.tools.LogService; /** * This is the main component for all data or statistics plotters. Depending on * the selected plotter type the options panel part is created or adapted. The * option panel usually contains selectors for up to three axis and other * options depending on the plotter like a plot amount slider or option buttons. * * @author Ingo Mierswa, Simon Fischer * @version $Id: PlotterPanel.java,v 1.27 2008/08/25 08:10:35 ingomierswa Exp $ */ public class PlotterPanel extends JPanel implements ItemListener, Runnable, Renderable, CoordinatesHandler { private static final long serialVersionUID = -8724351470349745191L; public static final int DEFAULT_MAX_NUMBER_OF_DATA_POINTS = 1000; public final static LinkedHashMap<String,Class<? extends Plotter>> COMPLETE_PLOTTER_SELECTION = new LinkedHashMap<String,Class<? extends Plotter>>(); public final static LinkedHashMap<String,Class<? extends Plotter>> WEIGHT_PLOTTER_SELECTION = new LinkedHashMap<String,Class<? extends Plotter>>(); public final static LinkedHashMap<String,Class<? extends Plotter>> DATA_SET_PLOTTER_SELECTION = new LinkedHashMap<String, Class<? extends Plotter>>(); public final static LinkedHashMap<String,Class<? extends Plotter>> MODEL_PLOTTER_SELECTION = new LinkedHashMap<String, Class<? extends Plotter>>(); static { COMPLETE_PLOTTER_SELECTION.put("Scatter", ScatterPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Scatter Matrix", ScatterMatrixPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Scatter 3D", ScatterPlot3D.class); COMPLETE_PLOTTER_SELECTION.put("Scatter 3D Color", ScatterPlot3DColor.class); COMPLETE_PLOTTER_SELECTION.put("Bubble", BubbleChartPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Parallel", ParallelPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Deviation", DeviationChartPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Series", SeriesChartPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Survey", SurveyPlotter.class); COMPLETE_PLOTTER_SELECTION.put("SOM", SOMPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Density", DensityPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Pie", PieChart2DPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Pie 3D", PieChart3DPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Ring", RingChartPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Bars", BarChart2DPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Bars 3D", BarChart3DPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Andrews Curves", AndrewsCurves.class); COMPLETE_PLOTTER_SELECTION.put("Distribution", DistributionPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Histogram", HistogramPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Histogram Color", ColorHistogramPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Histogram Matrix", HistogramMatrixPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Histogram Color Matrix", ColorHistogramMatrixPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Quartile", QuartilePlotter.class); COMPLETE_PLOTTER_SELECTION.put("Quartile Color", ColorQuartilePlotter.class); COMPLETE_PLOTTER_SELECTION.put("Quartile Color Matrix", ColorQuartileMatrixPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Sticks", SticksPlot2D.class); COMPLETE_PLOTTER_SELECTION.put("Sticks 3D", SticksPlot3D.class); COMPLETE_PLOTTER_SELECTION.put("Box", BoxPlot2D.class); COMPLETE_PLOTTER_SELECTION.put("Box 3D", BoxPlot3D.class); COMPLETE_PLOTTER_SELECTION.put("RadViz", RadVizPlotter.class); COMPLETE_PLOTTER_SELECTION.put("GridViz", GridVizPlotter.class); COMPLETE_PLOTTER_SELECTION.put("Surface 3D", SurfacePlot3D.class); COMPLETE_PLOTTER_SELECTION.put("Hinton", HintonDiagram.class); COMPLETE_PLOTTER_SELECTION.put("Bound", BoundDiagram.class); WEIGHT_PLOTTER_SELECTION.put("Lines", ScatterPlotter.class); WEIGHT_PLOTTER_SELECTION.put("Histogram", HistogramPlotter.class); WEIGHT_PLOTTER_SELECTION.put("Hinton", HintonDiagram.class); WEIGHT_PLOTTER_SELECTION.put("Bound", BoundDiagram.class); WEIGHT_PLOTTER_SELECTION.put("Pie", PieChart2DPlotter.class); WEIGHT_PLOTTER_SELECTION.put("Pie 3D", PieChart3DPlotter.class); WEIGHT_PLOTTER_SELECTION.put("Ring", RingChartPlotter.class); WEIGHT_PLOTTER_SELECTION.put("Bars", BarChart2DPlotter.class); WEIGHT_PLOTTER_SELECTION.put("Bars 3D", BarChart3DPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Scatter", ScatterPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Scatter Matrix", ScatterMatrixPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Scatter 3D", ScatterPlot3D.class); DATA_SET_PLOTTER_SELECTION.put("Scatter 3D Color", ScatterPlot3DColor.class); DATA_SET_PLOTTER_SELECTION.put("Bubble", BubbleChartPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Parallel", ParallelPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Deviation", DeviationChartPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Series", SeriesChartPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Survey", SurveyPlotter.class); DATA_SET_PLOTTER_SELECTION.put("SOM", SOMPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Density", DensityPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Pie", PieChart2DPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Pie 3D", PieChart3DPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Ring", RingChartPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Bars", BarChart2DPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Bars 3D", BarChart3DPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Andrews Curves", AndrewsCurves.class); DATA_SET_PLOTTER_SELECTION.put("Distribution", DistributionPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Histogram", HistogramPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Histogram Color", ColorHistogramPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Histogram Matrix", HistogramMatrixPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Histogram Color Matrix", ColorHistogramMatrixPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Quartile", QuartilePlotter.class); DATA_SET_PLOTTER_SELECTION.put("Quartile Color", ColorQuartilePlotter.class); DATA_SET_PLOTTER_SELECTION.put("Quartile Color Matrix", ColorQuartileMatrixPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Sticks", SticksPlot2D.class); DATA_SET_PLOTTER_SELECTION.put("Sticks 3D", SticksPlot3D.class); DATA_SET_PLOTTER_SELECTION.put("Box", BoxPlot2D.class); DATA_SET_PLOTTER_SELECTION.put("Box 3D", BoxPlot3D.class); DATA_SET_PLOTTER_SELECTION.put("RadViz", RadVizPlotter.class); DATA_SET_PLOTTER_SELECTION.put("GridViz", GridVizPlotter.class); DATA_SET_PLOTTER_SELECTION.put("Surface 3D", SurfacePlot3D.class); MODEL_PLOTTER_SELECTION.put("SOM", SOMModelPlotter.class); } /** The line style rendered for the legend (or key). */ private static class LineStyleCellRenderer extends JLabel implements ListCellRenderer { private static final long serialVersionUID = -7039142638209143602L; Plotter plotter; public LineStyleCellRenderer(Plotter plotter) { this.plotter = plotter; } public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { String s = value.toString(); setText(s); Icon icon = plotter.getIcon(index); if (icon != null) setIcon(icon); if (isSelected) { setBackground(list.getSelectionBackground()); setForeground(list.getSelectionForeground()); } else { setBackground(list.getBackground()); setForeground(list.getForeground()); } setEnabled(list.isEnabled()); setFont(list.getFont()); setOpaque(true); return this; } } /** The currently selected plotter object. */ private Plotter plotter = null; /** The current data table object which backs up the plotting. */ private transient DataTable dataTable; /** * The label which shows the coordinates in data space. Not supported by all * plotters. */ private JLabel coordinatesLabel = new JLabel(" "); /** The selected plotter type. */ private String selectedPlotter = null; /** The main panel containing the axes selection panel and the actual plotter component. */ private JPanel mainPanel = new JPanel(new BorderLayout()); /** The plotter selection combo box. */ private JComboBox plotterCombo = new JComboBox(); /** Indicates if the plotter will be available. */ private LinkedHashMap<String,Class<? extends Plotter>> availablePlotters = new LinkedHashMap<String,Class<? extends Plotter>>(); /** * Creates a new plotter panel based on the given {@link DataTable} object. */ public PlotterPanel(DataTable dataTable) { this(dataTable, DATA_SET_PLOTTER_SELECTION); } /** * Creates a new plotter panel based on the given {@link DataTable} object. */ public PlotterPanel(DataTable dataTable, LinkedHashMap<String, Class<? extends Plotter>> availablePlotters) { super(new BorderLayout()); // set available plotters and select first this.availablePlotters = availablePlotters; if ((this.availablePlotters == null) || (this.availablePlotters.size() == 0)) throw new IllegalArgumentException("The list of available plotters must not be null or empty!"); Iterator<String> i = availablePlotters.keySet().iterator(); this.selectedPlotter = i.next(); JScrollPane plotterScrollPane = new ExtendedJScrollPane(mainPanel); add(plotterScrollPane, BorderLayout.CENTER); setDataTable(dataTable); } public void setSelectedPlotter(String name) { this.selectedPlotter = name; update(false); } public Plotter getSelectedPlotter() { return this.plotter; } public void setDataTable(DataTable dataTable) { this.dataTable = dataTable; // perform sampling int maxRowNumber = DEFAULT_MAX_NUMBER_OF_DATA_POINTS; String maxRowNumberString = System.getProperty(MainFrame.PROPERTY_RAPIDMINER_GUI_PLOTTER_ROWS_MAXIMUM); if ((maxRowNumberString != null) && (maxRowNumberString.trim().length() > 0)) { try { int newMaxRows = Integer.parseInt(maxRowNumberString); maxRowNumber = newMaxRows; } catch (NumberFormatException e) { LogService.getGlobal().log("Plotter: cannot read maximum number of plotter points (was '" + maxRowNumberString + "').", LogService.WARNING); } } if (this.dataTable.getNumberOfRows() > maxRowNumber) { this.dataTable.sample(maxRowNumber); LogService.getGlobal().log("Cannot plot all data points, using only a sample of " + maxRowNumber + " rows. You can increase the number of values in the properties dialog from the tools menu, the property name is '" + MainFrame.PROPERTY_RAPIDMINER_GUI_PLOTTER_ROWS_MAXIMUM + "'", LogService.WARNING); } update(true); } private void update(boolean fillPlotterList) { int[] axis = null; List<Integer> valuesList = new LinkedList<Integer>(); if (plotter != null) { axis = new int[plotter.getNumberOfAxes()]; for (int i = 0; i < axis.length; i++) axis[i] = plotter.getAxis(i); for (int i = 0; i < dataTable.getNumberOfColumns(); i++) if (plotter.getPlotColumn(i)) valuesList.add(i); } int[] selectedIndices = new int[valuesList.size()]; int k = 0; Iterator v = valuesList.iterator(); while (v.hasNext()) selectedIndices[k++] = ((Integer) v.next()).intValue(); try { Class plotterClass = availablePlotters.get(this.selectedPlotter); if (plotterClass != null) { this.plotter = availablePlotters.get(this.selectedPlotter).newInstance(); this.plotter.setDataTable(dataTable); } } catch (Exception e) { SwingTools.showSimpleErrorMessage("Cannot instantiate plotter '" + this.selectedPlotter + "':", e); return; } mainPanel.removeAll(); PlotterMouseHandler mouseHandler = new PlotterMouseHandler(plotter, this); plotter.addMouseMotionListener(mouseHandler); plotter.addMouseListener(mouseHandler); JComponent plotterComponent = plotter.getPlotter(); mainPanel.add(plotterComponent, BorderLayout.CENTER); GridBagLayout gridBag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; c.gridwidth = GridBagConstraints.REMAINDER; c.insets = new Insets(2, 2, 2, 2); // axis selection panel (main) JPanel axesSelectionPanel = new JPanel(gridBag); // plotter list String toolTip = "The plotter which should be used for displaying data."; JLabel label = new JLabel("Plotter"); label.setToolTipText(toolTip); gridBag.setConstraints(label, c); axesSelectionPanel.add(label); if (fillPlotterList) { Thread thread = new Thread(this); thread.setPriority(Thread.MAX_PRIORITY); thread.start(); } gridBag.setConstraints(plotterCombo, c); axesSelectionPanel.add(plotterCombo); // axis selections for (int i = 0; i < plotter.getNumberOfAxes(); i++) { toolTip = "Select a column for " + plotter.getAxisName(i); label = new JLabel(plotter.getAxisName(i)); label.setToolTipText(toolTip); gridBag.setConstraints(label, c); axesSelectionPanel.add(label); final JComboBox axisCombo = new ExtendedJComboBox(200); axisCombo.setToolTipText(toolTip); axisCombo.addItem("None"); for (int j = 0; j < dataTable.getNumberOfColumns(); j++) { axisCombo.addItem(dataTable.getColumnName(j)); } final int index = i; axisCombo.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { plotter.setAxis(index, axisCombo.getSelectedIndex() - 1); } }); if ((axis != null) && (axis.length > i)) axisCombo.setSelectedIndex(Math.max(0, axis[i] + 1)); gridBag.setConstraints(axisCombo, c); axesSelectionPanel.add(axisCombo); // log scale if (plotter.isSupportingLogScale(i)) { final JCheckBox logScaleBox = new JCheckBox("Log Scale", false); logScaleBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { plotter.setLogScale(index, logScaleBox.isSelected()); } }); gridBag.setConstraints(logScaleBox, c); axesSelectionPanel.add(logScaleBox); } } // plots (colors, values, etc.) if (plotter.getValuePlotSelectionType() != Plotter.NO_SELECTION) { JLabel plotLabel; if (plotter.getPlotName() == null) { plotLabel = new JLabel("Plots"); toolTip = "Select the column which should be plotted."; } else { plotLabel = new JLabel(plotter.getPlotName()); toolTip = "Select a column for " + plotter.getPlotName(); } plotLabel.setToolTipText(toolTip); gridBag.setConstraints(plotLabel, c); axesSelectionPanel.add(plotLabel); } switch (plotter.getValuePlotSelectionType()) { case Plotter.MULTIPLE_SELECTION: ExtendedListModel model = new ExtendedListModel(); for (String name : dataTable.getColumnNames()) { model.addElement(name, "Select column '" + name + "' for plotting."); } final JList plotList = new ExtendedJList(model, 200); plotList.setToolTipText(toolTip); plotList.setBorder(BorderFactory.createLoweredBevelBorder()); plotList.setCellRenderer(new LineStyleCellRenderer(plotter)); plotList.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { for (int i = 0; i < plotList.getModel().getSize(); i++) plotter.setPlotColumn(i, plotList.isSelectedIndex(i)); } }); plotList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); plotList.setSelectedIndices(selectedIndices); JScrollPane listScrollPane = new ExtendedJScrollPane(plotList); listScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); c.weighty = 1.0; c.weightx = 0; gridBag.setConstraints(listScrollPane, c); axesSelectionPanel.add(listScrollPane); c.weighty = 0.0; c.weightx = 1; break; case Plotter.SINGLE_SELECTION: final JComboBox plotCombo = new ExtendedJComboBox(200); plotCombo.setToolTipText(toolTip); plotCombo.addItem("None"); for (int j = 0; j < dataTable.getNumberOfColumns(); j++) { plotCombo.addItem(dataTable.getColumnName(j)); } plotCombo.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { plotter.setPlotColumn(plotCombo.getSelectedIndex() - 1, true); } }); if (selectedIndices.length > 0) plotCombo.setSelectedIndex(selectedIndices[0] + 1); gridBag.setConstraints(plotCombo, c); axesSelectionPanel.add(plotCombo); break; case Plotter.NO_SELECTION: // do nothing break; } // sorting if (plotter.isSupportingSorting()) { final JCheckBox sortingBox = new JCheckBox("Sorting", false); sortingBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { plotter.setSorting(sortingBox.isSelected()); } }); gridBag.setConstraints(sortingBox, c); axesSelectionPanel.add(sortingBox); } // sorting if (plotter.isSupportingAbsoluteValues()) { final JCheckBox absoluteBox = new JCheckBox("Absolute Values", false); absoluteBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { plotter.setAbsolute(absoluteBox.isSelected()); } }); gridBag.setConstraints(absoluteBox, c); axesSelectionPanel.add(absoluteBox); } // zooming if (plotter.canHandleZooming()) { label = new JLabel("Zooming"); toolTip = "Set a new zooming factor."; label.setToolTipText(toolTip); gridBag.setConstraints(label, c); axesSelectionPanel.add(label); final JSlider zoomingSlider = new JSlider(1, 100, plotter.getInitialZoomFactor()); zoomingSlider.setToolTipText(toolTip); gridBag.setConstraints(zoomingSlider, c); axesSelectionPanel.add(zoomingSlider); zoomingSlider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { plotter.setZooming(zoomingSlider.getValue()); } }); } // jitter if (plotter.canHandleJitter()) { label = new JLabel("Jitter"); toolTip = "Select the amount of jittering (small perturbation of data points)."; label.setToolTipText(toolTip); gridBag.setConstraints(label, c); axesSelectionPanel.add(label); final JSlider jitterSlider = new JSlider(0, 100, 0); jitterSlider.setToolTipText(toolTip); gridBag.setConstraints(jitterSlider, c); axesSelectionPanel.add(jitterSlider); jitterSlider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { if (plotter.canHandleContinousJittering() || (!jitterSlider.getValueIsAdjusting())) plotter.setJitter(jitterSlider.getValue()); } }); } // option dialog if (plotter.hasOptionsDialog()) { toolTip = "Opens a dialog with further options for this plotter."; JButton optionsButton = new JButton("Options"); optionsButton.setToolTipText(toolTip); gridBag.setConstraints(optionsButton, c); axesSelectionPanel.add(optionsButton); optionsButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { plotter.showOptionsDialog(); } }); } // Add the plotter options components for user interaction, if provided int componentCounter = 0; while (plotter.getOptionsComponent(componentCounter) != null) { Component options = plotter.getOptionsComponent(componentCounter); gridBag.setConstraints(options, c); axesSelectionPanel.add(options); componentCounter++; } // Save image button for the plotter if (!plotter.hasSaveImageButton()) { toolTip = "Saves an image of the current plot."; JButton imageButton = new JButton("Save Image..."); imageButton.setToolTipText(toolTip); imageButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Component tosave = plotter.getPlotter(); ExportDialog exportDialog = new ExportDialog("RapidMiner"); exportDialog.showExportDialog(getPanel(), "Save Image...", tosave, "plot"); } }); gridBag.setConstraints(imageButton, c); axesSelectionPanel.add(imageButton); } // check if savable (for data) if (plotter.isSaveable()) { toolTip = "Saves the data underlying this plot into a file."; JButton saveButton = new JButton("Save..."); saveButton.setToolTipText(toolTip); saveButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { plotter.save(); } }); gridBag.setConstraints(saveButton, c); axesSelectionPanel.add(saveButton); } // coordinates if (plotter.isProvidingCoordinates()) { coordinatesLabel = new JLabel(" "); toolTip = "The current coordinates of the mouese cursor with respect to the data dimensions."; coordinatesLabel.setToolTipText(toolTip); coordinatesLabel.setBorder(BorderFactory.createEtchedBorder()); coordinatesLabel.setFont(new Font("Monospaced", Font.PLAIN, coordinatesLabel.getFont().getSize())); gridBag.setConstraints(coordinatesLabel, c); axesSelectionPanel.add(coordinatesLabel); } // add fill component if necessary (glue) if (plotter.getValuePlotSelectionType() != Plotter.MULTIPLE_SELECTION) { c.weighty = 1.0; JPanel fillPanel = new JPanel(); gridBag.setConstraints(fillPanel, c); axesSelectionPanel.add(fillPanel); c.weighty = 0.0; } axesSelectionPanel.setAlignmentX(LEFT_ALIGNMENT); mainPanel.add(axesSelectionPanel, BorderLayout.WEST); revalidate(); repaint(); } private Component getPanel() { return this; } public void itemStateChanged(ItemEvent e) { setSelectedPlotter((String)plotterCombo.getSelectedItem()); } public void run() { synchronized (plotterCombo) { plotterCombo.removeItemListener(this); plotterCombo.removeAllItems(); Iterator<String> n = availablePlotters.keySet().iterator(); while (n.hasNext()) { String plotterName = n.next(); try { Class<? extends Plotter> plotterClass = availablePlotters.get(plotterName); if (plotterClass != null) { Plotter plotter = plotterClass.newInstance(); PlotterCondition condition = plotter.getPlotterCondition(); if (condition.acceptDataTable(this.dataTable)) { plotterCombo.addItem(plotterName); } else { LogService.getGlobal().log("Cannot use plotter '" + plotterName + "': " + condition.getRejectionReason(this.dataTable), LogService.NOTE); } } } catch (InstantiationException e) { LogService.getGlobal().log("Plotter panel: cannot instantiate plotter '" + plotterName + "'. Skipping...", LogService.WARNING); } catch (IllegalAccessException e) { LogService.getGlobal().log("Plotter panel: cannot acess plotter '" + plotterName + "'. Skipping...", LogService.WARNING); } } plotterCombo.setToolTipText("The plotter which should be used for displaying data."); plotterCombo.addItemListener(this); } } public void prepareRendering() { plotter.prepareRendering(); } public int getRenderHeight(int preferredHeight) { return plotter.getRenderHeight(preferredHeight); } public int getRenderWidth(int preferredWidth) { return plotter.getRenderWidth(preferredWidth); } public void render(Graphics graphics, int width, int height) { plotter.render(graphics, width, height); } public void updateCoordinates(String coordinateInfo) { this.coordinatesLabel.setText(coordinateInfo); } }