/**
* Copyright (C) 2001-2017 by RapidMiner and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapidminer.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.mathplot;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.AbstractButton;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import org.math.plot.PlotPanel;
import com.rapidminer.datatable.DataTable;
import com.rapidminer.gui.plotter.Plotter;
import com.rapidminer.gui.plotter.PlotterAdapter;
import com.rapidminer.gui.plotter.PlotterConfigurationModel;
import com.rapidminer.gui.plotter.PlotterLegend;
/**
* The abstract super class for all plotters using the JMathPlot library. The actual plotting must
* be done in the method {@link #paintComponent(Graphics)} where some helper methods defined in this
* class can be used. Another method usually implemented is {@link #getNumberOfAxes()}.
*
* @author Ingo Mierswa, Sebastian Land
*/
public abstract class JMathPlotter extends PlotterAdapter {
/**
*
*/
private static final long serialVersionUID = -7018389000051768349L;
/** Indicates the position of the JMathPlot legend. */
private static final String LEGEND_POSITION = "NORTH";
/** The currently used data table object. */
private DataTable dataTable;
/** The actual plotter panel of JMathPlot. */
private PlotPanel plotpanel;
/** The plotter legend which can be used to display the values with respect to the used colors. */
private PlotterLegend legend;
/** Indicates which columns will be plotted. */
private boolean[] columns = new boolean[0];
/** The used axes columns. */
private int[] axis = new int[] { -1, -1 };
/**
* Creates a new JMathPlotter. If the method {@link #hasRapidMinerValueLegend()} returns true,
* the usual RapidMiner color legend will be used ( {@link PlotterLegend}).
*/
public JMathPlotter(PlotterConfigurationModel settings) {
super(settings);
this.axis = new int[getNumberOfAxes()];
for (int i = 0; i < this.axis.length; i++) {
this.axis[i] = -1;
}
}
/** Creates the new plotter and sets the data table. */
public JMathPlotter(PlotterConfigurationModel settings, DataTable dataTable) {
this(settings);
setDataTable(dataTable);
}
/**
* Returns this. Subclasses which do not want to use this object (JPanel) for plotting should
* directly implement {@link Plotter}.
*/
@Override
public JComponent getPlotter() {
if (this.plotpanel == null) {
this.plotpanel = createPlotPanel();
if (hasLegend()) {
this.plotpanel.addLegend(LEGEND_POSITION);
}
GridBagLayout layout = new GridBagLayout();
this.setLayout(layout);
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.gridwidth = GridBagConstraints.REMAINDER;
c.weightx = 1;
if (hasRapidMinerValueLegend()) {
legend = new PlotterLegend(this);
c.weighty = 0;
JPanel legendPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
legendPanel.setBackground(Color.white);
legendPanel.add(legend);
layout.setConstraints(legendPanel, c);
add(legendPanel);
}
c.weighty = 1;
layout.setConstraints(plotpanel, c);
add(plotpanel);
}
return this;
}
/** Must be implemented by subclasses in order to support 2D or 3D plots. */
protected abstract PlotPanel createPlotPanel();
protected abstract void update();
protected abstract int getNumberOfOptionIcons();
// =============================
// helper method for subclasses
// =============================
protected PlotterLegend getLegendComponent() {
return this.legend;
}
protected boolean hasLegend() {
return true;
}
protected boolean hasRapidMinerValueLegend() {
return false;
}
protected DataTable getDataTable() {
return this.dataTable;
}
protected int countColumns() {
return this.columns.length;
}
protected PlotPanel getPlotPanel() {
if (this.plotpanel == null) {
getPlotter();
}
return this.plotpanel;
}
// ==============================================
@Override
public void setAxis(int index, int dimension) {
if (index < getNumberOfAxes()) {
if (axis[index] != dimension) {
axis[index] = dimension;
}
}
repaint();
}
@Override
public int getAxis(int index) {
if (index >= 0 && index < getNumberOfAxes()) {
if (this.axis == null) {
return -1;
} else {
return this.axis[index];
}
} else {
return -1;
}
}
@Override
public void setDataTable(DataTable dataTable) {
super.setDataTable(dataTable);
this.dataTable = dataTable;
columns = new boolean[dataTable.getNumberOfColumns()];
}
@Override
public Icon getIcon(int index) {
return null;
}
@Override
public int getNumberOfAxes() {
return 2;
}
@Override
public String getAxisName(int index) {
switch (index) {
case 0:
return "x-Axis";
case 1:
return "y-Axis";
default:
return "none";
}
}
@Override
public void setPlotColumn(int index, boolean plot) {
if (getValuePlotSelectionType() == MULTIPLE_SELECTION) {
if (this.columns[index] != plot) {
if (index != -1) {
columns[index] = plot;
}
}
} else {
this.columns = new boolean[columns.length];
if (index != -1) {
this.columns[index] = plot;
}
}
repaint();
}
@Override
public boolean getPlotColumn(int index) {
return columns[index];
}
/**
* Removes the data view button and adds the legend under the plotter panel if the method
* {@link #hasLegend()} returns true.
*/
@Override
public JComponent getOptionsComponent(int index) {
if (index == 0) {
// removes the icon for dataview in the toolbar
while (this.plotpanel.plotToolBar.getComponentCount() > getNumberOfOptionIcons()) {
this.plotpanel.plotToolBar.remove(this.plotpanel.plotToolBar.getComponentCount() - 1);
}
for (int i = 0; i < plotpanel.plotToolBar.getComponentCount(); i++) {
Component c = plotpanel.plotToolBar.getComponent(i);
if (c instanceof JButton) {
((AbstractButton) c).setContentAreaFilled(false);
}
}
return this.plotpanel.plotToolBar;
} else {
return null;
}
}
@Override
public void repaint() {
update();
super.repaint();
}
}