def use_single_line(self, line_index, line_slice=None, align=align_none): """ Returns a control, that will change the notification to a single line view, if it is grabbed. """ assert (line_index >= 0 and line_index < len(self._display_lines)) display = self._display_lines[line_index] display = line_slice is not None and display.subdisplay[line_slice] layer = Layer(priority=MESSAGE_BOX_PRIORITY, display_line1=display) return _CallbackControl( self._token_control, partial(self._set_message_box_layout, layer, maybe(partial(align, display.width))))
def use_single_line(self, line_index, line_slice = None, align = align_none): """ Returns a control, that will change the notification to a single line view, if it is grabbed. """ if not (line_index >= 0 and line_index < len(self._display_lines)): raise AssertionError display = self._display_lines[line_index] display = line_slice is not None and display.subdisplay[line_slice] layer = Layer(priority=MESSAGE_BOX_PRIORITY, display_line1=display) return _CallbackControl(self._token_control, partial(self._set_message_box_layout, layer, maybe(partial(align, display.width))))
class NotificationComponent(CompoundComponent): """ Displays notifications to the user for a given amount of time. A notification time of -1 creates an infinite duration notification. To adjust the way notifications are shown in special cases, assign a generated control using use_single_line or use_full_display to a layer. If the layer is on top, it will set the preferred view. This will show the notification on line 1 if my_component is enabled and the priority premise of the layer is met: my_component.layer = Layer( _notification = notification_component.use_single_line(1)) """ _default_align_text_fn = partial(maybe(partial(align_none, DISPLAY_LENGTH))) def __init__(self, notification_time=2.5, blinking_time=0.3, display_lines=[], *a, **k): super(NotificationComponent, self).__init__(*a, **k) self._display_lines = display_lines self._token_control = _TokenControlElement() self._align_text_fn = self._default_align_text_fn self._message_box = self.register_component(MessageBoxComponent()) self._message_box.set_enabled(False) self._notification_timeout_task = self._tasks.add( Task.sequence(Task.wait(notification_time), Task.run(self.hide_notification)) ).kill() if notification_time != -1 else self._tasks.add(Task.Task()) self._blink_text_task = self._tasks.add( Task.loop( Task.sequence( Task.run(lambda: self._message_box. __setattr__('text', self._original_text)), Task.wait(blinking_time), Task.run(lambda: self._message_box.__setattr__( 'text', self._blink_text)), Task.wait(blinking_time)))).kill() self._original_text = None self._blink_text = None message_box_layer = forward_property('_message_box')('layer') def show_notification(self, text, blink_text=None): """ Triggers a notification with the given text. """ text = self._align_text_fn(text) blink_text = self._align_text_fn(blink_text) if blink_text is not None: self._original_text = text self._blink_text = blink_text self._blink_text_task.restart() self._message_box.text = text self._message_box.set_enabled(True) self._notification_timeout_task.restart() def hide_notification(self): """ Hides the current notification, if any existing. """ self._blink_text_task.kill() self._message_box.set_enabled(False) def use_single_line(self, line_index, line_slice=None, align=align_none): """ Returns a control, that will change the notification to a single line view, if it is grabbed. """ if not (line_index >= 0 and line_index < len(self._display_lines)): raise AssertionError display = self._display_lines[line_index] display = line_slice is not None and display.subdisplay[line_slice] layer = Layer(priority=MESSAGE_BOX_PRIORITY, display_line1=display) return _CallbackControl( self._token_control, partial(self._set_message_box_layout, layer, maybe(partial(align, display.width)))) def use_full_display(self, message_line_index=2): """ Returns a control, that will change the notification to use the whole display, if it is grabbed. """ layer = Layer( priority=MESSAGE_BOX_PRIORITY, **dict([ ('display_line1' if i == message_line_index else 'bg%d' % i, line) for i, line in enumerate(self._display_lines) ])) return _CallbackControl(self._token_control, partial(self._set_message_box_layout, layer)) def _set_message_box_layout(self, layer, align_text_fn=None): self._message_box.layer = layer self._align_text_fn = partial(align_text_fn or self._default_align_text_fn)