blob: 184f53d6896cbcd45984d290ce3b5a88ddd14c7f [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2015, 2020 CEA LIST and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.nebula.widgets.nattable.extension.e4.css;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.e4.ui.css.core.css2.CSS2ColorHelper;
import org.eclipse.e4.ui.css.core.css2.CSS2FontHelper;
import org.eclipse.e4.ui.css.core.dom.properties.css2.CSS2FontProperties;
import org.eclipse.e4.ui.css.core.engine.CSSElementContext;
import org.eclipse.e4.ui.css.core.engine.CSSEngine;
import org.eclipse.e4.ui.css.swt.helpers.CSSSWTFontHelper;
import org.eclipse.nebula.widgets.nattable.NatTable;
import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes;
import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
import org.eclipse.nebula.widgets.nattable.data.convert.DefaultBigDecimalDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.convert.DefaultBigIntegerDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.convert.DefaultBooleanDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.convert.DefaultByteDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.convert.DefaultCharacterDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.convert.DefaultDateDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.convert.DefaultDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.convert.DefaultDoubleDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.convert.DefaultFloatDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.convert.DefaultIntegerDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.convert.DefaultLongDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.convert.DefaultShortDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.convert.IDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.convert.PercentageDisplayConverter;
import org.eclipse.nebula.widgets.nattable.style.BorderStyle;
import org.eclipse.nebula.widgets.nattable.style.BorderStyle.BorderModeEnum;
import org.eclipse.nebula.widgets.nattable.style.BorderStyle.LineStyleEnum;
import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes;
import org.eclipse.nebula.widgets.nattable.style.CellStyleProxy;
import org.eclipse.nebula.widgets.nattable.style.ConfigAttribute;
import org.eclipse.nebula.widgets.nattable.style.DefaultDisplayModeOrdering;
import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
import org.eclipse.nebula.widgets.nattable.style.IDisplayModeOrdering;
import org.eclipse.nebula.widgets.nattable.style.IStyle;
import org.eclipse.nebula.widgets.nattable.style.Style;
import org.eclipse.nebula.widgets.nattable.ui.util.CellEdgeEnum;
import org.eclipse.nebula.widgets.nattable.util.GUIHelper;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.widgets.Display;
import org.w3c.dom.css.CSSPrimitiveValue;
import org.w3c.dom.css.CSSValue;
import org.w3c.dom.css.CSSValueList;
/**
* Helper class for converting and applying CSS styles.
*/
@SuppressWarnings("restriction")
public final class NatTableCSSHelper {
private NatTableCSSHelper() {
// private default constructor for helper class
}
private static final IDisplayModeOrdering displayModeOrdering = new DefaultDisplayModeOrdering();
/**
* Return the <code>boolean</code> value that represents the given
* {@link CSSValue}.
*
* @param value
* The value for which the boolean value should be returned.
* @param defaultValue
* The default value to return if the given value can not be
* converted to a boolean.
* @return The boolean representation of the given value or the default
* value if it can not be converted.
*/
public static boolean getBoolean(CSSValue value, boolean defaultValue) {
String stringValue = value.getCssText().toLowerCase();
Boolean result = defaultValue;
if ("true".equals(stringValue)) {
result = true;
} else if ("false".equals(stringValue)) {
result = false;
}
return result;
}
/**
* Returns the NatTable {@link DisplayMode} for the given pseudo class.
*
* @param pseudo
* The pseudo class.
* @return The {@link DisplayMode} value for the given pseudo class.
*/
public static String getDisplayMode(String pseudo) {
if (pseudo != null) {
if ("select".equals(pseudo)) {
return DisplayMode.SELECT;
} else if ("edit".equals(pseudo)) {
return DisplayMode.EDIT;
} else if ("hover".equals(pseudo)) {
return DisplayMode.HOVER;
} else if ("select-hover".equals(pseudo)) {
return DisplayMode.SELECT_HOVER;
}
}
return DisplayMode.NORMAL;
}
/**
* Returns the NatTable {@link CellEdgeEnum} for the given string
* representation.
*
* @param value
* The string representation of the {@link CellEdgeEnum}
* @return The {@link CellEdgeEnum} for the string representation.
*/
public static CellEdgeEnum getCellEdgeEnum(String value) {
if ("top".equalsIgnoreCase(value)) {
return CellEdgeEnum.TOP;
} else if ("bottom".equalsIgnoreCase(value)) {
return CellEdgeEnum.BOTTOM;
} else if ("right".equalsIgnoreCase(value)) {
return CellEdgeEnum.RIGHT;
} else if ("left".equalsIgnoreCase(value)) {
return CellEdgeEnum.LEFT;
} else if ("top-right".equalsIgnoreCase(value)) {
return CellEdgeEnum.TOP_RIGHT;
} else if ("top-left".equalsIgnoreCase(value)) {
return CellEdgeEnum.TOP_LEFT;
} else if ("bottom-right".equalsIgnoreCase(value)) {
return CellEdgeEnum.BOTTOM_RIGHT;
} else if ("bottom-left".equalsIgnoreCase(value)) {
return CellEdgeEnum.BOTTOM_LEFT;
}
return CellEdgeEnum.NONE;
}
/**
* Returns the NatTable {@link IDisplayConverter} for the given string
* representation.
*
* @param value
* The string representation of the {@link IDisplayConverter}
* @param format
* flag for number display converters to specify whether
* {@link NumberFormat} should be used to format or not.
* @param minFractionDigits
* number of minimum fraction digits to use in case a
* {@link NumberFormat} is used for formatting a number value
* @param maxFractionDigits
* number of maximum fraction digits to use in case a
* {@link NumberFormat} is used for formatting a number value
* @param datePattern
* The pattern to use for formatting a date value when a date
* display converter requested
* @return The {@link IDisplayConverter} for the string representation.
*/
public static IDisplayConverter getDisplayConverter(
String value,
boolean format,
Integer minFractionDigits,
Integer maxFractionDigits,
String datePattern) {
if ("boolean".equalsIgnoreCase(value)) {
return new DefaultBooleanDisplayConverter();
} else if ("character".equalsIgnoreCase(value)) {
return new DefaultCharacterDisplayConverter();
} else if ("date".equalsIgnoreCase(value)) {
return new DefaultDateDisplayConverter(datePattern);
} else if ("default".equalsIgnoreCase(value)) {
return new DefaultDisplayConverter();
} else if ("percentage".equalsIgnoreCase(value)) {
return new PercentageDisplayConverter();
} else if ("byte".equalsIgnoreCase(value)) {
return new DefaultByteDisplayConverter();
} else if ("short".equalsIgnoreCase(value)) {
return new DefaultShortDisplayConverter(format);
} else if ("int".equalsIgnoreCase(value)) {
return new DefaultIntegerDisplayConverter(format);
} else if ("long".equalsIgnoreCase(value)) {
return new DefaultLongDisplayConverter(format);
} else if ("big-int".equalsIgnoreCase(value)) {
return new DefaultBigIntegerDisplayConverter();
} else if ("float".equalsIgnoreCase(value)) {
DefaultFloatDisplayConverter result = new DefaultFloatDisplayConverter(format);
if (minFractionDigits != null) {
result.getNumberFormat().setMinimumFractionDigits(minFractionDigits);
}
if (maxFractionDigits != null) {
result.getNumberFormat().setMaximumFractionDigits(maxFractionDigits);
}
return result;
} else if ("double".equalsIgnoreCase(value)) {
DefaultDoubleDisplayConverter result = new DefaultDoubleDisplayConverter(format);
if (minFractionDigits != null) {
result.getNumberFormat().setMinimumFractionDigits(minFractionDigits);
}
if (maxFractionDigits != null) {
result.getNumberFormat().setMaximumFractionDigits(maxFractionDigits);
}
return result;
} else if ("big-decimal".equalsIgnoreCase(value)) {
DefaultBigDecimalDisplayConverter result = new DefaultBigDecimalDisplayConverter();
if (minFractionDigits != null) {
result.getNumberFormat().setMinimumFractionDigits(minFractionDigits);
}
if (maxFractionDigits != null) {
result.getNumberFormat().setMaximumFractionDigits(maxFractionDigits);
}
return result;
}
return new DefaultDateDisplayConverter();
}
/**
*
* @param converter
* The {@link IDisplayConverter} for which the String
* representation is requested.
* @return The String representation for the given
* {@link IDisplayConverter}.
*/
public static String getDisplayConverterString(IDisplayConverter converter) {
if (converter instanceof DefaultBooleanDisplayConverter) {
return "boolean";
} else if (converter instanceof DefaultCharacterDisplayConverter) {
return "character";
} else if (converter instanceof DefaultDateDisplayConverter) {
return "date";
} else if (converter instanceof PercentageDisplayConverter) {
return "percentage";
} else if (converter instanceof DefaultByteDisplayConverter) {
return "byte";
} else if (converter instanceof DefaultShortDisplayConverter) {
return "short";
} else if (converter instanceof DefaultIntegerDisplayConverter) {
return "int";
} else if (converter instanceof DefaultLongDisplayConverter) {
return "long";
} else if (converter instanceof DefaultBigIntegerDisplayConverter) {
return "big-int";
} else if (converter instanceof DefaultFloatDisplayConverter) {
return "float";
} else if (converter instanceof DefaultDoubleDisplayConverter) {
return "double";
} else if (converter instanceof DefaultBigDecimalDisplayConverter) {
return "big-decimal";
}
return "default";
}
/**
*
* @param value
* The value to check.
* @return <code>true</code> if the given value represents a valid converter
* key, <code>false</code> if not.
*/
public static boolean isConverterString(String value) {
return ("boolean".equalsIgnoreCase(value)
|| "character".equalsIgnoreCase(value)
|| "date".equalsIgnoreCase(value)
|| "default".equalsIgnoreCase(value)
|| "percentage".equalsIgnoreCase(value)
|| "byte".equalsIgnoreCase(value)
|| "short".equalsIgnoreCase(value)
|| "int".equalsIgnoreCase(value)
|| "long".equalsIgnoreCase(value)
|| "big-int".equalsIgnoreCase(value)
|| "float".equalsIgnoreCase(value)
|| "double".equalsIgnoreCase(value)
|| "big-decimal".equalsIgnoreCase(value));
}
/**
* Retrieves the style attribute for the given display mode and config
* labels out of the NatTable configuration. Uses the NatTable internal
* inheritance model to always retrieve a style configuration attribute if
* there is one configured at any level.
*
* @param <T>
* The type of the configuration attribute.
* @param natTable
* The NatTable whose {@link ConfigRegistry} should be checked
* for the style configuration.
* @param styleConfig
* The style {@link ConfigAttribute} that is requested.
* @param displayMode
* The {@link DisplayMode} for which the configuration is
* requested.
* @param configLabels
* The config labels for which the configuration is requested.
* @return The style attribute for the given display mode and config labels
* out of the NatTable configuration.
*/
public static <T> T getNatTableStyle(NatTable natTable, ConfigAttribute<T> styleConfig, String displayMode, String... configLabels) {
IConfigRegistry configRegistry = natTable.getConfigRegistry();
CellStyleProxy style = new CellStyleProxy(configRegistry, displayMode, Arrays.asList(configLabels));
return style.getAttributeValue(styleConfig, CellStyleAttributes.FONT.equals(styleConfig));
}
/**
* Apply a style attribute value for the {@link IStyle} registered for
* {@link CellConfigAttributes#CELL_STYLE}.
*
* @param <T>
* The type of the configuration attribute.
* @param natTable
* The NatTable to apply the style configuration to.
* @param styleConfig
* The style {@link ConfigAttribute} that should be applied.
* @param value
* The value to apply.
* @param displayMode
* The {@link DisplayMode} for which the configuration should be
* applied.
* @param configLabel
* The label for which the configuration should be applied.
*/
public static <T> void applyNatTableStyle(
NatTable natTable,
ConfigAttribute<T> styleConfig,
T value,
String displayMode,
String configLabel) {
applyNatTableStyle(natTable, CellConfigAttributes.CELL_STYLE, styleConfig, value, displayMode, configLabel);
}
/**
* Apply a style attribute value for the {@link IStyle} registered for the
* given styleAttribute.
*
* @param <T>
* The type of the configuration attribute.
* @param natTable
* The NatTable to apply the style configuration to.
* @param styleAttribute
* The {@link ConfigAttribute} that points to the {@link IStyle}
* that should be configured.
* @param styleConfig
* The style {@link ConfigAttribute} that should be applied.
* @param value
* The value to apply.
* @param displayMode
* The {@link DisplayMode} for which the configuration should be
* applied.
* @param configLabel
* The label for which the configuration should be applied.
*/
public static <T> void applyNatTableStyle(
NatTable natTable,
ConfigAttribute<IStyle> styleAttribute,
ConfigAttribute<T> styleConfig,
T value,
String displayMode,
String configLabel) {
IConfigRegistry configRegistry = natTable.getConfigRegistry();
// retrieve the style object for the given selector
IStyle style = configRegistry.getSpecificConfigAttribute(
styleAttribute,
displayMode,
configLabel);
if (style == null) {
style = new Style();
if (configLabel != null) {
configRegistry.registerConfigAttribute(
styleAttribute,
style,
displayMode,
configLabel);
} else {
configRegistry.registerConfigAttribute(
styleAttribute,
style,
displayMode);
}
}
// set the value to the style object
style.setAttributeValue(
styleConfig,
value);
}
/**
* Returns the {@link CSS2FontProperties} out of the given
* {@link CSSElementContext} for the given parameters. If no
* {@link CSS2FontProperties} exist, a new instance will be created and
* pre-filled with font values based on inheritance.
*
* @param context
* The {@link CSSElementContext} to search for the context value.
* @param contextKey
* The context key under which the font properties are stored.
* @param natTable
* The NatTable instance to apply the styles to
* @param displayMode
* The target {@link DisplayMode} to check for the value.
* @param label
* The label for which the font properties are requested.
* @return The {@link CSS2FontProperties} for the given attributes.
*/
public static CSS2FontProperties getFontProperties(
CSSElementContext context, String contextKey,
NatTable natTable, String displayMode, String label) {
// check if there are font properties already registered
CSS2FontProperties fontProperties = (CSS2FontProperties) getContextValue(context, displayMode, contextKey);
if (fontProperties == null) {
// check if there is a font registered in the hierarchy
Font font = getNatTableStyle(natTable, CellStyleAttributes.FONT, displayMode, label);
if (font == null) {
// if there are no font properties already and no font, use the
// default font
font = GUIHelper.DEFAULT_FONT;
}
fontProperties = CSSSWTFontHelper.getCSS2FontProperties(font);
// store the font properties for further use
storeContextValue(context, displayMode, contextKey, fontProperties);
}
return fontProperties;
}
/**
* Sets the values from the given {@link CSSValueList} to the given
* {@link CSS2FontProperties}CSS2FontProperties.
*
* @param valueList
* The value list containing the css property values
* @param font
* The font properties to set the values to
*/
public static void setFontProperties(CSSValueList valueList, CSS2FontProperties font) {
int length = valueList.getLength();
for (int i = 0; i < length; i++) {
CSSValue value2 = valueList.item(i);
if (value2.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
String fontProperty = CSS2FontHelper.getCSSFontPropertyName((CSSPrimitiveValue) value2);
if (fontProperty != null) {
if (NatTableCSSConstants.FONT_FAMILY.equalsIgnoreCase(fontProperty)) {
font.setFamily((CSSPrimitiveValue) value2);
} else if (NatTableCSSConstants.FONT_SIZE.equalsIgnoreCase(fontProperty)) {
font.setSize((CSSPrimitiveValue) value2);
} else if (NatTableCSSConstants.FONT_STYLE.equalsIgnoreCase(fontProperty)) {
font.setStyle((CSSPrimitiveValue) value2);
} else if (NatTableCSSConstants.FONT_WEIGHT.equalsIgnoreCase(fontProperty)) {
font.setWeight((CSSPrimitiveValue) value2);
}
}
}
}
}
/**
* Returns the {@link BorderStyle} out of the given
* {@link CSSElementContext} for the given {@link DisplayMode}.
*
* @param context
* The {@link CSSElementContext} to search for the context value.
* @param displayMode
* The {@link DisplayMode} for which the value should be stored.
* @return The {@link BorderStyle}
*/
public static BorderStyle getBorderStyle(CSSElementContext context, String displayMode) {
BorderStyle borderStyle = (BorderStyle) getContextValue(context, displayMode, NatTableCSSConstants.CV_BORDER_CONFIGURATION);
if (borderStyle == null) {
borderStyle = new BorderStyle();
storeContextValue(context, displayMode, NatTableCSSConstants.CV_BORDER_CONFIGURATION, borderStyle);
}
return borderStyle;
}
/**
* Convert and store the values of the given {@link CSSValueList} to the
* given {@link BorderStyle}.
*
* @param valueList
* The {@link CSSValueList} with the values to convert.
* @param borderStyle
* The {@link BorderStyle} to store the converted values to.
* @param engine
* The {@link CSSEngine} needed for conversion.
* @param display
* The display needed for color conversion.
* @throws Exception
* if the value conversion fails
*/
public static void storeBorderStyle(
CSSValueList valueList,
BorderStyle borderStyle,
CSSEngine engine,
Display display) throws Exception {
int length = valueList.getLength();
for (int i = 0; i < length; i++) {
CSSValue value2 = valueList.item(i);
if (value2.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
CSSPrimitiveValue primitiveValue = (CSSPrimitiveValue) value2;
short type = primitiveValue.getPrimitiveType();
switch (type) {
case CSSPrimitiveValue.CSS_IDENT:
if (CSS2ColorHelper.isColorName(primitiveValue.getStringValue())) {
borderStyle.setColor(
(Color) engine.convert(value2, Color.class, display));
} else if (isLineStyle(primitiveValue.getStringValue().toUpperCase())) {
borderStyle.setLineStyle(
LineStyleEnum.valueOf(primitiveValue.getStringValue().toUpperCase()));
} else {
borderStyle.setBorderMode(
BorderModeEnum.valueOf(primitiveValue.getStringValue().toUpperCase()));
}
break;
case CSSPrimitiveValue.CSS_RGBCOLOR:
borderStyle.setColor(
(Color) engine.convert(value2, Color.class, display));
break;
case CSSPrimitiveValue.CSS_PT:
case CSSPrimitiveValue.CSS_NUMBER:
case CSSPrimitiveValue.CSS_PX:
borderStyle.setThickness(
(int) ((CSSPrimitiveValue) value2).getFloatValue(CSSPrimitiveValue.CSS_PT));
break;
}
}
}
}
/**
*
* @param style
* The String value that should be checked if it is a
* {@link LineStyleEnum} value.
* @return <code>true</code> if the given String is a {@link LineStyleEnum},
* <code>false</code> if not.
*/
private static boolean isLineStyle(String style) {
try {
LineStyleEnum.valueOf(style);
} catch (IllegalArgumentException e) {
return false;
}
return true;
}
/**
* Convert and store the padding value for the given key in the painter
* properties map.
*
* @param paddingKey
* The key of the padding property.
* @param value
* The {@link CSSValue} of the padding that should be converted
* and stored.
* @param context
* The {@link CSSElementContext} to search for the configuration
* value.
* @param displayMode
* The target {@link DisplayMode} to check for the value.
*/
public static void storePadding(
String paddingKey,
CSSValue value,
CSSElementContext context,
String displayMode) {
if (value.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
CSSPrimitiveValue primitiveValue = (CSSPrimitiveValue) value;
short type = primitiveValue.getPrimitiveType();
if (type == CSSPrimitiveValue.CSS_PT
|| type == CSSPrimitiveValue.CSS_NUMBER
|| type == CSSPrimitiveValue.CSS_PX) {
int padding = (int) primitiveValue.getFloatValue(CSSPrimitiveValue.CSS_PT);
getPainterProperties(context, displayMode)
.put(paddingKey, padding);
}
}
}
/**
* Check if the automatic painter resolution is enabled or disabled via CSS
* property.
*
* @param context
* The {@link CSSElementContext} to search for the configuration
* value.
* @param natTableContext
* The {@link CSSElementContext} of the parent NatTable or
* <code>null</code> in case the context parameter is already
* from the NatTable itself.
* @param displayMode
* The target {@link DisplayMode} to check for the value.
* @return <code>true</code> if the painter to use should be automatically
* resolved, <code>false</code> if the painter is configured
* elsewhere and therefore no automatic resolution should be
* performed. Default is <code>true</code>.
*/
public static boolean resolvePainter(
CSSElementContext context, CSSElementContext natTableContext, String displayMode) {
Object cv = getContextValueInherited(
context,
natTableContext,
displayMode,
NatTableCSSConstants.PAINTER_RESOLUTION);
return (cv != null) ? (Boolean) cv : Boolean.TRUE;
}
/**
* Returns the string representation list of cell painter decorators that
* should be used to build up the cell painter for rendering.
*
* @param context
* The {@link CSSElementContext} to search for the context value.
* @param displayMode
* The {@link DisplayMode} for which the value should be stored.
* @return The string representation of decorator painter that should be
* used for rendering.
*/
public static List<String> getDecoratorPainter(CSSElementContext context, String displayMode) {
@SuppressWarnings("unchecked")
List<String> decorator = (List<String>) getContextValue(context, displayMode, NatTableCSSConstants.CV_DECORATOR_PAINTER);
if (decorator == null) {
decorator = new ArrayList<>();
storeContextValue(context, displayMode, NatTableCSSConstants.CV_DECORATOR_PAINTER, decorator);
}
return decorator;
}
/**
* Returns the painter properties out of the given {@link CSSElementContext}
* for the given {@link DisplayMode}.
*
* @param context
* The {@link CSSElementContext} to search for the context value.
* @param displayMode
* The {@link DisplayMode} for which the value should be stored.
* @return The properties that should be used to create content painter.
*/
public static Map<String, Object> getPainterProperties(CSSElementContext context, String displayMode) {
@SuppressWarnings("unchecked")
Map<String, Object> painterProperties =
(Map<String, Object>) getContextValue(context, displayMode, NatTableCSSConstants.CV_PAINTER_CONFIGURATION);
if (painterProperties == null) {
painterProperties = new HashMap<>();
storeContextValue(context, displayMode, NatTableCSSConstants.CV_PAINTER_CONFIGURATION, painterProperties);
}
return painterProperties;
}
/**
* Returns the painter properties out of the given {@link CSSElementContext}
* for the given {@link DisplayMode} enriched with the painter property
* values out of inheritance.
*
* @param context
* The {@link CSSElementContext} to search for the context value.
* @param natTableContext
* The {@link CSSElementContext} of the parent NatTable or
* <code>null</code> in case the context parameter is already
* from the NatTable itself.
* @param targetDisplayMode
* The target {@link DisplayMode} to check for the value.
* @return The painter properties with values out of inheritance
*/
public static Map<String, Object> getPainterPropertiesInherited(
CSSElementContext context, CSSElementContext natTableContext, String targetDisplayMode) {
Map<String, Object> painterProperties = new HashMap<>();
List<String> displayModes = displayModeOrdering.getDisplayModeOrdering(targetDisplayMode);
String displayMode = null;
if (natTableContext != null) {
// first get the painter properties from tbe NatTable in reverse
// displaymode ordering
for (int i = displayModes.size() - 1; i >= 0; i--) {
displayMode = displayModes.get(i);
painterProperties.putAll(
getPainterProperties(natTableContext, displayMode));
}
}
// then do the same for the element context
for (int i = displayModes.size() - 1; i >= 0; i--) {
displayMode = displayModes.get(i);
painterProperties.putAll(
getPainterProperties(context, displayMode));
}
return painterProperties;
}
/**
* Resolves the painter representations out of the given {@link CSSValue}.
*
* @param value
* The {@link CSSValue} to resolve.
* @return The list of string representations for painters.
*/
public static List<String> resolvePainterRepresentation(CSSValue value) {
List<String> painterValues = new ArrayList<>();
if (value.getCssValueType() == CSSValue.CSS_VALUE_LIST) {
CSSValueList valueList = (CSSValueList) value;
int length = valueList.getLength();
for (int i = 0; i < length; i++) {
CSSValue value2 = valueList.item(i);
if (value2.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
painterValues.add(value2.getCssText().toLowerCase());
}
}
} else if (value.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
painterValues.add(value.getCssText().toLowerCase());
}
return painterValues;
}
/**
* Put a value for the given key and {@link DisplayMode} to the given
* {@link CSSElementContext}.
*
* @param context
* The {@link CSSElementContext} to put the value to.
* @param displayMode
* The {@link DisplayMode} for which the value should be stored.
* @param key
* The key for which the value should be stored.
* @param value
* The value to store.
*/
public static void storeContextValue(CSSElementContext context, String displayMode, Object key, Object value) {
Object subContext = context.getData(displayMode);
if (subContext == null) {
subContext = new HashMap<>();
context.setData(displayMode, subContext);
}
@SuppressWarnings("unchecked")
Map<Object, Object> displayModeContext = (Map<Object, Object>) subContext;
displayModeContext.put(key, value);
}
/**
* Search the value for the given key and {@link DisplayMode} out of the
* given {@link CSSElementContext}.
*
* @param context
* The {@link CSSElementContext} out of which the value should be
* retrieved.
* @param displayMode
* The {@link DisplayMode} for which the value is requested.
* @param key
* The key for which the value is requested.
* @return The value for the given {@link DisplayMode} and key out of the
* given {@link CSSElementContext}. If no value is found for the
* given {@link DisplayMode}, the value out of the given
* {@link CSSElementContext} directly is returned. Can be
* <code>null</code>.
*/
public static Object getContextValue(CSSElementContext context, String displayMode, Object key) {
Object subContext = context.getData(displayMode);
if (subContext != null) {
@SuppressWarnings("unchecked")
Map<Object, Object> displayModeContext = (Map<Object, Object>) subContext;
return displayModeContext.get(key);
}
return context.getData(key);
}
/**
* Search the value for the given key and {@link DisplayMode} out of the
* given {@link CSSElementContext}. Will search for the value also via
* inheritance, that means first it will check the
* {@link IDisplayModeOrdering} and if there is no value found, it searches
* in the parent NatTable context.
*
* @param context
* The {@link CSSElementContext} to search for the context value.
* @param natTableContext
* The {@link CSSElementContext} of the parent NatTable or
* <code>null</code> in case the context parameter is already
* from the NatTable itself.
* @param targetDisplayMode
* The target {@link DisplayMode} to check for the value.
* @param key
* The key of the context value to search for.
* @return The context value for the given key.
*/
public static Object getContextValueInherited(
CSSElementContext context, CSSElementContext natTableContext,
String targetDisplayMode, Object key) {
Object cv = null;
for (String displayMode : displayModeOrdering.getDisplayModeOrdering(targetDisplayMode)) {
cv = getContextValue(context, displayMode, key);
if (cv != null) {
break;
}
}
// not found for any displaymode in context
// search in parent context
if (cv == null && natTableContext != null) {
cv = getContextValueInherited(natTableContext, null, targetDisplayMode, key);
}
return cv;
}
}