package com.onaro.sanscreen.client.view.tabular;
import com.onaro.commons.swing.table.OnaroTableUtils;
import com.onaro.sanscreen.client.view.init.HighlightsInitInfo;
import com.onaro.util.IllegalInitException;
import com.onaro.util.enumeration.EnumPresentation;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.swing.JComponent;
import javax.swing.JTable;
import java.awt.Color;
import java.util.HashMap;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* Allows for highlighting rows in a grouping-table. To determine if a highlight is applicable for a row
* or a group, the value of a preconfigured column is evaluated. If the value matches the preconfigured value,
* the row should be highlighted. A "style" is used to specify the foreground and/or background color that will
* be used for the highlight.
*
* In order for the highlight to support grouping it must be (and is) applied to a {@link com.onaro.sanscreen.client.view.GroupingDirector} instead
* of a {@link ConfigurableTableModel} (because the {@link ConfigurableTableModel} is ignorant of the actual {@link ConfigurableTableModel}).
*
* For simplicity reasons, the highlight isn't aware of the actual grouping. Yet it will be activated for a row
* having an integer value greater than 0. Therefore, if a counting summarizer is configured for the column that is
* used for the highlight, a group will be highlighted if at least one row in the group is highlighted too.
*/
public class Highlight implements HighlightInterface {
static final Logger logger = LogManager.getLogger(Highlight.class);
/**
* The column number in the {@link com.onaro.sanscreen.client.view.GroupingDirector} that is evaluated to
* determine if the highlight should be applied or not.
*/
private int columnNumber;
/**
* The value that if exist in a row at the column specified by {@link Highlight#columnNumber}, the row will be highlighted.
*/
private String value;
private boolean shouldReset;
/**
* If true the highlight is always on regardless of the row being evaluated
*/
private boolean alwaysOn = false;
/**
* Caches color by style. Initialized gradually as the styles are being used.
*/
private static final Map colorByStyleName = new HashMap();
private static final ResourceBundle resources = ResourceBundle.getBundle("com.onaro.sanscreen.client.Highlight"); //$NON-NLS-1$
private Color foreground;
private Color background;
private Color selectedForeground;
private Color selectedBackground;
public Highlight(HighlightsInitInfo.HighlightInitInfo highlightInitInfo, ITabularTableModel tableModel, boolean shouldReset) throws IllegalInitException {
this.shouldReset = shouldReset;
String styleName = highlightInitInfo.getStyleName();
foreground = getColor(styleName + ".foreground"); //$NON-NLS-1$
background = getColor(styleName + ".background"); //$NON-NLS-1$
selectedForeground = getColor(styleName + ".selected.foreground"); //$NON-NLS-1$
selectedBackground = getColor(styleName + ".selected.background"); //$NON-NLS-1$
String columnName = highlightInitInfo.getColumnName();
value = highlightInitInfo.getValue();
if (StringUtils.isBlank(columnName)) {
if (StringUtils.isBlank(value)) {
// if both are null, the highlight is always on!
alwaysOn = true;
} else {
throw new IllegalInitException("Column name is blank, but value is specified"); //$NON-NLS-1$
}
} else {
alwaysOn = false;
columnNumber = OnaroTableUtils.findColumnIndexByColumnId(tableModel, columnName) + 1;
}
}
private Color getColor(String colorKey) throws IllegalInitException {
if (!colorByStyleName.containsKey(colorKey)) {
try {
Color color = null;
String colorCode = resources.getString(colorKey);
if (colorCode != null && colorCode.length() > 0) {
color = Color.decode(colorCode);
}
colorByStyleName.put(colorKey, color);
} catch (MissingResourceException e) {
throw new IllegalInitException("Failed to get color named '" + colorKey + '\'', e); //$NON-NLS-1$
}
}
return colorByStyleName.get(colorKey);
}
public JComponent apply(JTable table, JComponent compRenderer, int row) {
if (shouldReset) {
compRenderer.setForeground(table.getForeground());
}
if (alwaysOn || shouldApply(table, row)) {
if (table.isRowSelected(row)) {
if (selectedForeground != null) compRenderer.setForeground(selectedForeground);
if (selectedBackground != null) compRenderer.setBackground(selectedBackground);
} else {
if (foreground != null) compRenderer.setForeground(foreground);
if (background != null) compRenderer.setBackground(background);
}
}
return compRenderer;
}
private boolean shouldApply(JTable table, int row) {
boolean shouldApply = false;
try {
shouldApply = shouldApplyImpl(table, row);
} catch (Exception e) {
if (logger.isDebugEnabled()) logger.debug(e.getMessage(), e);
}
return shouldApply;
}
private boolean shouldApplyImpl(JTable table, int row) {
boolean shouldApply = false;
Object conditionValue = table.getModel().getValueAt(row, columnNumber);
if (conditionValue != null) {
if (conditionValue instanceof Integer) {
shouldApply = ((Integer) conditionValue).intValue() > 0;
} else {
String conditionValueStr;
if (conditionValue instanceof EnumPresentation.Attributes) {
conditionValueStr = ((EnumPresentation.Attributes) conditionValue).value;
} else {
conditionValueStr = conditionValue.toString();
}
shouldApply = value.equals(conditionValueStr);
}
}
return shouldApply;
}
}