def __init__(self, parent, viewer): wx.Panel.__init__(self, parent) self.viewer = viewer # construct find_label = wx.StaticText(self, -1, _('Find')) self.TextControl = find_input = wx.TextCtrl(self, -1, size = (180, -1), style = wx.TE_PROCESS_ENTER) nextbutton = self.nextbutton = UberButton(self, label = _('Next'), skin = 'AppDefaults.PastButton') prevbutton = self.prevbutton = UberButton(self, label = _('Prev'), skin = 'AppDefaults.PastButton') # layout sz = self.Sizer = wx.BoxSizer(wx.HORIZONTAL) sz.AddMany([(find_label, 0, TOP | BOTTOM | LEFT | ALIGN_CENTER_VERTICAL | ALIGN_RIGHT, 6), (find_input, 0, TOP | BOTTOM | LEFT | ALIGN_CENTER_VERTICAL , 6), (nextbutton, 0, TOP | BOTTOM | LEFT | ALIGN_CENTER_VERTICAL | EXPAND , 6), (prevbutton, 0, TOP | BOTTOM | LEFT | ALIGN_CENTER_VERTICAL | EXPAND , 6)]) self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) Bind = self.Bind Bind(wx.EVT_PAINT, self.OnPaint) self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) fiBind = find_input.Bind fiBind(wx.EVT_TEXT, self.OnFindText) fiBind(wx.EVT_KEY_DOWN, self.OnFindKey) nextbutton.Bind(wx.EVT_BUTTON, self.OnFindText) prevbutton.Bind(wx.EVT_BUTTON, lambda e: self.OnFindText(e,False)) self.EnableFindButtons('')
def buttons(parent): yahoo = skin.load_bitmap('../../protocols/yahoo.png') s = 'button' b1 = UberButton(parent, -1, 'Skinned', skin=s) b2 = UberButton(parent, -1, 'Native', skin=None) b3 = UberButton(parent, -1, 'SkinnedPic', skin=s, icon=yahoo) b4 = UberButton(parent, -1, 'NativePic', skin=None, icon=yahoo) return [b1, b2, b3, b4]
def __init__(self, parent, skinkey): SimplePanel.__init__(self, parent) self.tabs = [] # a list of all the tabs self.rows = [] # a list of all the visible row, each a list of all the tabs in that row self.rowindex = 0 # the first visible row self.tabindex = 0 # the first tab of the first visible row self.tabendex = 0 # the last tab of the last visible row events = [(wx.EVT_PAINT, self.OnPaint), (wx.EVT_SIZE, self.OnSize), (wx.EVT_BUTTON, self.OnButton), (wx.EVT_MOUSEWHEEL, self.OnWheel), (wx.EVT_MOTION,self.OnMotion)] for event, method in events: self.Bind(event, method) self.flagedrows = set() self.lastsize=self.Size self.rowheight=0#height of a row in pixels self.SetSkinKey(skinkey,True) #buttons for verticle alignment self.cupb = UberButton(self, CUPID, skin=self.scrollbuttonskin, icon=self.upicon) self.cupb.Show(False) self.cdownb = UberButton(self, CDOWNID, skin=self.scrollbuttonskin, icon=self.downicon) self.cdownb.Show(False) #the navigation box self.navi=Navi(self) self.dragorigin = None#when draging the tab that you are dragging self.dragtarget = None#when dragging the mouse is over and at that point released on # the arrow image shown when dragging tabs self.dropmarker=OverlayImage(self, self.dropmarkerimage) # self.dropmarker = Storage(Show = lambda v=True: None) self.dragside=None#was the tab droped on the left or right of the target tab #linking prefs link = profile.prefs.link #@UndefinedVariable link('tabs.rows', self.Generate, False) link('tabs.tabbar_x', self.Generate, False) link('tabs.hide_at_1', self.Generate, False) link('tabs.side_tabs', self.SkinRedirect, False) self.Top.Bind(wx.EVT_MENU, self.OnMenuEvent)
def __init__(self, parent, xferlist): wx.Panel.__init__(self, parent) self.xferlist = xferlist self.Sizer = s = wx.BoxSizer(wx.VERTICAL) ftlist = FileTransferList(self, xferlist) s.Add(ftlist, 1, wx.EXPAND | wx.ALL) from gui.uberwidgets.UberBar import UberBar bar = self.bar = UberBar( self, skinkey=skin.get('FileTransfers.CleanupTaskBar'), alignment=wx.ALIGN_RIGHT) s.Add(self.bar, 0, wx.EXPAND) bar.AddStretchSpacer(1) self.cleanup = cleanup = UberButton(bar, -1, _('Clean Up')) cleanup.Bind(wx.EVT_BUTTON, self.on_cleanup) # button disabled when there are no transfers cleanup.Enable(bool(xferlist)) xferlist.add_gui_observer(self.on_xfer) self.Bind(wx.EVT_WINDOW_DESTROY, lambda e, w=self: self.xferlist.remove_observer(self.on_xfer) if e.EventObject is w else None) bar.Add(cleanup)
def __init__(self): wx.Frame.__init__(self, None, title='Simple Menu Test') self.panel = wx.Panel(self) self.panel.Sizer = wx.BoxSizer(wx.VERTICAL) menu = SimpleMenu(self, skinkey='simplemenu', maxheight=10, width=100) items = [ SimpleMenuItem('Test1'), #,self.DifferentMethodTest), SimpleMenuItem('Test2'), SimpleMenuItem('Test3'), SimpleMenuItem(id=-1), SimpleMenuItem('Test4') ] menu.SetItems(items) skin = 'button' size = None #(100,100)# type = 'menu' #None#'toggle'# #menu=None#self.menu# icon = None #wx.Bitmap('../../../res/skins/default/statusicons/mobile.png',wx.BITMAP_TYPE_PNG)#wx.Bitmap('../../res/skins/default/tinydigsby.png',wx.BITMAP_TYPE_PNG) self.smb1 = UberButton(self.panel, wx.NewId(), "SMB", skin, icon=icon, style=wx.HORIZONTAL, size=size, type=type, menu=menu) self.panel.Sizer.Add(self.smb1)
def __init__(self, parent): SimplePanel.__init__(self, parent, wx.FULL_REPAINT_ON_RESIZE) content = self.content = wx.BoxSizer(wx.VERTICAL) self.SetSkinKey('AccountPanels', True) cl = self.cl = ConnectionList(self) content.Add(cl, 1, wx.EXPAND) statebutton = self.statebutton = UberButton(self, icon=self.iconshow, skin=self.buttonskin) self.button_has_been_pressed = False statebutton.Bind(wx.EVT_BUTTON, self.__OnButtonClick) if self.expandup: content.Add(statebutton, 0, wx.EXPAND) else: content.Insert(0, statebutton, 0, wx.EXPAND) self.Sizer = MarginSizer(self.framesize, content) Bind = self.Bind Bind(wx.EVT_SIZE, self.OnSize) Bind(wx.EVT_PAINT, self.OnPaint) profile.prefs.add_observer(self.WhenOrderChanges, 'buddylist.order') #@UndefinedVariable
def __init__(self): wx.Frame.__init__(self,None,title='Extended Simple Menu Test') self.panel=wx.Panel(self) self.panel.Sizer=wx.BoxSizer(wx.VERTICAL) menu=SimpleMenu(self, 'simplemenu',width=100) submenu=SimpleMenu(menu, 'simplemenu',width=100) submenu2=SimpleMenu(submenu, 'simplemenu',width=100) subitems=[ SimpleMenuItem('Test5'), SimpleMenuItem(id=-1), SimpleMenuItem('Test6'), SimpleMenuItem('Test7',menu=submenu2), SimpleMenuItem('Test8') ] submenu.SetItems(subitems) items=[ SimpleMenuItem('Test1'), SimpleMenuItem('Test2'), SimpleMenuItem("Test3 is a submenu m'kay",menu=submenu), SimpleMenuItem(id=-1), SimpleMenuItem('Test4'), ] items3=[ SimpleMenuItem('Test9'), SimpleMenuItem('Test10'), SimpleMenuItem('Test11'), SimpleMenuItem('Test12'), SimpleMenuItem('Test13'), SimpleMenuItem('Test14'), SimpleMenuItem('Test15'), SimpleMenuItem('Test16'), SimpleMenuItem('Test17') ] submenu2.SetItems(items3) menu.SetItems(items) skin='button' size=None#(100,100)# type='menu'#None#'toggle'# #menu=None#self.menu# icon=wx.Bitmap('../../../res/skins/default/statusicons/mobile.png',wx.BITMAP_TYPE_PNG)#wx.Bitmap('../../res/skins/default/tinydigsby.png',wx.BITMAP_TYPE_PNG) self.smb1=UberButton(self.panel,wx.NewId(),"SMB",skin,icon=icon,style=wx.HORIZONTAL,size=size,type=type,menu=menu) self.panel.Sizer.Add(self.smb1) self.Bind(wx.EVT_MENU,self.OnMenu)
def CreateSendButton(self): self.spacer = SpacerPanel(self, skinkey='inputspacer') self.inputsizer.Add(self.spacer, 0, wx.EXPAND) sendbutton = self.sendbutton = UberButton( self, label=_('Send'), skin='InputButton') #wx.Button(self, label = _('Send')) self.inputsizer.Add(sendbutton, 0, wx.EXPAND) sendbutton.Bind(wx.EVT_BUTTON, lambda e: self.entercallback(self))
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)
def __init__(self, parent): """ standard fair """ wx.Panel.__init__(self, parent, style=0) events=[ (wx.EVT_PAINT,self.OnPaint), (wx.EVT_ERASE_BACKGROUND, lambda e:None), (wx.EVT_BUTTON, self.OnButton) ] do(self.Bind(event, method) for (event, method) in events) #make sizers self.Sizer=wx.BoxSizer(wx.HORIZONTAL) self.hsizer=wx.BoxSizer(wx.HORIZONTAL) self.vsizer=wx.BoxSizer(wx.VERTICAL) #make Buttons self.closebutton=UberButton(self, CLOSEID, skin=self.Parent.closebuttonskin, icon=self.Parent.closeicon) self.prevb=UberButton(self, PREVID, skin=self.Parent.scrollbuttonskin, icon=self.Parent.lefticon) self.nextb=UberButton(self, NEXTID, skin=self.Parent.scrollbuttonskin, icon=self.Parent.righticon) self.upb=UberButton(self, UPID, skin=self.Parent.scrollbuttonskin, icon=self.Parent.upicon) self.downb=UberButton(self, DOWNID, skin=self.Parent.scrollbuttonskin, icon=self.Parent.downicon) #add butons to sizers self.hsizer.Add(self.prevb, 0, wx.EXPAND) self.hsizer.Add(self.nextb, 0, wx.EXPAND) self.vsizer.Add(self.upb, 1, wx.EXPAND) self.vsizer.Add(self.downb, 1, wx.EXPAND) self.Sizer.Add(self.hsizer, 0, wx.EXPAND) self.Sizer.Add(self.closebutton, 0, wx.CENTER|wx.ALL, 5) #Hide all buttons self.prevb.Show(False) self.nextb.Show(False) self.upb.Show(False) self.downb.Show(False) self.closebutton.Show(pref('tabs.tabbar_x', False)) self.type=None
def _constructSkinElements(self): 'Creates the buttons that launch menu dropdowns in the bar.' s, p = self.skin, self.panel p.bg = s.get("background", SkinColor(wx.WHITE)) pad = p.padding = s.get("padding", wx.Point(0, 0)) for child in list(p.Children): child.Hide() child.Destroy() v = wx.BoxSizer(wx.VERTICAL) h = wx.BoxSizer(wx.HORIZONTAL) v.Add(h, 1, wx.EXPAND | wx.TOP | wx.BOTTOM, pad.y) p.Sizer = s.get('margins', Margins()).Sizer(v) # create a button for each item in the menubar self.buttons = [] addb = self.buttons.append menus, nummenus = self.Menus, len(self.Menus) for i, (menu, label) in enumerate(menus): del menu.OnDismiss[:] # the API sucks for getting Titles with mnemonic characters label = self.toptitles.get(menu, label) # (self, parent, id = -1, label='', skin='Button', icon=None, # pos=wx.DefaultPosition, size=None, style=wx.HORIZONTAL, # type=None, menu=None, menubarmode=False, onclick = None): button = UberButton(p, -1, skin=s.itemskin, label=label, type="menu", menu=menu, menubarmode=True) addb(button) # store some special attributes in the menu, which it will use for # keyboard/mouse navigation of the menubar menu._next = menus[(i + 1) % nummenus][0] menu._prev = menus[i - 1][0] menu._button = button # add buttons to the size h.AddMany((b, 0, wx.EXPAND | wx.LEFT, pad.x) for b in self.buttons) # bind keyboard accelerators self._bindAccelerators()
def main(): a = testapp() f = wx.Frame(None) bar = UberBar(f, skinkey='ButtonBarSkin', overflowmode=True) for x in xrange(5): title = 'test %d' % x b = UberButton(bar, -1, title) bar.Add(b) f.Show() a.MainLoop()
def __init__(self): wx.Frame.__init__(self, None, wx.NewId(), "UberBar sampler", (0, 0), (600, 150)) events = [ #(wx.EVT_BUTTON,self.onButton) ] do(self.Bind(event, method) for (event, method) in events) content = wx.BoxSizer(wx.VERTICAL) self.skin = 'buttonbar' #None# self.ubar = UberBar(self, skinkey=self.skin, alignment=wx.ALIGN_LEFT) self.b1 = UberButton(self.ubar, -1, 'Button 1', icon=wx.Bitmap( resdir / 'skins/default/digsbybig.png', wx.BITMAP_TYPE_PNG)) self.b2 = UberButton(self.ubar, -1, 'Button 2', style=wx.VERTICAL, icon=wx.Bitmap( resdir / 'skins/default/digsbybig.png', wx.BITMAP_TYPE_PNG)) self.b3 = UberButton(self.ubar, -1, 'Button 3', icon=wx.Bitmap( resdir / 'skins/default/digsbybig.png', wx.BITMAP_TYPE_PNG)) self.ubar.Add(self.b1) self.ubar.Add(self.b2) self.ubar.AddSpacer() self.ubar.Add(self.b3) content.Add(self.ubar, 0, wx.EXPAND, 0) self.SetSizer(content)
class F4(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, wx.NewId(), "UberBar Overflow sampler", (0, 0), (600, 150)) content = wx.BoxSizer(wx.VERTICAL) self.skin = 'buttonbar' #None# self.ubar = UberBar(self, skinkey=self.skin, overflowmode=True, alignment=wx.ALIGN_LEFT) self.b1 = UberButton(self.ubar, -1, 'Button 1') self.b2 = UberButton(self.ubar, -1, 'Button 2') self.bi = UberButton(self.ubar, -1, 'Button i') self.b3 = UberButton(self.ubar, -1, 'Button 3') self.b4 = UberButton(self.ubar, -1, 'Button 4') self.ubar.Add(self.b1) self.ubar.Add(self.b2) self.ubar.Add(self.bi) self.ubar.Add(self.b3) self.ubar.Add(self.b4) # self.b1.Show(self.b1,False) self.bi.Show(self.bi, False) self.ubar.AddMenuItem(SimpleMenuItem('Menu Item 1')) self.ubar.AddMenuItem(SimpleMenuItem('Menu Item 2')) self.ubar.AddMenuItem(SimpleMenuItem('Menu Item 3')) self.b4 = UberButton(self.ubar, -1, icon=wx.Bitmap( resdir / 'skins/default/digsbybig.png', wx.BITMAP_TYPE_PNG)) self.ubar.AddStatic(self.b4) content.Add(self.ubar, 0, wx.EXPAND, 0) self.SetSizer(content)
def __init__(self, parent, buddylist, statuses, get_status_method=get_profile_status, set_status_method=set_profile_status): ''' StatusCombo constructor. parent - a wx.Window parent window statuses - an observable list of StatusMessage objects ''' self.buddylist = buddylist self.buddylist.Bind(wx.EVT_KEY_DOWN, self.on_buddylist_key) self.searching = False self.searchHintShown = False if not getattr(StatusCombo, 'searchThresholdRegistered', False) and pref('search.buddylist.show_hint', True): def SearchThresholdReached(*a, **k): if pref('search.buddylist.show_hint', True): setpref('search.buddylist.show_hint', False) Hook('digsby.achievements.threshold', 'buddylist.search').register(SearchThresholdReached) StatusCombo.searchThresholdRegistered = True self.offline_item = None self.get_profile_status = get_status_method self.set_profile_status = set_status_method status = self.get_profile_status() UberCombo.__init__(self, parent, skinkey='combobox', typeable=True, valuecallback=self.on_text_lose_focus, empty_text=getattr(status, 'hint', status.title.title()), maxmenuheight=15) self.buttoncallback = self.on_status_button self.cbutton = UberButton(self, -1, skin=self.cbuttonskin) self.cbutton.Bind(wx.EVT_BUTTON, self._on_left_button) self.content.Insert(0, self.cbutton, 0, wx.EXPAND) self.cbutton.BBind(RIGHT_UP=self.on_status_button_right_click, LEFT_DOWN=self.on_status_button_left_click, LEFT_UP=self.on_status_button_left_up) self.display.Bind( wx.EVT_LEFT_DOWN, lambda e: (e.Skip(), setattr(self, 'oldValue', self.Value))) # the on_allow_status_changes method is called when the list of connected # im accounts changes size. if all accounts are offline this control # becomes disabled.. #profile.account_manager.connected_accounts.add_observer(self.on_allow_status_changes) profile.account_manager.connected_accounts.add_observer( self.on_offline_allowed, obj=self) # Listen on status messages (changes, additions, deletes). _obs_link = statuses.add_list_observer(self.on_status_messages_changed, self.on_status_messages_changed) self.Bind( wx.EVT_WINDOW_DESTROY, lambda e: (log.info('status combo removing observers'), e.Skip(), _obs_link.disconnect())) self.on_status_messages_changed(statuses) # when the profile's status changes, update to reflect it profile.add_observer(self.on_profile_status_changed, 'status') # Display the current status. self.show_status(self.get_profile_status()) # Timer for committing status messages after a delay. self.timer = wx.PyTimer(self.SetFocus) self.Bind(wx.EVT_TEXT, self.on_typing) self.button_timer = wx.PyTimer(self.on_status_button_right_click) textbind = self.TextField.Bind textbind(wx.EVT_SET_FOCUS, lambda e: setattr(self, 'skipenter', False)) textbind(wx.EVT_KEY_DOWN, self._on_key_down) textbind(wx.EVT_TEXT_ENTER, self._on_enter) self.DropDownButton.Bind(wx.EVT_LEFT_DOWN, self._dbutton_left) self.OnActivateSearch = Delegate() self.OnDeactivateSearch = Delegate()
bitmap = skin.load_bitmap('error.png') b = UButton(p, label = '&Digsby', bitmap = bitmap); s.Add(b) b.Bind(wx.EVT_BUTTON, lambda e, but=b: setattr(but, 'Native', not getattr(but, 'Native'))) b = UButton(p, label = 'Digsby &Rocks', bitmap = bitmap); s.Add(b) b = UButton(p, label = '&Exact Fit', style = wx.BU_EXACTFIT); s.Add(b) b = UButton(p, label = '&Cancel'); s.Add(b) b = UButton(p, label = 'Disab&led'); s.Add(b); b.Enable(False) b = UButton(p, label = 'Digs&by', bitmap = bitmap, style = wx.BU_RIGHT, menuMode = True); s.Add(b, 0, wx.EXPAND) b = UButton(p, label = 'Digsby Rocks', bitmap = bitmap, style = wx.BU_RIGHT); s.Add(b, 0, wx.EXPAND) b = UButton(p, label = '&OK'); s.Add(b, 0, wx.EXPAND) b = UButton(p, label = 'Cancel'); s.Add(b, 0, wx.EXPAND) s.AddSpacer((30,30)) from gui.uberwidgets.UberButton import UberButton hs = wx.BoxSizer(wx.HORIZONTAL) for x in xrange(4): b = UberButton(p, label = 'UberButton'); hs.Add(b, 1, wx.EXPAND) s.Add(hs, 0, wx.EXPAND) def printsrc(e): print e.EventObject p.Bind(wx.EVT_BUTTON, printsrc) f.Show() a.MainLoop()
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 TabBar(SimplePanel, UberWidget): """ Where the tabs live, handles all display and organization functionality """ def __init__(self, parent, skinkey): SimplePanel.__init__(self, parent) self.tabs = [] # a list of all the tabs self.rows = [] # a list of all the visible row, each a list of all the tabs in that row self.rowindex = 0 # the first visible row self.tabindex = 0 # the first tab of the first visible row self.tabendex = 0 # the last tab of the last visible row events = [(wx.EVT_PAINT, self.OnPaint), (wx.EVT_SIZE, self.OnSize), (wx.EVT_BUTTON, self.OnButton), (wx.EVT_MOUSEWHEEL, self.OnWheel), (wx.EVT_MOTION,self.OnMotion)] for event, method in events: self.Bind(event, method) self.flagedrows = set() self.lastsize=self.Size self.rowheight=0#height of a row in pixels self.SetSkinKey(skinkey,True) #buttons for verticle alignment self.cupb = UberButton(self, CUPID, skin=self.scrollbuttonskin, icon=self.upicon) self.cupb.Show(False) self.cdownb = UberButton(self, CDOWNID, skin=self.scrollbuttonskin, icon=self.downicon) self.cdownb.Show(False) #the navigation box self.navi=Navi(self) self.dragorigin = None#when draging the tab that you are dragging self.dragtarget = None#when dragging the mouse is over and at that point released on # the arrow image shown when dragging tabs self.dropmarker=OverlayImage(self, self.dropmarkerimage) # self.dropmarker = Storage(Show = lambda v=True: None) self.dragside=None#was the tab droped on the left or right of the target tab #linking prefs link = profile.prefs.link #@UndefinedVariable link('tabs.rows', self.Generate, False) link('tabs.tabbar_x', self.Generate, False) link('tabs.hide_at_1', self.Generate, False) link('tabs.side_tabs', self.SkinRedirect, False) self.Top.Bind(wx.EVT_MENU, self.OnMenuEvent) side_tabs = prefprop('tabs.side_tabs') tab_rows = prefprop('tabs.rows', 2) def UpdateSkin(self): key = self.tabskin = self.skinkey g = lambda k, default = sentinel: skin.get(key + '.' + k, default) sg = lambda k, default = sentinel: skin.get('side' + key + '.' + k, default) elems = (('spacing', 'spacing', 2), ('bg', 'backgrounds.bar'), ('dropmarkerimage', 'dropmarker.image'), # ('dropmarkeroverlay', 'dropmarker.overlay', 0), ('dropmarkeroffset', 'dropmarker.offset', 0), ('closebuttonskin', 'closebuttonskin', ''), ('closeicon', 'icons.close', None), ('scrollbuttonskin', 'scrollbuttonskin', ''), ('lefticon', 'icons.left', ''), ('righticon', 'icons.right', ''), ('upicon', 'icons.up', ''), ('downicon', 'icons.down', '')) for elem in elems: setattr(self, 'top' + elem[0], g(*elem[1:])) setattr(self, 'side' + elem[0], sg(elem[1],getattr(self,'top' + elem[0]))) setattr(self, elem[0], getattr(self, ('side' if self.side_tabs else 'top') + elem[0])) if hasattr(self,'dropmarker'): self.dropmarker.SetImage(self.dropmarkerimage) self.dropmarker.SetRotation((self.side_tabs and not self.dropmarkerimage)) navi = getattr(self, 'navi', None) if navi is not None: self.cdownb.SetSkinKey(self.scrollbuttonskin) self.cupb.SetSkinKey(self.scrollbuttonskin) self.cdownb.SetIcon(self.downicon) self.cupb.SetIcon(self.upicon) self.navi.closebutton.SetSkinKey(self.closebuttonskin) self.navi.closebutton.SetIcon(self.closeicon) scrollskin = self.scrollbuttonskin navi.prevb.SetSkinKey(scrollskin) navi.nextb.SetSkinKey(scrollskin) navi.upb.SetSkinKey(scrollskin) navi.downb.SetSkinKey(scrollskin) navi.prevb.SetIcon(self.lefticon) navi.nextb.SetIcon(self.righticon) navi.upb.SetIcon(self.upicon) navi.downb.SetIcon(self.downicon) wx.CallAfter(self.Generate) def SkinRedirect(self,val=None): elems = ('spacing', 'bg', 'dropmarkerimage', #'dropmarkeroverlay', 'closebuttonskin', 'closeicon', 'scrollbuttonskin', 'lefticon', 'righticon', 'upicon', 'downicon' ) for elem in elems: setattr(self, elem, getattr(self,('side' if self.side_tabs else 'top') + elem)) self.UpdateChildSkins() def UpdateChildSkins(self): self.cdownb.SetSkinKey(self.scrollbuttonskin,True) self.cupb.SetSkinKey(self.scrollbuttonskin,True) navi, sbs = self.navi, self.scrollbuttonskin navi.closebutton.SetSkinKey(self.closebuttonskin,True) navi.prevb.SetSkinKey(sbs, True) navi.nextb.SetSkinKey(sbs, True) navi.upb.SetSkinKey(sbs, True) navi.downb.SetSkinKey(sbs, True) self.UpdateChildrenIcons() for tab in self.tabs: tab.UpdateMode() self.Generate() def __repr__(self): return '<TabBar %r>' % self.tabs def OnDragStart(self, tab): 'Catches the tab drag event and starts the tab dragging system.' self.NotifyDrag(tab) def OnMotion(self,event): 'Positioning updates during drag and drop' if event.LeftIsDown() and (self.dragorigin or self.Manager.source): self.DragCalc(event.Position) def __getitem__(self, index): return self.tabs[index] def OnPaint(self, event): dc = wx.PaintDC(self) rect = RectS(self.Size) if not self.side_tabs: rcount = min(len(self.rows), pref('tabs.rows', 2)) height = self.tabs[0].Size.height y=0 for unused_i in xrange(rcount): self.bg.Draw(dc, Rect(rect.x, y, rect.width, height)) y += height else: self.bg.Draw(dc,rect) def Add(self, page, focus, resort = True): """ Adds a tab to the bar. Should only be used by parent NoteBook. page - page in PageContainer the tab is to be associated with focus - whether that tab should steal focus from current tab """ tab = Tab(self, page, skinkey = self.tabskin) tab.Bind(wx.EVT_CONTEXT_MENU, self.ShowMenu) tab.Show(False) self.tabs.append(tab) if focus: wx.CallAfter(tab.SetActive, True) elif resort: if self.side_tabs: self.ReVgenerate() else: self.Regenerate(True) return tab def ShowMenu(self, e): self._menutab = e.EventObject try: menu = self._tabmenu except AttributeError: from gui.uberwidgets.umenu import UMenu menu = self._tabmenu = UMenu(self) menu.AddItem('Close &Other Tabs', id = CLOSE_OTHER_TABS) menu.AddSep() menu.AddItem('&Close Tab', id = CLOSE_TAB) menu.PopupMenu() def OnMenuEvent(self, e): '''Invoked when a tab context menu item is clicked.''' if e.Id == CLOSE_TAB: self._menutab.CloseTab() elif e.Id == CLOSE_OTHER_TABS: menutab = self._menutab # switch to that tab first menutab.active = True with self.Frozen(): for tab in self.tabs[:]: if tab is not menutab: tab.CloseTab() else: e.Skip() def Generate(self, val=None): self.navi.closebutton.Show(pref('tabs.tabbar_x', False)) if self.side_tabs: self.ReVgenerate(True) else: self.Regenerate() def ReVgenerate(self,total=False, safe=False, dotoggle=True): """ It's like Doo... err.. Regenerate, only vertical """ # print "Starting: Regenerate",self.Top.Title,'\n'#,'='*80,'\n','\n'.join(format_stack()) # print '='*80 #TODO: Should we be careful about the tab leaving the bar? tabs = self.tabs if not tabs: return do(tab.Show(False) for tab in self.tabs) for tab in self.tabs: tab.row = None del self.rows[:] # Safty precautions prevent list access errors if self.tabindex < 0 or self.tabindex >= len(tabs): self.tabindex = 0 # Preset variables n = self.tabindex # the first tab shown self.rowheight = tabs[0].GetMinHeight() area = self.Notebook.Size.height - 32 # Height in pixels of the tabbar # number of fully visible rows in the given area at the given height i = area//self.rowheight count = len(tabs) #one tab per row for r in xrange(count): tabs[r].row=r rows = self.rows size = self.Size #Sets navimode and position navi = self.navi navi.ShowNav(4) navi.Hide() navi.Position = wx.Point(size.width - navi.Size.width,0) # Totally reconstructs the list if it's told to or there are not tabs in the rows or # if there isn't one more tab than there is room for and there is enough room to fit # them all and number of tabs in the row equals the number of tabs if total or not rows or (i + 1 != len(rows[0])) and not (i > len(rows[0])) and len(rows[0]) == len(tabs): rows.append([]) col = rows[0] #if all tabs fit if i >= count: n=0 self.tabindex=0 do(col.append(tab) for tab in tabs) av=col[0].MinSize.height #calculate and show range else: for t in xrange(n,n+i+1): if t < len(tabs):col.append(tabs[t]) # populate with earlier stuff while len(col) < i and n > 0: n-=1 col.insert(0,tabs[n]) if col: av = col[0].MinSize.height else: #just leave the new values the same as the old col = rows[0] av = col[0].MinSize.height # Show all tabs in the bar count = 16 for t in col: t.Size = (self.Size.width,av) t.Position = (0,count) count += av t.Show() self.tabindex=n endex = self.tabendex=n+len(col) if dotoggle: self.Toggle() cupb, cdownb = self.cupb, self.cdownb cupb.Enable(self.tabindex != 0) cdownb.Enable(endex < len(tabs) or tabs[endex - 1].Position.y + tabs[endex-1].Size.height > size.height - 16) self.UpdateNotify() def Regenerate(self, safe = False, dotoggle=True): ''' Regenerates layout information. safe is a flag to indicate if we should try to keep the currently active tab in view at all times. (This doesn't occur when scrolling, for instance.) ''' # print "Starting: Regenerate",self.Top.Title,'\n','='*80,'\n','\n'.join(format_stack()) # print '='*80 # early exit for when the tabbar isn't visible. if not self.IsShown() and len(self.tabs) == 1: return with self.Frozen(): self._Regenerate(safe = safe, dotoggle = dotoggle) self.Refresh(False) def _Regenerate(self, safe = False, dotoggle = True): self.cupb.Show(False) self.cdownb.Show(False) parentpage = self.Parent.pagecontainer # style is the number of rows (or 0 for single) style = self.tab_rows # Should we be careful about the tab leaving the bar? careful = not safe and parentpage.active # Hide all tabs preparation for refilling for tab in self.tabs: tab.Show(False) tab.row = None del self.rows[:] # navi set up, see if arrows are needed and placement tally = sum(tab.MinSize.width for tab in self.tabs) #total size of tabs navi = self.navi tabs = self.tabs rows = self.rows if not tabs: return # Tab alignment calculations # Saftey precautions prevent list access errors if self.tabindex < 0 or self.tabindex >= len(tabs): self.tabindex = 0 # Preset variables n = self.tabindex # the first tab shown i = n row = 0 self.rowheight = tabs[0].MinHeight my_w, nav_w = self.Size.width, navi.Size.width # Decide what kind of navigation panel, if any, to use... if tally >= my_w - nav_w and not style: navi.ShowNav(1) # arrows left and right elif tally >= (my_w - nav_w): navi.ShowNav(3) # arrows up and down next to the X else: navi.ShowNav(0) #Where to put navigation panel. navi.Freeze() navi.Show(True) navi.Fit() navi.Position = wx.Point(self.Size.width-navi.Size.width,0) navi.Size = wx.Size(-1,self.Size.height) navi.Thaw() #More preparing vars area = self.Notebook.Size.width - navi.Size.width #While more tabs are not in a row while len(tabs) > i: tally = tabs[i].MinSize.width rows.append([]) # Loop through each visible tab, fitting tabs on the right. while i < len(tabs) and tally < area: i += 1 if i < len(tabs): tally += tabs[i].MinSize.width #Be carefull that the active tab doesn't scroll off the bar if careful and not style: activeindex = tabs.index(parentpage.active.tab) change=False #add tabs until the active tab is visible while activeindex>=i and n!=i: i += 1 tally += tabs[i].MinSize.width change = True #Remove tab if more tabs than room if tally >= area and change: tally -= tabs[n].MinSize.width n += 1 self.tabindex=n # If extra space, fit tabs to the right of the row if not style: # if single row, while n > 0 and area - tally > tabs[n-1].MinSize.width: n -= 1 self.tabindex = n tally += tabs[n].MinSize.width # Injects tabs calculated to fit in that row into that row if range(n, i): rows[row] = [tabs[t] for t in xrange(n, i)] for tab in rows[row]: tab.row=row else: rows[row].append(tabs[i]) i += 1 if not style: break # If we're in single row, break now. row += 1 n = i # Row calculation if self.rowindex >= len(rows): self.rowindex = len(rows) - 1 #cycle through visible rows row = self.rowindex visible = self.tab_rows or 1 if careful and style: #print "Being Careful" active = parentpage.active.tab #print active for ir,r in enumerate(rows): #print ir,r if active in r: if ir<row: #print "moving index down" row = self.rowindex = ir elif ir >= row + visible: #print "moving index up" row = ir - (visible - 1) # If we're closing tabs above where is visible, keep the visible # index "where it is" if len(rows) - (row + 1) < visible and len(rows) >= visible: row = len(rows) - visible self.rowindex = row # Place tabs! while row < len(rows) and row < self.rowindex + visible and len( rows[row] ) != 0: # if this is a row that needs to be scrunched... if rows.index(rows[row]) == len(rows)-1 and \ (style or len(rows[row]) == len(tabs)): for t in xrange(0,len(rows[row])): thistab = rows[row][t] thistab.SetSize(thistab.MinSize) if not t: # The first tab is set to it's minimum width at x: 0 thistab.SetPosition((0, self.rowheight*(row-self.rowindex))) else: # Every other tab is placed right next to the tab # before it. thistab.SetPosition((rows[row][t-1].Position.x \ + rows[row][t-1].Size.width, self.rowheight*(row-self.rowindex))) thistab.Show(True) # If there are more rows than the current row... elif len(rows) > row: # Get a list of tab indices, widest to smallest. ordered = [rows[row].index(t) for t in sorted(rows[row], key=lambda o: o.MinSize.width, reverse=True) ] length = len(ordered) reserved=0 o=0 # o_O ? # Average width of tab if all tabs are the same size, and # fill up all the area. av = (area - reserved) / (length - o) mark = 0 while o < length: # Loop from "current" tab to the end for t in xrange(o, length): tab = rows[row][ordered[t]] # If this tab is larger than average... if tab.GetMinSize()[0] > av: # Make it it's minimum, and keep track of it tab.SetSize(tab.MinSize) reserved += tab.MinSize.width o += 1 mark = o # If we're not on the last tab, recalc average if (length - o): av=(area-reserved)/(length-o) else: o += 1 break # For tabs less than the average, set them to average for t in xrange(mark, length): tab = rows[row][ordered[t]] tab.SetSize((av, tab.MinSize.height)) # For every tab in the row for t, tab in enumerate(rows[row]): if not t: # If it's the first tab: if length==1: # If the row is so small it can only fit one tab, # make due. tab.Size = wx.Size(area, tab.MinSize.height) tab.Position = wx.Point(0, self.rowheight * (row - self.rowindex)) else: tab.Position = wx.Point(rows[row][t-1].Position.x + rows[row][t-1].Size.width, self.rowheight * (row - self.rowindex)) tab.Show(True) row += 1 if dotoggle: self.Toggle() # If total rows is less than total rows being shown, shrink the # tab area so that it's only just big enough. if len(rows) < style or not style: rows_shown = len(rows) else: rows_shown = style if self.Parent.SashPosition != rows_shown * self.rowheight:#self.MinSize.height self.MinSize = wx.Size(-1, rows_shown * self.rowheight) self.Parent.SetSashPosition(self.MinSize.height) # self.Size=self.MinSize # Determine if the Navi needs to enable or show arrows navi.Enabler() #self.Parent.Layout() # Relayout self self.tabendex = i-1 # final tab being shown self.UpdateNotify() navi.Size = wx.Size(-1,rows_shown * self.rowheight) def Remove(self, target): 'Removes the tab specified from the bar.' index=self.tabs.index(target) self.tabs.remove(target) #if no more tabs close window if len(self.tabs)==0: self.Notebook.window.Close() else: #if index is between index and endex and bring one tab from the left if index>self.tabindex and index<self.tabendex and self.tabindex>0: self.tabindex-=1 if self.side_tabs: self.ReVgenerate(total=True) else: self.Regenerate(safe = True) def OnSize(self, event): 'ReLayout the tabs if the bar on event of a resize' event.Skip() if self.side_tabs and self.tabs: cupb = self.cupb cdownb = self.cdownb size = self.Size tabs = self.tabs endex = self.tabendex # position and size buttons cupb.Position = (0,0) cupb.Size = (size.width, 16) cupb.Show() cupb.Enable(self.tabindex != 0) cdownb.Position = (0, size.height - 16) cdownb.Size = (size.width, 16) cdownb.Show() cdownb.Enable(endex < len(tabs) or tabs[endex - 1].Position.y + tabs[endex-1].Size.height > size.height - 16) sz = self.Size if ((sz.width != self.lastsize.width and not self.side_tabs) or (sz != self.lastsize and self.side_tabs)) and self.IsShownOnScreen(): self.lastsize = sz if self.side_tabs: self.ReVgenerate(dotoggle = False) else: self.Regenerate(False,dotoggle = False) try: wx.CallAfter(wx.CallAfter,self.Parent.pagecontainer.active.panel.input_area.expandEvent) except AttributeError: pass self.Refresh(False) def GetTabCount(self): """ Returns the number of tabs in the bar """ return len([t for t in self if t]) def NextTab(self): self.SetNextActive(self.ActiveTab, wrap = True) def PrevTab(self): self.SetLastActive(self.ActiveTab, wrap = True) def SetNextActive(self, origin,wrap=False): """ Sets the tab after the curent active -if it does not exist does the previbus -or the first if wrap is true """ if origin in self.tabs: index=self.tabs.index(origin) if not index < len(self.tabs)-1 and wrap: self.tabs[0].SetActive(True) elif index < len(self.tabs)-1: self.tabs[index+1].SetActive(True) elif index>0: self.tabs[index-1].SetActive(True) self.Refresh(False) def SetLastActive(self, origin, wrap = False): """ Sets the tab before the curent active -if it does not exist does the next -or the last if wrap is true """ if origin in self.tabs: index=self.tabs.index(origin) if not index > 0 and wrap: self.tabs[len(self.tabs)-1].SetActive(True) elif index >0: self.tabs[index-1].SetActive(True) elif index<0: self.tabs[index+1].SetActive(True) self.Refresh(False) def SyncActive(self,atab): """ Moves the index and endex so that the active tab is in the bar """ if not atab: return if self.side_tabs: if atab < self.tabindex: self.tabindex=atab self.ReVgenerate(True) else: thetab=self.tabs[atab] while atab >= self.tabendex or thetab.Position.y+thetab.Size.height > self.Size.height-16: self.tabindex+=1 self.ReVgenerate(True) else: style = self.tab_rows if atab < self.rowindex: self.rowindex=atab self.Regenerate() elif atab > self.rowindex+style-1: self.rowindex=atab-style+1 self.Regenerate() def OnWheel(self,event): """ Event that handles mouse wheeling, maps the events to SetNextActive and SetLastActive """ if RectS(self.Size).Contains(event.Position): direction = event.GetWheelRotation() if direction<0: self.SetNextActive(self.ActiveTab, True) elif direction>0: self.SetLastActive(self.ActiveTab, True) @property def Notebook(self): return self.Parent @property def Manager(self): return self.Notebook.manager @property def ActiveTab(self): active = self.Notebook.pagecontainer.active if active is not None: return active.tab def OnButton(self,event): """ The button events for vertical alignment for up and down """ if event.GetId()==CUPID: if self.tabindex > 0: self.tabindex -= 1 self.ReVgenerate(total = True) elif event.GetId()==CDOWNID: if self.tabendex<len(self.tabs) or self.tabs[self.tabendex-1].Position.y+self.tabs[self.tabendex-1].Size.height>self.Size.height-16: self.tabindex+=1 self.ReVgenerate(total=True) self.UpdateNotify() def NotifyDrag(self, origin): """ When a tab is dragged this is called to start the tabbar handling dragging origin - tab being dragged """ # Lets the TabMan know a tab as been dragged self.dragorigin = origin origin.SetCursor(wx.StockCursor(wx.CURSOR_NO_ENTRY)) self.Manager.Notify(self.Notebook) def DragCalc(self,point): """ This does the dragging calculations for the tabs """ sidetabs = self.side_tabs # if here is no local origin tab but there is a remote source identified in TabMan if not self.dragorigin and self.Manager.source: #setting a local drag origin master = self.Manager.source dragorigin=master.tabbar.dragorigin # announcing to TabMan it is expecting a tab self.Manager.Request(self.Notebook) # if there is a local origin use that else: dragorigin=self.dragorigin # if dragtarget is out of date find what you're dragging to if not self.dragtarget or not self.dragtarget.Rect.Contains(point): wap = wx.FindWindowAtPointer() self.dragtarget = wap if isinstance(wap,Tab) else None self.dragside = None # if there is a tab as target if self.dragtarget and self.dragtarget != dragorigin: dtrect=self.dragtarget.Rect # data to decide what side the tab would be dropped on if not sidetabs: x = point[0] - dtrect.x x2 = dtrect.width / 2 else: x = point[1] - dtrect.y x2 = dtrect.height / 2 # make the left/top or right/bottom decision if x <= x2:#left/top if self.dragside!=False: self.dragside=False if not sidetabs: self.DrawDropMarker(dtrect.x, dtrect.y)# + (dtrect.height // 2) else: self.DrawDropMarker(dtrect.x, dtrect.y)# + dtrect.width // 2 elif not self.dragside:#right/bottom self.dragside=True if not sidetabs: self.DrawDropMarker(dtrect.x+dtrect.width,dtrect.y)#+(dtrect.height//2) else: self.DrawDropMarker(dtrect.x,dtrect.y+dtrect.height)#+dtrect.width//2 self.SetFocus() # if being dropped in the whitespace of the TabBar elif (dragorigin and self.dragtarget!=dragorigin) or (dragorigin==None and self.dragtarget==None) and self.Rect.Contains(point): # find what row the tab is being dropped in if not sidetabs: row=self.rows[(point[1]//self.rowheight)+self.rowindex] tab=row[len(row)-1] self.dragside=True # or in vertical if at the beginning or end else: if point.y>self.rowheight: tab=self.rows[0][len(self.rows[0])-1] self.dragside=True else: tab=self.rows[0][0] self.dragside=False dtrect=tab.Rect #Place marker if not sidetabs: self.DrawDropMarker(dtrect.x+dtrect.width,dtrect.y)#+(dtrect.height//2) elif self.dragside==True: self.DrawDropMarker(dtrect.x,dtrect.y+dtrect.height)#+dtrect.width//2 else: self.DrawDropMarker(dtrect.x+dtrect.width/2,dtrect.y) self.SetFocus() #cleanup self.dragtarget=tab else:#if not in tabbar anymore don't show arrow self.dropmarker.Show(False) def DragFinish(self,new=False): """ Ends dragging and does any rearranging if required """ if not wx.IsDestroyed(self.dragorigin): self.dragorigin.SetCursor(wx.StockCursor(wx.CURSOR_ARROW)) if self.dragorigin and self.dragorigin.previewtabs: # Destroy the preview tab self.dragorigin.previewtabs.Stop() self.dragorigin.previewtabs = None rect = RectPS(self.Notebook.ClientToScreen(self.Position), self.Size) parentrect = self.Notebook.window.Rect mousepos = wx.GetMousePosition() manager = self.Manager #if released out of the window... if not new and ((manager.destination and not parentrect.Contains(mousepos)) or not rect.Contains(mousepos)): if self.ActiveTab==self.dragorigin: self.SetNextActive(self.dragorigin) self.dragorigin.Show(False) #If no or invalid destination in manager create a new window and sets it destination dest = manager.destination if not dest or not dest.tabbar.Rect.Contains(dest.ScreenToClient(wx.GetMousePosition())): # FIXME: SWIG doesn't like subtracting a wx.Size from a wx.Point, so do it the hard way # until the SIP migration is finished. originsize = self.dragorigin.GetSize() newpoint = wx.Point(mousepos[0] - originsize[0], mousepos[1] - originsize[1]) destination = self.Notebook.winman.NewWindow(newpoint, self.Notebook.window.GetSize()).notebook #else set the destination to the manager's destination else: destination = dest #clear tabman's destination manager.Request() # Grab a reference to the tab's page page = self.dragorigin.page # Make the tab "forget" about the page self.Notebook.did_remove(page.panel) del self.dragorigin.page del page.tab # Remove the tab from the tabs list, and destroy the wxWindow self.tabs.remove(self.dragorigin) self.dragorigin.Close() # remove page from this notebook and insert it into the target notebook #page.Parent.RemoveChild(page) destination.Insert(page, False) # cleanup manager.Notify() self.dragorigin=None # re-sort tabs if self.side_tabs: self.ReVgenerate(True) else: self.Regenerate(safe = True) # if released inside of the window # used both for moving within a window and as the last step of a # interwindow move in case of interwindow tab has already been moved to # this window at the end of the list and all that is left is to move it # to the correct position. elif self.dragtarget and self.dragorigin and self.dragorigin!=self.dragtarget and self.Rect.Contains(self.Notebook.ScreenToClient(mousepos)): #remove the tab from the list self.tabs.remove(self.dragorigin) #decide which side of the target the tab should be dropped pos = self.tabs.index(self.dragtarget) + (1 if self.dragside else 0) # Reinsert the tab in it's new position self.tabs.insert(pos, self.dragorigin) after = self.tabs[pos+1] if pos+1 < len(self.tabs) else None if after is not None: after = after.page.panel # call after so that windows are all in their correct places wx.CallAfter(self.Notebook.did_rearrange, self.dragorigin.page.panel, after) # # Resort if self.side_tabs: self.ReVgenerate(True) else: self.Regenerate() elif new: if self.side_tabs: self.ReVgenerate(True) else: self.Regenerate() #if there is a dragorigin run onMouseLeave on it to reset it's look if self.dragorigin: self.dragorigin.OnMouseLeave() #local cleanup self.dropmarker.Show(False) self.dragorigin=None self.dragtarget=None #destination and manager cleanup dest = manager.destination if dest: dest.tabbar.dragorigin=None dest.tabbar.dragtarget=None manager.Request() manager.Notify() if len(self.tabs)==0: self.Notebook.window.Close() def DrawDropMarker(self,x,y): """ Places the marker for where to drop the tab x and y are center position, saves calculation that way """ # if self.side_tabs: # self.dropmarker.SetSize((self.Size.width - self.dropmarkeroverlay, -1)) # else: # self.dropmarker.SetSize((-1, self.rowheight - self.dropmarkeroverlay)) self.dropmarker.Teleport(self.ClientToScreen((x, y+self.dropmarkeroffset))) if not self.dropmarker.IsShown(): self.Manager.ShowDropMarker(self.dropmarker) def Toggle(self, switch = None): 'Toggle whether the tabbar is hidden or shown.' if pref('tabs.hide_at_1', True) and len(self.tabs) <= 1 and not switch: self.Notebook.Split(False) #make sure the content of the IM win resizes if tabbaar hides self.ProcessEvent(wx.CommandEvent(wx.wxEVT_SIZE)) else: self.Notebook.Split(True) def UpdateNotify(self): frows = self.flagedrows frows.clear() # Resort if self.side_tabs: tabs=self.tabs for i, tab in enumerate(tabs): if tab.notified: frows.add(i) elif i in self.flagedrows: frows.remove(i) self.cupb.SetNotify(len(frows) and min(frows) < self.tabindex) self.cdownb.SetNotify(len(frows) and (max(frows) >= self.tabendex or tabs[max(frows)].Position.y + tabs[max(frows)].Size.height > self.Size.height - 16)) else: for i, row in enumerate(self.rows): flaged = False for tab in row: if tab and tab.notified: flaged = True frows.add(i) self.navi.upb.SetNotify(len(frows) and min(frows)<self.rowindex) self.navi.downb.SetNotify(len(frows) and max(frows)>self.rowindex + self.tab_rows - 1)
class P(wx.Panel): def __init__(self,parent): wx.Panel.__init__(self,parent,-1)#,style = wx.CLIP_CHILDREN|wx.CLIP_SIBLINGS self.Bind(wx.EVT_BUTTON,self.onButton), self.Bind(wx.EVT_LEFT_UP,self.OnMouse), self.Bind(wx.EVT_LEFT_DOWN,self.OnMouse) self.skin = 'button' # print self.skin # self.menu=UMenu(self) # self.menu.Append(wx.NewId(),'item 1') # self.menu.Append(wx.NewId(),'item 2') # self.menu.Append(wx.NewId(),'item 3') content=wx.BoxSizer(wx.VERTICAL) size=None#(200,50)# type=None#'menu'#'toggle'#'toggle'# menu=None#self.menu# icon=wx.Bitmap('../../../../res/skins/default/statusicons/mobile.png',wx.BITMAP_TYPE_PNG)#wx.Bitmap('../../res/skins/default/tinydigsby.png',wx.BITMAP_TYPE_PNG) #label= "button"#"Super wide Button Name of Impending doooooooooooom!!!"#"button"# skin=self.skin#None# self.b1=UberButton(self,wx.NewId(),'&One',skin,icon=icon,style=wx.HORIZONTAL,size=size,type=type,menu=menu) # self.b1.SetStaticWidth(60) self.b2=UberButton(self,wx.NewId(),'&Two',icon=icon,style=wx.HORIZONTAL,size=size,type=type,menu=menu) self.b3=UberButton(self,wx.NewId(),'T&hree',skin,icon=icon,style=wx.VERTICAL,size=size,type=type,menu=menu) self.b4=UberButton(self,wx.NewId(),'&Four',icon=icon,style=wx.VERTICAL,size=size,type=type,menu=menu) self.b5=UberButton(self,wx.NewId(),"",skin,icon=icon,size=size,type=type,menu=menu) self.b6=UberButton(self,wx.NewId(),"",icon=icon,size=size,type=type,menu=menu) self.b7=UberButton(self,wx.NewId(),'Fi&ve',skin,size=size,type=type,menu=menu) self.b8=UberButton(self,wx.NewId(),'&Six',size=size,type=type,menu=menu) self.b9=UberButton(self,wx.NewId(),"",skin,size=size,type=type,menu=menu) self.b10=UberButton(self,wx.NewId(),"",size=size,type=type,menu=menu) self.b11 = wx.Button(self, wx.NewId(), 'Native') self.b12= wx.Button(self, wx.NewId(), ' ') self.b12.Bind(wx.EVT_BUTTON,self.ToggleAlignment) self.b13 = UberButton(self, wx.NewId(), 'active?', self.skin) self.b13.Bind(wx.EVT_BUTTON,self.ToggleSkin) wexp = 0#wx.EXPAND#wx.ALL| hrat = 0#1# pad = 0 content.Add(self.b1,hrat,wexp,pad) content.Add(self.b2,hrat,wexp,pad) content.Add(self.b3,hrat,wexp,pad) content.Add(self.b4,hrat,wexp,pad) content.Add(self.b5,hrat,wexp,pad) content.Add(self.b6,hrat,wexp,pad) content.Add(self.b7,hrat,wexp,pad) content.Add(self.b8,hrat,wexp,pad) content.Add(self.b9,hrat,wexp,pad) content.Add(self.b10,hrat,wexp,pad) content.Add(self.b11,hrat,wexp,pad) content.Add(self.b12,hrat,wexp,pad) content.Add(self.b13, hrat, wexp, pad) self.SetSizer(content) def onButton(self,event): print event.GetEventObject().Label # print "..." # if type(event.EventObject)==wx.Button: # print event.EventObject.Label # else: # print event.EventObject.label # switch= not self.b1.IsEnabled() # self.b1.Enable(switch) # self.b2.Enable(switch) # self.b3.Enable(switch) # self.b4.Enable(switch) # self.b5.Enable(switch) # self.b6.Enable(switch) # self.b7.Enable(switch) # self.b8.Enable(switch) # self.b9.Enable(switch) # self.b10.Enable(switch) # self.b11.Enable(switch) def ToggleSkin(self,event = None): key = None if self.b1.skinkey else 'button' print 'toggleskin to',key self.b1.SetSkinKey(key,1) self.b3.SetSkinKey(key,1) self.b5.SetSkinKey(key,1) self.b7.SetSkinKey(key,1) self.b9.SetSkinKey(key,1) def ToggleAlignment(self,event = None): print "ToggleAlignment DISABLED!!! It can not be!!!" # align = wx.VERTICAL if self.b1.Alignment == wx.HORIZONTAL else wx.HORIZONTAL # self.b1.Alignment = align # self.b3.Alignment = align # self.b5.Alignment = align # self.b7.Alignment = align # self.b9.Alignment = align # self.Layout() def OnMouse(self,event): print "window caught mouse"
def __init__(self, parent): wx.Frame.__init__(self, parent, -1, "Shaped Window", style=wx.FRAME_SHAPED | wx.SIMPLE_BORDER | wx.FRAME_NO_TASKBAR | wx.STAY_ON_TOP) self.hasShape = False self.delta = (0, 0) [ self.Bind(e, m) for e, m in [ (wx.EVT_LEFT_DCLICK, self.OnDoubleClick), (wx.EVT_LEFT_DOWN, self.OnLeftDown), (wx.EVT_LEFT_UP, self.OnLeftUp), (wx.EVT_MOTION, self.OnMouseMove), (wx.EVT_RIGHT_UP, self.OnExit), (wx.EVT_PAINT, self.OnPaint), ] ] from skins import images as imgmngr from skins import skins f = file("../../res/skins/halloween/skin.yaml") images = util.to_storage(yaml.load(f)).Images f.close() skins.res_path = "../../res/skins/halloween" mimg = MultiImage(images) from gui.uberwidgets.UberBar import UberBar as UberBar from gui.uberwidgets.UberButton import UberButton as UberButton self.content = wx.Panel(self) innerSizer = wx.BoxSizer(wx.HORIZONTAL) self.bsizer = wx.BoxSizer(wx.VERTICAL) self.menu = UberBar(self.content) [ self.menu.add(UberButton(self.menu, -1, s)) for s in 'Digsby Edit Help'.split() ] self.bsizer.Add(self.menu, 0, wx.EXPAND, 0) self.content.SetSizer(self.bsizer) self.hsizer = wx.BoxSizer(wx.HORIZONTAL) self.hsizer.Add(self.content, 1, wx.EXPAND | wx.ALL, 140) self.SetSizer(self.hsizer) w, h = 400, 400 self.SetClientSize((w, h)) dc = wx.ClientDC(self) destbitmap = wx.EmptyBitmap(w, h) temp_dc = wx.MemoryDC() temp_dc.SelectObject(destbitmap) mimg.draw(temp_dc, wx.Rect(0, 0, w, h)) temp_dc.SelectObject(wx.NullBitmap) destbitmap.SetMask(wx.Mask(destbitmap, wx.BLACK)) self.bmp = destbitmap if wx.Platform != "__WXMAC__": # wxMac clips the tooltip to the window shape, YUCK!!! self.SetToolTipString( "Right-click to close the window\n" "Double-click the image to set/unset the window shape") if wx.Platform == "__WXGTK__": # wxGTK requires that the window be created before you can # set its shape, so delay the call to SetWindowShape until # this event. self.Bind(wx.EVT_WINDOW_CREATE, self.SetWindowShape) else: # On wxMSW and wxMac the window has already been created, so go for it. self.SetWindowShape() dc.DrawBitmap(destbitmap, 0, 0, True)
def __init__(self,parent): wx.Panel.__init__(self,parent,-1)#,style = wx.CLIP_CHILDREN|wx.CLIP_SIBLINGS self.Bind(wx.EVT_BUTTON,self.onButton), self.Bind(wx.EVT_LEFT_UP,self.OnMouse), self.Bind(wx.EVT_LEFT_DOWN,self.OnMouse) self.skin = 'button' # print self.skin # self.menu=UMenu(self) # self.menu.Append(wx.NewId(),'item 1') # self.menu.Append(wx.NewId(),'item 2') # self.menu.Append(wx.NewId(),'item 3') content=wx.BoxSizer(wx.VERTICAL) size=None#(200,50)# type=None#'menu'#'toggle'#'toggle'# menu=None#self.menu# icon=wx.Bitmap('../../../../res/skins/default/statusicons/mobile.png',wx.BITMAP_TYPE_PNG)#wx.Bitmap('../../res/skins/default/tinydigsby.png',wx.BITMAP_TYPE_PNG) #label= "button"#"Super wide Button Name of Impending doooooooooooom!!!"#"button"# skin=self.skin#None# self.b1=UberButton(self,wx.NewId(),'&One',skin,icon=icon,style=wx.HORIZONTAL,size=size,type=type,menu=menu) # self.b1.SetStaticWidth(60) self.b2=UberButton(self,wx.NewId(),'&Two',icon=icon,style=wx.HORIZONTAL,size=size,type=type,menu=menu) self.b3=UberButton(self,wx.NewId(),'T&hree',skin,icon=icon,style=wx.VERTICAL,size=size,type=type,menu=menu) self.b4=UberButton(self,wx.NewId(),'&Four',icon=icon,style=wx.VERTICAL,size=size,type=type,menu=menu) self.b5=UberButton(self,wx.NewId(),"",skin,icon=icon,size=size,type=type,menu=menu) self.b6=UberButton(self,wx.NewId(),"",icon=icon,size=size,type=type,menu=menu) self.b7=UberButton(self,wx.NewId(),'Fi&ve',skin,size=size,type=type,menu=menu) self.b8=UberButton(self,wx.NewId(),'&Six',size=size,type=type,menu=menu) self.b9=UberButton(self,wx.NewId(),"",skin,size=size,type=type,menu=menu) self.b10=UberButton(self,wx.NewId(),"",size=size,type=type,menu=menu) self.b11 = wx.Button(self, wx.NewId(), 'Native') self.b12= wx.Button(self, wx.NewId(), ' ') self.b12.Bind(wx.EVT_BUTTON,self.ToggleAlignment) self.b13 = UberButton(self, wx.NewId(), 'active?', self.skin) self.b13.Bind(wx.EVT_BUTTON,self.ToggleSkin) wexp = 0#wx.EXPAND#wx.ALL| hrat = 0#1# pad = 0 content.Add(self.b1,hrat,wexp,pad) content.Add(self.b2,hrat,wexp,pad) content.Add(self.b3,hrat,wexp,pad) content.Add(self.b4,hrat,wexp,pad) content.Add(self.b5,hrat,wexp,pad) content.Add(self.b6,hrat,wexp,pad) content.Add(self.b7,hrat,wexp,pad) content.Add(self.b8,hrat,wexp,pad) content.Add(self.b9,hrat,wexp,pad) content.Add(self.b10,hrat,wexp,pad) content.Add(self.b11,hrat,wexp,pad) content.Add(self.b12,hrat,wexp,pad) content.Add(self.b13, hrat, wexp, pad) self.SetSizer(content)
class StatusCombo(UberCombo): # number of milliseconds to wait after clicking the status button before the # status is set (if the user hasn't entered any text) set_delay = 3000 def __init__(self, parent, buddylist, statuses, get_status_method=get_profile_status, set_status_method=set_profile_status): ''' StatusCombo constructor. parent - a wx.Window parent window statuses - an observable list of StatusMessage objects ''' self.buddylist = buddylist self.buddylist.Bind(wx.EVT_KEY_DOWN, self.on_buddylist_key) self.searching = False self.searchHintShown = False if not getattr(StatusCombo, 'searchThresholdRegistered', False) and pref('search.buddylist.show_hint', True): def SearchThresholdReached(*a, **k): if pref('search.buddylist.show_hint', True): setpref('search.buddylist.show_hint', False) Hook('digsby.achievements.threshold', 'buddylist.search').register(SearchThresholdReached) StatusCombo.searchThresholdRegistered = True self.offline_item = None self.get_profile_status = get_status_method self.set_profile_status = set_status_method status = self.get_profile_status() UberCombo.__init__(self, parent, skinkey='combobox', typeable=True, valuecallback=self.on_text_lose_focus, empty_text=getattr(status, 'hint', status.title.title()), maxmenuheight=15) self.buttoncallback = self.on_status_button self.cbutton = UberButton(self, -1, skin=self.cbuttonskin) self.cbutton.Bind(wx.EVT_BUTTON, self._on_left_button) self.content.Insert(0, self.cbutton, 0, wx.EXPAND) self.cbutton.BBind(RIGHT_UP=self.on_status_button_right_click, LEFT_DOWN=self.on_status_button_left_click, LEFT_UP=self.on_status_button_left_up) self.display.Bind( wx.EVT_LEFT_DOWN, lambda e: (e.Skip(), setattr(self, 'oldValue', self.Value))) # the on_allow_status_changes method is called when the list of connected # im accounts changes size. if all accounts are offline this control # becomes disabled.. #profile.account_manager.connected_accounts.add_observer(self.on_allow_status_changes) profile.account_manager.connected_accounts.add_observer( self.on_offline_allowed, obj=self) # Listen on status messages (changes, additions, deletes). _obs_link = statuses.add_list_observer(self.on_status_messages_changed, self.on_status_messages_changed) self.Bind( wx.EVT_WINDOW_DESTROY, lambda e: (log.info('status combo removing observers'), e.Skip(), _obs_link.disconnect())) self.on_status_messages_changed(statuses) # when the profile's status changes, update to reflect it profile.add_observer(self.on_profile_status_changed, 'status') # Display the current status. self.show_status(self.get_profile_status()) # Timer for committing status messages after a delay. self.timer = wx.PyTimer(self.SetFocus) self.Bind(wx.EVT_TEXT, self.on_typing) self.button_timer = wx.PyTimer(self.on_status_button_right_click) textbind = self.TextField.Bind textbind(wx.EVT_SET_FOCUS, lambda e: setattr(self, 'skipenter', False)) textbind(wx.EVT_KEY_DOWN, self._on_key_down) textbind(wx.EVT_TEXT_ENTER, self._on_enter) self.DropDownButton.Bind(wx.EVT_LEFT_DOWN, self._dbutton_left) self.OnActivateSearch = Delegate() self.OnDeactivateSearch = Delegate() def UpdateSkin(self): key = 'statuspanel' if not skin.get(key, False) or skin.get(key + '.mode', '') == 'native': s = lambda k, d: None else: s = lambda k, default: skin.get('%s.%s' % (key, k), default) comboskinkey = s('comboboxskin', None) self.cbuttonskin = cbskinkey = s('statusbuttonskin', None) self.SetSkinKey(comboskinkey) UberCombo.UpdateSkin(self) if hasattr(self, 'cbutton'): self.cbutton.SetSkinKey(cbskinkey, True) self.SetButtonIcon(StatusMessage.icon_for(self.status_state)) if hasattr(self, 'menu') and self.menu: self.on_status_messages_changed() def SetButtonIcon(self, icon): """set the icon for the cycle button""" self.cbutton.SetIcon(icon) self._button_icon = icon self.Layout() def SetCallbacks(self, selection=sentinel, value=sentinel, button=sentinel): 'Sets callbacks for this combobox.' UberCombo.SetCallbacks(self, selection, value) if button is not sentinel: self.buttoncallback = button def on_allow_status_changes(self, *a, **k): if self.Show(profile.allow_status_changes): self.Parent.gui_layout() def setandshow(self, statusmsg): 'Immediately sets the status message and shows it.' log.info('setandshow %r', statusmsg) self.oldValue = None self.show_status(statusmsg) self.set_profile_status(statusmsg) def show_status(self, status, force=False): 'Displays the specified status message.' if not force and status is getattr(self, '_shown_status', None): return # make the text area not editable for statuses like "Invisble" and # "Offline", which have the "editable" attribute set to False self.Editable = status.editable self.display.empty_text = getattr(status, 'hint', '') self.ChangeValue(status.message) # change text self.SetButtonIcon(StatusMessage.icon_for(status)) # change icon self.status_state = status.status # store the state self._shown_status = status # # events # def on_typing(self, e): 'Invoked when the user is typing in the textfield.' if self.searching: search.link_prefs(profile.prefs) e.Skip() self.buddylist.search(e.EventObject.Value) else: self.cancel_timer() def on_status_button(self, button): ''' Invoked when the user clicks the state button to the left of the dropdown. ''' # toggle the control's status state isavail = StatusMessage.is_available_state(self.status_state) # do we need to change the shown text? needs_change = self._shown_status in StatusMessage.SpecialStatuses or not self._shown_status.editable self.oldValue = None self.change_state(state='Away' if isavail else 'Available', ) #change_text = needs_change) def change_state(self, state, change_text=False): if not isinstance(state, basestring): raise TypeError('change_state takes a string got a %s' % type(state)) self.status_state = state if change_text: self.ChangeValue(self.status_state, state.title()) else: self.Default = state.title() edit_toggle = getattr(profile.status, 'edit_toggle', True) if getattr(profile.status, 'edit_toggle', True): # update the icon self.SetButtonIcon(StatusMessage.icon_for(self.status_state)) self.cancel_timer() self.timer.StartOneShot(self.set_delay) # select all text in the textfield disp = self.display disp.TypeField() wx.CallAfter(disp.txtfld.SetSelection, -1, -1) else: self.setandshow( profile.status.copy(status=self.status_state, editable=None, edit_toggle=None)) def on_status_button_left_click(self, e=None): if self.searching: return self.TextField.SetFocus() self.skipenter = True self.button_timer.Start(BUTTON_HOLD_TIME, True) if e: e.Skip(True) def on_status_button_left_up(self, e=None): if not self.searching: self.button_timer.Stop() if e: e.Skip(True) def on_status_button_right_click(self, e=None): if not self.searching: self.show_extended_status_menu() def show_extended_status_menu(self): from gui.status import get_state_choices m = SimpleMenu(self, skinkey=skin.get('%s.MenuSkin' % self.skinkey)) for status in get_state_choices(): statusname, statuslabel = status def onclick(item, state=statusname): self.change_state( state ) #, change_text = self.status_state == self.GetValue()) m.AppendItem( SimpleMenuItem( [StatusMessage.icon_for(statusname), statuslabel], method=onclick)) if m.GetCount() > 0: m.Display(self.cbutton) def on_text_lose_focus(self, new_msg): if self.searching: return self.on_search_timer() # Cancel the status button timer if it's running. self.cancel_timer() if getattr(self, 'skipenter', False): wx.CallAfter(lambda: setattr(self, 'skipenter', False)) else: # don't set status if we lost focus because the user is clicking # on the state button if wx.GetMouseState().LeftDown() and wx.FindWindowAtPoint( wx.GetMousePosition()) is self.cbutton: return profile_status = self.get_profile_status() if new_msg == '': self.display.empty_text = profile_status.hint if new_msg != profile_status.message or self.status_state != profile_status.status: # entering a new text value clears all exceptions newmsg = StatusMessage(new_msg, self.status_state, new_msg) self.set_profile_status(newmsg) def on_profile_status_changed(self, *a): "Invoked when the profile's status changes." self.show_status(profile.status) @calllimit(1) def on_offline_allowed(self, *a): if not self: return show_offline = profile.allow_status_changes if not show_offline and self.offline_item: log.info('removing the offline item') self.RemoveItem(self.offline_item) self.offline_item = None elif show_offline and not self.offline_item: log.info('adding the offline item') self.offline_item = self.additem( [skin.get('statusicons.offline'), _('Offline')], self.on_offline) def additem(self, *a, **k): i = SimpleMenuItem(*a, **k) self.AppendItem(i) return i @calllimit(1) def on_status_messages_changed(self, *a): ''' Invoked when a status message changes, or the user status list changes. Rebuilds the status menu items. ''' log.info('on_status_messages_changed, updating menu') self.RemoveAllItems() additem = self.additem def add_status_item(pname, name): additem([skin.get('statusicons.%s' % pname), name], method=getattr(self, 'on_' + pname)) # Available add_status_item('available', _('Available')) # user statuses self.sortedstatuses = msgs = sorted([c for c in profile.statuses], key=lambda msg: msg.away) # Find where to insert the special "Away" status item j = -1 found = False for j, msg in enumerate(msgs): if msg.away: found = True break for i, msg in enumerate(msgs): if found and i == j: add_status_item('away', _('Away')) online_image = skin.get( 'statusicons.away' if msg.away else 'statusicons.available') additem([online_image, msg.title], method=lambda mi, msg=msg: self.setandshow(msg), id=i) if not found or j == -1: add_status_item('away', _('Away')) # Custom... additem(_('Custom...'), method=self.on_custom) self.AppendSeparator() if global_status_enabled(): additem([skin.get('icons.globalstatus'), _('Global Status')], method=self.on_global) log.info('updating status menu with %d extra statuses', len(Hook('digsby.im.statusmessages'))) for msg in Hook('digsby.im.statusmessages'): message = msg() if message is None: continue additem([message.icon, message.title], method=lambda mi, msg=msg: self.setandshow(msg())) if global_status_enabled(): additem([skin.get('statusicons.promote'), _('Promote Digsby!')], method=self.on_promote) # Invisible additem([skin.get('statusicons.invisible'), _('Invisible')], self.on_invisible) # Offline self.offline_item = None self.on_offline_allowed() # # special entries in the status menu. # def on_offline(self, combo_item): self.setandshow(StatusMessage.Offline) def on_available(self, comboitem): self.show_status(StatusMessage.Available) self.display.TypeField() def on_away(self, comboitem): self.show_status(StatusMessage.Away) self.display.TypeField() def on_custom(self, combo_item): edit_custom_status(self) def on_global(self, combo_item): wx.CallAfter(wx.GetApp().SetStatusPrompt) def on_promote(self, combo_item): wx.CallAfter(wx.GetApp().SetStatusPrompt, 'ALL', PROMOTE_STATUS_STRING(), editable=False, edit_toggle=False) def on_nowplaying(self, combo_item): self.setandshow(StatusMessage.NowPlaying) def on_invisible(self, combo_item): sta = self.get_profile_status() cpy = StatusMessage.Invisible.copy(message=sta.message) self.setandshow(cpy) def cancel_timer(self): if self.timer.IsRunning(): self.timer.Stop() # # search functionality # def _on_left_button(self, e): if not self.searching: return self.buttoncallback(self.cbutton) def _on_enter(self, e): if self.searching: self.buddylist.activate_selected_item() self.stop_searching() else: e.Skip() def _on_key_down(self, e): if self.searching: if e.KeyCode == wx.WXK_ESCAPE: self.buddylist.SetFocus() self.stop_searching() elif e.KeyCode in txtcontrol_keys: e.Skip() else: self.buddylist.on_key_down(e) else: e.Skip() def _interpret_char_event(self, e): key = None backspace = False if e is not None: mod = e.Modifiers & ~wx.MOD_SHIFT if e.KeyCode == wx.WXK_BACK: backspace = True elif mod or e.KeyCode <= ord(' ') or e.KeyCode in non_alphanumeric: return key, backspace else: key = unichr(e.UnicodeKey) return key, backspace def ShowSearchHint(self): self.searchHintShown = True def size_like(img, i): img = img.ResizedSmaller(max(i.Width, i.Height)).PIL return img.ResizeCanvas(i.Width, i.Height).WXB self.cbutton.SetIcon( size_like(skin.get('StatusPanel.SearchIcon'), self._button_icon)) self.DropDownButton.SetIcon(skin.get('StatusPanel.CancelSearchIcon')) self.display.DisplayLabel = _("Press 'Ctrl+F' to Search List") def HideSearchHint(self): self.SetButtonIcon(self._button_icon) self.DropDownButton.SetIcon(self.dropdownicon) self.searchHintShown = False self.display.DisplayLabel = None def search(self, e=None): if not pref('search.buddylist.enabled', True): if e is not None: e.Skip() return key, backspace = self._interpret_char_event(e) def size_like(img, i): img = img.ResizedSmaller(max(i.Width, i.Height)).PIL return img.ResizeCanvas(i.Width, i.Height).WXB icon = skin.get('StatusPanel.SearchIcon') self.ForceTextFieldBackground = True self.cbutton.SetIcon(size_like(icon, self._button_icon)) self.DropDownButton.SetIcon(skin.get('StatusPanel.CancelSearchIcon')) self.searching = True if not hasattr(self, 'search_timer'): self.search_timer = wx.PyTimer(self.on_search_timer) self.search_timer.Start(500) self.display.TypeField() # emulate a keypress if one started the search self.TextField.ChangeValue(profile.blist.search_string) if key is not None: self.TextField.AppendText(key) if backspace: # emulate a backspace size = self.TextField.LastPosition self.TextField.Remove(size - 1, size) self.OnActivateSearch() def on_search_timer(self): active = wx.GetActiveWindow() focused = wx.Window.FindFocus() if active is None or not self.searching: self.stop_searching() if not hasattr(self, '_allowed_windows'): # active windows search will stick around for from gui.infobox.infobox import InfoBox from gui.buddylist.buddylistframe import BuddyListFrame from gui.searchgui import SearchEditDialog self._allowed_windows = frozenset( [InfoBox, BuddyListFrame, SearchEditDialog]) self._empty_textfield_cancels = frozenset([BuddyListFrame]) clz = active.__class__ if clz not in self._allowed_windows: self.stop_searching() # if search loses focus to the buddylist and there is no text in the # search field, just cancel the search elif clz in self._empty_textfield_cancels and \ focused is not self.TextField and \ not self.TextField.Value: self.stop_searching() def stop_searching(self): if not self.searching: return log.info('stopping search') self.ForceTextFieldBackground = False self.SetButtonIcon(self._button_icon) self.DropDownButton.SetIcon(self.dropdownicon) self.search_timer.Stop() self.searching = False focused_window = wx.Window.FindFocus() if focused_window is self.TextField: self.buddylist.SetFocus() self.show_status(get_profile_status(), force=True) self.buddylist.clear_search() self.OnDeactivateSearch() hooks.notify('digsby.statistics.buddylist.search') def _dbutton_left(self, e): if self.searching: return self.stop_searching() else: e.Skip() def on_buddylist_key(self, e): if self.searching and e.KeyCode == wx.WXK_ESCAPE: self.stop_searching() else: e.Skip()
class FormattingBar(ToolBar, NewSkinModule): initover = False def __init__(self, parent, textctrl, skinkey, formatOptions): ToolBar.__init__(self, parent, skinkey = None, alignment = wx.ALIGN_LEFT) self.SetSkinKey(skinkey, FormattingBarSkinDefaults) self.textctrl = textctrl if sys.platform.startswith("win"): textctrl.Bind(EVT_SELECTION_CHANGED, self.OnCursorMove) textctrl.Bind(EVT_TEXT_FORMAT_CHANGED, self.OnCursorMove) self.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu) self.fontdd = FontDropDown(self, skinkey = self.skinTB['buttonskin']) self.fontdd.SetMenuSkinKey(self.skinTB["menuskin"]) self.fontdd.Bind(wx.EVT_COMMAND_CHOICE_SELECTED, self.OnFontSelected) icons = self.icons self.msize = SimpleMenu(self, self.skinTB['menuskin'], maxheight = 10) self.msize.SetItems(self.GenSizeItems(DEFAULT_SIZES)) #TODO: None default sizes # self.msize.Bind(wx.EVT_COMMAND_CHOICE_SELECTED, self.OnSizeSelected) self.bsize = UberButton(self, -1, '10', menu = self.msize, type = 'menu') self.bsize.SetStaticWidth(self.skinFB['sizedropdownwidth']) self.msize.SetWidth(self.skinFB['sizedropdownwidth']) self.bbold = UberButton(self, -1, icon = icons['bold'], type = 'toggle') self.bbold.Bind(wx.EVT_TOGGLEBUTTON, self.OnBoldButton) self.bitalic = UberButton(self, -1, icon = icons['italic'], type="toggle") self.bitalic.Bind(wx.EVT_TOGGLEBUTTON, self.OnItalicButton) self.bunderline = UberButton(self, -1, icon = icons['underline'], type="toggle") self.bunderline.Bind(wx.EVT_TOGGLEBUTTON, self.OnUnderlineButton) self.bcolor = UberButton(self, -1, icon = icons['foregroundcolor'] ) self.bcolor.Bind(wx.EVT_BUTTON, self.OnColorButton) self.bbgcolor = UberButton(self,-1, icon = icons['backgroundcolor']) self.bbgcolor.Bind(wx.EVT_BUTTON, self.OnBGColorButton) self.bemote = UberButton(self, -1, icon = icons['emote']) self.bemote.Bind(wx.EVT_BUTTON, self.OnEmoteButton) # import pdb # pdb.set_trace() self.AddMany([self.fontdd, self.bsize, self.bbold, self.bitalic, self.bunderline, self.bcolor, self.bbgcolor, self.bemote]) self.initover = True self.EnableFormattingButtons(formatOptions) self.UpdateDisplay() def OnContextMenu(self, event): from gui.uberwidgets.umenu import UMenu m = UMenu(self) m.AddItem(_('Hide Formatting Bar'), callback = lambda: wx.CallAfter(setpref, 'messaging.show_formatting_bar', False)) m.PopupMenu() def OnFontSelected(self, event): """ Updates the button to the new font and applies it to the selection or calls ApplyStlye """ self.textctrl.ApplyStyle(facename = self.fontdd.GetClientData(self.fontdd.GetSelection()).GetFaceName()) def OnSizeSelected(self, item): """ Updates the Size button to the new size and applies it to the selection or calls ApplyStyle """ self.bsize.label = str(item.id) self.textctrl.ApplyStyle(pointsize = item.id) def OnBoldButton(self, event): self.textctrl.ApplyStyle(bold = event.EventObject.IsActive()) def OnItalicButton(self, event): self.textctrl.ApplyStyle(italic = event.EventObject.IsActive()) def OnUnderlineButton(self, event): self.textctrl.ApplyStyle(underline = event.EventObject.IsActive()) def OnColorButton(self, event): oldtextcolor = self.textctrl.GetFormat().GetTextColour() self.textctrl.ApplyStyle(textcolor = wx.GetColourFromUser(self, oldtextcolor, _('Choose a foreground color'))) def OnBGColorButton(self, event): oldbgcolor = self.textctrl.GetFormat().GetTextColour() self.textctrl.ApplyStyle(bgcolor = wx.GetColourFromUser(self, oldbgcolor, _('Choose a background color'))) def OnEmoteButton(self, event): self.DisplayEmotibox(self.bemote.ScreenRect) def DisplayEmotibox(self, rect): import hooks hooks.notify('digsby.statistics.emoticons.box_viewed') ebox = self.GetEmotibox() # position and display the emotibox ebox.Display(rect) def GetEmotibox(self): 'Shares the emoticon box between all instances of this class.' b = None old_name, new_name = getattr(self, '_emotipack_name', None), pref('appearance.conversations.emoticons.pack', type = unicode, default = u'default') self._emotipack_name = new_name try: b = self.__class__.emotibox if not wx.IsDestroyed(b): if old_name != new_name: b.Destroy() elif b.Parent is not self: b.Reparent(self) except AttributeError: pass if b is None or wx.IsDestroyed(b): from gui.imwin.emoticons import get_emoticon_bitmaps b = self.__class__.emotibox = UberEmotiBox(self, get_emoticon_bitmaps(self._emotipack_name), self.textctrl, maxwidth = 12) else: b.SetTextCtrl(self.textctrl) return b def OnCursorMove(self, event): event.Skip() wx.CallAfter(self.UpdateDisplay) def UpdateDisplay(self): if wx.IsDestroyed(self.textctrl): return selection = self.textctrl.GetSelection() if selection[0] != selection[1]: return textattr = self.textctrl.GetFormat() font = textattr.GetFont() facename = font.GetFaceName() self.fontdd.SetSelection(self.fontdd.FindString(facename, False)) self.bsize.SetLabel(str(font.GetPointSize())) self.bbold.Active(font.GetWeight() == wx.FONTWEIGHT_BOLD) self.bitalic.Active(font.GetStyle() == wx.FONTSTYLE_ITALIC) self.bunderline.Active(font.GetUnderlined()) def EnableFormattingButtons(self, enabledict): if enabledict is None: return default = enabledict['default'] if 'default' in enabledict else True #TODO: fontdd should be disableable buttons = [#('font', self.fontdd), ('size', self.bsize), ('bold', self.bbold), ('italic', self.bitalic), ('underline', self.bunderline), ('color', self.bcolor), ('bgcolor', self.bbgcolor), ('emote', self.bemote)] for key, button in buttons: button.Enable(enabledict[key] if key in enabledict else default) def GenSizeItems(self, sizes = DEFAULT_SIZES): """ Sets the list of selectable sizes If not set sizes default to ['8', '10', '12', '14', '18', '24', '36'] """ return [SimpleMenuItem([str(size)], id=size, method = self.OnSizeSelected) for size in sizes] def DoUpdateSkin(self, skin): self.skinFB = skin ToolBar.DoUpdateSkin(self, SkinProxy(skin['toolbarskin'], ToolBarSkinDefaults)) icons = self.icons = {} icons['bold'] = skin['icons.bold'] icons['italic'] = skin['icons.italic'] icons['underline'] = skin['icons.underline'] icons['foregroundcolor'] = skin['icons.foregroundcolor'] icons['backgroundcolor'] = skin['icons.backgroundcolor'] icons['emote'] = skin['icons.emote'] iconsize = skin['iconsize'] for key in icons: if icons[key] is not None: icons[key] = icons[key].Resized(iconsize) if self.initover: self.bsize.SetStaticWidth(skin['sizedropdownwidth']) self.msize.SetWidth(skin['sizedropdownwidth']) self.bbold.SetIcon(icons['bold']) self.bitalic.SetIcon(icons['italic']) self.bunderline.SetIcon(icons['underline']) self.bcolor.SetIcon(icons['foregroundcolor']) self.bbgcolor.SetIcon(icons['backgroundcolor']) self.bemote.SetIcon(icons['emote']) def GetSkinProxy(self): return self.skinFB if hasattr(self, 'skinFB') else None
class Navi(wx.Panel): """ Container for in bar close button and navigation arrows """ def __init__(self, parent): """ standard fair """ wx.Panel.__init__(self, parent, style=0) events=[ (wx.EVT_PAINT,self.OnPaint), (wx.EVT_ERASE_BACKGROUND, lambda e:None), (wx.EVT_BUTTON, self.OnButton) ] do(self.Bind(event, method) for (event, method) in events) #make sizers self.Sizer=wx.BoxSizer(wx.HORIZONTAL) self.hsizer=wx.BoxSizer(wx.HORIZONTAL) self.vsizer=wx.BoxSizer(wx.VERTICAL) #make Buttons self.closebutton=UberButton(self, CLOSEID, skin=self.Parent.closebuttonskin, icon=self.Parent.closeicon) self.prevb=UberButton(self, PREVID, skin=self.Parent.scrollbuttonskin, icon=self.Parent.lefticon) self.nextb=UberButton(self, NEXTID, skin=self.Parent.scrollbuttonskin, icon=self.Parent.righticon) self.upb=UberButton(self, UPID, skin=self.Parent.scrollbuttonskin, icon=self.Parent.upicon) self.downb=UberButton(self, DOWNID, skin=self.Parent.scrollbuttonskin, icon=self.Parent.downicon) #add butons to sizers self.hsizer.Add(self.prevb, 0, wx.EXPAND) self.hsizer.Add(self.nextb, 0, wx.EXPAND) self.vsizer.Add(self.upb, 1, wx.EXPAND) self.vsizer.Add(self.downb, 1, wx.EXPAND) self.Sizer.Add(self.hsizer, 0, wx.EXPAND) self.Sizer.Add(self.closebutton, 0, wx.CENTER|wx.ALL, 5) #Hide all buttons self.prevb.Show(False) self.nextb.Show(False) self.upb.Show(False) self.downb.Show(False) self.closebutton.Show(pref('tabs.tabbar_x', False)) self.type=None # def UpdateSkin(self): # p = self.Parent # # self.closebutton.SetSkinKey(p.closeskin) # # self.closebutton.SetIcon(p.closeicon) # # scrollskin = p.scrollbuttonskin # # self.prevb.SetSkinKey(scrollskin) # self.nextb.SetSkinKey(scrollskin) # self.upb.SetSkinKey(scrollskin) # self.downb.SetSkinKey(scrollskin) # # self.prevb.SetIcon(p.lefticon) # self.nextb.SetIcon(p.righticon) # self.upb.SetIcon(p.upicon) # self.downb.SetIcon(p.downicon) def Enabler(self): """ Enable/Disable each button based off of acceptable scrolling """ self.prevb.Enable(self.Parent.tabindex>0) self.nextb.Enable(self.Parent.tabendex<self.Parent.GetTabCount()-1) self.upb.Enable(self.Parent.rowindex>0) self.downb.Enable(self.Parent.rowindex<len(self.Parent.rows)-pref('tabs.rows',2))#self.Parent.visible) def ShowNav(self, type=None): """ tells the navi which set of nav aroows to show type 0 - No arrows type 1 - left and right next to close button type 3 - up and down below close button """ #do nothing if no change if self.type==type: #self.Layout() return #hide everything in prep for change self.prevb.Show(False) self.nextb.Show(False) self.upb.Show(False) self.downb.Show(False) self.Sizer.Detach(self.vsizer) if not type:#No arrows self.Sizer.Detach(self.closebutton) self.Sizer.Add(self.closebutton, 0, wx.CENTER|wx.ALL, 5) self.prevb.Show(False) self.nextb.Show(False) elif type==1:#Horizantel Arrows self.Sizer.Detach(self.closebutton) self.Sizer.Add(self.closebutton, 0, wx.CENTER|wx.ALL, 5) self.Sizer.SetOrientation(wx.HORIZONTAL) self.prevb.Show(True) self.nextb.Show(True) elif type==3:#Vertical arrows self.Sizer.Detach(self.closebutton) self.Sizer.Add(self.closebutton, 0, wx.CENTER|wx.ALL, 5) self.Sizer.SetOrientation(wx.VERTICAL) self.Sizer.Add(self.vsizer, 1, wx.EXPAND) self.upb.Show(True) self.downb.Show(True) elif type==4:#sidebar mode, no arrows as they are part of TabBar self.prevb.Show(False) self.nextb.Show(False) self.Sizer.Detach(self.closebutton) self.Sizer.Add(self.closebutton, 0, wx.CENTER) self.type=type #self.Layout() def OnButton(self, event): """ Handels all events for any button clciked in the navi """ if event.GetId()==CLOSEID: self.Parent.Parent.pagecontainer.active.tab.Close() elif event.GetId()==PREVID: if self.Parent.tabindex>0: self.Parent.tabindex-=1 self.Parent.Regenerate(True) elif event.GetId()==NEXTID: endex=self.Parent.tabendex if endex<self.Parent.GetTabCount()-1: while self.Parent.tabendex==endex: self.Parent.tabindex+=1 self.Parent.Regenerate(True) elif event.GetId()==UPID: if self.Parent.rowindex>0: self.Parent.rowindex-=1 self.Parent.Regenerate(True) elif event.GetId()==DOWNID: if self.Parent.rowindex<len(self.Parent.rows)-pref('tabs.rows',2):#self.Parent.visible: self.Parent.rowindex+=1 self.Parent.Regenerate(True) self.Enabler() # SmokeAndMirrorsBomb(self,[self.prevb,self.nextb,self.upb,self.downb,self.closebutton]) self.Parent.Refresh() self.Parent.UpdateNotify() def OnPaint(self,event): dc=wx.PaintDC(self) rect=wx.RectS(self.Size) dc.Brush=wx.WHITE_BRUSH dc.Pen=wx.TRANSPARENT_PEN dc.DrawRectangleRect(rect)
def construct_gui(self): self.Sizer = wx.BoxSizer(wx.VERTICAL) s = self.subject_bar = UberBar(self, skinkey=self.subjectskin) self.subject_input = SkinTextCtrl( s, skinkey=('EmailSubjectBar', 'SubjectField'), skinkey_bg='EmailSubjectBar.FieldBackgroundColor', validator=LengthLimit(1024), ) self.subject_label = ClearText(s, _('Subject:'), alignment=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT) self.subject_label.Font = self.subjectfont self.subject_label.FontColor = self.subjectfc s.Add(self.subject_label) s.Add(self.subject_input, 1) # construct email buttons panel email_buttons = self.email_buttons = UberBar( self, skinkey=self.buttonbarskin) ept = self.email_progress_text = ClearText( email_buttons, '', alignment=wx.ALIGN_CENTER_VERTICAL) ept.SetFont(self.buttonbarfont) ept.SetFontColor(self.buttonnarfc) # email body text input self.email_input_area = wx.TextCtrl( self, style=wx.TE_MULTILINE, validator=LengthLimit(20480), ) # "open in" and "send" self.openin = UberButton(email_buttons, -1, _('Edit...'), onclick=self.OnEditEmail) self.send_button = UberButton(email_buttons, -1, _('Send'), onclick=self.OnSendClicked) # layout email buttons email_buttons.Add(ept) email_buttons.Add(wx.Size(1, 1), 1) #StretchSpacer(1) email_buttons.Add(self.openin) email_buttons.Add(self.send_button) # Make sure Tab from the subject input goes to the body input. self.email_input_area.MoveAfterInTabOrder(self.subject_bar) s = self.Sizer s.AddMany([(self.subject_bar, 0, wx.EXPAND), (self.email_input_area, 1, wx.EXPAND), (self.email_buttons, 0, wx.EXPAND)]) self.gui_constructed = True
class CapabilitiesBar(SimplePanel): ''' A specialized UberBar used used in the infobox and the IM window has a subbar with to/from combos. ''' def __init__(self, parent, buddy_callback, showCapabilities=True, infoboxmode=False): SimplePanel.__init__(self, parent) self.buddy_callback = buddy_callback self.Bind(wx.EVT_PAINT, lambda e: wx.PaintDC(self)) self.infoboxmode = infoboxmode self._lastcaps = None self.UpdateSkin() self.Sizer = wx.BoxSizer(wx.VERTICAL) # create delegates for callbacks for action in ('OnSendFiles', 'OnSendFolder', 'OnViewPastChats', 'OnAlert', 'OnBlock', 'OnAddContact'): setattr(self, action, Delegate()) # Create the uberbar for the capabilities. self.cbar = bar = UberBar(self, skinkey=self.capabilitiesskin, overflowmode=True) # FIXME: we should simply not allow the capabilities bar to be created for native mode if not showCapabilities or nativeIMWindow: self.cbar.Hide() if not infoboxmode: self.cbar.Bind(wx.EVT_CONTEXT_MENU, lambda e: self.ActionsBarMenu.PopupMenu(event=e)) # Create all the buttons for the capabilities bar. iconsize = skin.get('ActionsBar.IconSize') icons = skin.get('ActionsBar.Icons') for attr, title, tooltip in buttons: icon = getattr(icons, attr).Resized(iconsize) if attr == 'files': # "files" has a dropdown menu button = UberButton(bar, -1, title, icon=icon, type='menu', menu=self.FileMenu) # Change the label and action of the files button when it's overflowed into # the menu on the right. button.overflow_label = _('Send File') button.overflow_callback = self.OnSendFiles else: # hack until I fix this :[ -kevin if attr == 'video' and infoboxmode: continue button = UberButton(bar, -1, title, icon=icon) button.overflow_label = title button.SetToolTipString(tooltip) setattr(self, 'b' + attr, button) bar.Add(button, calcSize=False) bar.OnUBSize() #TODO Add button logics # if not self.infoboxmode: # self.badd = UberButton(bar,-1,'',icon = getattr(icons, 'add').Resized(iconsize)) # bar.AddStatic(self.badd) # self.badd.Bind(wx.EVT_BUTTON,lambda e: self.OnAddContact()) # Create multichat icon for the roomlist if pref('messaging.groupchat.enabled', False) and not self.infoboxmode: self.bmultichat = UberButton( bar, -1, icon=skin.get('actionsbar.icons.roomlist').Resized(16), type='toggle') self.bmultichat.SetToolTipString(_('Group Chat')) bar.AddStatic(self.bmultichat) self.ihistory = SimpleMenuItem(_('View Past Chats'), method=self.OnViewPastChats) def show_prefs_notifications(a): import gui.pref.prefsdialog as prefsdialog prefsdialog.show('notifications') self.ialert = SimpleMenuItem(_("Alert Me When..."), method=show_prefs_notifications) self.iblock = SimpleMenuItem(_("Block"), method=self.OnBlock) if not self.infoboxmode: self.iadd = SimpleMenuItem(_("Add Contact"), method=self.OnAddContact) bar.AddMenuItem(self.iadd) bar.AddMenuItem(self.ihistory) bar.AddMenuItem(self.ialert) if not self.infoboxmode: bar.AddMenuItem(SimpleMenuItem(id=-1)) bar.AddMenuItem(self.iblock) self.Sizer.Add(bar, 0, wx.EXPAND) # create the To/From bar self.tfbar = tfbar = UberBar(self, skinkey=self.tofromskin) self.tfbar.Hide() tofrom_font = skin.get('tofrombar.font', default_font) tofrom_color = skin.get('tofrombar.fontcolor', wx.BLACK) talign = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT self.to_label = ClearText(tfbar, _('To:'), alignment=talign) self.to_label.Font = tofrom_font self.to_label.FontColor = tofrom_color self.from_label = ClearText(tfbar, _('From:'), alignment=talign) self.from_label.Font = tofrom_font self.from_label.FontColor = tofrom_color self.cto = UberCombo(tfbar, skinkey=self.tofromcomboskin, typeable=False, size=(100, 20), minmenuwidth=200) self.cfrom = UberCombo(tfbar, skinkey=self.tofromcomboskin, typeable=False, size=(100, 20), minmenuwidth=200) tfbar.Add(self.to_label, calcSize=False) tfbar.Add(self.cto, True, calcSize=False) tfbar.Add(self.from_label, calcSize=False) tfbar.Add(self.cfrom, True) self.Sizer.Add(tfbar, 0, wx.EXPAND) profile.prefs.link(action_icons_key, self.UpdateIcons) self.cbar.overflowmenu.BeforeDisplay += self.ApplyCaps ToCombo = property(lambda self: self.cto) FromCombo = property(lambda self: self.cfrom) def UpdateSkin(self): 'Tells the subbars what skins they should load.' sget = skin.get self.capabilitiesskin = sget('actionsbar.toolbarskin', None) self.tofromskin = sget('tofrombar.toolbarskin', None) self.menuskin = sget('%s.menuskin' % self.capabilitiesskin, None) self.tofromcomboskin = sget("tofrombar.comboboxskin", None) self.iconsize = sget('ActionsBar.IconSize') self.icons = sget('ActionsBar.Icons') if hasattr(self, 'to_label'): tofrom_font = sget('tofrombar.font', lambda: default_font()) tofrom_color = sget('tofrombar.fontcolor', lambda: wx.BLACK) self.to_label.Font = self.from_label.Font = tofrom_font self.to_label.FontColor = self.from_label.FontColor = tofrom_color if hasattr(self, 'cbar'): self.cbar.SetSkinKey(self.capabilitiesskin) if hasattr(self, 'tfbar'): self.tfbar.SetSkinKey(self.tofromskin) if hasattr(self, 'cto'): self.cto.SetSkinKey(self.tofromcomboskin) if hasattr(self, 'cfrom'): self.cfrom.SetSkinKey(self.tofromcomboskin) self.UpdateIcons() def UpdateIcons(self, *a): 'Updates icon sizes for buttons.' icons_pref = pref(action_icons_key) textonly = icons_pref == 'text' icons = self.icons size = self.iconsize #TODO: Add Button logics # allbuttons = list(buttons) # allbuttons.append(('add','')) with self.Frozen(): for attr, title, tooltip in buttons: icon = None if textonly else getattr(icons, attr).Resized(size) button = getattr(self, 'b' + attr, None) if button is not None: button.SetIcon(icon) button.SetAlignment(wx.VERTICAL if icons_pref == 'above' else wx.HORIZONTAL) button.SetLabel('' if icons_pref == 'icons' else title) self.Parent.Layout() self.Refresh() def ShowToFrom(self, show=True): 'Show or hide the to/from bar.' return self.tfbar.Show(show) @property def RoomListButtonShown(self): bmultichat = getattr(self, 'bmultichat', None) return bmultichat is not None and bmultichat.IsShown() @property def ToFromShown(self): 'Returns True if the To/From bar is shown.' return self.tfbar.IsShown() def ShowCapabilities(self, show=True): 'Show/Hide the capabilities bar.' return self.cbar.Show(show) #self.Layout() def CapabilitiesIsShown(self): 'Returns True if the capabilities bar is shown.' return self.cbar.IsShown() def GetButton(self, button): 'Returns one of the butons by name.' return getattr(self, 'b' + button, None) def ApplyCaps(self, contact=None, convo=None): 'Those shows and hides options depending on the capabilities the Contact reports.' if contact is None and convo is None: convo = self.buddy_callback() from common.Conversation import Conversation if not isinstance(convo, Conversation): contact = convo convo = None c = None if convo is not None: if convo.ischat: c = set([caps.IM]) elif contact is None: contact = convo.buddy if c is None: c = set(contact.caps) if contact is not None: c.add(('blocked', contact.blocked)) # early exit if capabilities are the same. if c == self._lastcaps: return buttons_caps = [('binfo', contact is not None and not any( (contact.sms and contact.mobile, self.infoboxmode))), ('bim', caps.IM in c), ('bfiles', caps.FILES in c), ('bemail', caps.EMAIL in c), ('bsms', caps.SMS in c), ('bvideo', caps.VIDEO in c)] for name, val in buttons_caps: ctrl = getattr(self, name, None) if ctrl is not None: ctrl.Show(ctrl, val, False) cbar = self.cbar menu = cbar.overflowmenu count = menu.spine.items.count iblock = self.iblock if caps.BLOCKABLE in c and not count(iblock): cbar.AddMenuItem(SimpleMenuItem(id=-1)) cbar.AddMenuItem(iblock) elif not caps.BLOCKABLE in c and count(iblock): cbar.overflowmenu.RemoveItem(iblock) if contact is not None: if contact.blocked: content = _('Unblock {name}') else: content = _('Block {name}') iblock.content = [content.format(name=contact.name)] self.set_groupchat_visibility(contact, convo) i = len(menu.spine.items) - 1 if menu.GetItem(i).id == -1: menu.RemoveItem(i) # don't show the dropdown on the right for widgets. self.cbar.overflowbutton.Show(not getattr(contact, 'iswidget', False)) self._lastcaps = c cbar.GenWidthRestriction(True) self.update_add_contact_shown(convo) self.Parent.Layout() def update_add_contact_shown(self, convo): if not hasattr(self, 'iadd'): return ischat = convo is not None and convo.ischat overflow = self.cbar.overflowmenu if ischat: if overflow.GetIndex(self.iadd) != -1: overflow.RemoveItem(self.iadd) else: if overflow.GetIndex(self.iadd) == -1: overflow.InsertItem(overflow.GetIndex(self.ihistory), self.iadd) def set_groupchat_visibility(self, contact, convo): if not hasattr(self, 'bmultichat'): return proto = getattr(contact, 'protocol', getattr(convo, 'protocol', None)) groupchat = False if proto is not None: groupchat = getattr(proto, 'supports_group_chat', False) and getattr( contact, 'supports_group_chat', False) self.bmultichat.Show(groupchat) @property def FileMenu(self): self._filemenu = SimpleMenu(self, self.menuskin) self.send_file_item = SimpleMenuItem(_('Send File'), lambda *a: self.OnSendFiles()) # if b and b.online: self._filemenu.AppendItem(self.send_file_item) self._filemenu.AppendItem( SimpleMenuItem(_('Transfer History'), lambda *a: FileTransferDialog.Display())) return self._filemenu # try: # return self._filemenu # except AttributeError: # self._filemenu = self.build_file_menu() # return self._filemenu @property def ActionsBarMenu(self): try: return self._actionsbarmenu except AttributeError: self._actionsbarmenu = self.build_actionsbar_menu() return self._actionsbarmenu def build_actionsbar_menu(self): m = UMenu(self, onshow=self.update_actionsbar_menu) c = self._actionsbar_checks = {} for name, label in [('icons', _('Icons Only')), ('text', _('Text Only')), ('next', _('Icons Next to Text')), ('above', _('Icons Above Text'))]: def cb(name=name): with self.Frozen(): setpref(action_icons_key, name) c[name] = m.AddCheckItem(label, callback=cb) m.AddSep() m.AddItem( _('Hide Actions Bar'), callback=lambda: setpref('messaging.show_actions_bar', False)) return m def update_actionsbar_menu(self, menu): p = pref(action_icons_key) for name, item in self._actionsbar_checks.iteritems(): item.Check(p == name)
def __init__(self, parent, textctrl, skinkey, formatOptions): ToolBar.__init__(self, parent, skinkey = None, alignment = wx.ALIGN_LEFT) self.SetSkinKey(skinkey, FormattingBarSkinDefaults) self.textctrl = textctrl if sys.platform.startswith("win"): textctrl.Bind(EVT_SELECTION_CHANGED, self.OnCursorMove) textctrl.Bind(EVT_TEXT_FORMAT_CHANGED, self.OnCursorMove) self.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu) self.fontdd = FontDropDown(self, skinkey = self.skinTB['buttonskin']) self.fontdd.SetMenuSkinKey(self.skinTB["menuskin"]) self.fontdd.Bind(wx.EVT_COMMAND_CHOICE_SELECTED, self.OnFontSelected) icons = self.icons self.msize = SimpleMenu(self, self.skinTB['menuskin'], maxheight = 10) self.msize.SetItems(self.GenSizeItems(DEFAULT_SIZES)) #TODO: None default sizes # self.msize.Bind(wx.EVT_COMMAND_CHOICE_SELECTED, self.OnSizeSelected) self.bsize = UberButton(self, -1, '10', menu = self.msize, type = 'menu') self.bsize.SetStaticWidth(self.skinFB['sizedropdownwidth']) self.msize.SetWidth(self.skinFB['sizedropdownwidth']) self.bbold = UberButton(self, -1, icon = icons['bold'], type = 'toggle') self.bbold.Bind(wx.EVT_TOGGLEBUTTON, self.OnBoldButton) self.bitalic = UberButton(self, -1, icon = icons['italic'], type="toggle") self.bitalic.Bind(wx.EVT_TOGGLEBUTTON, self.OnItalicButton) self.bunderline = UberButton(self, -1, icon = icons['underline'], type="toggle") self.bunderline.Bind(wx.EVT_TOGGLEBUTTON, self.OnUnderlineButton) self.bcolor = UberButton(self, -1, icon = icons['foregroundcolor'] ) self.bcolor.Bind(wx.EVT_BUTTON, self.OnColorButton) self.bbgcolor = UberButton(self,-1, icon = icons['backgroundcolor']) self.bbgcolor.Bind(wx.EVT_BUTTON, self.OnBGColorButton) self.bemote = UberButton(self, -1, icon = icons['emote']) self.bemote.Bind(wx.EVT_BUTTON, self.OnEmoteButton) # import pdb # pdb.set_trace() self.AddMany([self.fontdd, self.bsize, self.bbold, self.bitalic, self.bunderline, self.bcolor, self.bbgcolor, self.bemote]) self.initover = True self.EnableFormattingButtons(formatOptions) self.UpdateDisplay()
def __init__(self, parent, buddy_callback, showCapabilities=True, infoboxmode=False): SimplePanel.__init__(self, parent) self.buddy_callback = buddy_callback self.Bind(wx.EVT_PAINT, lambda e: wx.PaintDC(self)) self.infoboxmode = infoboxmode self._lastcaps = None self.UpdateSkin() self.Sizer = wx.BoxSizer(wx.VERTICAL) # create delegates for callbacks for action in ('OnSendFiles', 'OnSendFolder', 'OnViewPastChats', 'OnAlert', 'OnBlock', 'OnAddContact'): setattr(self, action, Delegate()) # Create the uberbar for the capabilities. self.cbar = bar = UberBar(self, skinkey=self.capabilitiesskin, overflowmode=True) # FIXME: we should simply not allow the capabilities bar to be created for native mode if not showCapabilities or nativeIMWindow: self.cbar.Hide() if not infoboxmode: self.cbar.Bind(wx.EVT_CONTEXT_MENU, lambda e: self.ActionsBarMenu.PopupMenu(event=e)) # Create all the buttons for the capabilities bar. iconsize = skin.get('ActionsBar.IconSize') icons = skin.get('ActionsBar.Icons') for attr, title, tooltip in buttons: icon = getattr(icons, attr).Resized(iconsize) if attr == 'files': # "files" has a dropdown menu button = UberButton(bar, -1, title, icon=icon, type='menu', menu=self.FileMenu) # Change the label and action of the files button when it's overflowed into # the menu on the right. button.overflow_label = _('Send File') button.overflow_callback = self.OnSendFiles else: # hack until I fix this :[ -kevin if attr == 'video' and infoboxmode: continue button = UberButton(bar, -1, title, icon=icon) button.overflow_label = title button.SetToolTipString(tooltip) setattr(self, 'b' + attr, button) bar.Add(button, calcSize=False) bar.OnUBSize() #TODO Add button logics # if not self.infoboxmode: # self.badd = UberButton(bar,-1,'',icon = getattr(icons, 'add').Resized(iconsize)) # bar.AddStatic(self.badd) # self.badd.Bind(wx.EVT_BUTTON,lambda e: self.OnAddContact()) # Create multichat icon for the roomlist if pref('messaging.groupchat.enabled', False) and not self.infoboxmode: self.bmultichat = UberButton( bar, -1, icon=skin.get('actionsbar.icons.roomlist').Resized(16), type='toggle') self.bmultichat.SetToolTipString(_('Group Chat')) bar.AddStatic(self.bmultichat) self.ihistory = SimpleMenuItem(_('View Past Chats'), method=self.OnViewPastChats) def show_prefs_notifications(a): import gui.pref.prefsdialog as prefsdialog prefsdialog.show('notifications') self.ialert = SimpleMenuItem(_("Alert Me When..."), method=show_prefs_notifications) self.iblock = SimpleMenuItem(_("Block"), method=self.OnBlock) if not self.infoboxmode: self.iadd = SimpleMenuItem(_("Add Contact"), method=self.OnAddContact) bar.AddMenuItem(self.iadd) bar.AddMenuItem(self.ihistory) bar.AddMenuItem(self.ialert) if not self.infoboxmode: bar.AddMenuItem(SimpleMenuItem(id=-1)) bar.AddMenuItem(self.iblock) self.Sizer.Add(bar, 0, wx.EXPAND) # create the To/From bar self.tfbar = tfbar = UberBar(self, skinkey=self.tofromskin) self.tfbar.Hide() tofrom_font = skin.get('tofrombar.font', default_font) tofrom_color = skin.get('tofrombar.fontcolor', wx.BLACK) talign = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT self.to_label = ClearText(tfbar, _('To:'), alignment=talign) self.to_label.Font = tofrom_font self.to_label.FontColor = tofrom_color self.from_label = ClearText(tfbar, _('From:'), alignment=talign) self.from_label.Font = tofrom_font self.from_label.FontColor = tofrom_color self.cto = UberCombo(tfbar, skinkey=self.tofromcomboskin, typeable=False, size=(100, 20), minmenuwidth=200) self.cfrom = UberCombo(tfbar, skinkey=self.tofromcomboskin, typeable=False, size=(100, 20), minmenuwidth=200) tfbar.Add(self.to_label, calcSize=False) tfbar.Add(self.cto, True, calcSize=False) tfbar.Add(self.from_label, calcSize=False) tfbar.Add(self.cfrom, True) self.Sizer.Add(tfbar, 0, wx.EXPAND) profile.prefs.link(action_icons_key, self.UpdateIcons) self.cbar.overflowmenu.BeforeDisplay += self.ApplyCaps
class ImWinEmailPanel(SimplePanel): def __init__(self, parent): SimplePanel.__init__(self, parent) self.OnEditEmail = Delegate() self.OnSendEmail = Delegate() self.gui_constructed = False self.UpdateSkin() self.construct_gui() def SetEmailClient(self, email_account): ''' Changes the "Edit In..." button to show the name of an email client. If None, the button becomes disabled. ''' client = email_account.client_name if email_account is not None else None if client is not None: self.send_button.Enable(True) self.openin.Enable(True) if client: label = _('Edit in {client}...').format(client=client) else: label = _('Edit...') self.openin.SetLabel(label) else: self.send_button.Enable(False) self.openin.Enable(False) self.openin.SetLabel(_('Edit...')) def UpdateSkin(self): g = skin.get self.buttonbarskin = g('SendBar.ToolBarSkin', None) self.subjectskin = g('EmailSubjectBar.ToolBarSkin', None) self.subjectfont = g('EmailSubjectBar.Fonts.SubjectLabel', lambda: default_font()) self.subjectfc = g('EmailSubjectBar.FontColors.SubjectLabel', wx.BLACK) self.buttonbarfont = g('SendBar.Font', default_font) self.buttonnarfc = g('SendBar.FontColor', wx.BLACK) if self.gui_constructed: self.subject_bar.SetSkinKey(self.subjectskin) self.email_buttons.SetSkinKey(self.buttonbarskin) ept = self.email_progress_text ept.SetFont(self.buttonbarfont) ept.SetFontColor(self.buttonnarfc) sl = self.subject_label sl.SetFont(self.subjectfont) sl.SetFontColor(self.subjectfc) def construct_gui(self): self.Sizer = wx.BoxSizer(wx.VERTICAL) s = self.subject_bar = UberBar(self, skinkey=self.subjectskin) self.subject_input = SkinTextCtrl( s, skinkey=('EmailSubjectBar', 'SubjectField'), skinkey_bg='EmailSubjectBar.FieldBackgroundColor', validator=LengthLimit(1024), ) self.subject_label = ClearText(s, _('Subject:'), alignment=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT) self.subject_label.Font = self.subjectfont self.subject_label.FontColor = self.subjectfc s.Add(self.subject_label) s.Add(self.subject_input, 1) # construct email buttons panel email_buttons = self.email_buttons = UberBar( self, skinkey=self.buttonbarskin) ept = self.email_progress_text = ClearText( email_buttons, '', alignment=wx.ALIGN_CENTER_VERTICAL) ept.SetFont(self.buttonbarfont) ept.SetFontColor(self.buttonnarfc) # email body text input self.email_input_area = wx.TextCtrl( self, style=wx.TE_MULTILINE, validator=LengthLimit(20480), ) # "open in" and "send" self.openin = UberButton(email_buttons, -1, _('Edit...'), onclick=self.OnEditEmail) self.send_button = UberButton(email_buttons, -1, _('Send'), onclick=self.OnSendClicked) # layout email buttons email_buttons.Add(ept) email_buttons.Add(wx.Size(1, 1), 1) #StretchSpacer(1) email_buttons.Add(self.openin) email_buttons.Add(self.send_button) # Make sure Tab from the subject input goes to the body input. self.email_input_area.MoveAfterInTabOrder(self.subject_bar) s = self.Sizer s.AddMany([(self.subject_bar, 0, wx.EXPAND), (self.email_input_area, 1, wx.EXPAND), (self.email_buttons, 0, wx.EXPAND)]) self.gui_constructed = True def OnSendClicked(self, e): self.OnSendEmail(e) def Clear(self): self.subject_input.Clear() self.email_input_area.Clear() def SetStatusMessage(self, msg): self.email_progress_text.SetLabel(msg) def EnableSendButton(self, enabled): self.send_button.Enable(enabled)
def __init__(self,parent): SimplePanel.__init__(self, parent, wx.FULL_REPAINT_ON_RESIZE) self.BackgroundColour = wx.WHITE self.Sizer = wx.BoxSizer(HORIZONTAL) sz = wx.BoxSizer(HORIZONTAL) self.Sizer.Add(sz,1,EXPAND|ALL,3) leftcol = wx.BoxSizer(VERTICAL) acctcombo = self.acctcombo = UberCombo(self, value='',skinkey='AppDefaults.PrefCombo') acctcont = PrefPanel(self,acctcombo,_('Account')) leftcol.Add(acctcont,0,EXPAND|ALL,3) buddylist = self.buddylist = ListOBuddies(self) self.buddies_panel = buddycont = PrefPanel(self, buddylist, _('Buddy')) leftcol.Add(buddycont, 1, EXPAND | TOPLESS, 3) style = wx.NO_BORDER | CAL_SUNDAY_FIRST | CAL_SEQUENTIAL_MONTH_SELECTION | CAL_SHOW_HOLIDAYS cal = self.cal = CalendarCtrl(self, -1, wx.DateTime.Now(), wx.DefaultPosition, wx.DefaultSize, style) cal.SetForegroundColour(wx.Color(160, 160, 160)) cal.SetHolidayColours(wx.BLACK, wx.WHITE) cal.SetHeaderColours(Color(160, 160, 160), Color(239, 239, 239)) calcont = PrefPanel(self,cal,_('Date')) leftcol.Add(calcont, 0, EXPAND | TOPLESS, 3) sz.Add(leftcol, 0, EXPAND) viewpanel = wx.Panel(self) viewer = self.viewer = PastBrowserWebkitWindow(viewpanel) # viewer.SetMouseWheelZooms(True) finder = self.finder = FindBar(viewpanel,viewer) menu = UMenu(viewer) menu.AddItem(_('Copy'), id = wx.ID_COPY, callback = lambda *a: viewer.Copy()) viewer.BindWheel(self) viewer.BindScrollWin(self) viewer.Bind(wx.EVT_CONTEXT_MENU, lambda e: (menu.GetItemById(wx.ID_COPY).Enable(viewer.CanCopy()), menu.PopupMenu(event = e))) viewer.Bind(wx.EVT_KEY_DOWN,self.OnKeyDown) finder.TextControl.Bind(wx.EVT_KEY_DOWN,self.OnKeyDown) nav = BoxSizer(wx.HORIZONTAL) prev = self.prev = UberButton(viewpanel, label = '<-', skin = BUTTON_SKIN) next = self.next = UberButton(viewpanel, label = '->', skin = BUTTON_SKIN) datelabel = wx.StaticText(viewpanel, -1, style = wx.ALIGN_CENTER| wx.ST_NO_AUTORESIZE) datelabel.SetMinSize((140, -1)) prev.Bind(wx.EVT_BUTTON, lambda e: self.Flip(-1)) next.Bind(wx.EVT_BUTTON, lambda e: self.Flip( 1)) nav.AddStretchSpacer(1) nav.AddMany([(prev, 0, wx.EXPAND | wx.ALIGN_CENTER), (datelabel, 0, wx.EXPAND | wx.ALIGN_CENTER), (next, 0, wx.EXPAND | wx.ALIGN_CENTER)]) nav.AddStretchSpacer(1) viewpanel.Sizer = wx.BoxSizer(wx.VERTICAL) viewpanel.Sizer.AddMany([ (nav, 0, EXPAND), (viewer, 1, EXPAND), (finder, 0, EXPAND) ]) sz.Add(PrefPanel(self, viewpanel, _('Conversation Log')), 1, EXPAND | ALL, 3) Bind = self.Bind Bind(wx.EVT_PAINT, self.OnPaint) def OnAcct(*a): ''' Handle selection of a new account from the Account drop down ''' if self.GroupChatsSelected(): from collections import defaultdict self.groupchats = defaultdict(list) for g in GetGroupChats(): d = g['time'] key = DateTimeFromDMY(d.day, d.month-1, d.year) self.groupchats[key].append(g) #dates = sorted((g['date'], g) for g in self.dates = sorted(self.groupchats.keys()) UpdateCal() self.buddies_panel.SetTitle(_('Chats')) else: buddylist.SetList(GetBuddies(acctcombo.Value.id), BuddyRenderer()) OnBuddy() self.buddies_panel.SetTitle(_('Buddy')) def OnBuddy(*a): ''' Handels selection of a buddy from the buddy pannel ''' if not self.GroupChatsSelected(): self.dates = GetDates(buddylist.SelectedBuddy.dir) UpdateCal() else: ViewLogForFile(buddylist.SelectedItem['file'], do_aliases=False) def UpdateCal(): ''' Switches the date to the last date conversed with the selected budy ''' self.next.Enable(True) self.prev.Enable(True) if self.dates: self.cal.Date = self.dates[-1] self.cal.Enable(True) OnCalChange() def OnCalChange(*a): ''' Update the Calendar UI to a new date ''' caldate = cal.Date currentyear = caldate.GetYear() currentmonth = caldate.GetMonth() relevantdates = frozenset(date.GetDay() for date in self.dates if date.GetYear() == currentyear and date.GetMonth() == currentmonth and date.GetDay()) SetHoliday, SetAttr = cal.SetHoliday, cal.SetAttr for i in xrange(1, 32): if i in relevantdates: SetHoliday(i) else: SetAttr(i, CalendarDateAttr(Color(160,160,160))) OnDayChange() self.OnCalChange = OnCalChange def ViewLogForDay(date): ''' Load the log file for the specified date for the currently selected buddy ''' logpath = logpath_for_date(buddylist.SelectedBuddy, date) ViewLogForFile(logpath) def ViewLogForFile(logpath, do_aliases=True): ''' Update the log viewer with the file specified ''' with viewer.Frozen(): viewer.SetPageSource(logpath.text('utf-8', 'replace'), logpath.url()) viewer.RunScript('window.scroll(0, 0);') if do_aliases: substitue_aliases() import hooks hooks.notify('digsby.statistics.logviewer.log_viewed') def substitue_aliases(): ''' Swap out buddy names with their allies ''' import gui with open(gui.skin.resourcedir() / 'html' / 'jquery-1.3.2.js', 'rb') as f: viewer.RunScript(f.read()) buddy = buddylist.SelectedBuddy aliases = IAliasProvider(profile()) import simplejson as json names = set(json.loads(viewer.RunScript("var foo = []; $('.buddy').each(function(){foo.push($(this).html())}); JSON.stringify(foo);"))) for name in names: alias = aliases.get_alias(name, buddy.service, buddy.protocol) or name viewer.RunScript(SUBHTML % (json.dumps(name), json.dumps(alias))) def OnDayChange(*a): ''' Show the log for the day selected in the clander ''' date = cal.Date self.date = date datelabel.SetLabel(date.FormatDate()) if cal.GetAttr(date.GetDay()).IsHoliday(): if self.GroupChatsSelected(): chats = sorted(self.groupchats[date], key=lambda g: g['time'], reverse=True) buddylist.SetList(chats, GroupChatRenderer()) if chats: ViewLogForFile(chats[0]['file'], do_aliases=False) else: ViewLogForDay(date) else: year = str(date.GetYear()) month = date.GetMonth() month = wx.DateTime.GetMonthName(int(month)) day = str(date.GetDay()) specific_day_string = _('{month}, {day}, {year}').format(month=month, day=day, year=year) if self.GroupChatsSelected(): msg = _("There are no chat logs for {specific_day_string}.").format(specific_day_string=specific_day_string) else: msg = _("There are no chat logs for {specific_day_string} with {name}.").format(specific_day_string=specific_day_string, name=buddylist.SelectedBuddy.name) viewer.SetPageSource(msg, 'file:///C:/') viewer.SetFocus() wx.CallAfter(cal.Refresh) self.OnDayChange = OnDayChange acctcombo.SetCallbacks(value = OnAcct) buddylist.Bind(wx.EVT_LISTBOX, OnBuddy) cBind = cal.Bind cBind(EVT_CALENDAR_YEAR, OnCalChange) cBind(EVT_CALENDAR_MONTH, OnCalChange) cBind(EVT_CALENDAR_SEL_CHANGED, OnDayChange) acctcombo.SetItems(MakeAccountItems(), 0)