# Copyright (c) 2016, Tim Wentzlau
# Licensed under MIT
"""
A Kervi controller is a class that acts upon input from users or events or the underlaying os.
"""
from kervi.spine import Spine
from kervi.utility.thread import KerviThread
from kervi.utility.component import KerviComponent
from kervi.hal import GPIO
class UISelectControllerInput(KerviComponent):
r"""
Select component for Kervi controller
Usage:
.. code-block:: python
class CameraFrameRate(ControllerSelect):
def __init__(self, controller):
ControllerSelect.__init__(self, controller.controllerId+".framerate", "Framerate" , controller)
self.addOption("5", "5 / sec")
self.addOption("10", "10 / sec")
self.addOption("15", "15 / sec", True)
def change(self, selectedOptions):
print("Frame rate changed", selectedOptions)
"""
def __init__(self, select_id, name, controller):
KerviComponent.__init__(self, select_id, "select", name)
#self.spine = Spine()
self.controller = controller
self._persist_value = False
self.options = []
self.selected_options = []
self.change_command = self.component_id + ".change"
self.spine.register_command_handler(self.change_command, self._on_change_handler)
self._ui_parameters = {
"size": 0,
"type": "dropdown",
"link_to_header": False,
"label_icon": None,
"label" : self.name,
"flat": False,
"inline": False,
"input_size": 50
}
self.controller.add_input(self)
@property
def input_id(self):
return self.component_id
@property
def value(self):
"""Current value/state of the component"""
return self.selected_options
@value.setter
def value(self, new_value):
self._on_change_handler(new_value)
@property
def persist_value(self):
""" If true the value is saved to kervi DB when it change"""
return self._persist_value
@persist_value.setter
def persist_value(self, do_persist):
self._persist_value = do_persist
def _load_persisted(self):
if self.persist_value:
self._on_change_handler(self.settings.retrieve_value("selected_options"), False)
def link_to_dashboard(self, dashboard_id, panel_id, **kwargs):
r"""
Links this input to a dashboard panel.
:param dashboard_id:
Id of the dashboard to link to.
:type dashboard_id: str
:param panel_id:
Id of the panel on the dashboard to link to.
:type panel_id: str
:param \**kwargs:
Use the kwargs below to override default values for ui parameters
:Keyword Arguments:
* *size* (``int``) -- The number of dashboard cells the input should occupy horizontal.
If size is 0 (default) the input and label will expand to the width of the panel.
* *type* (``str``) -- Type of select box, dropdown or list.
* *link_to_header* (``str``) -- Link this input to header of the panel.
* *label_icon* (``str``) -- Icon that should be displayed together with label.
* *label* (``str``) -- Label text, default value is the name of the input.
* *flat* (``bool``) -- Flat look and feel.
* *inline* (``bool``) -- Display input and label in its actual size
If you set inline to true the size parameter is ignored.
The input will only occupy as much space as the label and input takes.
* *input_size* (``int``) -- width of the select box as a percentage of the total container it sits in.
"""
KerviComponent.link_to_dashboard(
self,
dashboard_id,
panel_id,
**kwargs
)
def _get_info(self):
return {
"onSelect": self.change_command,
"options": self.options,
}
def add_option(self, value, text, selected=False):
"""
Add option to select
"""
option = {"value": value, "text": text, "selected":selected}
self.options += [option]
if selected:
self.selected_options += [option]
if self._persist_value:
self.settings.store_value("selected_options", self.selected_options)
def _on_change_handler(self, selected_options, allow_persist=True):
self.spine.log.debug(
"controller select change:{0}/{1}",
self.controller.component_id,
self.component_id
)
for option in self.options:
option["selected"] = False
self.selected_options = []
for selected_option in selected_options:
for option in self.options:
if option["value"] == selected_option:
option["selected"] = True
self.selected_options += [option]
self.change(self.selected_options)
if self._persist_value and allow_persist:
self.settings.store_value("value", self.selected_options)
self.spine.trigger_event(
"controllerSelectChange",
self.component_id,
{"select":self.component_id, "value":self.options}
)
def change(self, selected_options):
""" Abstract method fill in with your own code to be executed when a change occur. """
self.controller.input_changed(self)
class UIButtonControllerInput(KerviComponent):
def __init__(self, button_id, name, controller):
KerviComponent.__init__(self, button_id, "button", name)
self.controller = controller
self.state = False
self._down_command = self.component_id + ".down"
self._up_command = self.component_id + ".up"
self.spine.register_command_handler(self._down_command, self._on_down_handler)
self.spine.register_command_handler(self._up_command, self._on_up_handler)
self._ui_parameters = {
"size": 0,
"input_size": None,
"type": "normal",
"link_to_header": False,
"label_icon": None,
"label": None,
"flat": False,
"inline": False,
"button_text": self.name,
"button_icon": None
}
self.state = False
self.controller.add_input(self)
@property
def input_id(self):
return self._component_id
@property
def value(self):
"""Current state of the component"""
return self.state
@value.setter
def value(self, new_value):
if new_value:
self._on_down_handler()
else:
self._on_up_handler()
def _load_persisted(self):
pass
def link_to_dashboard(self, dashboard_id, section_id, **kwargs):
r"""
Links this input to a dashboard panel.
:param dashboard_id:
Id of the dashboard to link to.
:type dashboard_id: str
:param panel_id:
Id of the panel on the dashboard to link to.
:type panel_id: str
:param \**kwargs:
Use the kwargs below to override default values for ui parameters
:Keyword Arguments:
* *size* (``int``) -- The number of dashboard cells the input should occupy horizontal.
If size is 0 (default) the input and label will expand to the width of the panel.
* *link_to_header* (``str``) -- Link this input to header of the panel.
* *label_icon* (``str``) -- Ico