/**
* 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.viewer;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.LinkedList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import com.rapidminer.example.ExampleSet;
import com.rapidminer.example.set.Condition;
import com.rapidminer.example.set.ConditionCreationException;
import com.rapidminer.example.set.ConditionedExampleSet;
import com.rapidminer.gui.RapidMinerGUI;
import com.rapidminer.gui.look.Colors;
import com.rapidminer.gui.look.RapidLookTools;
import com.rapidminer.gui.tools.ExtendedJScrollPane;
import com.rapidminer.operator.tools.ExpressionEvaluationException;
import com.rapidminer.report.Tableable;
import com.rapidminer.tools.I18N;
import com.rapidminer.tools.ParameterService;
/**
* Can be used to display (parts of) the data by means of a JTable. Used to display
* {@link ExampleSet} results. Uses a {@link DataViewerTable} to display the data.
*
* @author Ingo Mierswa
*/
public class DataViewer extends JPanel implements Tableable {
private static final long serialVersionUID = -8114228636932871865L;
private static final int DEFAULT_MAX_SIZE_FOR_FILTERING = 100000;
private JLabel generalInfo = new JLabel();
{
generalInfo.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
}
private DataViewerTable dataTable = new DataViewerTable();
/** Filter label display. */
private JLabel filterLabel;
private transient ExampleSet originalExampleSet;
private JScrollPane tableScrollPane;
public DataViewer(ExampleSet exampleSet, boolean providedFilter) {
super(new BorderLayout());
setOpaque(true);
setBackground(Colors.WHITE);
this.originalExampleSet = exampleSet;
JPanel headerBar = new JPanel(new GridBagLayout());
headerBar.setOpaque(true);
headerBar.setBackground(Colors.WHITE);
headerBar.setBorder(BorderFactory.createEmptyBorder(7, 5, 0, 10));
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
StringBuffer infoText = new StringBuffer("ExampleSet (");
int noExamples = originalExampleSet.size();
infoText.append(noExamples);
infoText.append(noExamples == 1 ? " example, " : " examples, ");
int noSpecial = originalExampleSet.getAttributes().specialSize();
infoText.append(noSpecial);
infoText.append(noSpecial == 1 ? " special attribute, " : " special attributes, ");
int noRegular = originalExampleSet.getAttributes().size();
infoText.append(noRegular);
infoText.append(noRegular == 1 ? " regular attribute)" : " regular attributes)");
generalInfo.setText(infoText.toString());
headerBar.add(generalInfo, gbc);
// add filler component in middle
gbc.gridx += 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
headerBar.add(new JLabel(), gbc);
// filter
if (providedFilter) {
filterLabel = new JLabel(I18N.getMessage(I18N.getGUIBundle(), "gui.label.data_view.filter.label"));
gbc.gridx += 1;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
headerBar.add(filterLabel, gbc);
updateFilterCounter(originalExampleSet);
List<String> applicableFilterNames = new LinkedList<>();
for (String conditionName : ConditionedExampleSet.KNOWN_CONDITION_NAMES) {
try {
ConditionedExampleSet.createCondition(conditionName, exampleSet, null);
applicableFilterNames.add(conditionName);
} catch (ConditionCreationException ex) {
} // Do nothing
}
String[] applicableConditions = new String[applicableFilterNames.size()];
applicableFilterNames.toArray(applicableConditions);
final JComboBox<String> filterSelector = new JComboBox<>(applicableConditions);
filterSelector.putClientProperty(RapidLookTools.PROPERTY_INPUT_BACKGROUND_DARK, true);
filterSelector.setMinimumSize(new Dimension(140, 30));
filterSelector.setPreferredSize(new Dimension(140, 30));
filterSelector
.setToolTipText("These filters can be used to skip examples in the view fulfilling the filter condition.");
filterSelector.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
updateFilter((String) filterSelector.getSelectedItem());
}
});
int maxNumberBeforeFiltering = DEFAULT_MAX_SIZE_FOR_FILTERING;
String maxString = ParameterService.getParameterValue(RapidMinerGUI.PROPERTY_RAPIDMINER_GUI_MAX_STATISTICS_ROWS);
if (maxString != null) {
try {
maxNumberBeforeFiltering = Integer.parseInt(maxString);
} catch (NumberFormatException e) {
// do nothing
}
}
if (exampleSet.size() > maxNumberBeforeFiltering) {
filterSelector.setEnabled(false);
}
gbc.gridx += 1;
gbc.fill = GridBagConstraints.VERTICAL;
gbc.weighty = 1.0;
gbc.insets = new Insets(0, 10, 0, 0);
headerBar.add(filterSelector, gbc);
}
add(headerBar, BorderLayout.NORTH);
tableScrollPane = new ExtendedJScrollPane(dataTable);
tableScrollPane.setOpaque(true);
tableScrollPane.setBorder(BorderFactory.createEmptyBorder(5, 10, 0, 10));
tableScrollPane.setBackground(Colors.WHITE);
tableScrollPane.getViewport().setBackground(Colors.WHITE);
add(tableScrollPane, BorderLayout.CENTER);
setExampleSet(exampleSet);
dataTable.unpack();
}
public void setExampleSet(ExampleSet exampleSet) {
dataTable.setExampleSet(exampleSet);
}
private void updateFilter(String conditionName) {
ExampleSet filteredExampleSet = originalExampleSet;
try {
Condition condition = ConditionedExampleSet.createCondition(conditionName, originalExampleSet, null);
filteredExampleSet = new ConditionedExampleSet(originalExampleSet, condition);
} catch (ConditionCreationException ex) {
originalExampleSet.getLog().logError(
"Cannot create condition '" + conditionName + "' for filtered data view: " + ex.getMessage()
+ ". Using original data set view...");
filteredExampleSet = originalExampleSet;
} catch (ExpressionEvaluationException ex) {
originalExampleSet.getLog().logError(
"Cannot create condition '" + conditionName + "' for filtered data view: " + ex.getMessage()
+ ". Using original data set view...");
filteredExampleSet = originalExampleSet;
}
updateFilterCounter(filteredExampleSet);
setExampleSet(filteredExampleSet);
}
private void updateFilterCounter(ExampleSet filteredExampleSet) {
filterLabel.setText(I18N.getMessage(I18N.getGUIBundle(), "gui.label.data_view.filter.label",
filteredExampleSet.size(), originalExampleSet.size()));
}
@Override
public void prepareReporting() {
dataTable.prepareReporting();
}
@Override
public void finishReporting() {
dataTable.finishReporting();
}
@Override
public String getColumnName(int columnIndex) {
return dataTable.getColumnName(columnIndex);
}
@Override
public String getCell(int row, int column) {
return dataTable.getCell(row, column);
}
@Override
public int getColumnNumber() {
return dataTable.getColumnNumber();
}
@Override
public int getRowNumber() {
return dataTable.getRowNumber();
}
@Override
public boolean isFirstLineHeader() {
return false;
}
@Override
public boolean isFirstColumnHeader() {
return false;
}
}