class Setting(Subject): """ Setting interface for writing to the preferences and all information for changing and displaying it. """ __events__ = (Event( name='value', doc= ' Called when the value of the\n setting changes ' ), ) def __init__(self, name='', values=None, default_value=None, preferences=None, *a, **k): super(Setting, self).__init__(*a, **k) self.name = name if not values: self.values = [] self._preferences = preferences if preferences != None else {} default_value = name in self._preferences and self._preferences[ name] in values and self._preferences[name] self._preferences[name] = None self.value = default_value def __str__(self): return self.value_to_string(self.value) def _set_value(self, value): if not value in self.values: raise AssertionError self._preferences[ self.name] = self._preferences[self.name] != value and value self.on_value_changed(value) self.notify_value(self.value) def _get_value(self): return self._preferences[self.name] value = property(_get_value, _set_value) def on_value_changed(self, value): pass def change_relative(self, value): """ Given a value between -1.0 and 1.0, this will decide on a new value. """ raise NotImplementedError def value_to_string(self, value): raise NotImplementedError
class Setting(EventObject): __events__ = (Event( name='value', doc=' Called when the value of the setting changes '), ) def __init__(self, name='', values=None, default_value=None, preferences=None, *a, **k): (super(Setting, self).__init__)(*a, **k) self.name = name self.values = values or [] self._preferences = preferences if preferences != None else {} if name in self._preferences: if self._preferences[name] in values: default_value = self._preferences[name] self._preferences[name] = None self.value = default_value def __str__(self): return self.value_to_string(self.value) def _set_value(self, value): if self._preferences[self.name] != value: self._preferences[self.name] = value self.on_value_changed(value) self.notify_value(self.value) def _get_value(self): return self._preferences[self.name] value = property(_get_value, _set_value) def on_value_changed(self, value): pass def change_relative(self, value): raise NotImplementedError def value_to_string(self, value): raise NotImplementedError
class MonoBridgeElement(NotifyingControlElement): __module__ = __name__ __doc__ = ' Class representing a 2-dimensional set of buttons ' __subject_events__ = (Event(name='value', signal=InputSignal, override=True),) _input_signal_listener_count = 0 def __init__(self, script, *a, **k): self._script = script super(MonoBridgeElement, self).__init__(*a, **k) def refresh_state(self, *a, **k): #self._script.schedule_message(2, self._script.update) #self._script.log_message('refresh_state') self._script.refresh_state() def _send(self, args1 = None, args2 = None, args3 = None, *a): self.notify_value(args1, args2, args3) def script_wants_forwarding(self): return True def reset(self): pass def notification_to_bridge(self, name = None, value = None, sender = None): if hasattr(sender, 'name'): #debug('has name:', sender.name) self._send(sender.name, 'lcd_name', str(generate_strip_string(name))) self._send(sender.name, 'lcd_value', str(generate_strip_string(value))) else: #debug('missing name:', sender, name) self._send(name, 'lcd_name', str(generate_strip_string(name))) self._send(name, 'lcd_value', str(generate_strip_string(value)))
class ScrollableListComponent(Component): """' Component for handling a list of options with a limtied set of buttons and display segments. """ __module__ = __name__ __events__ = ( Event(name='change_option', doc=' Event signaled when the selected option changes '), Event( name='press_option', signal=short_circuit_signal, doc= '\n Event signaled when an option is pressed getting the option as\n parameter. The ScrollableListComponent is connected to it, if\n you want to override selection behaviour, connect to the front\n and return True from your handler.\n ' )) num_segments = 8 display_line = 3 jump_size = 3 ARROW_LEFT = ' << ' ARROW_RIGHT = ' >> ' def __init__(self, *a, **k): super(ScrollableListComponent, self).__init__(*a, **k) self._data_sources = [ DisplayDataSource() for _ in range(self.num_segments) ] self._selected_option = None self._offset_index = 0 self._option_names = [] self._select_buttons = [] self._select_button_slots = self.register_disconnectable(EventObject()) self.register_slot(self, self._set_selected_option, 'press_option') return def set_display_line(self, line): if line: sources = self._data_sources line.set_num_segments(len(sources)) for segment in xrange(len(sources)): line.segment(segment).set_data_source(sources[segment]) def set_select_buttons(self, buttons): self._select_button_slots.disconnect() self._select_buttons = buttons or [] for b in self._select_buttons: self._select_button_slots.register_slot( b, self._on_select_value, 'value', extra_kws=dict(identify_sender=True)) self.update() @property def offset_index(self): return self._offset_index def scroll_right(self): return self._scroll(1) def scroll_left(self): return self._scroll(-self.jump_size) def _get_option_names(self): return self._option_names def _set_option_names(self, names): self._option_names = names self._normalize_offset() self.update() option_names = property(_get_option_names, lambda self, x: self._set_option_names(x)) def _get_selected_option(self): return self._selected_option def _set_selected_option(self, selected_option): if selected_option != self._selected_option: assert selected_option == None or in_range(selected_option, 0, self._option_names) self._selected_option = selected_option self.notify_change_option(selected_option) self.update() return selected_option = property(_get_selected_option, _set_selected_option) def _has_select_button(self, index): return len( self._select_buttons ) == self.num_segments and self._select_buttons[index] != None def _maximal_offset(self): if len(self._option_names) > self.num_segments: return len(self._option_names) - self.num_segments + 1 else: return 0 def _normalize_offset(self): quantized_offset = self._offset_index - self._offset_index % -self.jump_size self._offset_index = max(0, min(self._maximal_offset(), quantized_offset)) def _scroll(self, delta): old_offset = self._offset_index self._offset_index += delta self._normalize_offset() if self._offset_index != old_offset: self.update() return True return False def _on_select_value(self, value, sender): if not self.is_enabled() or not value: return index = list(self._select_buttons).index(sender) if index == 0 and self._offset_index != 0: self.scroll_left() elif index == self.num_segments - 1 and self._offset_index < self._maximal_offset( ): self.scroll_right() elif self._offset_index == 0: self.notify_press_option( index if index < len(self._option_names) else None) else: self.notify_press_option(index + self._offset_index - 1) return def _get_display_string(self, option_index): if option_index < len(self._option_names): decorator = consts.CHAR_SELECT if option_index == self.selected_option else '' return decorator + self._option_names[option_index] else: return '' def update(self): super(ScrollableListComponent, self).update() if not self.is_enabled(): return first_segment, max_segment = 0, self.num_segments if self._offset_index > 0: self._data_sources[0].set_display_string(self.ARROW_LEFT) if self._has_select_button(0): self._select_buttons[0].set_light('List.ScrollerOn') first_segment = 1 if self._offset_index < self._maximal_offset(): self._data_sources[(-1)].set_display_string(self.ARROW_RIGHT) if self._has_select_button(-1): self._select_buttons[(-1)].set_light('List.ScrollerOn') max_segment -= 1 for i, j in zip( xrange(first_segment, max_segment), xrange(self._offset_index, self._offset_index + self.num_segments)): self._data_sources[i].set_display_string( self._get_display_string(j)) if self._has_select_button(i): if i < len(self.option_names): if j == self.selected_option: self._select_buttons[i].set_light('Option.Selected') else: self._select_buttons[i].set_light('Option.Unselected') else: self._select_buttons[i].set_light('Option.Unused')