Source code for clay.notifications

"""
Notification widgets.
"""
import urwid


[docs]class _Notification(urwid.Columns): """ Single notification widget. Can be updated or closed. """ TEMPLATE = u' \u26A1 {}'
[docs] def __init__(self, area, notification_id, message): self.area = area self._id = notification_id self.text = urwid.Text('') self._set_text(message) super(_Notification, self).__init__([ urwid.AttrWrap( urwid.Columns([ self.text, ('pack', urwid.Text('[Hit ESC to close] ')) ]), 'notification' ) ])
@property def id(self): # pylint: disable=invalid-name """ Notification ID. """ return self._id
[docs] def _set_text(self, message): """ Set contents for this notification. """ message = message.split('\n') message = '\n'.join([ message[0] ] + [' {}'.format(line) for line in message[1:]]) self.text.set_text(_Notification.TEMPLATE.format(message))
[docs] def update(self, message): """ Update notification message. """ self._set_text(message) if not self.is_alive: self.area.append_notification(self) self.area.app.redraw()
@property def is_alive(self): """ Return True if notification is currently visible. """ for notification, _ in self.area.contents: if notification is self: return True return False
[docs] def close(self): """ Close notification. """ for notification, props in reversed(self.area.contents): if notification is self: self.area.contents.remove((notification, props)) if self.area.app is not None: self.area.app.redraw()
[docs]class _NotificationArea(urwid.Pile): """ Notification area widget. """
[docs] def __init__(self): self.app = None self.last_id = 0 self.notifications = {} super(_NotificationArea, self).__init__([])
[docs] def set_app(self, app): """ Set app instance. Required for proper screen redraws when new notifications are created asynchronously. """ self.app = app
[docs] def notify(self, message): """ Create new notification with message. """ self.last_id += 1 notification = _Notification(self, self.last_id, message) self.append_notification(notification) return notification
[docs] def append_notification(self, notification): """ Append an existing notification (that was probably closed). """ self.contents.append( ( notification, ('weight', 1) ) ) if self.app is not None: self.app.redraw()
[docs] def close_all(self): """ Close all notifications. """ while self.contents: self.contents[0][0].close()
[docs] def close_newest(self): """ Close newest notification """ if not self.contents: return self.contents[-1][0].close()
notification_area = _NotificationArea() # pylint: disable=invalid-name