Extend "iconcolor" attribute to all sitemap elements (#3403)

* iconcolor attribute added to all sitemap elements

This attribute was already available in syntax for the Image element but
was probably not used by any UI.
It is now available for any sitemap element and allows defining a color
for the widget icon based on conditional statements on the item value.

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
pull/3411/head
lolodomo 2023-02-26 19:49:51 +01:00 committed by GitHub
parent 8c905b108e
commit f2b8fa77c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 107 additions and 19 deletions

View File

@ -43,6 +43,7 @@ import org.openhab.core.ui.items.ItemUIRegistry;
* This is a class that listens on item state change events and creates sitemap events for a dedicated sitemap page.
*
* @author Kai Kreuzer - Initial contribution
* @author Laurent Garnier - Added support for icon color
*/
public class PageChangeListener implements StateChangeListener {
@ -152,6 +153,10 @@ public class PageChangeListener implements StateChangeListener {
for (ColorArray rule : widget.getValueColor()) {
addItemWithName(items, rule.getItem());
}
// now scan value icon rules
for (ColorArray rule : widget.getIconColor()) {
addItemWithName(items, rule.getItem());
}
}
}
return items;
@ -236,6 +241,7 @@ public class PageChangeListener implements StateChangeListener {
event.label = itemUIRegistry.getLabel(widget);
event.labelcolor = itemUIRegistry.getLabelColor(widget);
event.valuecolor = itemUIRegistry.getValueColor(widget);
event.iconcolor = itemUIRegistry.getIconColor(widget);
event.widgetId = itemUIRegistry.getWidgetId(widget);
event.visibility = itemUIRegistry.getVisiblity(widget);
event.descriptionChanged = false;
@ -274,22 +280,10 @@ public class PageChangeListener implements StateChangeListener {
}
private boolean definesVisibilityOrColor(Widget w, String name) {
for (VisibilityRule rule : w.getVisibility()) {
if (name.equals(rule.getItem())) {
return true;
}
}
for (ColorArray rule : w.getLabelColor()) {
if (name.equals(rule.getItem())) {
return true;
}
}
for (ColorArray rule : w.getValueColor()) {
if (name.equals(rule.getItem())) {
return true;
}
}
return false;
return w.getVisibility().stream().anyMatch(r -> name.equals(r.getItem()))
|| w.getLabelColor().stream().anyMatch(r -> name.equals(r.getItem()))
|| w.getValueColor().stream().anyMatch(r -> name.equals(r.getItem()))
|| w.getIconColor().stream().anyMatch(r -> name.equals(r.getItem()));
}
public void sitemapContentChanged(EList<Widget> widgets) {

View File

@ -123,6 +123,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
* @author Yordan Zhelev - Added Swagger annotations
* @author Markus Rathgeb - Migrated to JAX-RS Whiteboard Specification
* @author Wouter Born - Migrated to OpenAPI annotations
* @author Laurent Garnier - Added support for icon color
*/
@Component(service = RESTResource.class)
@JaxrsResource
@ -514,6 +515,7 @@ public class SitemapResource
bean.icon = itemUIRegistry.getCategory(widget);
bean.labelcolor = itemUIRegistry.getLabelColor(widget);
bean.valuecolor = itemUIRegistry.getValueColor(widget);
bean.iconcolor = itemUIRegistry.getIconColor(widget);
bean.label = itemUIRegistry.getLabel(widget);
bean.type = widget.eClass().getName();
bean.visibility = itemUIRegistry.getVisiblity(widget);
@ -732,10 +734,11 @@ public class SitemapResource
if (widget instanceof Frame) {
items.addAll(getAllItems(((Frame) widget).getChildren()));
}
// Consider items involved in any visibility, labelcolor and valuecolor condition
// Consider items involved in any visibility, labelcolor, valuecolor and iconcolor condition
items.addAll(getItemsInVisibilityCond(widget.getVisibility()));
items.addAll(getItemsInColorCond(widget.getLabelColor()));
items.addAll(getItemsInColorCond(widget.getValueColor()));
items.addAll(getItemsInColorCond(widget.getIconColor()));
}
return items;
}

View File

@ -18,6 +18,7 @@ import org.openhab.core.io.rest.core.item.EnrichedItemDTO;
* A sitemap event, which provides details about a widget that has changed.
*
* @author Kai Kreuzer - Initial contribution
* @author Laurent Garnier - New field iconcolor
*/
public class SitemapWidgetEvent extends SitemapEvent {
@ -27,6 +28,7 @@ public class SitemapWidgetEvent extends SitemapEvent {
public String icon;
public String labelcolor;
public String valuecolor;
public String iconcolor;
public boolean visibility;
public String state;
public EnrichedItemDTO item;

View File

@ -23,6 +23,7 @@ import org.openhab.core.io.rest.core.item.EnrichedItemDTO;
*
* @author Kai Kreuzer - Initial contribution
* @author Chris Jackson - Initial contribution
* @author Laurent Garnier - New field iconcolor
*/
public class WidgetDTO {
@ -35,6 +36,7 @@ public class WidgetDTO {
public String icon;
public String labelcolor;
public String valuecolor;
public String iconcolor;
// widget-specific attributes
public final List<MappingDTO> mappings = new ArrayList<>();

View File

@ -79,6 +79,7 @@ public class SitemapResourceTest extends JavaTest {
private static final String VISIBILITY_RULE_ITEM_NAME = "visibilityRuleItem";
private static final String LABEL_COLOR_ITEM_NAME = "labelColorItemName";
private static final String VALUE_COLOR_ITEM_NAME = "valueColorItemName";
private static final String ICON_COLOR_ITEM_NAME = "iconColorItemName";
private static final String WIDGET1_LABEL = "widget 1";
private static final String WIDGET2_LABEL = "widget 2";
private static final String WIDGET1_ID = "00";
@ -91,6 +92,7 @@ public class SitemapResourceTest extends JavaTest {
private @NonNullByDefault({}) GenericItem visibilityRuleItem;
private @NonNullByDefault({}) GenericItem labelColorItem;
private @NonNullByDefault({}) GenericItem valueColorItem;
private @NonNullByDefault({}) GenericItem iconColorItem;
private @Mock @NonNullByDefault({}) HttpHeaders headersMock;
private @Mock @NonNullByDefault({}) Sitemap defaultSitemapMock;
@ -118,6 +120,7 @@ public class SitemapResourceTest extends JavaTest {
visibilityRuleItem = new TestItem(VISIBILITY_RULE_ITEM_NAME);
labelColorItem = new TestItem(LABEL_COLOR_ITEM_NAME);
valueColorItem = new TestItem(VALUE_COLOR_ITEM_NAME);
iconColorItem = new TestItem(ICON_COLOR_ITEM_NAME);
when(localeServiceMock.getLocale(null)).thenReturn(Locale.US);
@ -265,6 +268,7 @@ public class SitemapResourceTest extends JavaTest {
assertThat(pageDTO.widgets.get(0).label, is(WIDGET1_LABEL));
assertThat(pageDTO.widgets.get(0).labelcolor, is("GREEN"));
assertThat(pageDTO.widgets.get(0).valuecolor, is("BLUE"));
assertThat(pageDTO.widgets.get(0).iconcolor, is("ORANGE"));
assertThat(pageDTO.widgets.get(0).state, nullValue());
assertThat(pageDTO.widgets.get(0).item, notNullValue());
assertThat(pageDTO.widgets.get(0).item.name, is(ITEM_NAME));
@ -274,6 +278,7 @@ public class SitemapResourceTest extends JavaTest {
assertThat(pageDTO.widgets.get(1).label, is(WIDGET2_LABEL));
assertThat(pageDTO.widgets.get(1).labelcolor, nullValue());
assertThat(pageDTO.widgets.get(1).valuecolor, nullValue());
assertThat(pageDTO.widgets.get(1).iconcolor, nullValue());
assertThat(pageDTO.widgets.get(1).state, is("ON"));
assertThat(pageDTO.widgets.get(1).item, notNullValue());
assertThat(pageDTO.widgets.get(1).item.name, is(ITEM_NAME));
@ -286,6 +291,7 @@ public class SitemapResourceTest extends JavaTest {
when(itemUIRegistryMock.getItem(VISIBILITY_RULE_ITEM_NAME)).thenReturn(visibilityRuleItem);
when(itemUIRegistryMock.getItem(LABEL_COLOR_ITEM_NAME)).thenReturn(labelColorItem);
when(itemUIRegistryMock.getItem(VALUE_COLOR_ITEM_NAME)).thenReturn(valueColorItem);
when(itemUIRegistryMock.getItem(ICON_COLOR_ITEM_NAME)).thenReturn(iconColorItem);
when(itemUIRegistryMock.getWidgetId(widgets.get(0))).thenReturn(WIDGET1_ID);
when(itemUIRegistryMock.getCategory(widgets.get(0))).thenReturn("");
@ -293,6 +299,7 @@ public class SitemapResourceTest extends JavaTest {
when(itemUIRegistryMock.getVisiblity(widgets.get(0))).thenReturn(true);
when(itemUIRegistryMock.getLabelColor(widgets.get(0))).thenReturn("GREEN");
when(itemUIRegistryMock.getValueColor(widgets.get(0))).thenReturn("BLUE");
when(itemUIRegistryMock.getIconColor(widgets.get(0))).thenReturn("ORANGE");
when(itemUIRegistryMock.getState(widgets.get(0))).thenReturn(state1);
when(itemUIRegistryMock.getWidgetId(widgets.get(1))).thenReturn(WIDGET2_ID);
@ -301,6 +308,7 @@ public class SitemapResourceTest extends JavaTest {
when(itemUIRegistryMock.getVisiblity(widgets.get(1))).thenReturn(true);
when(itemUIRegistryMock.getLabelColor(widgets.get(1))).thenReturn(null);
when(itemUIRegistryMock.getValueColor(widgets.get(1))).thenReturn(null);
when(itemUIRegistryMock.getIconColor(widgets.get(1))).thenReturn(null);
when(itemUIRegistryMock.getState(widgets.get(1))).thenReturn(state2);
}
@ -337,9 +345,17 @@ public class SitemapResourceTest extends JavaTest {
valueColors.add(valueColor);
when(w1.getValueColor()).thenReturn(valueColors);
// add icon color conditions to the item:
ColorArray iconColor = mock(ColorArray.class);
when(iconColor.getItem()).thenReturn(ICON_COLOR_ITEM_NAME);
EList<ColorArray> iconColors = new BasicEList<>();
iconColors.add(iconColor);
when(w1.getIconColor()).thenReturn(iconColors);
visibilityRules = new BasicEList<>();
labelColors = new BasicEList<>();
valueColors = new BasicEList<>();
iconColors = new BasicEList<>();
Widget w2 = mock(Widget.class);
EClass switchEClass = mock(EClass.class);
@ -351,6 +367,7 @@ public class SitemapResourceTest extends JavaTest {
when(w2.getVisibility()).thenReturn(visibilityRules);
when(w2.getLabelColor()).thenReturn(labelColors);
when(w2.getValueColor()).thenReturn(valueColors);
when(w2.getIconColor()).thenReturn(iconColors);
BasicEList<Widget> widgets = new BasicEList<>(2);
widgets.add(w1);

View File

@ -27,18 +27,21 @@ Frame:
{Frame} 'Frame' (('item=' item=ItemRef)? & ('label=' label=(ID | STRING))? & ('icon=' icon=Icon)? &
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)* ']'))? &
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)* ']'))? &
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)* ']'))? &
('visibility=[' (Visibility+=VisibilityRule (',' Visibility+=VisibilityRule)* ']'))?);
Text:
{Text} 'Text' (('item=' item=ItemRef)? & ('label=' label=(ID | STRING))? & ('icon=' icon=Icon)? &
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)* ']'))? &
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)* ']'))? &
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)* ']'))? &
('visibility=[' (Visibility+=VisibilityRule (',' Visibility+=VisibilityRule)* ']'))?);
Group:
'Group' (('item=' item=GroupItemRef) & ('label=' label=(ID | STRING))? & ('icon=' icon=Icon)? &
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)* ']'))? &
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)* ']'))? &
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)* ']'))? &
('visibility=[' (Visibility+=VisibilityRule (',' Visibility+=VisibilityRule)* ']'))?);
Image:
@ -54,6 +57,7 @@ Video:
('url=' url=(STRING)) & ('encoding=' encoding=(STRING))? &
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)* ']'))? &
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)* ']'))? &
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)* ']'))? &
('visibility=[' (Visibility+=VisibilityRule (',' Visibility+=VisibilityRule)* ']'))?);
Chart:
@ -62,6 +66,7 @@ Chart:
('legend=' legend=BOOLEAN_OBJECT)? & ('forceasitem=' forceAsItem=BOOLEAN_OBJECT)? &
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)* ']'))? &
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)* ']'))? &
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)* ']'))? &
('visibility=[' (Visibility+=VisibilityRule (',' Visibility+=VisibilityRule)* ']'))? &
('yAxisDecimalPattern=' yAxisDecimalPattern=(STRING))?);
@ -70,6 +75,7 @@ Webview:
('height=' height=INT)? & ('url=' url=(STRING)) &
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)* ']'))? &
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)* ']'))? &
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)* ']'))? &
('visibility=[' (Visibility+=VisibilityRule (',' Visibility+=VisibilityRule)* ']'))?);
Switch:
@ -77,6 +83,7 @@ Switch:
('mappings=[' mappings+=Mapping (',' mappings+=Mapping)* ']')? &
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)* ']'))? &
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)* ']'))? &
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)* ']'))? &
('visibility=[' (Visibility+=VisibilityRule (',' Visibility+=VisibilityRule)* ']'))?);
Mapview:
@ -84,6 +91,7 @@ Mapview:
('height=' height=INT)? &
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)* ']'))? &
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)* ']'))? &
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)* ']'))? &
('visibility=[' (Visibility+=VisibilityRule (',' Visibility+=VisibilityRule)* ']'))?);
Slider:
@ -92,6 +100,7 @@ Slider:
('minValue=' minValue=Number)? & ('maxValue=' maxValue=Number)? & ('step=' step=Number)? &
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)* ']'))? &
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)* ']'))? &
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)* ']'))? &
('visibility=[' (Visibility+=VisibilityRule (',' Visibility+=VisibilityRule)* ']'))?);
Selection:
@ -99,6 +108,7 @@ Selection:
('mappings=[' mappings+=Mapping (',' mappings+=Mapping)* ']')? &
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)* ']'))? &
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)* ']'))? &
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)* ']'))? &
('visibility=[' (Visibility+=VisibilityRule (',' Visibility+=VisibilityRule)* ']'))?);
List:
@ -106,6 +116,7 @@ List:
('separator=' separator=STRING) &
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)* ']'))? &
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)* ']'))? &
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)* ']'))? &
('visibility=[' (Visibility+=VisibilityRule (',' Visibility+=VisibilityRule)* ']'))?);
Setpoint:
@ -113,6 +124,7 @@ Setpoint:
('minValue=' minValue=Number)? & ('maxValue=' maxValue=Number)? & ('step=' step=Number)? &
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)* ']'))? &
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)* ']'))? &
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)* ']'))? &
('visibility=[' (Visibility+=VisibilityRule (',' Visibility+=VisibilityRule)* ']'))?);
Colorpicker:
@ -120,12 +132,14 @@ Colorpicker:
frequency=INT)? &
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)* ']'))? &
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)* ']'))? &
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)* ']'))? &
('visibility=[' (Visibility+=VisibilityRule (',' Visibility+=VisibilityRule)* ']'))?);
Input:
'Input' (('item=' item=ItemRef) & ('label=' label=(ID | STRING))? & ('icon=' icon=Icon)? &
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)* ']'))? &
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)* ']'))? &
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)* ']'))? &
('visibility=[' (Visibility+=VisibilityRule (',' Visibility+=VisibilityRule)* ']'))?);
Default:
@ -133,6 +147,7 @@ Default:
('height=' height=INT)? &
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)* ']'))? &
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)* ']'))? &
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)* ']'))? &
('visibility=[' (Visibility+=VisibilityRule (',' Visibility+=VisibilityRule)* ']'))?);
Mapping:

View File

@ -74,6 +74,7 @@ import org.slf4j.LoggerFactory;
* "system:sitemap" namespace.
*
* @author Yannick Schaus - Initial contribution
* @author Laurent Garnier - icon color support for all widgets
*/
@NonNullByDefault
@Component(service = SitemapProvider.class)
@ -186,7 +187,6 @@ public class UIComponentSitemapProvider implements SitemapProvider, RegistryChan
widget = imageWidget;
setWidgetPropertyFromComponentConfig(widget, component, "url", SitemapPackage.IMAGE__URL);
setWidgetPropertyFromComponentConfig(widget, component, "refresh", SitemapPackage.IMAGE__REFRESH);
addIconColor(imageWidget.getIconColor(), component);
break;
case "Video":
VideoImpl videoWidget = (VideoImpl) SitemapFactory.eINSTANCE.createVideo();
@ -284,6 +284,7 @@ public class UIComponentSitemapProvider implements SitemapProvider, RegistryChan
addWidgetVisibility(widget.getVisibility(), component);
addLabelColor(widget.getLabelColor(), component);
addValueColor(widget.getValueColor(), component);
addIconColor(widget.getIconColor(), component);
}
return widget;
@ -363,7 +364,7 @@ public class UIComponentSitemapProvider implements SitemapProvider, RegistryChan
}
private void addIconColor(EList<ColorArray> iconColor, UIComponent component) {
addColor(iconColor, component, "valuecolor");
addColor(iconColor, component, "iconcolor");
}
private void addColor(EList<ColorArray> color, UIComponent component, String key) {

View File

@ -107,6 +107,7 @@ import org.slf4j.LoggerFactory;
* @author Chris Jackson - Initial contribution
* @author Stefan Triller - Method to convert a state into something a sitemap entity can understand
* @author Erdoan Hadzhiyusein - Adapted the class to work with the new DateTimeType
* @author Laurent Garnier - new method getIconColor
*/
@NonNullByDefault
@Component(immediate = true, configurationPid = "org.openhab.sitemap", //
@ -743,6 +744,7 @@ public class ItemUIRegistryImpl implements ItemUIRegistry {
target.getVisibility().addAll(EcoreUtil.copyAll(source.getVisibility()));
target.getLabelColor().addAll(EcoreUtil.copyAll(source.getLabelColor()));
target.getValueColor().addAll(EcoreUtil.copyAll(source.getValueColor()));
target.getIconColor().addAll(EcoreUtil.copyAll(source.getIconColor()));
}
/**
@ -1176,6 +1178,11 @@ public class ItemUIRegistryImpl implements ItemUIRegistry {
return processColorDefinition(getState(w), w.getValueColor());
}
@Override
public @Nullable String getIconColor(Widget w) {
return processColorDefinition(getState(w), w.getIconColor());
}
@Override
public boolean getVisiblity(Widget w) {
// Default to visible if parameters not set

View File

@ -33,6 +33,7 @@ import org.openhab.core.types.State;
*
* @author Kai Kreuzer - Initial contribution
* @author Chris Jackson - Initial contribution
* @author Laurent Garnier - new method getIconColor
*/
@NonNullByDefault
public interface ItemUIRegistry extends ItemRegistry, ItemUIProvider {
@ -149,6 +150,16 @@ public interface ItemUIRegistry extends ItemRegistry, ItemUIProvider {
@Nullable
String getValueColor(Widget w);
/**
* Gets the icon color for the widget. Checks conditional statements to
* find the color based on the item value
*
* @param w Widget
* @return String with the color
*/
@Nullable
String getIconColor(Widget w);
/**
* Gets the widget visibility based on the item state
*

View File

@ -979,4 +979,40 @@ public class ItemUIRegistryImplTest {
color = uiRegistry.getValueColor(widgetMock);
assertEquals("blue", color);
}
@Test
public void getIconColor() {
ColorArray colorArray = mock(ColorArray.class);
when(colorArray.getState()).thenReturn("21");
when(colorArray.getCondition()).thenReturn("<");
when(colorArray.getArg()).thenReturn("yellow");
BasicEList<ColorArray> colorArrays = new BasicEList<>();
colorArrays.add(colorArray);
ColorArray colorArray2 = mock(ColorArray.class);
when(colorArray2.getState()).thenReturn("24");
when(colorArray2.getCondition()).thenReturn("<");
when(colorArray2.getArg()).thenReturn("red");
colorArrays.add(colorArray2);
ColorArray colorArray3 = mock(ColorArray.class);
when(colorArray3.getState()).thenReturn(null);
when(colorArray3.getCondition()).thenReturn(null);
when(colorArray3.getArg()).thenReturn("blue");
colorArrays.add(colorArray3);
when(widgetMock.getIconColor()).thenReturn(colorArrays);
when(itemMock.getState()).thenReturn(new DecimalType(20.9));
String color = uiRegistry.getIconColor(widgetMock);
assertEquals("yellow", color);
when(itemMock.getState()).thenReturn(new DecimalType(23.5));
color = uiRegistry.getIconColor(widgetMock);
assertEquals("red", color);
when(itemMock.getState()).thenReturn(new DecimalType(30.0));
color = uiRegistry.getIconColor(widgetMock);
assertEquals("blue", color);
}
}