/*
* Copyright (C) 2011 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* 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 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 General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see http://www.gnu.org/licenses/
*/
package org.esa.snap.rcp.statistics;
import org.esa.snap.core.datamodel.ProductNodeEvent;
import org.esa.snap.core.util.StringUtils;
import org.openide.windows.TopComponent;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import java.awt.Color;
import java.awt.Component;
import java.awt.FontMetrics;
import java.util.ArrayList;
import java.util.List;
/**
* @author Thomas Storm
*/
abstract class TablePagePanel extends PagePanel {
private final TableModel emptyTableModel;
private JTable table;
TablePagePanel(TopComponent parentDialog, String helpId, String titlePrefix, String defaultInformationText) {
super(parentDialog, helpId, titlePrefix);
emptyTableModel = new DefaultTableModel(1, 1);
emptyTableModel.setValueAt(defaultInformationText, 0, 0);
table = new JTable(emptyTableModel);
}
/**
* Notified when a node changed.
*
* @param event the product node which the listener to be notified
*/
@Override
public void nodeChanged(final ProductNodeEvent event) {
if (event.getSourceNode() == getRaster() || event.getSourceNode() == getProduct()) {
updateComponents();
}
}
protected JTable getTable() {
return table;
}
protected void showNoInformationAvailableMessage() {
table.setModel(emptyTableModel);
}
protected void setColumnRenderer(int column, TableCellRenderer renderer) {
getTable().getColumnModel().getColumn(column).setCellRenderer(renderer);
}
static class RendererFactory {
final static int ALTERNATING_ROWS = 1;
final static int TOOLTIP_AWARE = 2;
final static int WRAP_TEXT = 4;
static TableCellRenderer createRenderer(int spec) {
return createRenderer(spec, null);
}
static TableCellRenderer createRenderer(int spec, Object configurator) {
final List<RendererStrategy> strategies = new ArrayList<>();
if ((spec & WRAP_TEXT) == WRAP_TEXT) {
strategies.add(new WrapTextRenderer((ArrayList<Integer>) configurator));
}
if ((spec & ALTERNATING_ROWS) == ALTERNATING_ROWS) {
strategies.add(new AlternatingRowsRenderer());
}
if ((spec & TOOLTIP_AWARE) == TOOLTIP_AWARE) {
strategies.add(new TooltipAwareRenderer());
}
return new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JTextArea textArea = new JTextArea(value.toString());
for (RendererStrategy strategy : strategies) {
strategy.customise(table, textArea, value.toString(), row, column);
}
careForEmptyLines(value, textArea);
return textArea;
}
public void careForEmptyLines(Object value, JTextArea textArea) {
if (StringUtils.isNullOrEmpty(value.toString())) {
// imbecile code, but necessary in order to show empty lines
textArea.setText("____");
textArea.setForeground(textArea.getBackground());
}
}
};
}
}
private static interface RendererStrategy {
void customise(JTable table, JTextArea component, String value, int rowIndex, int colIndex);
}
private static class AlternatingRowsRenderer implements RendererStrategy {
private Color brightBackground;
private Color mediumBackground;
public AlternatingRowsRenderer() {
brightBackground = Color.white;
mediumBackground = new Color((14 * brightBackground.getRed()) / 15,
(14 * brightBackground.getGreen()) / 15,
(14 * brightBackground.getBlue()) / 15);
}
protected Color getBackground(int row) {
if (row % 2 == 0) {
return mediumBackground;
} else {
return brightBackground;
}
}
@Override
public void customise(JTable table, JTextArea component, String value, int rowIndex, int colIndex) {
component.setBorder(new EmptyBorder(0, 0, 0, 0));
component.setBackground(getBackground(rowIndex));
}
}
private static class TooltipAwareRenderer implements RendererStrategy {
@Override
public void customise(JTable table, JTextArea component, String value, int rowIndex, int colIndex) {
component.setToolTipText(value);
}
}
private static class WrapTextRenderer implements RendererStrategy {
List<Integer> wrappingRows;
private WrapTextRenderer(ArrayList<Integer> wrappingRows) {
this.wrappingRows = wrappingRows;
}
@Override
public void customise(JTable table, JTextArea component, String value, int rowIndex, int colIndex) {
if (!wrappingRows.contains(rowIndex)) {
return;
}
component.setLineWrap(true);
component.setWrapStyleWord(true);
int max = 230;
// if ((table).getCellSpanAt(rowIndex, colIndex).getColumnSpan() == table.getColumnCount()) {
// max *= 2;
// }
int numRows = countLines(component, value, max);
if (numRows > 1) {
int rowHeight = table.getRowHeight() * numRows;
table.setRowHeight(rowIndex, Math.max(table.getRowHeight(rowIndex), rowHeight));
}
}
private static int countLines(JTextArea component, String value, int max) {
int lineCount = 0;
FontMetrics fontMetrics = component.getFontMetrics(component.getFont());
for (String s : value.split("\n")) {
lineCount += 1 + fontMetrics.stringWidth(s) / max;
}
return lineCount;
}
}
static interface TableRow {}
protected static abstract class TablePagePanelModel implements TableModel {
private List<TableModelListener> listeners = new ArrayList<>();
protected List<TableRow> rows = new ArrayList<>();
public void addRow(TableRow row) {
rows.add(row);
notifyListeners();
}
public void clear() {
rows.clear();
notifyListeners();
}
private void notifyListeners() {
for (TableModelListener listener : listeners) {
listener.tableChanged(new TableModelEvent(this));
}
}
@Override
public void addTableModelListener(TableModelListener listener) {
listeners.add(listener);
}
@Override
public void removeTableModelListener(TableModelListener listener) {
listeners.remove(listener);
}
@Override
public void setValueAt(Object invalid1, int invalid2, int invalid3) {
throw new IllegalStateException("Table must be non-editable!");
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return String.class;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
@Override
public int getRowCount() {
return rows.size();
}
}
}