class NumberInputWindow(Dialog): MAX_VALUE = 999999.99 def __init__(self, parent, title=u"NumberInput"): Dialog.__init__(self, parent, title=title, size=(320, 240), style=BORDER_NONE) pnl = NumberInputWindowPanel(self) self.Bind(EVT_BUTTON, pnl.on_input_callback, pnl.keypad_0) self.Bind(EVT_BUTTON, pnl.on_input_callback, pnl.keypad_1) self.Bind(EVT_BUTTON, pnl.on_input_callback, pnl.keypad_2) self.Bind(EVT_BUTTON, pnl.on_input_callback, pnl.keypad_3) self.Bind(EVT_BUTTON, pnl.on_input_callback, pnl.keypad_4) self.Bind(EVT_BUTTON, pnl.on_input_callback, pnl.keypad_5) self.Bind(EVT_BUTTON, pnl.on_input_callback, pnl.keypad_6) self.Bind(EVT_BUTTON, pnl.on_input_callback, pnl.keypad_7) self.Bind(EVT_BUTTON, pnl.on_input_callback, pnl.keypad_8) self.Bind(EVT_BUTTON, pnl.on_input_callback, pnl.keypad_9) self.Bind(EVT_BUTTON, pnl.on_input_callback, pnl.keypad_00) self.Bind(EVT_BUTTON, pnl.on_delete, pnl.keypad_del) self.Bind(EVT_BUTTON, self.on_confirm, pnl.keypad_confirm) self.Bind(EVT_BUTTON, self.on_cancel, pnl.keypad_cancel) self.pnl = pnl # self._set_panel(pnl) self._sizer = BoxSizer() self._sizer.Clear() self._sizer.Add(self.pnl) self.SetSizer(self._sizer) def on_confirm(self, e): self.pnl.on_confirm(None) self.EndModal(ID_OK) def on_cancel(self, e): self.pnl.on_cancel(None) self.EndModal(ID_CANCEL) def get_result(self): return self.pnl.get_result() def get_value(self): return self.pnl.get_value()
class EntryListDialog(Dialog): def __init__(self, parent): Dialog.__init__(self, parent, title=u"Entries", size=(320, 240), style=BORDER_NONE) pnl = EntryListWindowPanel(self) self._pnl = pnl self._sizer = BoxSizer() self._sizer.Clear() self._sizer.Add(self._pnl) self.SetSizer(self._sizer)
class CategoryInputWindow(Dialog): def __init__(self, parent, title=u"Categories", categories=[]): Dialog.__init__(self, parent, title=title, size=(320, 240), style=BORDER_NONE) pnl = CategoryInputWindowPanel(self, title, categories) self.pnl = pnl self._sizer = BoxSizer() self._sizer.Clear() self._sizer.Add(self.pnl) self.SetSizer(self._sizer) def get_value(self): return self.pnl.get_value()
class PrefPanel(SimplePanel): def __init__(self, parent, content=None, title='', buttonlabel='', buttoncb=None, titlemaker=None, prefix=''): SimplePanel.__init__(self, parent, wx.FULL_REPAINT_ON_RESIZE) sizer = self.Sizer = BoxSizer(VERTICAL) self.headersizer = BoxSizer(HORIZONTAL) self.bodysizer = BoxSizer(VERTICAL) sizer.Add(self.headersizer, 0, EXPAND | TOP, space_over_header) sizer.Add(self.bodysizer, 1, EXPAND | TOP, space_under_header) self.title = None self.combo = None self.button = None self.content = None self.contents = {} self.titlemaker = titlemaker if wxMac: self.menuitems = {} if title and isinstance(title, basestring): self.title = wx.StaticText(self, -1, ' ' + title + ' ', style=wx.ALIGN_CENTER_VERTICAL) #need grey backgound behind label on mac to hide the line if wxMac: self.title.BackgroundColour = wx.Color(232, 232, 232) self.title.Font = self.HeaderFont self.headersizer.Add(self.title, 0, *header_sizer_flags) if callable(content): content = self.content = content(self, prefix) self.bodysizer.Add(self.content, 1, pref_sizer_style, 7) elif isinstance(content, wx.WindowClass): content.Reparent(self) self.content = content self.bodysizer.Add(self.content, 1, pref_sizer_style, 7) elif isinstance(content, list): self.SetContents(content) if buttoncb: self.SetButton(buttonlabel, buttoncb) Bind = self.Bind Bind(wx.EVT_PAINT, self.OnPaint) #darker border if mac so it is visible for now if not wxMac: self.pen = wx.Pen(wx.Colour(213, 213, 213)) else: self.pen = wx.Pen(wx.Colour(155, 155, 155)) def SetTitle(self, title): self.title.SetLabel(title) @property def HeaderFont(self): try: return self._headerfont except AttributeError: if not wxMac: PrefPanel._headerfont = makeFont('arial 8 bold') else: PrefPanel._headerfont = makeFont('9 bold') return self._headerfont _fg_brush = \ _bg_brush = \ _fg_pen = \ _bg_pen = lambda self: None def get_bg_brush(self): return self._bg_brush() or wx.WHITE_BRUSH def get_fg_brush(self): return self._fg_brush() or wx.TRANSPARENT_BRUSH def get_bg_pen(self): return self._bg_pen() or wx.TRANSPARENT_PEN def get_fg_pen(self): return self._fg_pen() or self.pen bg_brush = property(get_bg_brush) fg_brush = property(get_fg_brush) bg_pen = property(get_bg_pen) fg_pen = property(get_fg_pen) def OnPaint(self, event): size = self.Size dc = AutoDC(self) if not wxMac: # Non mac: white background, rounded rectangle around controls rect = wx.RectS(size) dc.Brush = self.bg_brush #background dc.Pen = self.bg_pen #background border dc.DrawRectangleRect(rect) ypos = self.headersizer.Size.height // 2 + space_over_header gc = wx.GraphicsContext.Create(dc) gc.SetBrush(self.fg_brush) #foreground gc.SetPen(self.fg_pen) #foreground gc.DrawRoundedRectangle(0, ypos, size.width - 1, size.height - ypos - 1, 5) else: # Mac: normal grey background, horizontal line above controls ypos = self.headersizer.Size.height // 2 + space_over_header + 2 dc.Pen = self.fg_pen button_width = 0 if self.button is None else ( self.button.Size.width) dc.DrawLine(10, ypos, self.headersizer.Size.width - 10 - button_width, ypos) content = self.content if isinstance(content, AnyList): # TODO: don't special case crect = wx.Rect(*content.Rect) crect = crect.Inflate(1, 1) dc.SetBrush(wx.TRANSPARENT_BRUSH) dc.SetPen(self.pen) dc.DrawRectangleRect(crect) def ChangeShownContent(self, *a): if self.content: self.content.Show(False) if wxMac: menu_item = self.menuitems[self.combo.GetStringSelection()] else: menu_item = self.combo.Value self.content = self.contents[menu_item] self.content.Show(True) self.Layout() def SetButton(self, label, callback): if self.button: self.headersizer.Detach(self.button) self.button.Destroy() # native button on mac instead of the vista clone button if not wxMac: self.button = UberButton(self, -1, label, skin='AppDefaults.PrefButton') else: self.button = wx.Button(self, -1, label) self.button.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) self.button.Bind(wx.EVT_BUTTON, lambda e: callback(self.button)) self.headersizer.AddStretchSpacer(1) self.headersizer.Add(self.button, 0, wx.ALIGN_CENTER_VERTICAL | RIGHT, 7) @property def MenuItems(self): combo = self.combo if wxMac: return [combo.GetClientData(i) for i in xrange(combo.Count)] else: return combo.menu.spine.items def SetContents(self, content, destroyold=False): if destroyold: if not self.contents: self.content.Destroy() for content in self.contents.values(): content.Destroy() # the currently showing pane in a multiple pane pref panel if self.content: self.content.Show(False) self.content = None self.bodysizer.Clear() contents = self.contents = {} titlemaker = self.titlemaker if self.combo is None: if not wxMac: self.combo = UberCombo(self, value='', skinkey='AppDefaults.PrefCombo', valuecallback=self.ChangeShownContent) else: # use a native ComboBox on mac self.combo = wx.ComboBox(self, style=wx.CB_DROPDOWN | wx.CB_READONLY) self.combo.Bind(wx.EVT_COMBOBOX, self.ChangeShownContent) newcombo = True else: self.combo.RemoveAllItems() newcombo = False for object in content: if isinstance(object, tuple): window, label = object elif isinstance(object, wx.WindowClass): window = object label = titlemaker(window) if titlemaker else object.Label window.Show(False) window.Reparent(self) assert window.Parent is self self.bodysizer.Add(window, 1, pref_sizer_style, 7) menuitem = SimpleMenuItem(label) contents[menuitem] = window if wxMac: itemname = menuitem.GetContentAsString() self.combo.Append(itemname) self.menuitems[itemname] = menuitem else: self.combo.AppendItem(menuitem) if self.combo: if wxMac: self.combo.SetSelection(0) self.ChangeShownContent() else: self.combo.Value = self.combo[0] if self.combo is not None and newcombo: self.headersizer.Add(self.combo, 1, *combo_sizer_flags)
class ContentsDisplay(ScrolledPanel): def __init__(self, main_window, timer_display, parent, id=-1, pos=DefaultPosition, size=DefaultSize, style=TAB_TRAVERSAL, name='scrolledpanel'): super().__init__(parent, id=id, pos=pos, size=size, style=style, name=name) self.main_window = main_window self.timer_display = timer_display self.contents_panel_list = [] self.layout() def layout(self): self.SetupScrolling(scroll_x=False) self.vbox = BoxSizer(VERTICAL) self.SetSizer(self.vbox) def add_contents_panel(self): time = self.timer_display.maneger.get_elapsed_time() contents = Contents(time, '') contents_panel = ContentsPanel(contents, parent=self, size=(WINDOW_WIDTH - 40, 100)) self.contents_panel_list.append(contents_panel) self.vbox.Add(contents_panel, 1, EXPAND | FIXED_MINSIZE) self.SetupScrolling(scrollToTop=False) self.ScrollChildIntoView(contents_panel) self.Layout() self.Refresh() def remove_contents_panel(self, contents_panel): index = self.contents_panel_list.index(contents_panel) self.contents_panel_list.remove(contents_panel) self.vbox.Hide(contents_panel) self.vbox.Remove(index) self.SetupScrolling(scrollToTop=False) self.Layout() self.Refresh() self.main_window.preview_window.update() def reset(self): for contents in self.contents_panel_list: contents.Hide() self.vbox.Clear() self.contents_panel_list = [] self.SetupScrolling(scrollToTop=False) def convert_string(self, space_length, wrap_length, newline_count): ret = '' for contents_panel in self.contents_panel_list: contents = contents_panel.contents total_seconds = contents.time.seconds h, m, s = map(str, get_hms(total_seconds)) time_formatted = '{}:{}:{}'.format(h.zfill(2), m.zfill(2), s.zfill(2)) indent_length = self.__count_east_asian_width( time_formatted) + space_length cap = contents.caption line = time_formatted + ' ' * space_length + cap ret += self.__text_wrap(line, indent_length, wrap_length) + '\n' * (newline_count + 1) return ret def __text_wrap(self, s, indent_length=0, wrap_length=80): indent = ' ' * indent_length count = 0 for n, c in enumerate(s): count += self.__count_east_asian_width(c) if count > wrap_length: return s[:n] + '\n' + self.__text_wrap( indent + s[n:], indent_length, wrap_length) if c == '\n': return s[:n + 1] + self.__text_wrap(indent + s[n + 1:], indent_length, wrap_length) return s def __count_east_asian_width(self, s): return sum(2 if east_asian_width(c) in 'FWA' else 1 for c in s) def export(self): sm = self.main_window.sm message = get_data_safety(sm.language, 'Save As...', 'Save As...') file_path = choose_file(self.main_window, message) if file_path is None: return space_length, wrap_length, newline_count = sm.formmat_parameter with open(file_path, mode='x') as f: f.write( self.convert_string(space_length, wrap_length, newline_count))