/** * 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.studio.io.gui.internal.steps.configuration; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.TableCellRenderer; import org.jdesktop.swingx.JXCollapsiblePane; import org.jdesktop.swingx.JXCollapsiblePane.Direction; import com.rapidminer.gui.tools.Ionicon; import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.tools.I18N; /** * A collapsible error table that shows the content of an {@link AbstractErrorWarningTableModel}. A * label shows whether the content of the table consists of errors or warnings or the table is * empty. * * @author Gisa Schaefer * @since 7.0.0 */ public class CollapsibleErrorTable extends JPanel { private static final long serialVersionUID = 1L; /** image indicating errors */ private static final ImageIcon ICON_ERRORS_FOUND = SwingTools.createIcon("16/error.png"); /** image indicating no errors or warnings */ private static final ImageIcon ICON_NO_ERRORS_FOUND = SwingTools.createIcon("16/ok.png"); private static final ImageIcon ICON_WARNINGS_FOUND = SwingTools.createIcon("16/sign_warning.png"); /** the text for opening the error table */ private static final String SHOW_ERROR_TABLE = "<html><span style=\"text-decoration: underline;\">" + I18N.getGUILabel("csv_format_specification.view_error_details") + " " + Ionicon.CHEVRON_UP.getHtml() + "</span>"; /** the text for closing the error table */ private static final String HIDE_ERROR_TABLE = "<html><span style=\"text-decoration: underline;\">" + I18N.getGUILabel("csv_format_specification.hide_error_details") + " " + Ionicon.CHEVRON_DOWN.getHtml() + "</span>"; /** the label text when there are errors */ private static final String ERRORS_TEXT = " " + I18N.getGUILabel("csv_format_specification.label_errors"); /** the label text when there are errors and warnings */ private static final String ERRORS_AND_TEXT = " " + I18N.getGUILabel("csv_format_specification.label_errors_and") + " "; /** the label text when there are warnings */ private static final String WARNINGS_TEXT = " " + I18N.getGUILabel("csv_format_specification.label_warnings"); /** the label text when there are no errors */ private static final String NO_ERRORS_TEXT = I18N.getGUILabel("csv_format_specification.label_no_problems"); /** buffer for the table height */ private static final int ERROR_TABLE_HEIGHT_BUFFER = 10; /** maximal height of the component */ private static final int MAXIMAL_HEIGHT = 200; private final AbstractErrorWarningTableModel errorWarningTableModel; private final JTable errorTable; private final JScrollPane errorScrollPane; private final JLabel errorLabel = new JLabel(); private final JLabel openErrorLabel = new JLabel(); private boolean errorPanelCollapsed = true; final JXCollapsiblePane collapsePane = new JXCollapsiblePane(Direction.UP); public CollapsibleErrorTable(AbstractErrorWarningTableModel errorWarningTableModel) { this.errorWarningTableModel = errorWarningTableModel; errorTable = new JTable(errorWarningTableModel) { private static final long serialVersionUID = 1L; @Override public Component prepareRenderer(TableCellRenderer renderer, int row, int column) { // add tooltip for last column JComponent component = (JComponent) super.prepareRenderer(renderer, row, column); if (column == getColumnCount() - 1) { component.setToolTipText(getValueAt(row, column).toString()); } return component; } }; errorScrollPane = new JScrollPane(errorTable); errorWarningTableModel.addTableModelListener(new TableModelListener() { @Override public void tableChanged(TableModelEvent e) { update(); } }); setupGUI(); } /** * @return the error panel which can be extended to show the {@link #errorTable} if there are * errors */ private void setupGUI() { errorScrollPane.setPreferredSize(new Dimension(errorScrollPane.getPreferredSize().width, MAXIMAL_HEIGHT)); errorScrollPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); collapsePane.add(errorScrollPane); collapsePane.setCollapsed(true); this.setLayout(new BorderLayout()); this.add(collapsePane, BorderLayout.NORTH); JPanel errorContainerPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); errorContainerPanel.add(errorLabel); openErrorLabel.setText(SHOW_ERROR_TABLE); openErrorLabel.setForeground(SwingTools.RAPIDMINER_ORANGE); openErrorLabel.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { errorPanelCollapsed = !errorPanelCollapsed; if (errorPanelCollapsed) { openErrorLabel.setText(SHOW_ERROR_TABLE); } else { openErrorLabel.setText(HIDE_ERROR_TABLE); } collapsePane.setCollapsed(errorPanelCollapsed); } }); openErrorLabel.setVisible(false); errorContainerPanel.add(openErrorLabel); this.add(errorContainerPanel, BorderLayout.CENTER); } /** * Updates the content of the {@link #errorTable} and the label that is used to show it. */ public void update() { // calculate the size of the table int rowCount = errorWarningTableModel.getRowCount(); int tableHeight = rowCount * errorTable.getRowHeight() + errorTable.getTableHeader().getHeight(); int height = Math.min(MAXIMAL_HEIGHT, tableHeight + ERROR_TABLE_HEIGHT_BUFFER); errorScrollPane.setPreferredSize(new Dimension(errorScrollPane.getPreferredSize().width, height)); // Update errors summary if (rowCount == 0) { errorLabel.setText(NO_ERRORS_TEXT); errorLabel.setIcon(ICON_NO_ERRORS_FOUND); // show no error table and no link to open it openErrorLabel.setVisible(false); errorPanelCollapsed = true; openErrorLabel.setText(SHOW_ERROR_TABLE); collapsePane.setCollapsed(errorPanelCollapsed); } else { int errorCount = errorWarningTableModel.getErrorCount(); int warningCount = errorWarningTableModel.getWarningCount(); if (errorCount > 0) { errorLabel.setIcon(ICON_ERRORS_FOUND); if (warningCount > 0) { errorLabel.setText(errorCount + ERRORS_AND_TEXT + warningCount + WARNINGS_TEXT); } else { errorLabel.setText(rowCount + ERRORS_TEXT); } } else { errorLabel.setIcon(ICON_WARNINGS_FOUND); errorLabel.setText(warningCount + WARNINGS_TEXT); } openErrorLabel.setVisible(true); } } /** * @return the underlying table */ public JTable getTable() { return errorTable; } }