def _columnar_interface(self): self.root = Row(layout_width=self.width, layout_height=self.height, padding=5, align=ALIGN_CENTER) count = 3 columns = [ Column( self.root, layout_width=self.width // count, wrap_content=False, # Fill parent padding=10, outline=True) for _ in range(count) ] for column in columns: column.add_text_content('Line 1 happens to be long', align=ALIGN_CENTER) column.add_text_content('Line 2', align=ALIGN_CENTER) column.add_text_content('Line 3', align=ALIGN_CENTER) column.add_text_content('Line 4', align=ALIGN_CENTER) column.add_text_content('Line 5', align=ALIGN_RIGHT) column.add_text_content('Line 6', align=ALIGN_LEFT) column.add_image(CALENDAR_40_40, 40, 40, align=ALIGN_CENTER) self.root.add_node(column)
def __init__(self, *args, **kwargs): kwargs['margin'] = kwargs.get('margin', 0) self.selected_item_index = None self.rows = kwargs.pop('rows', []) self.align = kwargs.get('align', 'l') self.spacing = kwargs.get('spacing', 4) self.draw_zebra = kwargs.pop('draw_zebra', True) # self.row_height = kwargs.pop('row_height', max([a.height for a in self.rows] + [self.font.size(' ')[1],])) self.row_height = kwargs.pop( 'row_height', max([a.height for a in self.rows] + [ self.font.get_linesize(), ])) self.inner_width = kwargs.pop('inner_width', 500) self.scrolling = kwargs.get('scrolling', True) self.hscrolling = kwargs.get('hscrolling', True) self.scrollRow = scrollRow = ScrollRow( (self.inner_width, self.row_height), 10, draw_zebra=self.draw_zebra, spacing=0, scrolling=self.scrolling, hscrolling=self.hscrolling) self.selected = None Column.__init__(self, [ scrollRow, ], **kwargs) self.shrink_wrap()
def __init__(self, nrows=15, height=None, header_height=None, row_height=None, scrolling=True, **kwds): columns = self.predict_attr(kwds, 'columns') if row_height is None: font = self.predict_font(kwds) row_height = font.get_linesize() if header_height is None: header_height = row_height row_width = 0 if columns: for column in columns: row_width += column.width row_width += 2 * self.column_margin * len(columns) contents = [] header = None if header_height: header = TableHeaderView(row_width, header_height) contents.append(header) row_size = (row_width, row_height) if not nrows and height: nrows = height // row_height self.rows = rows = TableRowView(row_size, nrows or 10, scrolling=scrolling) contents.append(rows) s = self.header_spacing Column.__init__(self, contents, align='l', spacing=s, **kwds) if header: header.font = self.header_font or self.font header.fg_color = fg_color = self.header_fg_color or self.fg_color header.bg_color = bg_color = self.header_bg_color or self.bg_color rows.font = self.font rows.fg_color = self.fg_color rows.bg_color = self.bg_color rows.sel_color = self.sel_color
def __init__(self, client=None, responses=None, default=0, cancel=-1, **kwds): Widget.__init__(self, **kwds) if client or responses: rows = [] w1 = 0 w2 = 0 if client: rows.append(client) w1 = client.width if responses: buttons = Row([ Button(text, action=lambda t=text: self.dismiss(t)) for text in responses]) rows.append(buttons) w2 = buttons.width if w1 < w2: a = 'l' else: a = 'r' contents = Column(rows, align=a) m = self.margin contents.topleft = (m, m) self.add(contents) self.shrink_wrap() if responses and default is not None: self.enter_response = responses[default] if responses and cancel is not None: self.cancel_response = responses[cancel]
def ask(mess, responses=["OK", "Cancel"], default=0, cancel=-1, wrap_width=60, **kwds): box = Dialog(**kwds) d = box.margin lb = wrapped_label(mess, wrap_width) lb.topleft = (d, d) buts = [] for caption in responses: but = Button(caption, action=lambda x=caption: box.dismiss(x)) buts.append(but) brow = Row(buts, spacing=d) lb.width = max(lb.width, brow.width) col = Column([lb, brow], spacing=d, align='r') col.topleft = (d, d) if default is not None: box.enter_response = responses[default] buts[default].is_default = True else: box.enter_response = None if cancel is not None: box.cancel_response = responses[cancel] else: box.cancel_response = None box.add(col) box.shrink_wrap() return box.present()
def ask(mess, responses=["OK", "Cancel"], default=0, cancel=-1, wrap_width=60, **kwds): # If height is specified as a keyword, the Dialog object will have this haight, and the inner massage will # be displayed in a scrolling widget colLbl = kwds.pop("colLabel", "") box = Dialog(**kwds) d = box.margin lb = wrapped_label(mess, wrap_width) buts = [] for caption in responses: but = Button(caption, action=lambda x=caption: box.dismiss(x)) buts.append(but) brow = Row(buts, spacing=d) lb.width = max(lb.width, brow.width) height = kwds.get("height", None) if height and lb.height > height - (2 * brow.height) - ScrollPanel.column_margin - box.margin: lines = mess.split("\n") # ScrolledPanel refuses to render properly for now, so Tableview is used instead. w = TableView().font.size(_(colLbl))[0] lb = TableView( columns=[TableColumn(colLbl, max(lb.width, w))], nrows=(height - (2 * brow.height) - box.margin - box.font.get_linesize()) / box.font.get_linesize(), height=height - (2 * brow.height) - (box.font.get_linesize() * 2) - box.margin, ) # , width=w) def num_rows(): return len(lines) lb.num_rows = num_rows lb.row_data = lambda x: (lines[x],) lb.topleft = (d, d) lb.width = max(lb.width, brow.width) col = Column([lb, brow], spacing=d, align="r") col.topleft = (d, d) if default is not None: box.enter_response = responses[default] buts[default].is_default = True else: box.enter_response = None if cancel is not None: box.cancel_response = responses[cancel] else: box.cancel_response = None box.add(col) box.shrink_wrap() def dispatchKeyForAsk(name, evt): if name == "key_down": if box.root.getKey(evt) == "Return": if default is not None: box.dismiss(responses[default]) box.dispatch_key = dispatchKeyForAsk return box.present()
def __init__(self, type_string, types=map_types_item, ok_action=None): self.type_string = type_string self.ok_action = ok_action title = Label("Choose default data") self.t, widget, self.v = types[type_string] self.n = u"" w_name = TextFieldWrapped(ref=AttrRef(self, 'n')) self.w_value = self.get_widget(widget) col = Column([Column([title,]), Label(_("Item Type: %s")%type_string, doNotTranslate=True), Row([Label("Name"), w_name], margin=0), Row([Label("Value"), self.w_value], margin=0), Row([Button("OK", action=ok_action or self.dismiss_ok), Button("Cancel", action=self.dismiss)], margin=0)], margin=0, spacing=2) Dialog.__init__(self, client=col)
def ask(mess, responses=["OK", "Cancel"], default=0, cancel=-1, wrap_width=60, **kwds): # If height is specified as a keyword, the Dialog object will have this haight, and the inner massage will # be displayed in a scrolling widget colLbl = kwds.pop('colLabel', "") box = Dialog(**kwds) d = box.margin lb = wrapped_label(mess, wrap_width) buts = [] for caption in responses: but = Button(caption, action=lambda x=caption: box.dismiss(x)) buts.append(but) brow = Row(buts, spacing=d) lb.width = max(lb.width, brow.width) height = kwds.get('height', None) if height and lb.height > height - (2 * brow.height) - ScrollPanel.column_margin - box.margin: lines = mess.split('\n') # ScrolledPanel refuses to render properly for now, so Tableview is used instead. w = TableView().font.size(_(colLbl))[0] lb = TableView(columns=[TableColumn(colLbl, max(lb.width, w)),], nrows=(height - (2 * brow.height) - box.margin - box.font.get_linesize()) / box.font.get_linesize(), height=height - (2 * brow.height) - (box.font.get_linesize() * 2) - box.margin) #, width=w) def num_rows(): return len(lines) lb.num_rows = num_rows lb.row_data = lambda x: (lines[x],) lb.topleft = (d, d) lb.width = max(lb.width, brow.width) col = Column([lb, brow], spacing=d, align='r') col.topleft = (d, d) if default is not None: box.enter_response = responses[default] buts[default].is_default = True else: box.enter_response = None if cancel is not None: box.cancel_response = responses[cancel] else: box.cancel_response = None box.add(col) box.shrink_wrap() def dispatchKeyForAsk(name, evt): if name == "key_down": if box.root.getKey(evt) == "Return": if default is not None: box.dismiss(responses[default]) box.dispatch_key = dispatchKeyForAsk return box.present()
def __init__(self, *args, **kwargs): self.menu = [ ("Add", "add_item"), ("Delete", "delete_item"), ("New child", "add_child"), ("Rename", "rename_item"), ("", ""), ("Cut", "cut_item"), ("Copy", "copy_item"), ("Paste", "paste_item"), ("Paste as child", "paste_child"), ] if not hasattr(self, 'map_types_item'): global map_types_item self.map_types_item = setup_map_types_item() self.selected_item_index = None # cached_item_index is set to False during startup to avoid a predefined selected item to be unselected when closed # the first time. self.cached_selected_item_index = False self.selected_item = None self.clicked_item = None self.copyBuffer = kwargs.pop('copyBuffer', None) self._parent = kwargs.pop('_parent', None) self.styles = kwargs.pop('styles', {}) self.compound_types = [ dict, ] + kwargs.pop('compound_types', []) self.item_types = self.compound_types + kwargs.pop( 'item_types', [a[0] for a in self.map_types_item.values()] or [int, float, unicode, bool]) for t in self.item_types: if 'create_%s' % t.__name__ in globals().keys(): setattr(self, 'create_%s' % t.__name__, globals()['create_%s' % t.__name__]) self.show_fields = kwargs.pop('show_fields', False) self.deployed = [] self.data = data = kwargs.pop("data", {}) self.draw_zebra = draw_zebra = kwargs.pop('draw_zebra', True) # self.inner_width = kwargs.pop('inner_width', 'auto') self.inner_width = kwargs.pop('inner_width', 500) self.__num_rows = len(data.keys()) self.build_layout() # row_height = self.font.size(' ')[1] row_height = self.font.get_linesize() self.treeRow = treeRow = TreeRow((self.inner_width, row_height), 10, draw_zebra=draw_zebra) Column.__init__(self, [ treeRow, ], **kwargs)
def __init__(self, title, responses, default=None, ok_action=None): self.response = responses[0] self.ok_action = ok_action title = Label(title) self.w_type = ChoiceButton(responses) col = Column([title, self.w_type, Row([Button("OK", action=ok_action or self.dismiss_ok), Button("Cancel", action=ok_action or self.dismiss)], margin=0)], margin=0, spacing=2) Dialog.__init__(self, client=col)
def __init__(self, *args, **kwargs): kwargs['margin'] = kwargs.get('margin', 0) self.selected_item_index = None self.rows = kwargs.pop('rows', []) self.align = kwargs.get('align', 'l') self.spacing = kwargs.get('spacing', 4) self.draw_zebra = kwargs.pop('draw_zebra', True) # self.row_height = kwargs.pop('row_height', max([a.height for a in self.rows] + [self.font.size(' ')[1],])) self.row_height = kwargs.pop('row_height', max([a.height for a in self.rows] + [self.font.get_linesize(),])) self.inner_width = kwargs.pop('inner_width', 500) self.scrolling = kwargs.get('scrolling', True) self.hscrolling = kwargs.get('hscrolling', True) self.scrollRow = scrollRow = ScrollRow((self.inner_width, self.row_height), 10, draw_zebra=self.draw_zebra, spacing=0, scrolling=self.scrolling, hscrolling=self.hscrolling) self.selected = None Column.__init__(self, [scrollRow,], **kwargs) self.shrink_wrap()
def input_text_buttons(prompt, width, initial=None, allowed_chars=None, **kwds): box = Dialog(**kwds) d = box.margin def ok(): box.dismiss(True) def cancel(): box.dismiss(False) buts = [Button("OK", action=ok), Button("Cancel", action=cancel)] brow = Row(buts, spacing=d) lb = Label(prompt) lb.topleft = (d, d) tf = TextFieldWrapped(width, allowed_chars=allowed_chars) if initial: tf.set_text(initial) tf.enter_action = ok tf.escape_action = cancel tf.top = lb.top tf.left = lb.right + 5 trow = Row([lb, tf], spacing=d) col = Column([trow, brow], spacing=d, align='c') col.topleft = (d, d) box.add(col) tf.focus() box.shrink_wrap() if box.present(): return tf.get_text() else: return None
def _build_textual_interface(self): self.root = Column(layout_width=self.width, layout_height=self.height, padding=20) # Nested Column column = Column(parent=self.root, padding=0) column.add_spacer(20) self.root.add_node(column) # Nested Row row = Row(parent=self.root, padding=10, align=ALIGN_CENTER) row.add_text_content('Test 1') row.add_text_content('Test 2') row.add_text_content('Test 3') row.add_text_content('Test 4') self.root.add_node(row) # Other text nodes self.root.add_text_content('Good Morning, Rahul', text_size=3) self.root.add_text_content('Some text') self.root.add_text_content('Some more text') self.root.add_text_content('Medium Text', text_size=5, align=ALIGN_CENTER) self.root.add_text_content('More Medium Text', text_size=5, align=ALIGN_RIGHT) self.root.add_text_content('Large Text', text_size=9, align=ALIGN_CENTER) self.root.add_text_content('Largest Text', text_size=10, align=ALIGN_CENTER)
def __init__(self, *args, **kwargs): self.menu = [ ("Add", "add_item"), ("Delete", "delete_item"), ("New child", "add_child"), ("Rename", "rename_item"), ("", ""), ("Cut", "cut_item"), ("Copy", "copy_item"), ("Paste", "paste_item"), ("Paste as child", "paste_child"), ] if not hasattr(self, "map_types_item"): global map_types_item self.map_types_item = setup_map_types_item() self.selected_item_index = None self.selected_item = None self.clicked_item = None self.copyBuffer = kwargs.pop("copyBuffer", None) self._parent = kwargs.pop("_parent", None) self.styles = kwargs.pop("styles", {}) self.compound_types = [dict] + kwargs.pop("compound_types", []) self.item_types = self.compound_types + kwargs.pop( "item_types", [a[0] for a in self.map_types_item.values()] or [int, float, unicode, bool] ) for t in self.item_types: if "create_%s" % t.__name__ in globals().keys(): setattr(self, "create_%s" % t.__name__, globals()["create_%s" % t.__name__]) self.show_fields = kwargs.pop("show_fields", False) self.deployed = [] self.data = data = kwargs.pop("data", {}) self.draw_zebra = draw_zebra = kwargs.pop("draw_zebra", True) # self.inner_width = kwargs.pop('inner_width', 'auto') self.inner_width = kwargs.pop("inner_width", 500) self.__num_rows = len(data.keys()) self.build_layout() # row_height = self.font.size(' ')[1] row_height = self.font.get_linesize() self.treeRow = treeRow = TreeRow((self.inner_width, row_height), 10, draw_zebra=draw_zebra) Column.__init__(self, [treeRow], **kwargs)
def __init__(self, *args, **kwargs): self.menu = [("Add", "add_item"), ("Delete", "delete_item"), ("New child", "add_child"), ("Rename", "rename_item"), ("", ""), ("Cut", "cut_item"), ("Copy", "copy_item"), ("Paste", "paste_item"), ("Paste as child", "paste_child"), ] if not hasattr(self, 'map_types_item'): global map_types_item self.map_types_item = setup_map_types_item() self.selected_item_index = None # cached_item_index is set to False during startup to avoid a predefined selected item to be unselected when closed # the first time. self.cached_selected_item_index = False self.selected_item = None self.clicked_item = None self.copyBuffer = kwargs.pop('copyBuffer', None) self._parent = kwargs.pop('_parent', None) self.styles = kwargs.pop('styles', {}) self.compound_types = [dict,] + kwargs.pop('compound_types', []) self.item_types = self.compound_types + kwargs.pop('item_types', [a[0] for a in self.map_types_item.values()] or [int, float, unicode, bool]) for t in self.item_types: if 'create_%s'%t.__name__ in globals().keys(): setattr(self, 'create_%s'%t.__name__, globals()['create_%s'%t.__name__]) self.show_fields = kwargs.pop('show_fields', False) self.deployed = [] self.data = data = kwargs.pop("data", {}) self.draw_zebra = draw_zebra = kwargs.pop('draw_zebra', True) # self.inner_width = kwargs.pop('inner_width', 'auto') self.inner_width = kwargs.pop('inner_width', 500) self.__num_rows = len(data.keys()) self.build_layout() # row_height = self.font.size(' ')[1] row_height = self.font.get_linesize() self.treeRow = treeRow = TreeRow((self.inner_width, row_height), 10, draw_zebra=draw_zebra) Column.__init__(self, [treeRow,], **kwargs)
def __init__(self, *args, **kwargs): self.menu = [("Add", "add_item"), ("Delete", "delete_item"), ("New child", "add_child"), ("Rename", "rename_item"), ] self.selected_item_index = None self.selected_item = None self._parent = kwargs.pop('_parent', None) self.styles = kwargs.pop('styles', {}) self.compound_types = [dict,] + kwargs.pop('compound_types', []) self.show_fields = kwargs.pop('show_fields', False) self.deployed = [] self.data = data = kwargs.pop("data", {}) self.draw_zebra = draw_zebra = kwargs.pop('draw_zebra', True) # self.inner_width = kwargs.pop('inner_width', 'auto') self.inner_width = kwargs.pop('inner_width', 500) self.__num_rows = len(data.keys()) self.build_layout() row_height = self.font.size(' ')[1] self.treeRow = treeRow = TreeRow((self.inner_width, row_height), 10, draw_zebra=draw_zebra) Column.__init__(self, [treeRow,], **kwargs)
def input_text_buttons(prompt, width, initial=None, allowed_chars=None, **kwds): box = Dialog(**kwds) d = box.margin def ok(): box.dismiss(True) def cancel(): box.dismiss(False) buts = [Button("OK", action=ok), Button("Cancel", action=cancel)] brow = Row(buts, spacing=d) lb = Label(prompt) lb.topleft = (d, d) tf = TextFieldWrapped(width,allowed_chars=allowed_chars) if initial: tf.set_text(initial) tf.enter_action = ok tf.escape_action = cancel tf.top = lb.top tf.left = lb.right + 5 trow = Row([lb, tf], spacing=d) col = Column([trow, brow], spacing=d, align='c') col.topleft = (d, d) box.add(col) tf.focus() box.shrink_wrap() if box.present(): return tf.get_text() else: return None
def __init__(self, items, keysColumn=None, buttonsColumn=None, item_spacing=None): if keysColumn is None: keysColumn = [] if buttonsColumn is None: buttonsColumn = [] Widget.__init__(self) for t in items: if len(t) == 3: (hotkey, title, action) = t tooltipText = None else: (hotkey, title, action, tooltipText) = t if isinstance(title, (str, unicode)): button = Button(title, action=action) else: button = ValueButton(ref=title, action=action, width=200) button.anchor = self.anchor label = Label(hotkey, width=75, margin=button.margin) label.anchor = "wh" label.height = button.height if tooltipText: button.tooltipText = tooltipText keysColumn.append(label) buttonsColumn.append(button) self.buttons = list(buttonsColumn) #.# if item_spacing == None: buttonsColumn = Column(buttonsColumn) else: buttonsColumn = Column(buttonsColumn, spacing=item_spacing) #.# buttonsColumn.anchor = self.anchor #.# if item_spacing == None: keysColumn = Column(keysColumn) else: keysColumn = Column(keysColumn, spacing=item_spacing) commandRow = Row((keysColumn, buttonsColumn)) self.add(commandRow) self.shrink_wrap()
def CheckBoxLabel(title, *args, **kw): tooltipText = kw.pop('tooltipText', None) l_kw = {'margin': 0} b_kw = {'margin': 0} expand = kw.pop('expand', 'none') r_kw = {} if expand != 'none': r_kw['expand'] = expand align = kw.pop('align', None) if align: r_kw['align'] = align cb = CheckBox(*args, **kw) lab = Label(title, fg_color=cb.fg_color) lab.mouse_down = cb.mouse_down if tooltipText: cb.tooltipText = tooltipText lab.tooltipText = tooltipText class CBRow(Row): margin = 0 @property def value(self): return self.checkbox.value @value.setter def value(self, val): self.checkbox.value = val row = CBRow((Column((lab, ), **l_kw), Column((cb, ), **b_kw)), **r_kw) row.checkbox = cb return row
def _build_calendar(self): self.root = Column(layout_width=self.width, layout_height=self.height, padding=20) header = Row(parent=self.root, layout_height=40, wrap_content=False) header.add_text_content('Calendar', text_size=4) header.add_image(CALENDAR_40_40, 40, 40, align=ALIGN_RIGHT) content_root = Row(parent=self.root, layout_height=440, wrap_content=False, outline=True) content = Column(parent=content_root, wrap_content=False) content.add_spacer(10, outline=True) content_root.add_node(content) status = Row(parent=self.root, layout_height=40, wrap_content=False, outline=True) status.add_text_content('Last updated at <>', align=ALIGN_RIGHT) self.root.add_node(header) self.root.add_node(content_root) self.root.add_node(status)
def _notify(self, title, messages=list()): root = Column(layout_width=self.width, layout_height=self.height, padding=10) header = Row(parent=root, layout_height=40, wrap_content=False) header.add_text_content('Calendar', text_size=4) header.add_image(CALENDAR_40_40, 40, 40, align=ALIGN_RIGHT) content_root = Row(parent=root, layout_height=520, wrap_content=False, outline=True) content = Column(parent=content_root, wrap_content=False) content.add_spacer(10, outline=True) content.add_spacer(self.width // 4) content.add_text_content(title, text_size=6, align=ALIGN_CENTER) for message in messages: content.add_text_content(message, align=ALIGN_CENTER) content_root.add_node(content) root.add_node(header) root.add_node(content_root) self._draw(root)
def _build_auth(self): self.root = Column(layout_width=self.width, layout_height=self.height, padding=10) header = Row(parent=self.root, layout_height=40, wrap_content=False) header.add_text_content('Calendar', text_size=4) header.add_image(CALENDAR_40_40, 40, 40, align=ALIGN_RIGHT) content_root = Row(parent=self.root, layout_height=520, wrap_content=False, outline=True) content = Column(parent=content_root, wrap_content=False) content.add_spacer(10, outline=True) content.add_spacer(self.width // 4) content.add_text_content('ABCD-EFGH', text_size=6, align=ALIGN_CENTER) content.add_text_content('google.com/auth/code to continue', align=ALIGN_CENTER) content_root.add_node(content) self.root.add_node(header) self.root.add_node(content_root)
def buildWidgets(self): keysColumn = self.keysColumn buttonsColumn = self.buttonsColumn items = self.items item_spacing = self.item_spacing if keysColumn is None or True: keysColumn = [] if buttonsColumn is None or True: buttonsColumn = [] labels = [] for w in self.subwidgets: for _w in w.subwidgets: w.remove(_w) self.remove(w) for i, t in enumerate(items): if type(self.translateButtons) is bool: trn = not self.translateButtons elif type(self.translateButtons) in (list, tuple): trn = not i in self.translateButtons if len(t) == 3: (hotkey, title, action) = t tooltipText = None else: (hotkey, title, action, tooltipText) = t if isinstance(title, (str, unicode)): button = Button(title, action=action, doNotTranslate=trn) else: button = ValueButton(ref=title, action=action, width=200, doNotTranslate=trn) button.anchor = self.anchor label = Label(hotkey, width=100, margin=button.margin) label.anchor = "wh" label.height = button.height labels.append(label) if tooltipText: button.tooltipText = tooltipText keysColumn.append(label) buttonsColumn.append(button) self.buttons = list(buttonsColumn) #.# if item_spacing == None: buttonsColumn = Column(buttonsColumn) else: buttonsColumn = Column(buttonsColumn, spacing=item_spacing) #.# buttonsColumn.anchor = self.anchor #.# if item_spacing == None: keysColumn = Column(keysColumn) else: keysColumn = Column(keysColumn, spacing=item_spacing) commandRow = Row((keysColumn, buttonsColumn)) self.labels = labels self.add(commandRow) self.shrink_wrap() self.invalidate()
def showProgress(progressText, progressIterator, cancel=False): """Show the progress for a long-running synchronous operation. progressIterator should be a generator-like object that can return either None, for an indeterminate indicator, A float value between 0.0 and 1.0 for a determinate indicator, A string, to update the progress info label or a tuple of (float value, string) to set the progress and update the label""" class ProgressWidget(Dialog): progressFraction = 0.0 firstDraw = False root = None def draw(self, surface): if self.root is None: self.root = self.get_root() Widget.draw(self, surface) frameStart = datetime.now() frameInterval = timedelta(0, 1, 0) / 2 amount = None try: while datetime.now() < frameStart + frameInterval: amount = progressIterator.next() if self.firstDraw is False: self.firstDraw = True break except StopIteration: self.dismiss() infoText = "" if amount is not None: if isinstance(amount, tuple): if len(amount) > 2: infoText = ": " + amount[2] amount, max = amount[:2] else: max = amount maxwidth = (self.width - self.margin * 2) if amount is None: self.progressBar.width = maxwidth self.progressBar.bg_color = (255, 255, 25, 255) elif isinstance(amount, basestring): self.statusText = amount else: self.progressAmount = amount if isinstance(amount, (int, float)): self.progressFraction = float(amount) / (float(max) or 1) self.progressBar.width = maxwidth * self.progressFraction self.statusText = str("{0} / {1}".format(amount, max)) else: self.statusText = str(amount) if infoText: self.statusText += infoText @property def estimateText(self): delta = (datetime.now() - self.startTime) progressPercent = (int(self.progressFraction * 10000)) left = delta * (10000 - progressPercent) / (progressPercent or 1) return _("Time left: {0}").format(left) def cancel(self): if cancel: self.dismiss(False) def idleevent(self, evt): self.invalidate() def key_down(self, event): pass def key_up(self, event): pass def mouse_up(self, event): try: if "SelectionTool" in str(self.root.editor.currentTool): if self.root.get_nudge_block().count > 0: self.root.get_nudge_block().mouse_up(event) except: pass widget = ProgressWidget() widget.progressText = _(progressText) widget.statusText = "" widget.progressAmount = 0.0 progressLabel = ValueDisplay(ref=AttrRef(widget, 'progressText'), width=550) statusLabel = ValueDisplay(ref=AttrRef(widget, 'statusText'), width=550) estimateLabel = ValueDisplay(ref=AttrRef(widget, 'estimateText'), width=550) progressBar = Widget(size=(550, 20), bg_color=(150, 150, 150, 255)) widget.progressBar = progressBar col = (progressLabel, statusLabel, estimateLabel, progressBar) if cancel: cancelButton = Button("Cancel", action=widget.cancel, fg_color=(255, 0, 0, 255)) col += (Column((cancelButton, ), align="r"), ) widget.add(Column(col)) widget.shrink_wrap() widget.startTime = datetime.now() if widget.present(): return widget.progressAmount else: return "Canceled"
class UI: ''' This helps with layout of the InkPlate UI. Everything is rendered via immediate mode & everything is being re-rendered via partial updates. ''' def __init__(self): self.display = Inkplate(Inkplate.INKPLATE_1BIT) self.display.begin() self.width = self.display.width() self.height = self.display.height() self._columnar_interface() def _build_textual_interface(self): self.root = Column(layout_width=self.width, layout_height=self.height, padding=20) # Nested Column column = Column(parent=self.root, padding=0) column.add_spacer(20) self.root.add_node(column) # Nested Row row = Row(parent=self.root, padding=10, align=ALIGN_CENTER) row.add_text_content('Test 1') row.add_text_content('Test 2') row.add_text_content('Test 3') row.add_text_content('Test 4') self.root.add_node(row) # Other text nodes self.root.add_text_content('Good Morning, Rahul', text_size=3) self.root.add_text_content('Some text') self.root.add_text_content('Some more text') self.root.add_text_content('Medium Text', text_size=5, align=ALIGN_CENTER) self.root.add_text_content('More Medium Text', text_size=5, align=ALIGN_RIGHT) self.root.add_text_content('Large Text', text_size=9, align=ALIGN_CENTER) self.root.add_text_content('Largest Text', text_size=10, align=ALIGN_CENTER) def _columnar_interface(self): self.root = Row(layout_width=self.width, layout_height=self.height, padding=5, align=ALIGN_CENTER) count = 3 columns = [ Column( self.root, layout_width=self.width // count, wrap_content=False, # Fill parent padding=10, outline=True) for _ in range(count) ] for column in columns: column.add_text_content('Line 1 happens to be long', align=ALIGN_CENTER) column.add_text_content('Line 2', align=ALIGN_CENTER) column.add_text_content('Line 3', align=ALIGN_CENTER) column.add_text_content('Line 4', align=ALIGN_CENTER) column.add_text_content('Line 5', align=ALIGN_RIGHT) column.add_text_content('Line 6', align=ALIGN_LEFT) column.add_image(CALENDAR_40_40, 40, 40, align=ALIGN_CENTER) self.root.add_node(column) def _build_calendar(self): self.root = Column(layout_width=self.width, layout_height=self.height, padding=20) header = Row(parent=self.root, layout_height=40, wrap_content=False) header.add_text_content('Calendar', text_size=4) header.add_image(CALENDAR_40_40, 40, 40, align=ALIGN_RIGHT) content_root = Row(parent=self.root, layout_height=440, wrap_content=False, outline=True) content = Column(parent=content_root, wrap_content=False) content.add_spacer(10, outline=True) content_root.add_node(content) status = Row(parent=self.root, layout_height=40, wrap_content=False, outline=True) status.add_text_content('Last updated at <>', align=ALIGN_RIGHT) self.root.add_node(header) self.root.add_node(content_root) self.root.add_node(status) def _build_auth(self): self.root = Column(layout_width=self.width, layout_height=self.height, padding=10) header = Row(parent=self.root, layout_height=40, wrap_content=False) header.add_text_content('Calendar', text_size=4) header.add_image(CALENDAR_40_40, 40, 40, align=ALIGN_RIGHT) content_root = Row(parent=self.root, layout_height=520, wrap_content=False, outline=True) content = Column(parent=content_root, wrap_content=False) content.add_spacer(10, outline=True) content.add_spacer(self.width // 4) content.add_text_content('ABCD-EFGH', text_size=6, align=ALIGN_CENTER) content.add_text_content('google.com/auth/code to continue', align=ALIGN_CENTER) content_root.add_node(content) self.root.add_node(header) self.root.add_node(content_root) def draw(self): self.display.clearDisplay() self.root.draw(self.display, 0, 0) self.display.display()
def buildWidgets(self): keysColumn = self.keysColumn buttonsColumn = self.buttonsColumn items = self.items item_spacing = self.item_spacing if keysColumn is None or True: keysColumn = [] if buttonsColumn is None or True: buttonsColumn = [] labels = [] for w in self.subwidgets: for _w in w.subwidgets: w.remove(_w) self.remove(w) for t in items: if len(t) == 3: (hotkey, title, action) = t tooltipText = None else: (hotkey, title, action, tooltipText) = t if isinstance(title, (str, unicode)): button = Button(title, action=action) else: button = ValueButton(ref=title, action=action, width=200) button.anchor = self.anchor label = Label(hotkey, width=100, margin=button.margin) label.anchor = "wh" label.height = button.height labels.append(label) if tooltipText: button.tooltipText = tooltipText keysColumn.append(label) buttonsColumn.append(button) self.buttons = list(buttonsColumn) #.# if item_spacing == None: buttonsColumn = Column(buttonsColumn) else: buttonsColumn = Column(buttonsColumn, spacing=item_spacing) #.# buttonsColumn.anchor = self.anchor #.# if item_spacing == None: keysColumn = Column(keysColumn) else: keysColumn = Column(keysColumn, spacing=item_spacing) commandRow = Row((keysColumn, buttonsColumn)) self.labels = labels self.add(commandRow) self.shrink_wrap() self.invalidate()
def ask(mess, responses=("OK", "Cancel"), default=0, cancel=-1, wrap_width=60, **kwds): # If height is specified as a keyword, the Dialog object will have this haight, and the inner massage will # be displayed in a scrolling widget # If 'responses_tooltips' it present in kwds, it must be dict with 'responses' as keys and the tooltips as values. # If 'tie_widget_to' is in kwds keys and the value is True, the global 'ask_tied_to' will be set up to the 'box'. # When called again with 'tie_widget_to', if 'ask_tied_to' is not None, the function returns a dummy answer. global ask_tied_to responses_tooltips = kwds.pop('responses_tooltips', {}) tie_widget_to = kwds.pop('tie_widget_to', None) # Return a dummy answer if tie_windget_to is True and the global 'ask_tied_to' is not None if tie_widget_to and ask_tied_to: return "_OK" colLbl = kwds.pop('colLabel', "") box = Dialog(**kwds) d = box.margin lb = wrapped_label(mess, wrap_width) buts = [] for caption in responses: but = Button(caption, action=lambda x=caption: box.dismiss(x)) if caption in responses_tooltips.keys(): but.tooltipText = responses_tooltips[caption] buts.append(but) brow = Row(buts, spacing=d) lb.width = max(lb.width, brow.width) height = kwds.get('height', None) if height and lb.height > height - (2 * brow.height) - ScrollPanel.column_margin - box.margin: lines = mess.split('\n') # ScrolledPanel refuses to render properly for now, so Tableview is used instead. w = TableView().font.size(_(colLbl))[0] lb = TableView(columns=[TableColumn(colLbl, max(lb.width, w)),], nrows=(height - (2 * brow.height) - box.margin - box.font.get_linesize()) / box.font.get_linesize(), height=height - (2 * brow.height) - (box.font.get_linesize() * 2) - box.margin) #, width=w) def num_rows(): return len(lines) lb.num_rows = num_rows lb.row_data = lambda x: (lines[x],) lb.topleft = (d, d) lb.width = max(lb.width, brow.width) col = Column([lb, brow], spacing=d, align='r') col.topleft = (d, d) if default is not None: box.enter_response = responses[default] buts[default].is_default = True else: box.enter_response = None if cancel is not None: box.cancel_response = responses[cancel] else: box.cancel_response = None box.add(col) box.shrink_wrap() def dispatchKeyForAsk(name, evt): if name == "key_down": if box.root.getKey(evt) == "Return": if default is not None: box.dismiss(responses[default]) box.dispatch_key = dispatchKeyForAsk if tie_widget_to: ask_tied_to = box ask_tied_tos.append(box) return box.present()
def ask(mess, responses=("OK", "Cancel"), default=0, cancel=-1, wrap_width=60, **kwds): # If height is specified as a keyword, the Dialog object will have this haight, and the inner massage will # be displayed in a scrolling widget # If 'responses_tooltips' it present in kwds, it must be dict with 'responses' as keys and the tooltips as values. # If 'tie_widget_to' is in kwds keys and the value is True, the global 'ask_tied_to' will be set up to the 'box'. # When called again with 'tie_widget_to', if 'ask_tied_to' is not None, the function returns a dummy answer. global ask_tied_to responses_tooltips = kwds.pop('responses_tooltips', {}) tie_widget_to = kwds.pop('tie_widget_to', None) # Return a dummy answer if tie_windget_to is True and the global 'ask_tied_to' is not None if tie_widget_to and ask_tied_to: return "_OK" colLbl = kwds.pop('colLabel', "") box = Dialog(**kwds) d = box.margin lb = wrapped_label(mess, wrap_width) buts = [] for caption in responses: but = Button(caption, action=lambda x=caption: box.dismiss(x)) if caption in responses_tooltips.keys(): but.tooltipText = responses_tooltips[caption] buts.append(but) brow = Row(buts, spacing=d) lb.width = max(lb.width, brow.width) height = kwds.get('height', None) if height and lb.height > height - ( 2 * brow.height) - ScrollPanel.column_margin - box.margin: lines = mess.split('\n') # ScrolledPanel refuses to render properly for now, so Tableview is used instead. w = TableView().font.size(_(colLbl))[0] lb = TableView( columns=[ TableColumn(colLbl, max(lb.width, w)), ], nrows=(height - (2 * brow.height) - box.margin - box.font.get_linesize()) / box.font.get_linesize(), height=height - (2 * brow.height) - (box.font.get_linesize() * 2) - box.margin) #, width=w) def num_rows(): return len(lines) lb.num_rows = num_rows lb.row_data = lambda x: (lines[x], ) lb.topleft = (d, d) lb.width = max(lb.width, brow.width) col = Column([lb, brow], spacing=d, align='r') col.topleft = (d, d) if default is not None: box.enter_response = responses[default] buts[default].is_default = True else: box.enter_response = None if cancel is not None: box.cancel_response = responses[cancel] else: box.cancel_response = None box.add(col) box.shrink_wrap() def dispatchKeyForAsk(name, evt): if name == "key_down" and box.root.getKey( evt) == "Return" and default is not None: box.dismiss(responses[default]) else: Dialog.dispatch_key(box, name, evt) box.dispatch_key = dispatchKeyForAsk if tie_widget_to: ask_tied_to = box ask_tied_tos.append(box) return box.present()
def build_calendar_ui(self): ''' Builds the actual Calendar UI after making the RESTful request. ''' if not self.device_auth.authorized: self._error('Need to authorize first.') if not self.calendar: self.calendar = Calendar(self.device_auth) events = self.calendar.events() date_today = DateTime.today() sync_at = date_today.formatted() sync_at_message = 'Last updated at %s' % (sync_at) if len(events) <= 0: messages = [sync_at_message] self._notify('No events.', messages=messages) else: root = Column(layout_width=self.width, layout_height=self.height, padding=10) header = Row(parent=root, layout_height=40, wrap_content=False) f_date_today = date_today.formatted(include_day=True, include_time=False) header.add_text_content('Today - %s' % (f_date_today), text_size=4) header.add_image(CALENDAR_40_40, 40, 40, align=ALIGN_RIGHT) content_root = Row(parent=root, layout_height=480, wrap_content=False, outline=True) content = Column(parent=content_root, wrap_content=False) content.add_spacer(10, outline=True) content.add_spacer(20) for event in events: summary = event.summary duration_info = None if event.start_at: include_day = not event.start_at.is_today() duration_info = 'At %s' % (event.start_at.formatted( include_day=include_day)) elif event.end_at: duration_info = 'Ends at %s' % (event.end_at.formatted( include_day=True, include_time=False)) content.add_text_content(summary) if duration_info: content.add_text_content(duration_info) content.add_spacer(height=15) content_root.add_node(content) status = Row(parent=root, layout_height=40, wrap_content=False, outline=True) status.add_text_content(sync_at_message, align=ALIGN_RIGHT) root.add_node(header) root.add_node(content_root) root.add_node(status) self._draw(root)