Skip to content

Commit

Permalink
Rework oh-knob and oh-slider, fixes #1003 (#1012)
Browse files Browse the repository at this point in the history
Fix oh-slider issue

Signed-off-by: Hubert Nusser <[email protected]>
  • Loading branch information
hubsif authored May 16, 2021
1 parent f590b28 commit d586b77
Show file tree
Hide file tree
Showing 12 changed files with 145 additions and 80 deletions.
10 changes: 10 additions & 0 deletions bundles/org.openhab.ui/doc/components/oh-knob-card.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,16 @@ Display a knob in a card to visualize and control a quantifiable item
Size the control using percentages instead of pixels
</PropDescription>
</PropBlock>
<PropBlock type="INTEGER" name="updateInterval" label="Update Interval">
<PropDescription>
Time to wait between subsequent commands in ms (default 500)
</PropDescription>
</PropBlock>
<PropBlock type="INTEGER" name="delayStateDisplay" label="Delay State Display">
<PropDescription>
Time to wait before switching from displaying user input to displaying item state in ms (default 2000)
</PropDescription>
</PropBlock>
</PropGroup>
</div>

Expand Down
10 changes: 10 additions & 0 deletions bundles/org.openhab.ui/doc/components/oh-knob-cell.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,16 @@ A cell expanding to a knob control
Size the control using percentages instead of pixels
</PropDescription>
</PropBlock>
<PropBlock type="INTEGER" name="updateInterval" label="Update Interval">
<PropDescription>
Time to wait between subsequent commands in ms (default 500)
</PropDescription>
</PropBlock>
<PropBlock type="INTEGER" name="delayStateDisplay" label="Delay State Display">
<PropDescription>
Time to wait before switching from displaying user input to displaying item state in ms (default 2000)
</PropDescription>
</PropBlock>
</PropGroup>
</div>

Expand Down
10 changes: 10 additions & 0 deletions bundles/org.openhab.ui/doc/components/oh-knob.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,16 @@ Knob control, allow to change a number value on a circular track
Size the control using percentages instead of pixels
</PropDescription>
</PropBlock>
<PropBlock type="INTEGER" name="updateInterval" label="Update Interval">
<PropDescription>
Time to wait between subsequent commands in ms (default 500)
</PropDescription>
</PropBlock>
<PropBlock type="INTEGER" name="delayStateDisplay" label="Delay State Display">
<PropDescription>
Time to wait before switching from displaying user input to displaying item state in ms (default 2000)
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="variable" label="Variable">
<PropDescription>
Name of the variable to set on input change
Expand Down
10 changes: 10 additions & 0 deletions bundles/org.openhab.ui/doc/components/oh-slider-card.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,16 @@ Display a slider in a card to control an item
Text to append to the label while dragging the cursor
</PropDescription>
</PropBlock>
<PropBlock type="INTEGER" name="updateInterval" label="Update Interval">
<PropDescription>
Time to wait between subsequent commands in ms (default 500)
</PropDescription>
</PropBlock>
<PropBlock type="INTEGER" name="delayStateDisplay" label="Delay State Display">
<PropDescription>
Time to wait before switching from displaying user input to displaying item state in ms (default 2000)
</PropDescription>
</PropBlock>
</PropGroup>
</div>

Expand Down
10 changes: 10 additions & 0 deletions bundles/org.openhab.ui/doc/components/oh-slider-cell.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,16 @@ A cell expanding to a big vertical slider
Text to append to the label while dragging the cursor
</PropDescription>
</PropBlock>
<PropBlock type="INTEGER" name="updateInterval" label="Update Interval">
<PropDescription>
Time to wait between subsequent commands in ms (default 500)
</PropDescription>
</PropBlock>
<PropBlock type="INTEGER" name="delayStateDisplay" label="Delay State Display">
<PropDescription>
Time to wait before switching from displaying user input to displaying item state in ms (default 2000)
</PropDescription>
</PropBlock>
</PropGroup>
</div>

Expand Down
10 changes: 10 additions & 0 deletions bundles/org.openhab.ui/doc/components/oh-slider-item.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,16 @@ Display a slider control in a list
Text to append to the label while dragging the cursor
</PropDescription>
</PropBlock>
<PropBlock type="INTEGER" name="updateInterval" label="Update Interval">
<PropDescription>
Time to wait between subsequent commands in ms (default 500)
</PropDescription>
</PropBlock>
<PropBlock type="INTEGER" name="delayStateDisplay" label="Delay State Display">
<PropDescription>
Time to wait before switching from displaying user input to displaying item state in ms (default 2000)
</PropDescription>
</PropBlock>
</PropGroup>
</div>

Expand Down
10 changes: 10 additions & 0 deletions bundles/org.openhab.ui/doc/components/oh-slider.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@ Slider control, allows to pick a number value on a scale
Text to append to the label while dragging the cursor
</PropDescription>
</PropBlock>
<PropBlock type="INTEGER" name="updateInterval" label="Update Interval">
<PropDescription>
Time to wait between subsequent commands in ms (default 500)
</PropDescription>
</PropBlock>
<PropBlock type="INTEGER" name="delayStateDisplay" label="Delay State Display">
<PropDescription>
Time to wait before switching from displaying user input to displaying item state in ms (default 2000)
</PropDescription>
</PropBlock>
<PropBlock type="TEXT" name="variable" label="Variable">
<PropDescription>
Name of the variable to set on input change
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ export default () => [
pt('secondaryColor', 'Secondary Color', 'Color of the rest of the control (HTML value, default #dcdfe6)'),
pt('textColor', 'Text Color', 'Color of the value text (HTML value, default #000000)'),
pt('strokeWidth', 'Stroke Width', 'Thickness of the arcs, default 17'),
pb('responsive', 'Responsive', 'Size the control using percentages instead of pixels')
pb('responsive', 'Responsive', 'Size the control using percentages instead of pixels'),
pn('updateInterval', 'Update Interval', 'Time to wait between subsequent commands in ms (default 500)').a(),
pn('delayStateDisplay', 'Delay State Display', 'Time to wait before switching from displaying user input to displaying item state in ms (default 2000)').a()
]
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ export default () => [
pb('scale', 'Display Scale', 'Display a scale on the slider'),
pn('scaleSteps', 'Scale steps', 'Number of (major) scale markers'),
pn('scaleSubSteps', 'Scale sub-steps', 'Number of scale minor markers between each major marker'),
pt('unit', 'Unit', 'Text to append to the label while dragging the cursor')
pt('unit', 'Unit', 'Text to append to the label while dragging the cursor'),
pn('updateInterval', 'Update Interval', 'Time to wait between subsequent commands in ms (default 500)').a(),
pn('delayStateDisplay', 'Delay State Display', 'Time to wait before switching from displaying user input to displaying item state in ms (default 2000)').a()
]
Original file line number Diff line number Diff line change
@@ -1,69 +1,20 @@
<template>
<knob-control v-bind="config" :text-color="config.textColor || ($f7.data.themeOptions.dark === 'dark') ? '#ffffff' : undefined" :value="value" @input="onChange" />
<knob-control v-bind="config" :text-color="config.textColor || ($f7.data.themeOptions.dark === 'dark') ? '#ffffff' : undefined" :value="value"
@input="sendCommandDebounced($event)" @click.native="sendCommandDebounced(value, true)" @touchend.native="sendCommandDebounced(value, true)" />
</template>

<script>
import mixin from '../widget-mixin'
import slideMixin from './slide-mixin'
import { OhKnobDefinition } from '@/assets/definitions/widgets/system'
import KnobControl from 'vue-knob-control'
export default {
mixins: [mixin],
mixins: [mixin, slideMixin],
components: {
KnobControl
},
widget: OhKnobDefinition,
data () {
return {
pendingCommand: null,
delayCommand: false,
delayUpdate: null
}
},
mounted () {
delete this.config.value
},
computed: {
value () {
if (this.config.variable) return this.context.vars[this.config.variable]
if (this.delayUpdate && this.pendingCommand) return this.pendingCommand // to keep the control reactive when operating
const value = this.context.store[this.config.item].state
// use as a brightness control for HSB values
if (value.split && value.split(',').length === 3) return parseFloat(value.split(',')[2])
return parseFloat(value)
}
},
methods: {
onChange (value) {
if (value === this.value) return
if (this.config.variable) {
this.$set(this.context.vars, this.config.variable, value)
return
}
this.pendingCommand = value
if (!this.delayCommand) {
this.delayCommand = true
this.setUpdateDelayTimout()
this.$store.dispatch('sendCommand', { itemName: this.config.item, cmd: value.toString() })
setTimeout(() => {
this.delayCommand = false
if (this.delayUpdate) clearTimeout(this.delayUpdate)
if (this.pendingCommand) {
this.setUpdateDelayTimout()
this.$store.dispatch('sendCommand', { itemName: this.config.item, cmd: this.pendingCommand.toString() })
}
}, 200)
}
},
setUpdateDelayTimout () {
if (this.delayUpdate) clearTimeout(this.delayUpdate)
this.delayUpdate = setTimeout(() => {
console.debug('End of update delay')
this.delayUpdate = null
this.pendingCommand = null
}, 2000)
}
}
widget: OhKnobDefinition
}
</script>
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<template>
<f7-range ref="rangeslider" class="oh-slider" v-bind="config" :value="value" @range:changed="onChange" :format-label="formatLabel" :format-scale-label="formatScaleLabel" />
<f7-range ref="rangeslider" class="oh-slider" v-bind="config" :value="value" :format-label="formatLabel" :format-scale-label="formatScaleLabel"
@range:change="sendCommandDebounced($event)" @click.native="sendCommandDebounced(value, true)" @touchend.native="sendCommandDebounced(value, true)" />
</template>

<style lang="stylus">
Expand All @@ -10,30 +11,22 @@

<script>
import mixin from '../widget-mixin'
import slideMixin from './slide-mixin'
import { OhSliderDefinition } from '@/assets/definitions/widgets/system'
export default {
mixins: [mixin],
mixins: [mixin, slideMixin],
widget: OhSliderDefinition,
mounted () {
delete this.config.value
// f7-range inside of masonry can get rendered faulty, as the masonry changes its breakpoint layout after being rendered
// re-calculate the range slider after masonry is updated
setTimeout(() => {
this.$refs.rangeslider.f7Range.calcSize()
this.$refs.rangeslider.f7Range.layout()
if (this.$refs.rangeslider) {
this.$refs.rangeslider.f7Range.calcSize()
this.$refs.rangeslider.f7Range.layout()
}
}, 0)
},
computed: {
value () {
if (this.config.variable) return this.context.vars[this.config.variable]
const value = this.context.store[this.config.item].state
// use as a brightness control for HSB values
if (value.split && value.split(',').length === 3) return parseFloat(value.split(',')[2])
return parseFloat(value)
}
},
methods: {
formatLabel (value) {
return this.toStepFixed(value) + (this.config.unit || '')
Expand All @@ -45,15 +38,6 @@ export default {
// uses the number of decimals in the step config to round the provided number
const nbDecimals = this.config.step ? Number(this.config.step).toString().replace(',', '.').split('.')[1] : 0
return parseFloat(Number(value).toFixed(nbDecimals))
},
onChange (value) {
const newValue = this.toStepFixed(value)
if (newValue === this.toStepFixed(this.value)) return
if (this.config.variable) {
this.$set(this.context.vars, this.config.variable, value)
} else if (this.config.item) {
this.$store.dispatch('sendCommand', { itemName: this.config.item, cmd: newValue.toString() })
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
export default {
data () {
return {
pendingCommand: null
}
},
mounted () {
delete this.config.value

this.updateInterval = this.config.updateInterval ? this.config.updateInterval : 200
this.delayStateDisplay = this.config.delayStateDisplay ? this.config.delayStateDisplay : 2000
},
computed: {
value () {
if (this.config.variable) return this.context.vars[this.config.variable]
if (this.pendingCommand) return this.pendingCommand // to keep the control reactive when operating
const value = this.context.store[this.config.item].state
// use as a brightness control for HSB values
if (value.split && value.split(',').length === 3) return parseFloat(value.split(',')[2])
return parseFloat(value)
}
},
methods: {
sendCommandDebounced (value, stop = false) {
if ((value === this.value && !stop) || value === this.lastValueSent) return

if (this.config.variable) {
this.$set(this.context.vars, this.config.variable, value)
return
}

if (!this.config.item) return

this.pendingCommand = value
let diff = this.lastDateSent ? Date.now() - this.lastDateSent : this.updateInterval
let delay = diff < this.updateInterval ? this.updateInterval - diff : stop ? 0 : this.updateInterval

if (this.sendCommandTimer && stop) {
clearTimeout(this.sendCommandTimer)
this.sendCommandTimer = null
}
if (!this.sendCommandTimer) {
if (this.displayLockTimer) clearTimeout(this.displayLockTimer)
this.sendCommandTimer = setTimeout(() => {
this.$store.dispatch('sendCommand', { itemName: this.config.item, cmd: this.pendingCommand.toString() })
this.lastValueSent = this.pendingCommand
this.lastDateSent = Date.now()
this.sendCommandTimer = null

// keep displaying `pendingCommand` as value for `delayStateDisplay` time to give sse state some time to update
this.displayLockTimer = setTimeout(() => { this.pendingCommand = null }, this.delayStateDisplay)
}, delay)
}
}
}
}

0 comments on commit d586b77

Please sign in to comment.