def __init__(self, executor_widgets): self.log_widget = ScrollingLog() self.latest_stats = LatestStats() self.cumulative_stats = CumulativeStats() stats_pane = Pile([(WEIGHT, 0.333, self.latest_stats), (WEIGHT, 0.667, self.cumulative_stats)]) self.graphs = ThreeGraphs() self.logo = TaurusLogo() ordered_widgets = sorted(executor_widgets, key=lambda x: x.priority) right_widgets = ListBox( SimpleListWalker([Pile([x, Divider()]) for x in ordered_widgets])) widget_pile = Pile([ (7, self.logo), right_widgets, ]) log_block = Pile([(1, Filler(Divider('─'))), self.log_widget]) right_pane = Pile([(WEIGHT, 0.667, widget_pile), (WEIGHT, 0.333, log_block)]) columns = [(WEIGHT, 0.25, self.graphs), (WEIGHT, 0.50, stats_pane), (WEIGHT, 0.25, right_pane)] super(TaurusConsole, self).__init__(columns)
def __init__(self, original_widget, title="", tlcorner=u'┌', tline=u'─', lline=u'│', trcorner=u'┐', blcorner=u'└', rline=u'│', bline=u'─', brcorner=u'┘'): """ Draw a line around original_widget. Use 'title' to set an initial title text with will be centered on top of the box. You can also override the widgets used for the lines/corners: tline: top line bline: bottom line lline: left line rline: right line tlcorner: top left corner trcorner: top right corner blcorner: bottom left corner brcorner: bottom right corner """ tline, bline = Divider(tline), Divider(bline) lline, rline = SolidFill(lline), SolidFill(rline) tlcorner, trcorner = Text(tlcorner), Text(trcorner) blcorner, brcorner = Text(blcorner), Text(brcorner) self.title_widget = Text(self.format_title(title)) self.tline_widget = Columns([ tline, ('flow', self.title_widget), tline, ]) top = Columns([('fixed', 1, tlcorner), self.tline_widget, ('fixed', 1, trcorner)]) middle = Columns([ ('fixed', 1, lline), original_widget, ('fixed', 1, rline), ], box_columns=[0, 2], focus_column=1) bottom = Columns([('fixed', 1, blcorner), bline, ('fixed', 1, brcorner)]) pile = Pile([('flow', top), middle, ('flow', bottom)], focus_item=1) WidgetDecoration.__init__(self, original_widget) WidgetWrap.__init__(self, pile)
def generate_display_widget(self, size): """ Actually generate display widget (ignoring cache) """ (maxcol,) = size d = Divider() if len(self.cells) == 0: # how dull return d if self.v_sep > 1: # increase size of divider d.top = self.v_sep-1 # cells per row bpr = (maxcol+self.h_sep) // (self.cell_width+self.h_sep) if bpr == 0: # too narrow, pile them on top of eachother l = [self.cells[0]] f = 0 for b in self.cells[1:]: if b is self.focus_cell: f = len(l) if self.v_sep: l.append(d) l.append(b) return Pile(l, f) if bpr >= len(self.cells): # all fit on one row k = len(self.cells) f = self.cells.index(self.focus_cell) cols = Columns(self.cells, self.h_sep, f) rwidth = (self.cell_width+self.h_sep)*k - self.h_sep row = Padding(cols, self.align, rwidth) return row out = [] s = 0 f = 0 while s < len(self.cells): if out and self.v_sep: out.append(d) k = min( len(self.cells), s+bpr ) cells = self.cells[s:k] if self.focus_cell in cells: f = len(out) fcol = cells.index(self.focus_cell) cols = Columns(cells, self.h_sep, fcol) else: cols = Columns(cells, self.h_sep) rwidth = (self.cell_width+self.h_sep)*(k-s)-self.h_sep row = Padding(cols, self.align, rwidth) out.append(row) s += bpr return Pile(out, f)
def setup_popup(self, title): """ Overlays a dialog box on top of the working view using a Frame """ # Header if self.small_display: header = Padding(Text(title, align='center')) else: header = LineBox(Text(title), tline=None, rline=' ', lline=' ', trcorner=' ', tlcorner=' ', blcorner='', brcorner='') header = AttrWrap(header, 'header') # Body error_text = Text("", align='center') # register the Text widget with the application, so we can change it self._error = error_text error_text = AttrWrap(error_text, 'error') body = Pile([ Divider(), error_text, Divider(), LineBox(GridFlow([self.setup_button("Dismiss", self.close_popup)], 12, 2, 0, 'center'), bline=None, lline=None, rline=None, tlcorner='─', trcorner='─') ]) body = LineBox(body) body = AttrWrap(body, 'body') # on small displays let the popup fill the screen (horizontal) if self.small_display: body = Padding(Filler(body, 'middle'), 'center') else: body = Padding(Filler(body, 'middle'), 'center', ('relative', 50)) body = AttrWrap(body, 'bg') # Main dialog widget dialog = Frame(body, header=header, focus_part='body') return dialog
def __init__(self, sidebar_widgets): self.log_widget = ScrollingLog() self.latest_stats = LatestStats() self.cumulative_stats = CumulativeStats() stats_pane = Pile([(WEIGHT, 0.33, self.latest_stats), (WEIGHT, 0.67, self.cumulative_stats), ]) self.graphs = ThreeGraphs() right_widgets = ListBox(SimpleListWalker([Pile([x, Divider()]) for x in sidebar_widgets])) self.logo = TaurusLogo() right_pane = Pile([(10, self.logo), right_widgets, (1, Filler(Divider('─'))), (WEIGHT, 1, self.log_widget)]) columns = [(WEIGHT, 0.25, self.graphs), (WEIGHT, 0.50, stats_pane), (WEIGHT, 0.25, right_pane)] super(TaurusConsole, self).__init__(columns)
def __init__(self, original_widget, title="", title_align="center", title_attr=None, tlcorner=u'┌', tline=u'─', lline=u'│', trcorner=u'┐', blcorner=u'└', rline=u'│', bline=u'─', brcorner=u'┘'): """ Draw a line around original_widget. Use 'title' to set an initial title text with will be centered on top of the box. Use `title_attr` to apply a specific attribute to the title text. Use `title_align` to align the title to the 'left', 'right', or 'center'. The default is 'center'. You can also override the widgets used for the lines/corners: tline: top line bline: bottom line lline: left line rline: right line tlcorner: top left corner trcorner: top right corner blcorner: bottom left corner brcorner: bottom right corner If empty string is specified for one of the lines/corners, then no character will be output there. This allows for seamless use of adjoining LineBoxes. """ if tline: tline = Divider(tline) if bline: bline = Divider(bline) if lline: lline = SolidFill(lline) if rline: rline = SolidFill(rline) tlcorner, trcorner = Text(tlcorner), Text(trcorner) blcorner, brcorner = Text(blcorner), Text(brcorner) if not tline and title: raise ValueError('Cannot have a title when tline is empty string') if title_attr: self.title_widget = Text((title_attr, self.format_title(title))) else: self.title_widget = Text(self.format_title(title)) if tline: if title_align not in ('left', 'center', 'right'): raise ValueError('title_align must be one of "left", "right", or "center"') if title_align == 'left': tline_widgets = [('flow', self.title_widget), tline] else: tline_widgets = [tline, ('flow', self.title_widget)] if title_align == 'center': tline_widgets.append(tline) self.tline_widget = Columns(tline_widgets) top = Columns([ ('fixed', 1, tlcorner), self.tline_widget, ('fixed', 1, trcorner) ]) else: self.tline_widget = None top = None middle_widgets = [] if lline: middle_widgets.append(('fixed', 1, lline)) else: # Note: We need to define a fixed first widget (even if it's 0 width) so that the other # widgets have something to anchor onto middle_widgets.append(('fixed', 0, SolidFill(u""))) middle_widgets.append(original_widget) focus_col = len(middle_widgets) - 1 if rline: middle_widgets.append(('fixed', 1, rline)) middle = Columns(middle_widgets, box_columns=[0, 2], focus_column=focus_col) if bline: bottom = Columns([ ('fixed', 1, blcorner), bline, ('fixed', 1, brcorner) ]) else: bottom = None pile_widgets = [] if top: pile_widgets.append(('flow', top)) pile_widgets.append(middle) focus_pos = len(pile_widgets) - 1 if bottom: pile_widgets.append(('flow', bottom)) pile = Pile(pile_widgets, focus_item=focus_pos) WidgetDecoration.__init__(self, original_widget) WidgetWrap.__init__(self, pile)
def __init__(self, original_widget, title="", title_align="center", tlcorner='┌', tline='─', lline='│', trcorner='┐', blcorner='└', rline='│', bline='─', brcorner='┘'): """ Draw a line around original_widget. Use 'title' to set an initial title text with will be centered on top of the box. Use `title_align` to align the title to the 'left', 'right', or 'center'. The default is 'center'. You can also override the widgets used for the lines/corners: tline: top line bline: bottom line lline: left line rline: right line tlcorner: top left corner trcorner: top right corner blcorner: bottom left corner brcorner: bottom right corner .. note:: This differs from the vanilla urwid LineBox by discarding the a line if the middle of the line is set to either None or the empty string. """ if tline: tline = Divider(tline) if bline: bline = Divider(bline) if lline: lline = SolidFill(lline) if rline: rline = SolidFill(rline) tlcorner, trcorner = Text(tlcorner), Text(trcorner) blcorner, brcorner = Text(blcorner), Text(brcorner) if not tline and title: raise ValueError('Cannot have a title when tline is unset') self.title_widget = Text(self.format_title(title)) if tline: if title_align not in ('left', 'center', 'right'): raise ValueError( 'title_align must be one of "left", "right", or "center"') if title_align == 'left': tline_widgets = [('flow', self.title_widget), tline] else: tline_widgets = [tline, ('flow', self.title_widget)] if title_align == 'center': tline_widgets.append(tline) self.tline_widget = Columns(tline_widgets) top = Columns([('fixed', 1, tlcorner), self.tline_widget, ('fixed', 1, trcorner)]) else: self.tline_widget = None top = None middle_widgets = [] if lline: middle_widgets.append(('fixed', 1, lline)) middle_widgets.append(original_widget) focus_col = len(middle_widgets) - 1 if rline: middle_widgets.append(('fixed', 1, rline)) middle = Columns(middle_widgets, box_columns=[0, 2], focus_column=focus_col) if bline: bottom = Columns([('fixed', 1, blcorner), bline, ('fixed', 1, brcorner)]) else: bottom = None pile_widgets = [] if top: pile_widgets.append(('flow', top)) pile_widgets.append(middle) focus_pos = len(pile_widgets) - 1 if bottom: pile_widgets.append(('flow', bottom)) pile = Pile(pile_widgets, focus_item=focus_pos) WidgetDecoration.__init__(self, original_widget) WidgetWrap.__init__(self, pile)
def process_message(self, message): if message[ 'message_type'] == 'heartbeat' and not self._heartbeat_is_animating: self._heartbeat_is_animating = True self._animate_heartbeat() if not self.seen_message and message[ 'message_type'] == 'certificate_update': self.right_text = urwid.Text('') self.frame.set_body( urwid.Columns(widget_list=[ urwid.Pile([ SidelessLineBox( self.list_box, title="CertStream Messages", bline="", ), ('flow', urwid.Columns([ ('fixed', 6, urwid.Text(u'└─────')), ('flow', self.counter_text), Divider('─'), ('fixed', 1, urwid.Text(u'┘')), ])) ]), SidelessLineBox(urwid.Filler(self.right_text, valign=urwid.TOP), title="Parsed JSON") ], )) self.seen_message = True if message['message_type'] == 'certificate_update': _, original_offset = self.list_box.get_focus() self.list_walker.insert( 0, urwid.AttrMap(FauxButton("[{}] {} - {}".format( message['data']['cert_index'], message['data']['source']['url'], message['data']['leaf_cert']['subject']['CN'], ), user_data=message, on_press=self.focus_right_panel), '', focus_map='buttons')) self.counter_text.set_text( self.COUNTER_FORMAT.format(original_offset, len(self.list_box.body) - 1)) offset = (len(self.list_box.body) - 1) logging.info("Disconnecting") urwid.disconnect_signal(self.list_walker, "modified", self.item_focused) logging.info("Setting focus") self.list_walker.set_focus(offset) logging.info("Reconnecting") urwid.connect_signal(self.list_walker, "modified", self.item_focused) logging.info("Done") self.right_text.set_text( json.dumps(self.list_walker[ offset - self.list_box.get_focus()[1] - 1].original_widget.user_data['data']['leaf_cert'], indent=4)) self.loop.draw_screen()
def setup_frame(self, title, input_title): """ Creates the main view, with a 3 horizontal pane container (Frame) """ self.keys = [] # List of keys added to the OSK self._shift = False # OSK Shift key state # title frame (header) uses a LineBox with just the bottom line enabled # if we're on a small display, use a simple Text with Padding if self.small_display: header = Padding(Text(title, align='center')) else: header = LineBox(Text(title), tline=None, rline=' ', lline=' ', trcorner=' ', tlcorner=' ', blcorner='', brcorner='') header = AttrWrap(header, 'header') # Body frame, containing the input and the OSK widget input = Text([('input text', ''), ('prompt', ASCII_BLOCK)]) self.input = input Key = self.add_osk_key # alias the key creation function osk = Pile([ # 1st keyboard row WrappableColumns([ (1, Text(" ")), (3, Key('`', shifted='~')), (3, Key('1', shifted='!')), (3, Key('2', shifted='@')), (3, Key('3', shifted='#')), (3, Key('4', shifted='$')), (3, Key('5', shifted='%')), (3, Key('6', shifted='^')), (3, Key('7', shifted='&')), (3, Key('8', shifted='*')), (3, Key('9', shifted='(')), (3, Key('0', shifted=')')), (3, Key('-', shifted='_')), (3, Key('=', shifted='+')), (1, Text(" ")), ], 0), Divider(), # 2nd keyboard row WrappableColumns([ (2, Text(" ")), (3, Key('q')), (3, Key('w')), (3, Key('e')), (3, Key('r')), (3, Key('t')), (3, Key('y')), (3, Key('u')), (3, Key('i')), (3, Key('o')), (3, Key('p')), (3, Key('[', shifted='{')), (3, Key(']', shifted='}')), (3, Key('\\', shifted='|')), ], 0), Divider(), # 3rd keyboard row WrappableColumns([ (3, Text(" ")), (3, Key('a')), (3, Key('s')), (3, Key('d')), (3, Key('f')), (3, Key('g')), (3, Key('h')), (3, Key('j')), (3, Key('k')), (3, Key('l')), (3, Key(';', shifted=':')), (3, Key('\'', shifted='"')), ], 0), Divider(), # 4th keyboard row WrappableColumns([(4, Text(" ")), (3, Key('z')), (3, Key('x')), (3, Key('c')), (3, Key('v')), (3, Key('b')), (3, Key('n')), (3, Key('m')), (3, Key(',', shifted='<')), (3, Key('.', shifted='>')), (3, Key('/', shifted='?'))], 0), Divider(), # 5th (last) keyboard row WrappableColumns([ (1, Text(" ")), (9, Key('↑ Shift', shifted='↑ SHIFT', callback=self.shift_key_press)), (2, Text(" ")), (15, Key('Space', value=' ', shifted=' ')), (2, Text(" ")), (10, Key('Delete ←', callback=self.bksp_key_press)), ], 0), Divider() ]) if self.small_display: # small displays: remove last divider line osk.contents.pop(len(osk.contents) - 1) osk = Padding(osk, 'center', 40) # setup the text input and the buttons input = AttrWrap(LineBox(input), 'input') input = Padding(AttrWrap(input, 'input text'), 'center', ('relative', 80), min_width=30) ok_btn = self.setup_button("OK", self.button_press, exitcode=0) cancel_btn = self.setup_button("Cancel", self.button_press, exitcode=1) # setup the main OSK area, depending on the screen size if self.small_display: body = Pile([ Text(f'Enter the {input_title}', align='center'), input, Divider(), osk, Divider(), GridFlow([ok_btn, cancel_btn], 10, 2, 0, 'center'), Divider() ]) else: body = Pile([ Divider(), input, Divider(), osk, LineBox(GridFlow([ok_btn, cancel_btn], 10, 2, 0, 'center'), bline=None, lline=None, rline=None, tlcorner='─', trcorner='─') ]) body = LineBox(body, f'Enter the {input_title}') body = AttrWrap(body, 'body') # Style the main OSK area # wrap and align the main OSK in the frame body = Padding(body, 'center', 55, min_width=42) body = Filler(body, 'middle') body = AttrWrap(body, 'bg') # Style the body containing the OSK frame = Frame(body, header=header, focus_part='body') return frame
def __init__(self, original_widget, title="", tlcorner=None, tline=None, lline=None, trcorner=None, blcorner=None, rline=None, bline=None, brcorner=None): """ Draw a line around original_widget. Use 'title' to set an initial title text with will be centered on top of the box. You can also override the widgets used for the lines/corners: tline: top line bline: bottom line lline: left line rline: right line tlcorner: top left corner trcorner: top right corner blcorner: bottom left corner brcorner: bottom right corner """ self.title_widget = Text(self.format_title(title)) def use_attr(a, t): if a is not None: t = AttrWrap(t, a) return t else: return t self.tline_widget = Columns([ Divider(self.ACS_HLINE), ('flow', self.title_widget), Divider(self.ACS_HLINE), ]) tline = use_attr(tline, self.tline_widget) bline = use_attr(bline, Divider(self.ACS_HLINE)) lline = use_attr(lline, SolidFill(self.ACS_VLINE)) rline = use_attr(rline, SolidFill(self.ACS_VLINE)) tlcorner = use_attr(tlcorner, Text(self.ACS_ULCORNER)) trcorner = use_attr(trcorner, Text(self.ACS_URCORNER)) blcorner = use_attr(blcorner, Text(self.ACS_LLCORNER)) brcorner = use_attr(brcorner, Text(self.ACS_LRCORNER)) top = Columns([('fixed', 1, tlcorner), tline, ('fixed', 1, trcorner)]) middle = Columns([('fixed', 1, lline), original_widget, ('fixed', 1, rline)], box_columns=[0, 2], focus_column=1) bottom = Columns([('fixed', 1, blcorner), bline, ('fixed', 1, brcorner)]) pile = Pile([('flow', top), middle, ('flow', bottom)], focus_item=1) WidgetDecoration.__init__(self, original_widget) WidgetWrap.__init__(self, pile)