Skip to content

Commit 5cd761b

Browse files
committed
sitemap registry
Signed-off-by: Mark Herwege <[email protected]>
1 parent 81e0cb6 commit 5cd761b

27 files changed

+267
-258
lines changed

bundles/org.openhab.ui.basic/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
<name>openHAB UI :: Bundles :: Basic UI</name>
1616

1717
<dependencies>
18+
<dependency>
19+
<groupId>org.openhab.core.bundles</groupId>
20+
<artifactId>org.openhab.core.sitemap</artifactId>
21+
<version>${project.version}</version>
22+
</dependency>
1823
<dependency>
1924
<groupId>org.openhab.core.bundles</groupId>
2025
<artifactId>org.openhab.core.ui</artifactId>

bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/AbstractWidgetRenderer.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
import org.openhab.core.items.ItemNotFoundException;
3232
import org.openhab.core.library.types.HSBType;
3333
import org.openhab.core.library.types.QuantityType;
34-
import org.openhab.core.model.sitemap.sitemap.Widget;
34+
import org.openhab.core.sitemap.Widget;
3535
import org.openhab.core.types.State;
3636
import org.openhab.core.ui.items.ItemUIRegistry;
3737
import org.openhab.core.util.ColorUtil;
@@ -53,6 +53,7 @@
5353
* @author Vlad Ivanov - BasicUI changes
5454
* @author Laurent Garnier - Refactor icon management to support other iconsets
5555
* @author Laurent Garnier - primary/secondary colors
56+
* @author Mark Herwege - Implement sitemap registry
5657
*/
5758
@NonNullByDefault
5859
public abstract class AbstractWidgetRenderer implements WidgetRenderer {
@@ -112,7 +113,7 @@ public ItemUIRegistry getItemUIRegistry() {
112113
* @return HTML code
113114
*/
114115
protected String preprocessSnippet(String originalSnippet, Widget w) {
115-
return preprocessSnippet(originalSnippet, w, w.getStaticIcon() != null || !w.getIconRules().isEmpty());
116+
return preprocessSnippet(originalSnippet, w, w.isStaticIcon() || !w.getIconRules().isEmpty());
116117
}
117118

118119
/**
@@ -130,7 +131,8 @@ protected String preprocessSnippet(String originalSnippet, Widget w, boolean ign
130131
snippet = snippet.replace("%cells_tablet%", String.valueOf(8 / DEFAULT_NB_COLUMNS_TABLET));
131132
snippet = snippet.replace("%widget_id%", itemUIRegistry.getWidgetId(w));
132133
snippet = snippet.replace("%icon_with_state%", Boolean.valueOf(!ignoreStateForIcon).toString());
133-
snippet = snippet.replace("%item%", w.getItem() != null ? w.getItem() : "");
134+
String itemName = w.getItem();
135+
snippet = snippet.replace("%item%", itemName != null ? itemName : "");
134136
// Optimization: avoid calling 3 times itemUIRegistry.getLabel(w)
135137
String text = itemUIRegistry.getLabel(w);
136138
snippet = snippet.replace("%label%", getLabel(text));
@@ -358,9 +360,10 @@ protected String processColor(Widget w, String originalSnippet) {
358360
String snippet = originalSnippet;
359361

360362
State itemState = null;
361-
if (w.getItem() != null) {
363+
String itemName = w.getItem();
364+
if (itemName != null) {
362365
try {
363-
Item item = itemUIRegistry.getItem(w.getItem());
366+
Item item = itemUIRegistry.getItem(itemName);
364367
itemState = item.getState();
365368
} catch (ItemNotFoundException e) {
366369
logger.debug("{}", e.getMessage());

bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/ButtongridRenderer.java

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import java.util.Map;
1919

2020
import org.eclipse.emf.common.util.ECollections;
21-
import org.eclipse.emf.common.util.EList;
2221
import org.eclipse.jdt.annotation.NonNullByDefault;
2322
import org.eclipse.jdt.annotation.Nullable;
2423
import org.openhab.core.i18n.LocaleProvider;
@@ -27,10 +26,10 @@
2726
import org.openhab.core.items.ItemNotFoundException;
2827
import org.openhab.core.library.items.NumberItem;
2928
import org.openhab.core.library.types.QuantityType;
30-
import org.openhab.core.model.sitemap.sitemap.Button;
31-
import org.openhab.core.model.sitemap.sitemap.ButtonDefinition;
32-
import org.openhab.core.model.sitemap.sitemap.Buttongrid;
33-
import org.openhab.core.model.sitemap.sitemap.Widget;
29+
import org.openhab.core.sitemap.Button;
30+
import org.openhab.core.sitemap.ButtonDefinition;
31+
import org.openhab.core.sitemap.Buttongrid;
32+
import org.openhab.core.sitemap.Widget;
3433
import org.openhab.core.types.State;
3534
import org.openhab.core.types.util.UnitUtils;
3635
import org.openhab.core.ui.items.ItemUIRegistry;
@@ -48,6 +47,7 @@
4847
* can produce HTML code for Buttongrid widgets.
4948
*
5049
* @author Laurent Garnier - Initial contribution
50+
* @author Mark Herwege - Implement sitemap registry
5151
*/
5252
@Component(service = WidgetRenderer.class)
5353
@NonNullByDefault
@@ -67,7 +67,7 @@ public boolean canRender(Widget w) {
6767
}
6868

6969
@Override
70-
public EList<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) throws RenderException {
70+
public List<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) throws RenderException {
7171
Buttongrid grid = (Buttongrid) w;
7272

7373
Map<Integer, Map<Integer, ButtonDefinition>> rowsButtons = new HashMap<>();
@@ -104,7 +104,7 @@ public EList<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) th
104104
}
105105
}
106106
// Go through buttons defined as sub-element of the Buttongrid to fill the map rowsWidgets
107-
for (Widget widget : grid.getChildren()) {
107+
for (Widget widget : grid.getWidgets()) {
108108
if (widget instanceof Button button) {
109109
int row = button.getRow();
110110
int column = button.getColumn();
@@ -205,9 +205,7 @@ private void buildRow(int columns, @Nullable Map<Integer, ButtonDefinition> butt
205205
} else if (buttonWidgets != null) {
206206
String buttonHtml = "";
207207
for (Button b : buttonWidgets) {
208-
String icon = b.getStaticIcon() != null || b.getIcon() != null || !b.getIconRules().isEmpty()
209-
? getCategory(b)
210-
: null;
208+
String icon = b.getIcon() != null || !b.getIconRules().isEmpty() ? getCategory(b) : null;
211209
buttonHtml += buildButton(b, b.getLabel(), b.getCmd(), b.getReleaseCmd(), icon, b.isStateless());
212210
}
213211
buildCell(false, sizeDessktop, col > 8, sizeTablet, col > 4, sizePhone, buttonHtml, builder);
@@ -263,7 +261,10 @@ private String buildButton(@Nullable Button buttonWidget, @Nullable String lab,
263261
if (buttonWidget != null) {
264262
Item item = null;
265263
try {
266-
item = itemUIRegistry.getItem(buttonWidget.getItem());
264+
String widgetItemName = buttonWidget.getItem();
265+
if (widgetItemName != null) {
266+
item = itemUIRegistry.getItem(widgetItemName);
267+
}
267268
} catch (ItemNotFoundException e) {
268269
logger.debug("Failed to retrieve item during widget rendering: {}", e.getMessage());
269270
}

bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/ChartRenderer.java

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.net.URLEncoder;
1616
import java.nio.charset.StandardCharsets;
1717
import java.util.List;
18+
import java.util.Objects;
1819

1920
import org.eclipse.emf.common.util.ECollections;
2021
import org.eclipse.emf.common.util.EList;
@@ -25,8 +26,8 @@
2526
import org.openhab.core.items.GroupItem;
2627
import org.openhab.core.items.Item;
2728
import org.openhab.core.items.ItemNotFoundException;
28-
import org.openhab.core.model.sitemap.sitemap.Chart;
29-
import org.openhab.core.model.sitemap.sitemap.Widget;
29+
import org.openhab.core.sitemap.Chart;
30+
import org.openhab.core.sitemap.Widget;
3031
import org.openhab.core.ui.items.ItemUIRegistry;
3132
import org.openhab.ui.basic.render.RenderException;
3233
import org.openhab.ui.basic.render.WidgetRenderer;
@@ -44,6 +45,7 @@
4445
* @author Kai Kreuzer - Initial contribution and API
4546
* @author Vlad Ivanov - BasicUI changes
4647
* @author Laurent Garnier - Delegate the definition of certain chart URL parameters to the frontend (smarthome.js)
48+
* @author Mark Herwege - Implement sitemap registry
4749
*/
4850
@Component(service = WidgetRenderer.class)
4951
@NonNullByDefault
@@ -70,11 +72,10 @@ public EList<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) th
7072

7173
try {
7274
String itemParam = null;
73-
boolean forceAsItem = false;
74-
if (chart.getForceAsItem() != null) {
75-
forceAsItem = chart.getForceAsItem();
76-
}
77-
Item item = itemUIRegistry.getItem(chart.getItem());
75+
boolean forceAsItem = chart.forceAsItem();
76+
Item item = null;
77+
String itemName = Objects.requireNonNull(w.getItem()); // Checked at creation there is an item
78+
item = itemUIRegistry.getItem(itemName);
7879
if (item instanceof GroupItem && !forceAsItem) {
7980
itemParam = "groups=" + chart.getItem();
8081
} else {
@@ -92,14 +93,12 @@ public EList<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) th
9293
}
9394

9495
// if legend parameter is given, add corresponding GET parameter
95-
boolean legend = item instanceof GroupItem && !forceAsItem;
96-
if (chart.getLegend() != null) {
97-
legend = chart.getLegend();
98-
if (chart.getLegend()) {
99-
chartUrl += "&legend=true";
100-
} else {
101-
chartUrl += "&legend=false";
102-
}
96+
boolean legend = chart.hasLegend();
97+
legend = legend || (item instanceof GroupItem && !forceAsItem);
98+
if (legend) {
99+
chartUrl += "&legend=true";
100+
} else {
101+
chartUrl += "&legend=false";
103102
}
104103

105104
if (chart.getInterpolation() instanceof String interpolationMethod) {
@@ -174,7 +173,8 @@ private void buildRow(Chart w, @Nullable String lab, String cmd, String current,
174173
String command = cmd;
175174
String label = lab == null ? cmd : lab;
176175

177-
rowSnippet = rowSnippet.replace("%item%", w.getItem() != null ? w.getItem() : "");
176+
String itemName = w.getItem();
177+
rowSnippet = rowSnippet.replace("%item%", itemName != null ? itemName : "");
178178
rowSnippet = rowSnippet.replace("%cmd%", escapeHtml(command));
179179
rowSnippet = rowSnippet.replace("%label%", escapeHtml(label));
180180

bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/ColorpickerRenderer.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
import org.eclipse.jdt.annotation.NonNullByDefault;
1818
import org.openhab.core.i18n.LocaleProvider;
1919
import org.openhab.core.i18n.TranslationProvider;
20-
import org.openhab.core.model.sitemap.sitemap.Colorpicker;
21-
import org.openhab.core.model.sitemap.sitemap.Widget;
20+
import org.openhab.core.sitemap.Colorpicker;
21+
import org.openhab.core.sitemap.Widget;
2222
import org.openhab.core.types.State;
2323
import org.openhab.core.ui.items.ItemUIRegistry;
2424
import org.openhab.ui.basic.render.RenderException;
@@ -39,6 +39,7 @@
3939
*
4040
* @author Kai Kreuzer - Initial contribution and API
4141
* @author Vlad Ivanov - BasicUI changes
42+
* @author Mark Herwege - Implement sitemap registry
4243
*/
4344
@Component(service = WidgetRenderer.class)
4445
@NonNullByDefault

bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/ColortemppickerRenderer.java

Lines changed: 46 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
import org.openhab.core.library.CoreItemFactory;
2929
import org.openhab.core.library.types.QuantityType;
3030
import org.openhab.core.library.unit.Units;
31-
import org.openhab.core.model.sitemap.sitemap.Colortemperaturepicker;
32-
import org.openhab.core.model.sitemap.sitemap.Widget;
31+
import org.openhab.core.sitemap.Colortemperaturepicker;
32+
import org.openhab.core.sitemap.Widget;
3333
import org.openhab.core.thing.DefaultSystemChannelTypeProvider;
3434
import org.openhab.core.types.State;
3535
import org.openhab.core.types.StateDescription;
@@ -51,6 +51,7 @@
5151
* Colortemperaturepicker widgets.
5252
*
5353
* @author Laurent Garnier - Initial contribution
54+
* @author Mark Herwege - Implement sitemap registry
5455
*/
5556
@Component(service = WidgetRenderer.class)
5657
@NonNullByDefault
@@ -86,59 +87,57 @@ public EList<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) th
8687
BigDecimal maxK = MAX_TEMPERATURE_KELVIN;
8788
String[] colorsRGB = null;
8889
String itemType = null;
89-
String itemName = w.getItem();
90-
if (itemName != null) {
91-
try {
92-
Item item = itemUIRegistry.getItem(itemName);
93-
itemType = item.getType();
94-
if ((CoreItemFactory.NUMBER + ":Temperature").equals(itemType)) {
95-
State state = itemUIRegistry.getState(w);
96-
if (state instanceof QuantityType<?> quantity) {
97-
if (unit == null) {
98-
unit = quantity.getUnit();
99-
}
100-
quantity = quantity.toInvertibleUnit(Units.KELVIN);
101-
if (quantity != null) {
102-
currentK = quantity.toBigDecimal();
103-
try {
104-
int[] rgb = ColorUtil
105-
.hsbToRgb(ColorUtil.xyToHsb(ColorUtil.kelvinToXY(currentK.doubleValue())));
106-
logger.debug("Current {} K => RGB {} {} {}", currentK, rgb[0], rgb[1], rgb[2]);
107-
currentRGB = "#%02x%02x%02x".formatted(rgb[0], rgb[1], rgb[2]);
108-
} catch (IllegalArgumentException | IndexOutOfBoundsException e) {
109-
logger.debug("Can't get RGB for {} Kelvin, bypassing color gradient!", currentK);
110-
}
111-
}
90+
String itemName = Objects.requireNonNull(w.getItem()); // Checked at creation there is an item
91+
try {
92+
Item item = itemUIRegistry.getItem(itemName);
93+
itemType = item.getType();
94+
if ((CoreItemFactory.NUMBER + ":Temperature").equals(itemType)) {
95+
State state = itemUIRegistry.getState(w);
96+
if (state instanceof QuantityType<?> quantity) {
97+
if (unit == null) {
98+
unit = quantity.getUnit();
11299
}
113-
if (unit == Units.KELVIN || unit == Units.MIRED) {
114-
minK = getMinimumInKelvin(ctp, unit, item.getStateDescription());
115-
maxK = getMaximumInKelvin(ctp, unit, item.getStateDescription());
116-
logger.debug("ColortemppickerRenderer current={} unit={} min={} max={}", currentK, unit, minK,
117-
maxK);
118-
119-
double valueKelvin = 0d;
100+
quantity = quantity.toInvertibleUnit(Units.KELVIN);
101+
if (quantity != null) {
102+
currentK = quantity.toBigDecimal();
120103
try {
121-
colorsRGB = new String[(int) Math.round(100 / GRADIENT_INCREMENT_PERCENT) + 1];
122-
for (int i = 0; Math.round(i * GRADIENT_INCREMENT_PERCENT) <= 100; i++) {
123-
valueKelvin = (maxK.doubleValue() - minK.doubleValue()) * i * GRADIENT_INCREMENT_PERCENT
124-
/ 100.0 + minK.doubleValue();
125-
int[] rgb = ColorUtil.hsbToRgb(ColorUtil.xyToHsb(ColorUtil.kelvinToXY(valueKelvin)));
126-
logger.debug("Gradient {}%: {} K => RGB {} {} {}", i * GRADIENT_INCREMENT_PERCENT,
127-
valueKelvin, rgb[0], rgb[1], rgb[2]);
128-
colorsRGB[i] = "#%02x%02x%02x".formatted(rgb[0], rgb[1], rgb[2]);
129-
}
104+
int[] rgb = ColorUtil
105+
.hsbToRgb(ColorUtil.xyToHsb(ColorUtil.kelvinToXY(currentK.doubleValue())));
106+
logger.debug("Current {} K => RGB {} {} {}", currentK, rgb[0], rgb[1], rgb[2]);
107+
currentRGB = "#%02x%02x%02x".formatted(rgb[0], rgb[1], rgb[2]);
130108
} catch (IllegalArgumentException | IndexOutOfBoundsException e) {
131-
logger.debug("Can't get RGB for {} Kelvin, bypassing color gradient!", valueKelvin);
132-
colorsRGB = null;
109+
logger.debug("Can't get RGB for {} Kelvin, bypassing color gradient!", currentK);
133110
}
134-
} else {
135-
logger.warn("Invalid unit {} for Colortemperaturepicker element", unit);
111+
}
112+
}
113+
if (unit == Units.KELVIN || unit == Units.MIRED) {
114+
minK = getMinimumInKelvin(ctp, unit, item.getStateDescription());
115+
maxK = getMaximumInKelvin(ctp, unit, item.getStateDescription());
116+
logger.debug("ColortemppickerRenderer current={} unit={} min={} max={}", currentK, unit, minK,
117+
maxK);
118+
119+
double valueKelvin = 0d;
120+
try {
121+
colorsRGB = new String[(int) Math.round(100 / GRADIENT_INCREMENT_PERCENT) + 1];
122+
for (int i = 0; Math.round(i * GRADIENT_INCREMENT_PERCENT) <= 100; i++) {
123+
valueKelvin = (maxK.doubleValue() - minK.doubleValue()) * i * GRADIENT_INCREMENT_PERCENT
124+
/ 100.0 + minK.doubleValue();
125+
int[] rgb = ColorUtil.hsbToRgb(ColorUtil.xyToHsb(ColorUtil.kelvinToXY(valueKelvin)));
126+
logger.debug("Gradient {}%: {} K => RGB {} {} {}", i * GRADIENT_INCREMENT_PERCENT,
127+
valueKelvin, rgb[0], rgb[1], rgb[2]);
128+
colorsRGB[i] = "#%02x%02x%02x".formatted(rgb[0], rgb[1], rgb[2]);
129+
}
130+
} catch (IllegalArgumentException | IndexOutOfBoundsException e) {
131+
logger.debug("Can't get RGB for {} Kelvin, bypassing color gradient!", valueKelvin);
132+
colorsRGB = null;
136133
}
137134
} else {
138-
logger.warn("Invalid item type {} for Colortemperaturepicker element", itemType);
135+
logger.warn("Invalid unit {} for Colortemperaturepicker element", unit);
139136
}
140-
} catch (ItemNotFoundException e) {
137+
} else {
138+
logger.warn("Invalid item type {} for Colortemperaturepicker element", itemType);
141139
}
140+
} catch (ItemNotFoundException e) {
142141
}
143142

144143
String snippet = getSnippet((CoreItemFactory.NUMBER + ":Temperature").equals(itemType)

bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/FrameRenderer.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616
import java.util.List;
1717

1818
import org.apache.commons.lang3.StringEscapeUtils;
19-
import org.eclipse.emf.common.util.EList;
2019
import org.eclipse.jdt.annotation.NonNullByDefault;
2120
import org.openhab.core.i18n.LocaleProvider;
2221
import org.openhab.core.i18n.TranslationProvider;
23-
import org.openhab.core.model.sitemap.sitemap.Frame;
24-
import org.openhab.core.model.sitemap.sitemap.Widget;
22+
import org.openhab.core.sitemap.Frame;
23+
import org.openhab.core.sitemap.Widget;
2524
import org.openhab.core.ui.items.ItemUIRegistry;
2625
import org.openhab.ui.basic.render.RenderException;
2726
import org.openhab.ui.basic.render.WidgetRenderer;
@@ -36,6 +35,7 @@
3635
*
3736
* @author Kai Kreuzer - Initial contribution and API
3837
* @author Vlad Ivanov - BasicUI changes
38+
* @author Mark Herwege - Implement sitemap registry
3939
*/
4040
@Component(service = WidgetRenderer.class)
4141
@NonNullByDefault
@@ -53,7 +53,7 @@ public boolean canRender(Widget w) {
5353
}
5454

5555
@Override
56-
public EList<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) throws RenderException {
56+
public List<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) throws RenderException {
5757
String snippet = getSnippet("frame");
5858
String label = StringEscapeUtils.escapeHtml4(itemUIRegistry.getLabel(w));
5959
List<String> frameClassList = new ArrayList<>();

bundles/org.openhab.ui.basic/src/main/java/org/openhab/ui/basic/internal/render/GroupRenderer.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
import org.eclipse.jdt.annotation.NonNullByDefault;
1818
import org.openhab.core.i18n.LocaleProvider;
1919
import org.openhab.core.i18n.TranslationProvider;
20-
import org.openhab.core.model.sitemap.sitemap.Group;
21-
import org.openhab.core.model.sitemap.sitemap.Widget;
20+
import org.openhab.core.sitemap.Group;
21+
import org.openhab.core.sitemap.Widget;
2222
import org.openhab.core.ui.items.ItemUIRegistry;
2323
import org.openhab.ui.basic.render.RenderException;
2424
import org.openhab.ui.basic.render.WidgetRenderer;
@@ -33,6 +33,7 @@
3333
*
3434
* @author Kai Kreuzer - Initial contribution and API
3535
* @author Vlad Ivanov - BasicUI changes
36+
* @author Mark Herwege - Implement sitemap registry
3637
*/
3738
@Component(service = WidgetRenderer.class)
3839
@NonNullByDefault

0 commit comments

Comments
 (0)