Skip to content

Commit

Permalink
[BasicUI] Fix slider behaviour and implement two different modes (#2535)
Browse files Browse the repository at this point in the history
Fix #2525
Also related to openhab/openhab-core#4084 and openhab/openhab-core#3430

Two behaviour modes are now supported.
- If releaseOnly parameter is set, the new value is sent to the item
only when the slider is released.
- If releaseOnly parameter is not set, new values are sent to the item
while moving the slider. Events are sent at a certain frequency, this
frequency is defined by the sendFrequency parameter if set or every 200
ms by default. Event is not sent when the value is is unchanged (when
stopping the move but keeping the mouse pressed).

The brightness slider of the colorpicker widget is also updated to send
regular new color commands when moving the slider.

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
  • Loading branch information
lolodomo authored Apr 21, 2024
1 parent 736d12c commit 0c7aa4d
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,6 @@ public EList<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) th
String snippetName = "slider";
String snippet = getSnippet(snippetName);

// set the default send-update frequency to 200ms
String frequency = s.getFrequency() == 0 ? "200" : Integer.toString(s.getFrequency());

String unit = getUnitForWidget(w);
if (unit == null) {
// Search the unit in the item state
Expand All @@ -82,7 +79,7 @@ public EList<Widget> renderWidget(Widget w, StringBuilder sb, String sitemap) th
}

snippet = preprocessSnippet(snippet, w);
snippet = snippet.replace("%frequency%", frequency);
snippet = snippet.replace("%release_only%", s.isReleaseOnly() ? "true" : "false");
snippet = snippet.replace("%switch%", s.isSwitchEnabled() ? "1" : "0");
snippet = snippet.replace("%unit%", unit == null ? "" : unit);
snippet = snippet.replace("%minValue%", minValueOf(s));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
data-icon-color="%icon_color%"
>
<input
data-freq="%frequency%"
data-release-only="%release_only%"
data-state="%state%"
class="mdl-slider mdl-js-slider"
type="range"
Expand Down
71 changes: 44 additions & 27 deletions bundles/org.openhab.ui.basic/web-src/smarthome.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,10 @@
callback.apply(null, args);
_t.lock = true;
setTimeout(function() {
_t.lock = false;
if (!finished) {
callback.apply(null, args);
_t.call(callback, callInterval);
}
_t.lock = false;
}, callInterval);
}
};
Expand Down Expand Up @@ -1627,7 +1627,8 @@
/* class Colorpicker */
function Colorpicker(parentNode, color, callback) {
var
_t = this;
_t = this,
lastBrightnessSent = null;

/* rgb2hsv and hsv2rgb are modified versions from http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c */
function rgb2hsv(rgbColor) {
Expand Down Expand Up @@ -1838,7 +1839,10 @@
}

_t.debounceProxy = new DebounceProxy(function() {
callback(_t.hsvValue);
if (_t.hsvValue.v !== lastBrightnessSent) {
callback(_t.hsvValue);
lastBrightnessSent = _t.hsvValue.v;
}
}, 200);

_t.updateColor = function(c) {
Expand All @@ -1849,26 +1853,30 @@
setColor(c);
};

// Some browsers fire onchange while the slider handle is being moved.
// This is incorrect, according to the specs, but it's impossible to detect,
// so DebounceProxy is used
function onSliderChangeStart() {
lastBrightnessSent = null;
}

function onSliderChange() {
_t.debounceProxy.finish();
_t.hsvValue.v = _t.slider.value / 100;
_t.debounceProxy.call();
if (_t.hsvValue.v !== lastBrightnessSent) {
callback(_t.hsvValue);
lastBrightnessSent = _t.hsvValue.v;
}
}

function onSliderFinish() {
function onSliderInput() {
_t.hsvValue.v = _t.slider.value / 100;

_t.debounceProxy.call();
_t.debounceProxy.finish();
}

var
eventMap = [
[ _t.slider, "touchstart", onSliderChangeStart ],
[ _t.slider, "mousedown", onSliderChangeStart ],
[ _t.slider, "input", onSliderInput ],
[ _t.slider, "change", onSliderChange ],
[ _t.slider, "touchend", onSliderFinish ],
[ _t.slider, "mouseup", onSliderFinish ],
[ _t.image, "mousedown", onMove ],
[ _t.image, "mousemove", onMove ],
[ _t.image, "touchmove", onMove ],
Expand Down Expand Up @@ -2354,9 +2362,12 @@
Control.call(this, parentNode);

var
_t = this;
_t = this,
unlockTimeout = null,
lastSentCmd = null;

_t.input = _t.parentNode.querySelector("input[type=range]");
_t.releaseOnly = _t.input.getAttribute("data-release-only") === "true";
_t.hasValue = _t.parentNode.getAttribute("data-has-value") === "true";
_t.valueNode = _t.parentNode.parentNode.querySelector(o.formValue);
_t.locked = false;
Expand All @@ -2379,14 +2390,22 @@
})();

function emitEvent() {
var command = _t.input.value;
var
value = _t.input.value,
command = value;

if (value === lastSentCmd) {
return;
}

if (_t.unit) {
command = command + " " + _t.unit;
}
_t.parentNode.dispatchEvent(createEvent("control-change", {
item: _t.item,
value: command
}));
lastSentCmd = value;
}

_t.debounceProxy = new DebounceProxy(function() {
Expand Down Expand Up @@ -2418,32 +2437,29 @@
_t.valueNode.style.color = smarthome.UI.adjustColorToTheme(_t.valueColor);
};

var
unlockTimeout = null;

function onChange() {
_t.debounceProxy.call();
_t.debounceProxy.finish();
emitEvent();
}

function onInput() {
if (!_t.releaseOnly) {
_t.debounceProxy.call();
}
}

function onChangeStart() {
if (unlockTimeout !== null) {
clearTimeout(unlockTimeout);
}
_t.locked = true;
smarthome.changeListener.pause();
lastSentCmd = null;
}

function onChangeEnd() {
// mouseUp is fired earlier than the value is changed
// quite a dirty hack, but I don't see any other way
_t.debounceProxy.call();
setTimeout(function() {
smarthome.changeListener.resume();
}, 5);
unlockTimeout = setTimeout(function() {
_t.locked = false;
}, 300);
_t.debounceProxy.finish();
}

var
Expand All @@ -2452,6 +2468,7 @@
[ _t.input, "mousedown", onChangeStart ],
[ _t.input, "touchend", onChangeEnd ],
[ _t.input, "mouseup", onChangeEnd ],
[ _t.input, "input", onInput ],
[ _t.input, "change", onChange ]
];

Expand Down

0 comments on commit 0c7aa4d

Please sign in to comment.