mirror of
https://github.com/danieldemus/openhab-core.git
synced 2025-01-10 13:21:53 +01:00
[Sitemap] Add optional conditional rules for icon (#3820)
This allows dynamic icons based on items states even with non OH icon sources. This also allows overwritting the default handling with state done by the icon servlet. Example: icon=[item1>0=temperature,==0=material:settings,f7:house] Related to openhab/openhab-webui#1938 Signed-off-by: Laurent Garnier <lg.hc@free.fr>
This commit is contained in:
parent
4001161810
commit
7281dca286
@ -39,6 +39,7 @@ import org.openhab.core.model.sitemap.sitemap.Chart;
|
||||
import org.openhab.core.model.sitemap.sitemap.ColorArray;
|
||||
import org.openhab.core.model.sitemap.sitemap.Condition;
|
||||
import org.openhab.core.model.sitemap.sitemap.Frame;
|
||||
import org.openhab.core.model.sitemap.sitemap.IconRule;
|
||||
import org.openhab.core.model.sitemap.sitemap.VisibilityRule;
|
||||
import org.openhab.core.model.sitemap.sitemap.Widget;
|
||||
import org.openhab.core.types.State;
|
||||
@ -50,6 +51,7 @@ import org.openhab.core.ui.items.ItemUIRegistry;
|
||||
* @author Kai Kreuzer - Initial contribution
|
||||
* @author Laurent Garnier - Added support for icon color
|
||||
* @author Laurent Garnier - Support added for multiple AND conditions in labelcolor/valuecolor/visibility
|
||||
* @author Laurent Garnier - New widget icon parameter based on conditional rules
|
||||
*/
|
||||
public class PageChangeListener implements EventSubscriber {
|
||||
|
||||
@ -122,6 +124,10 @@ public class PageChangeListener implements EventSubscriber {
|
||||
if (widget instanceof Frame frame) {
|
||||
items.addAll(getAllItems(frame.getChildren()));
|
||||
}
|
||||
// now scan icon rules
|
||||
for (IconRule rule : widget.getIconRules()) {
|
||||
addItemsFromConditions(items, rule.getConditions());
|
||||
}
|
||||
// now scan visibility rules
|
||||
for (VisibilityRule rule : widget.getVisibility()) {
|
||||
addItemsFromConditions(items, rule.getConditions());
|
||||
@ -194,7 +200,7 @@ public class PageChangeListener implements EventSubscriber {
|
||||
if (!skipWidget && w instanceof Chart chartWidget) {
|
||||
skipWidget = chartWidget.getRefresh() > 0;
|
||||
}
|
||||
if (!skipWidget || definesVisibilityOrColor(w, item.getName())) {
|
||||
if (!skipWidget || definesVisibilityOrColorOrIcon(w, item.getName())) {
|
||||
SitemapWidgetEvent event = constructSitemapEventForWidget(item, state, w);
|
||||
events.add(event);
|
||||
}
|
||||
@ -208,6 +214,8 @@ public class PageChangeListener implements EventSubscriber {
|
||||
event.pageId = pageId;
|
||||
event.label = itemUIRegistry.getLabel(widget);
|
||||
event.widgetId = itemUIRegistry.getWidgetId(widget);
|
||||
event.icon = itemUIRegistry.getCategory(widget);
|
||||
event.reloadIcon = widget.getStaticIcon() == null;
|
||||
event.visibility = itemUIRegistry.getVisiblity(widget);
|
||||
event.descriptionChanged = false;
|
||||
// event.item contains the (potentially changed) data of the item belonging to
|
||||
@ -248,11 +256,12 @@ public class PageChangeListener implements EventSubscriber {
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean definesVisibilityOrColor(Widget w, String name) {
|
||||
private boolean definesVisibilityOrColorOrIcon(Widget w, String name) {
|
||||
return w.getVisibility().stream().anyMatch(r -> conditionsDependsOnItem(r.getConditions(), name))
|
||||
|| w.getLabelColor().stream().anyMatch(r -> conditionsDependsOnItem(r.getConditions(), name))
|
||||
|| w.getValueColor().stream().anyMatch(r -> conditionsDependsOnItem(r.getConditions(), name))
|
||||
|| w.getIconColor().stream().anyMatch(r -> conditionsDependsOnItem(r.getConditions(), name));
|
||||
|| w.getIconColor().stream().anyMatch(r -> conditionsDependsOnItem(r.getConditions(), name))
|
||||
|| w.getIconRules().stream().anyMatch(r -> conditionsDependsOnItem(r.getConditions(), name));
|
||||
}
|
||||
|
||||
private boolean conditionsDependsOnItem(@Nullable EList<Condition> conditions, String name) {
|
||||
|
@ -82,6 +82,7 @@ import org.openhab.core.model.sitemap.sitemap.Chart;
|
||||
import org.openhab.core.model.sitemap.sitemap.ColorArray;
|
||||
import org.openhab.core.model.sitemap.sitemap.Condition;
|
||||
import org.openhab.core.model.sitemap.sitemap.Frame;
|
||||
import org.openhab.core.model.sitemap.sitemap.IconRule;
|
||||
import org.openhab.core.model.sitemap.sitemap.Image;
|
||||
import org.openhab.core.model.sitemap.sitemap.Input;
|
||||
import org.openhab.core.model.sitemap.sitemap.LinkableWidget;
|
||||
@ -137,6 +138,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
* @author Laurent Garnier - Added support for new sitemap element Buttongrid
|
||||
* @author Laurent Garnier - Added icon field for mappings used for switch element
|
||||
* @author Laurent Garnier - Support added for multiple AND conditions in labelcolor/valuecolor/visibility
|
||||
* @author Laurent Garnier - New widget icon parameter based on conditional rules
|
||||
*/
|
||||
@Component(service = { RESTResource.class, EventSubscriber.class })
|
||||
@JaxrsResource
|
||||
@ -529,7 +531,7 @@ public class SitemapResource
|
||||
}
|
||||
bean.widgetId = widgetId;
|
||||
bean.icon = itemUIRegistry.getCategory(widget);
|
||||
bean.staticIcon = widget.getStaticIcon() != null;
|
||||
bean.staticIcon = widget.getStaticIcon() != null || !widget.getIconRules().isEmpty();
|
||||
bean.labelcolor = convertItemValueColor(itemUIRegistry.getLabelColor(widget), itemState);
|
||||
bean.valuecolor = convertItemValueColor(itemUIRegistry.getValueColor(widget), itemState);
|
||||
bean.iconcolor = convertItemValueColor(itemUIRegistry.getIconColor(widget), itemState);
|
||||
@ -759,6 +761,8 @@ public class SitemapResource
|
||||
if (widget instanceof Frame frame) {
|
||||
items.addAll(getAllItems(frame.getChildren()));
|
||||
}
|
||||
// Consider items involved in any icon condition
|
||||
items.addAll(getItemsInIconCond(widget.getIconRules()));
|
||||
// Consider items involved in any visibility, labelcolor, valuecolor and iconcolor condition
|
||||
items.addAll(getItemsInVisibilityCond(widget.getVisibility()));
|
||||
items.addAll(getItemsInColorCond(widget.getLabelColor()));
|
||||
@ -784,6 +788,14 @@ public class SitemapResource
|
||||
return items;
|
||||
}
|
||||
|
||||
private Set<GenericItem> getItemsInIconCond(EList<IconRule> ruleList) {
|
||||
Set<GenericItem> items = new HashSet<>();
|
||||
for (IconRule rule : ruleList) {
|
||||
getItemsInConditions(rule.getConditions(), items);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
private void getItemsInConditions(@Nullable EList<Condition> conditions, Set<GenericItem> items) {
|
||||
if (conditions != null) {
|
||||
for (Condition condition : conditions) {
|
||||
|
@ -19,6 +19,7 @@ import org.openhab.core.io.rest.core.item.EnrichedItemDTO;
|
||||
*
|
||||
* @author Kai Kreuzer - Initial contribution
|
||||
* @author Laurent Garnier - New field iconcolor
|
||||
* @author Laurent Garnier - New field reloadIcon
|
||||
*/
|
||||
public class SitemapWidgetEvent extends SitemapEvent {
|
||||
|
||||
@ -26,6 +27,7 @@ public class SitemapWidgetEvent extends SitemapEvent {
|
||||
|
||||
public String label;
|
||||
public String icon;
|
||||
public boolean reloadIcon;
|
||||
public String labelcolor;
|
||||
public String valuecolor;
|
||||
public String iconcolor;
|
||||
|
@ -36,6 +36,11 @@ public class WidgetDTO {
|
||||
|
||||
public String label;
|
||||
public String icon;
|
||||
/**
|
||||
* staticIcon is a boolean indicating if the widget state must be ignored when requesting the icon.
|
||||
* It is set to true when the widget has either the staticIcon property set or the icon property set
|
||||
* with conditional rules.
|
||||
*/
|
||||
public Boolean staticIcon;
|
||||
public String labelcolor;
|
||||
public String valuecolor;
|
||||
|
@ -50,6 +50,7 @@ import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.model.sitemap.SitemapProvider;
|
||||
import org.openhab.core.model.sitemap.sitemap.ColorArray;
|
||||
import org.openhab.core.model.sitemap.sitemap.Condition;
|
||||
import org.openhab.core.model.sitemap.sitemap.IconRule;
|
||||
import org.openhab.core.model.sitemap.sitemap.Sitemap;
|
||||
import org.openhab.core.model.sitemap.sitemap.VisibilityRule;
|
||||
import org.openhab.core.model.sitemap.sitemap.Widget;
|
||||
@ -62,6 +63,7 @@ import org.openhab.core.ui.items.ItemUIRegistry;
|
||||
* Test aspects of the {@link SitemapResource}.
|
||||
*
|
||||
* @author Henning Treu - Initial contribution
|
||||
* @author Laurent Garnier - Extended tests for static icon and icon based on conditional rules
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
@ -80,10 +82,16 @@ public class SitemapResourceTest extends JavaTest {
|
||||
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 ICON_ITEM_NAME = "iconItemName";
|
||||
private static final String WIDGET1_LABEL = "widget 1";
|
||||
private static final String WIDGET2_LABEL = "widget 2";
|
||||
private static final String WIDGET3_LABEL = "widget 3";
|
||||
private static final String WIDGET1_ID = "00";
|
||||
private static final String WIDGET2_ID = "01";
|
||||
private static final String WIDGET3_ID = "02";
|
||||
private static final String WIDGET1_ICON = "icon1";
|
||||
private static final String WIDGET2_ICON = "icon2";
|
||||
private static final String WIDGET3_ICON = "icon3";
|
||||
private static final String CLIENT_IP = "127.0.0.1";
|
||||
|
||||
private @NonNullByDefault({}) SitemapResource sitemapResource;
|
||||
@ -93,6 +101,7 @@ public class SitemapResourceTest extends JavaTest {
|
||||
private @NonNullByDefault({}) GenericItem labelColorItem;
|
||||
private @NonNullByDefault({}) GenericItem valueColorItem;
|
||||
private @NonNullByDefault({}) GenericItem iconColorItem;
|
||||
private @NonNullByDefault({}) GenericItem iconItem;
|
||||
|
||||
private @Mock @NonNullByDefault({}) HttpHeaders headersMock;
|
||||
private @Mock @NonNullByDefault({}) Sitemap defaultSitemapMock;
|
||||
@ -121,6 +130,7 @@ public class SitemapResourceTest extends JavaTest {
|
||||
labelColorItem = new TestItem(LABEL_COLOR_ITEM_NAME);
|
||||
valueColorItem = new TestItem(VALUE_COLOR_ITEM_NAME);
|
||||
iconColorItem = new TestItem(ICON_COLOR_ITEM_NAME);
|
||||
iconItem = new TestItem(ICON_ITEM_NAME);
|
||||
|
||||
when(localeServiceMock.getLocale(null)).thenReturn(Locale.US);
|
||||
|
||||
@ -276,6 +286,30 @@ public class SitemapResourceTest extends JavaTest {
|
||||
// return
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenLongPollingShouldObserveItemsFromIconConditions() {
|
||||
ItemEvent itemEvent = mock(ItemEvent.class);
|
||||
when(itemEvent.getItemName()).thenReturn(iconItem.getName());
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Thread.sleep(STATE_UPDATE_WAIT_TIME); // wait for the #getPageData call and listeners to attach to the
|
||||
// item
|
||||
sitemapResource.receive(itemEvent);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}).start();
|
||||
|
||||
// non-null is sufficient here.
|
||||
when(headersMock.getRequestHeader(HTTP_HEADER_X_ATMOSPHERE_TRANSPORT)).thenReturn(List.of());
|
||||
|
||||
Response response = sitemapResource.getPageData(headersMock, null, SITEMAP_MODEL_NAME, SITEMAP_NAME, null,
|
||||
false);
|
||||
|
||||
PageDTO pageDTO = (PageDTO) response.getEntity();
|
||||
assertThat(pageDTO.timeout, is(false)); // assert that the item state change did trigger the blocking method to
|
||||
// return
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenGetPageDataShouldReturnPageBean() throws ItemNotFoundException {
|
||||
item.setState(new PercentType(50));
|
||||
@ -294,13 +328,15 @@ public class SitemapResourceTest extends JavaTest {
|
||||
assertThat(pageDTO.timeout, is(false));
|
||||
|
||||
assertThat(pageDTO.widgets, notNullValue());
|
||||
assertThat((Collection<?>) pageDTO.widgets, hasSize(2));
|
||||
assertThat((Collection<?>) pageDTO.widgets, hasSize(3));
|
||||
|
||||
assertThat(pageDTO.widgets.get(0).widgetId, is(WIDGET1_ID));
|
||||
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).icon, is(WIDGET1_ICON));
|
||||
assertThat(pageDTO.widgets.get(0).staticIcon, is(true));
|
||||
assertThat(pageDTO.widgets.get(0).state, nullValue());
|
||||
assertThat(pageDTO.widgets.get(0).item, notNullValue());
|
||||
assertThat(pageDTO.widgets.get(0).item.name, is(ITEM_NAME));
|
||||
@ -311,10 +347,24 @@ public class SitemapResourceTest extends JavaTest {
|
||||
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).icon, is(WIDGET2_ICON));
|
||||
assertThat(pageDTO.widgets.get(1).staticIcon, is(false));
|
||||
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));
|
||||
assertThat(pageDTO.widgets.get(1).item.state, is("50"));
|
||||
|
||||
assertThat(pageDTO.widgets.get(2).widgetId, is(WIDGET3_ID));
|
||||
assertThat(pageDTO.widgets.get(2).label, is(WIDGET3_LABEL));
|
||||
assertThat(pageDTO.widgets.get(2).labelcolor, nullValue());
|
||||
assertThat(pageDTO.widgets.get(2).valuecolor, nullValue());
|
||||
assertThat(pageDTO.widgets.get(2).iconcolor, nullValue());
|
||||
assertThat(pageDTO.widgets.get(2).icon, is(WIDGET3_ICON));
|
||||
assertThat(pageDTO.widgets.get(2).staticIcon, is(true));
|
||||
assertThat(pageDTO.widgets.get(2).state, is("ON"));
|
||||
assertThat(pageDTO.widgets.get(2).item, notNullValue());
|
||||
assertThat(pageDTO.widgets.get(2).item.name, is(ITEM_NAME));
|
||||
assertThat(pageDTO.widgets.get(2).item.state, is("50"));
|
||||
}
|
||||
|
||||
private void configureItemUIRegistry(State state1, State state2) throws ItemNotFoundException {
|
||||
@ -324,9 +374,10 @@ public class SitemapResourceTest extends JavaTest {
|
||||
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.getItem(ICON_ITEM_NAME)).thenReturn(iconItem);
|
||||
|
||||
when(itemUIRegistryMock.getWidgetId(widgets.get(0))).thenReturn(WIDGET1_ID);
|
||||
when(itemUIRegistryMock.getCategory(widgets.get(0))).thenReturn("");
|
||||
when(itemUIRegistryMock.getCategory(widgets.get(0))).thenReturn(WIDGET1_ICON);
|
||||
when(itemUIRegistryMock.getLabel(widgets.get(0))).thenReturn(WIDGET1_LABEL);
|
||||
when(itemUIRegistryMock.getVisiblity(widgets.get(0))).thenReturn(true);
|
||||
when(itemUIRegistryMock.getLabelColor(widgets.get(0))).thenReturn("GREEN");
|
||||
@ -335,13 +386,22 @@ public class SitemapResourceTest extends JavaTest {
|
||||
when(itemUIRegistryMock.getState(widgets.get(0))).thenReturn(state1);
|
||||
|
||||
when(itemUIRegistryMock.getWidgetId(widgets.get(1))).thenReturn(WIDGET2_ID);
|
||||
when(itemUIRegistryMock.getCategory(widgets.get(1))).thenReturn("");
|
||||
when(itemUIRegistryMock.getCategory(widgets.get(1))).thenReturn(WIDGET2_ICON);
|
||||
when(itemUIRegistryMock.getLabel(widgets.get(1))).thenReturn(WIDGET2_LABEL);
|
||||
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);
|
||||
|
||||
when(itemUIRegistryMock.getWidgetId(widgets.get(2))).thenReturn(WIDGET3_ID);
|
||||
when(itemUIRegistryMock.getCategory(widgets.get(2))).thenReturn(WIDGET3_ICON);
|
||||
when(itemUIRegistryMock.getLabel(widgets.get(2))).thenReturn(WIDGET3_LABEL);
|
||||
when(itemUIRegistryMock.getVisiblity(widgets.get(2))).thenReturn(true);
|
||||
when(itemUIRegistryMock.getLabelColor(widgets.get(2))).thenReturn(null);
|
||||
when(itemUIRegistryMock.getValueColor(widgets.get(2))).thenReturn(null);
|
||||
when(itemUIRegistryMock.getIconColor(widgets.get(2))).thenReturn(null);
|
||||
when(itemUIRegistryMock.getState(widgets.get(2))).thenReturn(state2);
|
||||
}
|
||||
|
||||
private EList<Widget> initSitemapWidgets() {
|
||||
@ -355,6 +415,19 @@ public class SitemapResourceTest extends JavaTest {
|
||||
when(w1.eClass()).thenReturn(sliderEClass);
|
||||
when(w1.getLabel()).thenReturn(WIDGET1_LABEL);
|
||||
when(w1.getItem()).thenReturn(ITEM_NAME);
|
||||
when(w1.getIcon()).thenReturn(null);
|
||||
when(w1.getStaticIcon()).thenReturn(null);
|
||||
|
||||
// add icon rules to the mock widget:
|
||||
IconRule iconRule = mock(IconRule.class);
|
||||
Condition conditon0 = mock(Condition.class);
|
||||
when(conditon0.getItem()).thenReturn(ICON_ITEM_NAME);
|
||||
EList<Condition> conditions0 = new BasicEList<>();
|
||||
conditions0.add(conditon0);
|
||||
when(iconRule.getConditions()).thenReturn(conditions0);
|
||||
EList<IconRule> iconRules = new BasicEList<>();
|
||||
iconRules.add(iconRule);
|
||||
when(w1.getIconRules()).thenReturn(iconRules);
|
||||
|
||||
// add visibility rules to the mock widget:
|
||||
VisibilityRule visibilityRule = mock(VisibilityRule.class);
|
||||
@ -400,6 +473,7 @@ public class SitemapResourceTest extends JavaTest {
|
||||
iconColors.add(iconColor);
|
||||
when(w1.getIconColor()).thenReturn(iconColors);
|
||||
|
||||
iconRules = new BasicEList<>();
|
||||
visibilityRules = new BasicEList<>();
|
||||
labelColors = new BasicEList<>();
|
||||
valueColors = new BasicEList<>();
|
||||
@ -412,14 +486,30 @@ public class SitemapResourceTest extends JavaTest {
|
||||
when(w2.eClass()).thenReturn(switchEClass);
|
||||
when(w2.getLabel()).thenReturn(WIDGET2_LABEL);
|
||||
when(w2.getItem()).thenReturn(ITEM_NAME);
|
||||
when(w2.getIcon()).thenReturn(WIDGET2_ICON);
|
||||
when(w2.getStaticIcon()).thenReturn(null);
|
||||
when(w2.getIconRules()).thenReturn(iconRules);
|
||||
when(w2.getVisibility()).thenReturn(visibilityRules);
|
||||
when(w2.getLabelColor()).thenReturn(labelColors);
|
||||
when(w2.getValueColor()).thenReturn(valueColors);
|
||||
when(w2.getIconColor()).thenReturn(iconColors);
|
||||
|
||||
EList<Widget> widgets = new BasicEList<>(2);
|
||||
Widget w3 = mock(Widget.class);
|
||||
when(w3.eClass()).thenReturn(switchEClass);
|
||||
when(w3.getLabel()).thenReturn(WIDGET3_LABEL);
|
||||
when(w3.getItem()).thenReturn(ITEM_NAME);
|
||||
when(w3.getIcon()).thenReturn(null);
|
||||
when(w3.getStaticIcon()).thenReturn(WIDGET3_ICON);
|
||||
when(w3.getIconRules()).thenReturn(iconRules);
|
||||
when(w3.getVisibility()).thenReturn(visibilityRules);
|
||||
when(w3.getLabelColor()).thenReturn(labelColors);
|
||||
when(w3.getValueColor()).thenReturn(valueColors);
|
||||
when(w3.getIconColor()).thenReturn(iconColors);
|
||||
|
||||
EList<Widget> widgets = new BasicEList<>(3);
|
||||
widgets.add(w1);
|
||||
widgets.add(w2);
|
||||
widgets.add(w3);
|
||||
return widgets;
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,9 @@ LinkableWidget:
|
||||
|
||||
Frame:
|
||||
{Frame} 'Frame' (('item=' item=ItemRef)? & ('label=' label=(ID | STRING))? &
|
||||
(('icon=' icon=Icon) | ('staticIcon=' staticIcon=Icon))? &
|
||||
(('icon=' icon=Icon) |
|
||||
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
|
||||
('staticIcon=' staticIcon=Icon))? &
|
||||
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
|
||||
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)*) ']')? &
|
||||
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)*) ']')? &
|
||||
@ -33,7 +35,9 @@ Frame:
|
||||
|
||||
Text:
|
||||
{Text} 'Text' (('item=' item=ItemRef)? & ('label=' label=(ID | STRING))? &
|
||||
(('icon=' icon=Icon) | ('staticIcon=' staticIcon=Icon))? &
|
||||
(('icon=' icon=Icon) |
|
||||
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
|
||||
('staticIcon=' staticIcon=Icon))? &
|
||||
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
|
||||
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)*) ']')? &
|
||||
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)*) ']')? &
|
||||
@ -41,7 +45,9 @@ Text:
|
||||
|
||||
Group:
|
||||
'Group' (('item=' item=GroupItemRef) & ('label=' label=(ID | STRING))? &
|
||||
(('icon=' icon=Icon) | ('staticIcon=' staticIcon=Icon))? &
|
||||
(('icon=' icon=Icon) |
|
||||
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
|
||||
('staticIcon=' staticIcon=Icon))? &
|
||||
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
|
||||
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)*) ']')? &
|
||||
('iconcolor=[' (IconColor+=ColorArray (',' IconColor+=ColorArray)*) ']')? &
|
||||
@ -49,7 +55,9 @@ Group:
|
||||
|
||||
Image:
|
||||
'Image' (('item=' item=ItemRef)? & ('label=' label=(ID | STRING))? &
|
||||
(('icon=' icon=Icon) | ('staticIcon=' staticIcon=Icon))? &
|
||||
(('icon=' icon=Icon) |
|
||||
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
|
||||
('staticIcon=' staticIcon=Icon))? &
|
||||
('url=' url=STRING)? & ('refresh=' refresh=INT)? &
|
||||
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
|
||||
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)*) ']')? &
|
||||
@ -58,7 +66,9 @@ Image:
|
||||
|
||||
Video:
|
||||
'Video' (('item=' item=ItemRef)? & ('label=' label=(ID | STRING))? &
|
||||
(('icon=' icon=Icon) | ('staticIcon=' staticIcon=Icon))? &
|
||||
(('icon=' icon=Icon) |
|
||||
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
|
||||
('staticIcon=' staticIcon=Icon))? &
|
||||
('url=' url=STRING) & ('encoding=' encoding=STRING)? &
|
||||
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
|
||||
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)*) ']')? &
|
||||
@ -67,7 +77,9 @@ Video:
|
||||
|
||||
Chart:
|
||||
'Chart' (('item=' item=ItemRef) & ('label=' label=(ID | STRING))? &
|
||||
(('icon=' icon=Icon) | ('staticIcon=' staticIcon=Icon))? &
|
||||
(('icon=' icon=Icon) |
|
||||
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
|
||||
('staticIcon=' staticIcon=Icon))? &
|
||||
('service=' service=STRING)? & ('refresh=' refresh=INT)? & ('period=' period=ID) &
|
||||
('legend=' legend=BOOLEAN_OBJECT)? & ('forceasitem=' forceAsItem=BOOLEAN_OBJECT)? &
|
||||
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
|
||||
@ -78,7 +90,9 @@ Chart:
|
||||
|
||||
Webview:
|
||||
'Webview' (('item=' item=ItemRef)? & ('label=' label=(ID | STRING))? &
|
||||
(('icon=' icon=Icon) | ('staticIcon=' staticIcon=Icon))? &
|
||||
(('icon=' icon=Icon) |
|
||||
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
|
||||
('staticIcon=' staticIcon=Icon))? &
|
||||
('height=' height=INT)? & ('url=' url=STRING) &
|
||||
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
|
||||
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)*) ']')? &
|
||||
@ -87,7 +101,9 @@ Webview:
|
||||
|
||||
Switch:
|
||||
'Switch' (('item=' item=ItemRef) & ('label=' label=(ID | STRING))? &
|
||||
(('icon=' icon=Icon) | ('staticIcon=' staticIcon=Icon))? &
|
||||
(('icon=' icon=Icon) |
|
||||
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
|
||||
('staticIcon=' staticIcon=Icon))? &
|
||||
('mappings=[' mappings+=Mapping (',' mappings+=Mapping)* ']')? &
|
||||
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
|
||||
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)*) ']')? &
|
||||
@ -96,7 +112,9 @@ Switch:
|
||||
|
||||
Mapview:
|
||||
'Mapview' (('item=' item=ItemRef) & ('label=' label=(ID | STRING))? &
|
||||
(('icon=' icon=Icon) | ('staticIcon=' staticIcon=Icon))? &
|
||||
(('icon=' icon=Icon) |
|
||||
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
|
||||
('staticIcon=' staticIcon=Icon))? &
|
||||
('height=' height=INT)? &
|
||||
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
|
||||
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)*) ']')? &
|
||||
@ -105,7 +123,9 @@ Mapview:
|
||||
|
||||
Slider:
|
||||
'Slider' (('item=' item=ItemRef) & ('label=' label=(ID | STRING))? &
|
||||
(('icon=' icon=Icon) | ('staticIcon=' staticIcon=Icon))? &
|
||||
(('icon=' icon=Icon) |
|
||||
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
|
||||
('staticIcon=' staticIcon=Icon))? &
|
||||
('sendFrequency=' frequency=INT)? & (switchEnabled?='switchSupport')? &
|
||||
('minValue=' minValue=Number)? & ('maxValue=' maxValue=Number)? & ('step=' step=Number)? &
|
||||
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
|
||||
@ -115,7 +135,9 @@ Slider:
|
||||
|
||||
Selection:
|
||||
'Selection' (('item=' item=ItemRef) & ('label=' label=(ID | STRING))? &
|
||||
(('icon=' icon=Icon) | ('staticIcon=' staticIcon=Icon))? &
|
||||
(('icon=' icon=Icon) |
|
||||
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
|
||||
('staticIcon=' staticIcon=Icon))? &
|
||||
('mappings=[' mappings+=Mapping (',' mappings+=Mapping)* ']')? &
|
||||
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
|
||||
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)*) ']')? &
|
||||
@ -124,7 +146,9 @@ Selection:
|
||||
|
||||
Setpoint:
|
||||
'Setpoint' (('item=' item=ItemRef) & ('label=' label=(ID | STRING))? &
|
||||
(('icon=' icon=Icon) | ('staticIcon=' staticIcon=Icon))? &
|
||||
(('icon=' icon=Icon) |
|
||||
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
|
||||
('staticIcon=' staticIcon=Icon))? &
|
||||
('minValue=' minValue=Number)? & ('maxValue=' maxValue=Number)? & ('step=' step=Number)? &
|
||||
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
|
||||
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)*) ']')? &
|
||||
@ -133,7 +157,9 @@ Setpoint:
|
||||
|
||||
Colorpicker:
|
||||
'Colorpicker' (('item=' item=ItemRef) & ('label=' label=(ID | STRING))? &
|
||||
(('icon=' icon=Icon) | ('staticIcon=' staticIcon=Icon))? &
|
||||
(('icon=' icon=Icon) |
|
||||
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
|
||||
('staticIcon=' staticIcon=Icon))? &
|
||||
('sendFrequency=' frequency=INT)? &
|
||||
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
|
||||
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)*) ']')? &
|
||||
@ -142,7 +168,9 @@ Colorpicker:
|
||||
|
||||
Input:
|
||||
'Input' (('item=' item=ItemRef) & ('label=' label=(ID | STRING))? &
|
||||
(('icon=' icon=Icon) | ('staticIcon=' staticIcon=Icon))? &
|
||||
(('icon=' icon=Icon) |
|
||||
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
|
||||
('staticIcon=' staticIcon=Icon))? &
|
||||
('inputHint=' inputHint=STRING)? &
|
||||
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
|
||||
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)*) ']')? &
|
||||
@ -151,7 +179,9 @@ Input:
|
||||
|
||||
Buttongrid:
|
||||
'Buttongrid' (('item=' item=ItemRef) & ('label=' label=(ID | STRING))? &
|
||||
(('icon=' icon=Icon) | ('staticIcon=' staticIcon=Icon))? &
|
||||
(('icon=' icon=Icon) |
|
||||
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
|
||||
('staticIcon=' staticIcon=Icon))? &
|
||||
('columns=' columns=INT) &
|
||||
('buttons=[' buttons+=Button (',' buttons+=Button)* ']') &
|
||||
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
|
||||
@ -161,7 +191,9 @@ Buttongrid:
|
||||
|
||||
Default:
|
||||
'Default' (('item=' item=ItemRef) & ('label=' label=(ID | STRING))? &
|
||||
(('icon=' icon=Icon) | ('staticIcon=' staticIcon=Icon))? &
|
||||
(('icon=' icon=Icon) |
|
||||
('icon=[' (IconRules+=IconRule (',' IconRules+=IconRule)*) ']') |
|
||||
('staticIcon=' staticIcon=Icon))? &
|
||||
('height=' height=INT)? &
|
||||
('labelcolor=[' (LabelColor+=ColorArray (',' LabelColor+=ColorArray)*) ']')? &
|
||||
('valuecolor=[' (ValueColor+=ColorArray (',' ValueColor+=ColorArray)*) ']')? &
|
||||
@ -193,6 +225,9 @@ IconName:
|
||||
ColorArray:
|
||||
((conditions+=Condition ('AND' conditions+=Condition)*) '=')? (arg=STRING);
|
||||
|
||||
IconRule:
|
||||
((conditions+=Condition ('AND' conditions+=Condition)*) '=')? (arg=Icon);
|
||||
|
||||
Condition:
|
||||
(item=ID)? (condition=('==' | '>' | '<' | '>=' | '<=' | '!='))? (sign=('-' | '+'))? (state=XState);
|
||||
|
||||
|
@ -31,6 +31,7 @@ import org.openhab.core.model.core.ModelRepositoryChangeListener;
|
||||
import org.openhab.core.model.sitemap.SitemapProvider;
|
||||
import org.openhab.core.model.sitemap.sitemap.Button;
|
||||
import org.openhab.core.model.sitemap.sitemap.ColorArray;
|
||||
import org.openhab.core.model.sitemap.sitemap.IconRule;
|
||||
import org.openhab.core.model.sitemap.sitemap.LinkableWidget;
|
||||
import org.openhab.core.model.sitemap.sitemap.Mapping;
|
||||
import org.openhab.core.model.sitemap.sitemap.Sitemap;
|
||||
@ -47,6 +48,7 @@ import org.openhab.core.model.sitemap.sitemap.impl.ConditionImpl;
|
||||
import org.openhab.core.model.sitemap.sitemap.impl.DefaultImpl;
|
||||
import org.openhab.core.model.sitemap.sitemap.impl.FrameImpl;
|
||||
import org.openhab.core.model.sitemap.sitemap.impl.GroupImpl;
|
||||
import org.openhab.core.model.sitemap.sitemap.impl.IconRuleImpl;
|
||||
import org.openhab.core.model.sitemap.sitemap.impl.ImageImpl;
|
||||
import org.openhab.core.model.sitemap.sitemap.impl.InputImpl;
|
||||
import org.openhab.core.model.sitemap.sitemap.impl.MappingImpl;
|
||||
@ -95,6 +97,7 @@ public class UIComponentSitemapProvider implements SitemapProvider, RegistryChan
|
||||
.compile("(?<item>[A-Za-z]\\w*)\\s*(?<condition>==|!=|<=|>=|<|>)\\s*(?<sign>\\+|-)?(?<state>.+)");
|
||||
private static final Pattern COLOR_PATTERN = Pattern.compile(
|
||||
"((?<item>[A-Za-z]\\w*)?\\s*((?<condition>==|!=|<=|>=|<|>)\\s*(?<sign>\\+|-)?(?<state>[^=]*[^= ]+))?\\s*=)?\\s*(?<arg>\\S+)");
|
||||
private static final Pattern ICON_PATTERN = COLOR_PATTERN;
|
||||
|
||||
private Map<String, Sitemap> sitemaps = new HashMap<>();
|
||||
private @Nullable UIComponentRegistryFactory componentRegistryFactory;
|
||||
@ -296,6 +299,7 @@ public class UIComponentSitemapProvider implements SitemapProvider, RegistryChan
|
||||
addLabelColor(widget.getLabelColor(), component);
|
||||
addValueColor(widget.getValueColor(), component);
|
||||
addIconColor(widget.getIconColor(), component);
|
||||
addIconRules(widget.getIconRules(), component);
|
||||
}
|
||||
|
||||
return widget;
|
||||
@ -429,6 +433,29 @@ public class UIComponentSitemapProvider implements SitemapProvider, RegistryChan
|
||||
}
|
||||
}
|
||||
|
||||
private void addIconRules(EList<IconRule> iconDef, UIComponent component) {
|
||||
if (component.getConfig() != null && component.getConfig().containsKey("icon")) {
|
||||
for (Object sourceIcon : (Collection<?>) component.getConfig().get("icon")) {
|
||||
if (sourceIcon instanceof String) {
|
||||
Matcher matcher = ICON_PATTERN.matcher(sourceIcon.toString());
|
||||
if (matcher.matches()) {
|
||||
IconRuleImpl iconRule = (IconRuleImpl) SitemapFactory.eINSTANCE.createIconRule();
|
||||
ConditionImpl condition = (ConditionImpl) SitemapFactory.eINSTANCE.createCondition();
|
||||
condition.setItem(matcher.group("item"));
|
||||
condition.setCondition(matcher.group("condition"));
|
||||
condition.setSign(matcher.group("sign"));
|
||||
condition.setState(matcher.group("state"));
|
||||
iconRule.eSet(SitemapPackage.ICON_RULE__CONDITIONS, condition);
|
||||
iconRule.setArg(matcher.group("arg"));
|
||||
iconDef.add(iconRule);
|
||||
} else {
|
||||
logger.warn("Syntax error in icon rule '{}' for widget {}", sourceIcon, component.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addModelChangeListener(ModelRepositoryChangeListener listener) {
|
||||
modelChangeListeners.add(listener);
|
||||
|
@ -68,6 +68,7 @@ import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.model.sitemap.sitemap.ColorArray;
|
||||
import org.openhab.core.model.sitemap.sitemap.Default;
|
||||
import org.openhab.core.model.sitemap.sitemap.Group;
|
||||
import org.openhab.core.model.sitemap.sitemap.IconRule;
|
||||
import org.openhab.core.model.sitemap.sitemap.LinkableWidget;
|
||||
import org.openhab.core.model.sitemap.sitemap.Mapping;
|
||||
import org.openhab.core.model.sitemap.sitemap.Sitemap;
|
||||
@ -110,6 +111,7 @@ import org.slf4j.LoggerFactory;
|
||||
* @author Laurent Garnier - new method getIconColor
|
||||
* @author Mark Herwege - new method getFormatPattern(widget), clean pattern
|
||||
* @author Laurent Garnier - Support added for multiple AND conditions in labelcolor/valuecolor/visibility
|
||||
* @author Laurent Garnier - new icon parameter based on conditional rules
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(immediate = true, configurationPid = "org.openhab.sitemap", //
|
||||
@ -639,11 +641,14 @@ public class ItemUIRegistryImpl implements ItemUIRegistry {
|
||||
// the default is the widget type name, e.g. "switch"
|
||||
String category = widgetTypeName.toLowerCase();
|
||||
|
||||
String conditionalIcon = getConditionalIcon(w);
|
||||
// if an icon is defined for the widget, use it
|
||||
if (w.getIcon() != null) {
|
||||
category = w.getIcon();
|
||||
} else if (w.getStaticIcon() != null) {
|
||||
category = w.getStaticIcon();
|
||||
} else if (conditionalIcon != null) {
|
||||
category = conditionalIcon;
|
||||
} else {
|
||||
// otherwise check if any item ui provider provides an icon for this item
|
||||
String itemName = w.getItem();
|
||||
@ -801,6 +806,7 @@ public class ItemUIRegistryImpl implements ItemUIRegistry {
|
||||
target.getLabelColor().addAll(EcoreUtil.copyAll(source.getLabelColor()));
|
||||
target.getValueColor().addAll(EcoreUtil.copyAll(source.getValueColor()));
|
||||
target.getIconColor().addAll(EcoreUtil.copyAll(source.getIconColor()));
|
||||
target.getIconRules().addAll(EcoreUtil.copyAll(source.getIconRules()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1220,6 +1226,42 @@ public class ItemUIRegistryImpl implements ItemUIRegistry {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getConditionalIcon(Widget w) {
|
||||
List<IconRule> ruleList = w.getIconRules();
|
||||
// Sanity check
|
||||
if (ruleList == null || ruleList.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
logger.debug("Checking icon for widget '{}'.", w.getLabel());
|
||||
|
||||
String icon = null;
|
||||
|
||||
// Loop through all elements looking for the definition associated
|
||||
// with the supplied value
|
||||
for (IconRule rule : ruleList) {
|
||||
if (allConditionsOk(rule.getConditions(), w)) {
|
||||
// We have the icon for this value - break!
|
||||
icon = rule.getArg();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (icon == null) {
|
||||
logger.debug("No icon found for widget '{}'.", w.getLabel());
|
||||
return null;
|
||||
}
|
||||
|
||||
// Remove quotes off the icon - if they exist
|
||||
if (icon.startsWith("\"") && icon.endsWith("\"")) {
|
||||
icon = icon.substring(1, icon.length() - 1);
|
||||
}
|
||||
logger.debug("icon for widget '{}' is '{}'.", w.getLabel(), icon);
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
private boolean allConditionsOk(@Nullable List<org.openhab.core.model.sitemap.sitemap.Condition> conditions,
|
||||
Widget w) {
|
||||
boolean allConditionsOk = true;
|
||||
|
@ -35,6 +35,7 @@ import org.openhab.core.types.State;
|
||||
* @author Chris Jackson - Initial contribution
|
||||
* @author Laurent Garnier - new method getIconColor
|
||||
* @author Mark Herwege - new method getFormatPattern
|
||||
* @author Laurent Garnier - new method getConditionalIcon
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface ItemUIRegistry extends ItemRegistry, ItemUIProvider {
|
||||
@ -170,6 +171,17 @@ public interface ItemUIRegistry extends ItemRegistry, ItemUIProvider {
|
||||
@Nullable
|
||||
String getIconColor(Widget w);
|
||||
|
||||
/**
|
||||
* Gets the icon for the widget. Checks conditional statements to
|
||||
* find the icon based on the item value
|
||||
*
|
||||
* @param w Widget
|
||||
* @return the icon reference or null in case no conditional statement is defined or no conditional statement is
|
||||
* fulfilled.
|
||||
*/
|
||||
@Nullable
|
||||
String getConditionalIcon(Widget w);
|
||||
|
||||
/**
|
||||
* Gets the widget visibility based on the item state
|
||||
*
|
||||
|
@ -27,6 +27,7 @@ import java.util.TimeZone;
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.eclipse.emf.common.util.BasicEList;
|
||||
import org.eclipse.emf.ecore.EClass;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -62,6 +63,7 @@ import org.openhab.core.model.sitemap.sitemap.ColorArray;
|
||||
import org.openhab.core.model.sitemap.sitemap.Colorpicker;
|
||||
import org.openhab.core.model.sitemap.sitemap.Condition;
|
||||
import org.openhab.core.model.sitemap.sitemap.Group;
|
||||
import org.openhab.core.model.sitemap.sitemap.IconRule;
|
||||
import org.openhab.core.model.sitemap.sitemap.Image;
|
||||
import org.openhab.core.model.sitemap.sitemap.Mapping;
|
||||
import org.openhab.core.model.sitemap.sitemap.Mapview;
|
||||
@ -86,6 +88,7 @@ import org.openhab.core.ui.items.ItemUIProvider;
|
||||
/**
|
||||
* @author Kai Kreuzer - Initial contribution
|
||||
* @author Laurent Garnier - Tests updated to consider multiple AND conditions + tests added for getVisiblity
|
||||
* @author Laurent Garnier - Tests added for getCategory
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
@ -1184,4 +1187,114 @@ public class ItemUIRegistryImplTest {
|
||||
|
||||
assertFalse(uiRegistry.getVisiblity(widgetMock));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCategoryWhenIconSetWithoutRules() {
|
||||
EClass textEClass = mock(EClass.class);
|
||||
when(textEClass.getName()).thenReturn("text");
|
||||
when(textEClass.getInstanceTypeName()).thenReturn("org.openhab.core.model.sitemap.Text");
|
||||
when(widgetMock.eClass()).thenReturn(textEClass);
|
||||
when(widgetMock.getIcon()).thenReturn("temperature");
|
||||
when(widgetMock.getStaticIcon()).thenReturn(null);
|
||||
when(widgetMock.getIconRules()).thenReturn(null);
|
||||
|
||||
String icon = uiRegistry.getCategory(widgetMock);
|
||||
assertEquals("temperature", icon);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCategoryWhenIconSetWithRules() {
|
||||
EClass textEClass = mock(EClass.class);
|
||||
when(textEClass.getName()).thenReturn("text");
|
||||
when(textEClass.getInstanceTypeName()).thenReturn("org.openhab.core.model.sitemap.Text");
|
||||
when(widgetMock.eClass()).thenReturn(textEClass);
|
||||
when(widgetMock.getIcon()).thenReturn(null);
|
||||
when(widgetMock.getStaticIcon()).thenReturn(null);
|
||||
Condition conditon = mock(Condition.class);
|
||||
when(conditon.getState()).thenReturn("21");
|
||||
when(conditon.getCondition()).thenReturn(">=");
|
||||
Condition conditon2 = mock(Condition.class);
|
||||
when(conditon2.getState()).thenReturn("24");
|
||||
when(conditon2.getCondition()).thenReturn("<");
|
||||
BasicEList<Condition> conditions = new BasicEList<>();
|
||||
conditions.add(conditon);
|
||||
conditions.add(conditon2);
|
||||
IconRule rule = mock(IconRule.class);
|
||||
when(rule.getConditions()).thenReturn(conditions);
|
||||
when(rule.getArg()).thenReturn("temperature");
|
||||
BasicEList<IconRule> rules = new BasicEList<>();
|
||||
rules.add(rule);
|
||||
BasicEList<Condition> conditions2 = new BasicEList<>();
|
||||
IconRule rule2 = mock(IconRule.class);
|
||||
when(rule2.getConditions()).thenReturn(conditions2);
|
||||
when(rule2.getArg()).thenReturn("humidity");
|
||||
rules.add(rule2);
|
||||
when(widgetMock.getIconRules()).thenReturn(rules);
|
||||
|
||||
when(itemMock.getState()).thenReturn(new DecimalType(20.9));
|
||||
|
||||
String icon = uiRegistry.getCategory(widgetMock);
|
||||
assertEquals("humidity", icon);
|
||||
|
||||
when(itemMock.getState()).thenReturn(new DecimalType(21.0));
|
||||
|
||||
icon = uiRegistry.getCategory(widgetMock);
|
||||
assertEquals("temperature", icon);
|
||||
|
||||
when(itemMock.getState()).thenReturn(new DecimalType(23.5));
|
||||
|
||||
icon = uiRegistry.getCategory(widgetMock);
|
||||
assertEquals("temperature", icon);
|
||||
|
||||
when(itemMock.getState()).thenReturn(new DecimalType(24.0));
|
||||
|
||||
icon = uiRegistry.getCategory(widgetMock);
|
||||
assertEquals("humidity", icon);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCategoryWhenStaticIconSet() {
|
||||
EClass textEClass = mock(EClass.class);
|
||||
when(textEClass.getName()).thenReturn("text");
|
||||
when(textEClass.getInstanceTypeName()).thenReturn("org.openhab.core.model.sitemap.Text");
|
||||
when(widgetMock.eClass()).thenReturn(textEClass);
|
||||
when(widgetMock.getIcon()).thenReturn(null);
|
||||
when(widgetMock.getStaticIcon()).thenReturn("temperature");
|
||||
when(widgetMock.getIconRules()).thenReturn(null);
|
||||
|
||||
String icon = uiRegistry.getCategory(widgetMock);
|
||||
assertEquals("temperature", icon);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCategoryWhenIconSetOnItem() {
|
||||
EClass textEClass = mock(EClass.class);
|
||||
when(textEClass.getName()).thenReturn("text");
|
||||
when(textEClass.getInstanceTypeName()).thenReturn("org.openhab.core.model.sitemap.Text");
|
||||
when(widgetMock.eClass()).thenReturn(textEClass);
|
||||
when(widgetMock.getIcon()).thenReturn(null);
|
||||
when(widgetMock.getStaticIcon()).thenReturn(null);
|
||||
when(widgetMock.getIconRules()).thenReturn(null);
|
||||
|
||||
when(itemMock.getCategory()).thenReturn("temperature");
|
||||
|
||||
String icon = uiRegistry.getCategory(widgetMock);
|
||||
assertEquals("temperature", icon);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCategoryDefaultIcon() {
|
||||
EClass textEClass = mock(EClass.class);
|
||||
when(textEClass.getName()).thenReturn("text");
|
||||
when(textEClass.getInstanceTypeName()).thenReturn("org.openhab.core.model.sitemap.Text");
|
||||
when(widgetMock.eClass()).thenReturn(textEClass);
|
||||
when(widgetMock.getIcon()).thenReturn(null);
|
||||
when(widgetMock.getStaticIcon()).thenReturn(null);
|
||||
when(widgetMock.getIconRules()).thenReturn(null);
|
||||
|
||||
when(itemMock.getCategory()).thenReturn(null);
|
||||
|
||||
String icon = uiRegistry.getCategory(widgetMock);
|
||||
assertEquals("text", icon);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user