/*
* Copyright (c) 2005-2016 Vincent Vandenschrick. All rights reserved.
*
* This file is part of the Jspresso framework.
*
* Jspresso is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Jspresso 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Jspresso. If not, see <http://www.gnu.org/licenses/>.
*/
package org.jspresso.framework.view.swing;
import java.awt.Color;
import java.awt.Component;
import java.awt.Rectangle;
import javax.swing.JCheckBox;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import org.jspresso.framework.binding.IValueConnector;
import org.jspresso.framework.binding.swing.CollectionConnectorTableModel;
import org.jspresso.framework.util.swing.SwingUtil;
/**
* Renders a table cell using a checkbox.
*
* @author Vincent Vandenschrick
*/
public class BooleanTableCellRenderer extends JCheckBox implements
TableCellRenderer, DynamicStyleRenderer {
private static final long serialVersionUID = 5944792695339009139L;
private static final Border NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1);
private Color unselectedForeground;
private Color unselectedBackground;
private String toolTipProperty;
private String backgroundProperty;
private String foregroundProperty;
private String fontProperty;
/**
* Constructs a new {@code BooleanTableCellRenderer} instance.
*/
public BooleanTableCellRenderer() {
super();
setHorizontalAlignment(SwingConstants.CENTER);
setBorderPainted(true);
}
/**
* Overridden for performance reasons.
* <p>
* {@inheritDoc}
*/
@Override
public void firePropertyChange(String propertyName, boolean oldValue,
boolean newValue) {
// NO-OP
}
/**
* {@inheritDoc}
*/
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
super.setForeground(table.getSelectionForeground());
super.setBackground(table.getSelectionBackground());
} else {
if (unselectedForeground != null) {
super.setForeground(unselectedForeground);
} else {
super.setForeground(table.getForeground());
}
Color actualBackground = table.getBackground();
if (unselectedBackground != null) {
actualBackground = unselectedBackground;
}
super.setBackground(SwingUtil.computeEvenOddBackground(actualBackground, false, row));
}
setValue(value);
if (hasFocus) {
Border border = null;
if (isSelected) {
border = UIManager.getBorder("Table.focusSelectedCellHighlightBorder");
}
if (border == null) {
border = UIManager.getBorder("Table.focusCellHighlightBorder");
}
setBorder(border);
if (!isSelected && table.isCellEditable(row, column)) {
Color col;
col = UIManager.getColor("Table.focusCellForeground");
if (col != null) {
super.setForeground(col);
}
col = UIManager.getColor("Table.focusCellBackground");
if (col != null) {
super.setBackground(col);
}
}
} else {
setBorder(NO_FOCUS_BORDER);
}
if (row >= 0) {
CollectionConnectorTableModel tm = getActualTableModel(table);
if (table.convertColumnIndexToModel(column) == 0) {
setToolTipText(tm.getRowToolTip(row));
} else if (getToolTipProperty() != null) {
setToolTipText(tm.getCellToolTip(row, getToolTipProperty()));
}
if (getBackgroundProperty() != null) {
setBackground(DefaultSwingViewFactory.createColor(tm.getCellBackground(
row, getBackgroundProperty())));
} else if (tm.getRowBackground(row) != null) {
setBackground(DefaultSwingViewFactory.createColor(tm
.getRowBackground(row)));
}
if (getForegroundProperty() != null) {
setForeground(DefaultSwingViewFactory.createColor(tm.getCellForeground(
row, getForegroundProperty())));
} else if (tm.getRowBackground(row) != null) {
setForeground(DefaultSwingViewFactory.createColor(tm
.getRowForeground(row)));
}
}
return this;
}
/**
* Sets the renderer value.
*
* @param value
* the model value.
*/
protected void setValue(Object value) {
if (value instanceof IValueConnector) {
Object connectorValue = ((IValueConnector) value).getConnectorValue();
setSelected((connectorValue != null && (Boolean) connectorValue));
} else {
setSelected((value != null && (Boolean) value));
}
}
/**
* Overridden for performance reasons.
* <p>
* {@inheritDoc}
*/
@Override
public void invalidate() {
// NO-OP
}
/**
* Overridden for performance reasons.
* <p>
* {@inheritDoc}
*/
@Override
public boolean isOpaque() {
Color back = getBackground();
Component p = getParent();
if (p != null) {
p = p.getParent();
}
// p should now be the JTable.
boolean colorMatch = (back != null) && (p != null)
&& back.equals(p.getBackground()) && p.isOpaque();
return !colorMatch && super.isOpaque();
}
/*
* The following methods are overridden for performance reasons (see
* DefaultTableCellRenderer comments for a reference).
*/
/**
* Overridden for performance reasons.
* <p>
* {@inheritDoc}
*/
@Override
public void repaint() {
// NO-OP
}
/**
* Overridden for performance reasons.
* <p>
* {@inheritDoc}
*/
@Override
public void repaint(long tm, int x, int y, int width, int height) {
// NO-OP
}
/**
* Overridden for performance reasons.
* <p>
* {@inheritDoc}
*/
@Override
public void repaint(Rectangle r) {
// NO-OP
}
/**
* Overridden for performance reasons.
* <p>
* {@inheritDoc}
*/
@Override
public void revalidate() {
// NO-OP
}
/**
* Notification from the {@code UIManager} that the look and feel [L&F]
* has changed. Replaces the current UI object with the latest version from
* the {@code UIManager}.
*/
@Override
public void updateUI() {
super.updateUI();
setForeground(null);
setBackground(null);
}
/**
* Overridden for performance reasons.
* <p>
* {@inheritDoc}
*/
@Override
public void validate() {
// NO-OP
}
/**
* Overridden for performance reasons.
* <p>
* {@inheritDoc}
*/
@Override
protected void firePropertyChange(String propertyName, Object oldValue,
Object newValue) {
// NO-OP
}
private CollectionConnectorTableModel getActualTableModel(JTable table) {
TableModel tm = table.getModel();
if (tm instanceof AbstractTableSorter) {
tm = ((AbstractTableSorter) tm).getTableModel();
}
return (CollectionConnectorTableModel) tm;
}
/**
* {@inheritDoc}
*/
@Override
public void setForeground(Color fg) {
super.setForeground(fg);
unselectedForeground = fg;
}
/**
* {@inheritDoc}
*/
@Override
public void setBackground(Color bg) {
super.setBackground(bg);
unselectedBackground = bg;
}
/**
* Gets the toolTipProperty.
*
* @return the toolTipProperty.
*/
protected String getToolTipProperty() {
return toolTipProperty;
}
/**
* Sets the toolTipProperty.
*
* @param toolTipProperty
* the toolTipProperty to set.
*/
@Override
public void setToolTipProperty(String toolTipProperty) {
this.toolTipProperty = toolTipProperty;
}
/**
* Gets the backgroundProperty.
*
* @return the backgroundProperty.
*/
protected String getBackgroundProperty() {
return backgroundProperty;
}
/**
* Sets the backgroundProperty.
*
* @param backgroundProperty
* the backgroundProperty to set.
*/
@Override
public void setBackgroundProperty(String backgroundProperty) {
this.backgroundProperty = backgroundProperty;
}
/**
* Gets the foregroundProperty.
*
* @return the foregroundProperty.
*/
protected String getForegroundProperty() {
return foregroundProperty;
}
/**
* Sets the foregroundProperty.
*
* @param foregroundProperty
* the foregroundProperty to set.
*/
@Override
public void setForegroundProperty(String foregroundProperty) {
this.foregroundProperty = foregroundProperty;
}
/**
* Gets the fontProperty.
*
* @return the fontProperty.
*/
protected String getFontProperty() {
return fontProperty;
}
/**
* Sets the fontProperty.
*
* @param fontProperty
* the fontProperty to set.
*/
@Override
public void setFontProperty(String fontProperty) {
this.fontProperty = fontProperty;
}
}