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; } }