home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 February / maximum-cd-2011-02.iso / DiscContents / digsby_setup85.exe / lib / gui / imwin / imtabs.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-11-24  |  25.6 KB  |  704 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. from wx import PyDeadObjectError
  6.  
  7. try:
  8.     _
  9. except:
  10.     import gettext
  11.     gettext.install('Digsby')
  12.  
  13. import wx
  14. import hooks
  15. from wx.lib import pubsub
  16. import config
  17. from gui import skin
  18. from gui.uberwidgets.uberbook.tabmanager import TabWindowManager
  19. from gui.uberwidgets.uberbook.UberBook import NoteBook
  20. from gui.toolbox import draw_tiny_text
  21. from PIL import Image
  22. from gui.windowfx import fadein
  23. from common import setpref, pref, profile, bind, prefprop
  24. from util import traceguard, default_timer
  25. from util.primitives.structures import oset
  26. from util.primitives.funcs import Delegate
  27. from gui.uberwidgets.UberEvents import EVT_TAB_NOTIFIED
  28. from gui.toolbox import saveWindowPos, preLoadWindowPos, snap_pref
  29. from gui.native import memory_event
  30. IMWIN_STAT_IDLE_TIME = 5 * 60 * 1000
  31. IMFRAME_MINSIZE = (320, 220)
  32. CLOSETABS_TITLE = _('Close IM Window')
  33. CHECKBOX_TEXT = _('Warn me when I attempt to close multiple conversations')
  34. CLOSETABS_MSG = _('You are about to close %d conversations.  Are you sure you want to continue?')
  35. CLOSE_BUTTON_TEXT = _('Close &tabs')
  36. WARN_PREF = 'messaging.tabs.warn_on_close'
  37. IMWIN_ALWAYS_ON_TOP_PREF = 'conversation_window.always_on_top'
  38.  
  39. def explodeAllWindows():
  40.     ImFrame = ImFrame
  41.     import gui.imwin.imtabs
  42.     newtabs = 0
  43.     for win in (lambda .0: for w in .0:
  44. if isinstance(w, ImFrame):
  45. wcontinue)(wx.GetTopLevelWindows()):
  46.         for page in win.notebook.Pages()[1:]:
  47.             newtabs += 1
  48.             pos = wx.Point(30, 30) + (20 * newtabs, 20 * newtabs)
  49.             win.notebook.Remove(page)
  50.             newwin = win.notebook.winman.NewWindow(pos)
  51.             newwin.notebook.Insert(page)
  52.         
  53.         win.notebook.Refresh()
  54.     
  55.  
  56.  
  57. class CloseTabsDialog(wx.Dialog):
  58.     
  59.     def WarnMe(self):
  60.         return self.panel.warn_cb.Value
  61.  
  62.     WarnMe = property(WarnMe)
  63.     
  64.     def __init__(self, parent, num_tabs, warn_value = True):
  65.         wx.Dialog.__init__(self, parent, title = CLOSETABS_TITLE)
  66.         self.panel = CloseTabsPanel(self, num_tabs, warn_value)
  67.         self.Sizer = wx.BoxSizer(wx.VERTICAL)
  68.         self.Sizer.Add(self.panel, 1, wx.EXPAND)
  69.         self.Fit()
  70.  
  71.  
  72.  
  73. class CloseTabsPanel(wx.Panel):
  74.     
  75.     def __init__(self, parent, num_tabs, warnme_value = True):
  76.         wx.Panel.__init__(self, parent)
  77.         self.Bind(wx.EVT_PAINT, self.OnPaint)
  78.         self.warn_cb = warn_cb = wx.CheckBox(self, -1, CHECKBOX_TEXT)
  79.         warn_cb.SetValue(warnme_value)
  80.         msgsizer = wx.BoxSizer(wx.VERTICAL)
  81.         self.close_msg = wx.StaticText(self, -1, CLOSETABS_MSG % num_tabs)
  82.         msgsizer.Add(self.close_msg, 0, wx.EXPAND | wx.SOUTH, 8)
  83.         msgsizer.Add(warn_cb, 0, wx.EXPAND)
  84.         h = wx.BoxSizer(wx.HORIZONTAL)
  85.         self.bitmap = wx.ArtProvider.GetBitmap(wx.ART_QUESTION)
  86.         self.bitmap.SetMaskColour(wx.BLACK)
  87.         h.Add((self.bitmap.Width, self.bitmap.Height), 0, wx.EXPAND | wx.ALL, 9)
  88.         h.Add(msgsizer, 0, wx.EXPAND | wx.ALL, 12)
  89.         close_button = wx.Button(self, wx.ID_OK, CLOSE_BUTTON_TEXT)
  90.         close_button.SetDefault()
  91.         close_button.SetFocus()
  92.         cancel_button = wx.Button(self, wx.ID_CANCEL, _('&Cancel'))
  93.         buttonsizer = wx.BoxSizer(wx.HORIZONTAL)
  94.         buttonsizer.AddStretchSpacer(1)
  95.         buttonsizer.Add(close_button, 0, wx.RIGHT, 6)
  96.         buttonsizer.Add(cancel_button)
  97.         buttonsizer.AddStretchSpacer(1)
  98.         s = self.Sizer = wx.BoxSizer(wx.VERTICAL)
  99.         s.Add(h, 0, wx.EXPAND | wx.ALL)
  100.         s.Add(buttonsizer, 0, wx.EXPAND | wx.BOTTOM, 12)
  101.  
  102.     
  103.     def OnPaint(self, e):
  104.         dc = wx.PaintDC(self)
  105.         pos = self.close_msg.Position
  106.         dc.DrawBitmap(self.bitmap, pos.x - self.bitmap.Width - 10, pos.y, True)
  107.  
  108.  
  109. from gui.native.toplevel import FlashOnce, Flash
  110.  
  111. class TitleBarTimer(wx.Timer):
  112.     shouldFlash = prefprop('conversation_window.notify_flash')
  113.     cyclePause = prefprop('conversation_window.unread_cycle_pause')
  114.     
  115.     def __init__(self, win, tabs):
  116.         wx.Timer.__init__(self)
  117.         self.win = win
  118.         self.tabs = tabs
  119.         self.index = 0
  120.  
  121.     
  122.     def Start(self):
  123.         self.title = self.win.Title
  124.         wx.Timer.Start(self, self.cyclePause)
  125.  
  126.     
  127.     def Notify(self):
  128.         win = self.win
  129.         tabs = self.tabs
  130.         if wx.IsDestroyed(win):
  131.             self.Stop()
  132.             return None
  133.         if not win.IsActive() and len(tabs):
  134.             tabNum = len(tabs)
  135.             if self.index >= tabNum:
  136.                 self.index = 0
  137.             
  138.             tab = tabs[self.index]
  139.             if not wx.IsDestroyed(tab):
  140.                 win.SetTitle('*' + tab.label1)
  141.                 self.index += 1
  142.             else:
  143.                 tabs.remove(tab)
  144.             if self.shouldFlash:
  145.                 FlashOnce(win)
  146.             
  147.         else:
  148.             self.Stop()
  149.  
  150.     
  151.     def Stop(self):
  152.         wx.Timer.Stop(self)
  153.         if not wx.IsDestroyed(self.win):
  154.             self.win.SetTitle(self.title)
  155.         
  156.         self.index = 0
  157.  
  158.  
  159.  
  160. class SkinnedNotebookPanel(wx.Panel):
  161.     
  162.     def __init__(self, *args, **kwargs):
  163.         preview = kwargs.pop('preview', None)
  164.         wx.Panel.__init__(self, *args, **kwargs)
  165.         self.notebook = NoteBook(self, skinkey = 'Tabs', preview = preview)
  166.         sz = self.Sizer = wx.BoxSizer(wx.VERTICAL)
  167.         sz.Add(self.notebook, 1, wx.EXPAND)
  168.  
  169.  
  170.  
  171. class SkinnedIMFrameEventHandler(wx.EvtHandler):
  172.     
  173.     def __init__(self, frame):
  174.         wx.EvtHandler.__init__(self)
  175.         self.frame = frame
  176.         self.notebook = self.frame.notebookPanel.notebook
  177.         self.mergetimer = None
  178.         self.notifiedtabs = oset()
  179.         self.titletimer = TitleBarTimer(self.frame, self.notifiedtabs)
  180.         self.BindEventsToFrame()
  181.  
  182.     
  183.     def BindEventsToFrame(self):
  184.         Bind = self.frame.Bind
  185.         Bind(wx.EVT_CLOSE, self.OnClose)
  186.         Bind(wx.EVT_MOVE, self.OnMove)
  187.         Bind(wx.EVT_SIZE, self.OnSize)
  188.         Bind(wx.EVT_ACTIVATE, self.OnActivate)
  189.         Bind(EVT_TAB_NOTIFIED, self.OnTabNotify)
  190.         publisher = pubsub.Publisher()
  191.         publisher.subscribe(self.OnPageTitleUpdated, 'tab.title.updated')
  192.         publisher.subscribe(self.OnPageIconUpdated, 'tab.icon.updated')
  193.  
  194.     
  195.     def OnClose(self, event):
  196.         if self.frame.CloseAndSaveState(event):
  197.             self.frame.Destroy()
  198.         else:
  199.             event.Veto()
  200.  
  201.     
  202.     def OnActivate(self, e):
  203.         e.Skip()
  204.         if e.GetActive():
  205.             tab = self.notebook.ActiveTab
  206.             if tab is not None:
  207.                 tab.SetNotify(False)
  208.                 tab.page.Content.FocusTextCtrl()
  209.             
  210.         
  211.         if self.titletimer.IsRunning():
  212.             self.titletimer.Stop()
  213.         
  214.  
  215.     
  216.     def OnPageIconUpdated(self, message):
  217.         (page, icon) = message.data
  218.         if not (self.frame) or wx.IsDestroyed(self.frame):
  219.             return None
  220.         for mypage in self.frame.notebook.Pages():
  221.             if mypage == page and self.frame.notebook.ActiveTab == mypage.tab:
  222.                 self.frame.SetFrameIcon(icon)
  223.                 continue
  224.             wx.IsDestroyed(self.frame)
  225.         
  226.  
  227.     
  228.     def OnPageTitleUpdated(self, message):
  229.         if not (self.frame) or wx.IsDestroyed(self.frame):
  230.             return None
  231.         (imwin, title, window_title) = message.data
  232.         imwin.SetName(title)
  233.         page = None
  234.         for mypage in self.frame.notebook.Pages():
  235.             if mypage.Content is imwin:
  236.                 page = mypage
  237.                 continue
  238.             wx.IsDestroyed(self.frame)
  239.         
  240.         if page is None or page.tab is not self.frame.notebook.ActiveTab:
  241.             return None
  242.         if window_title is not None:
  243.             frame_title = window_title
  244.         else:
  245.             frame_title = title
  246.         if self.titletimer.IsRunning():
  247.             self.titletimer.title = frame_title
  248.         else:
  249.             self.frame.SetTitle(frame_title)
  250.  
  251.     flashTime = prefprop('conversation_window.flash_time')
  252.     flashCount = prefprop('conversation_window.flash_count')
  253.     
  254.     def OnTabNotify(self, event):
  255.         tab = event.tab
  256.         if tab.notified:
  257.             self.notifiedtabs.add(tab)
  258.             notify_unread_message_hook()
  259.         elif tab in self.notifiedtabs:
  260.             self.notifiedtabs.remove(tab)
  261.             notify_unread_message_hook()
  262.             return None
  263.         return None
  264.         if not self.frame.cycleTitle:
  265.             if self.frame.shouldFlash:
  266.                 Flash(self.frame, timeout = self.flashTime, count = self.flashCount)
  267.             
  268.             return None
  269.         if len(self.notifiedtabs) and not self.frame.IsActive():
  270.             if not self.titletimer.IsRunning():
  271.                 self.titletimer.Start()
  272.             
  273.         elif self.titletimer.IsRunning():
  274.             self.titletimer.Stop()
  275.         
  276.  
  277.     
  278.     def OnMove(self, event):
  279.         event.Skip(True)
  280.         if pref('messaging.tabs.enabled', True):
  281.             mt = self.mergetimer
  282.             if mt is None:
  283.                 self.mergetimer = wx.CallLater(10, self.notebook.StartWindowDrag)
  284.             else:
  285.                 mt.Start(10)
  286.         
  287.         event.Skip(True)
  288.  
  289.     
  290.     def OnSize(self, event):
  291.         mt = self.mergetimer
  292.         if mt is not None:
  293.             mt.Stop()
  294.         
  295.         event.Skip(True)
  296.  
  297.  
  298. highlight_color = wx.Color(255, 214, 72)
  299. _highlight_bitmap = None
  300.  
  301. def get_highlight_bitmap():
  302.     global _highlight_bitmap
  303.     if _highlight_bitmap is None:
  304.         import PIL.Image as PIL
  305.         _highlight_bitmap = PIL.Image.new('RGBA', (5, 5), (226, 214, 139, 255)).WXB
  306.     
  307.     return _highlight_bitmap
  308.  
  309. if config.platform == 'win':
  310.     from gui.uberwidgets.uberbook.UberBook import UberBookTabController
  311.     from gui.buddylist.renderers import get_buddy_icon
  312.     
  313.     def icon_for_tab(tab, width, height):
  314.         window = tab.Window
  315.         if window.ischat:
  316.             return skin.get('actionsbar.icons.roomlist')
  317.         buddy = window.Buddy
  318.         notified = window.Tab.notified
  319.         icon = get_buddy_icon(buddy, size = height, round_size = 0, grey_offline = True, meta_lookup = True)
  320.         return icon.WXB
  321.  
  322.     
  323.     class ImTabController(UberBookTabController):
  324.         
  325.         def GetSmallIcon(self, tab):
  326.             bitmap = im_badge(tab.Window)
  327.             window = tab.Window
  328.             if not (window.ischat) and bitmap is None:
  329.                 bitmap = skin.get('statusicons.' + tab.Window.Buddy.status_orb, None).Resized((16, 16))
  330.             elif window.ischat:
  331.                 bitmap = window.chat_icon
  332.             
  333.             if bitmap is not None:
  334.                 return wx.IconFromBitmap(bitmap.WXB)
  335.             return wx.IconFromBitmap(wx.NullBitmap)
  336.  
  337.         
  338.         def GetIconicHBITMAP(self, tab, width, height):
  339.             import cgui
  340.             icon = icon_for_tab(tab, width, height)
  341.             notified = tab.Window.Tab.notified
  342.             highlight = None if notified else wx.NullBitmap
  343.             if icon is not None:
  344.                 return cgui.getBuddyPreview((width, height), icon, highlight)
  345.  
  346.         
  347.         def GetLivePreview(self, tab, rect):
  348.             overlay = skin.get('AppDefaults.TaskBarIcon')
  349.             bitmap = wx.EmptyBitmap(rect.width, rect.height, False)
  350.             dc = wx.MemoryDC(bitmap)
  351.             overlay.Resized(1).Draw(dc, wx.Rect(0, 0, 1, 1))
  352.             dc.SelectObject(wx.NullBitmap)
  353.             return bitmap
  354.  
  355.  
  356.  
  357.  
  358. class ImFrame(wx.Frame):
  359.     WindowName = u'IM Window'
  360.     
  361.     def __init__(self, pos = None, size = None, startMinimized = False, posId = ''):
  362.         if pref('imwin.ads', type = bool, default = False):
  363.             defaultSize = wx.Size(490, 470)
  364.         else:
  365.             defaultSize = wx.Size(470, 390)
  366.         (wininfo, placement) = preLoadWindowPos(ImFrame.WindowName, uniqueId = posId, defaultPos = wx.Point(200, 200), defaultSize = defaultSize)
  367.         wininfo['style'] |= wx.DEFAULT_FRAME_STYLE
  368.         setPos = pos is not None
  369.         setSize = size is not None
  370.         if setPos or setSize:
  371.             wininfo['style'] &= ~(wx.MAXIMIZE)
  372.         
  373.         if startMinimized:
  374.             wininfo['style'] |= wx.ICONIZE
  375.             self._starting_minimized = True
  376.         
  377.         if pref('imwin.ads', default = False):
  378.             wininfo['style'] |= wx.FULL_REPAINT_ON_RESIZE
  379.         
  380.         wx.Frame.__init__(self, parent = None, name = ImFrame.WindowName, **wininfo)
  381.         self.on_engaged_start = Delegate()
  382.         self.on_engaged_end = Delegate()
  383.         self.on_sent_message = Delegate()
  384.         if config.nativeIMWindow:
  385.             import gui.imwin.imwin_native as gui
  386.             self.notebookPanel = gui.imwin.imwin_native.NativeNotebookPanel(self, -1)
  387.             self.eventHandler = gui.imwin.imwin_native.NativeIMFrameEventHandler(self)
  388.         else:
  389.             preview = None
  390.             if config.platform == 'win':
  391.                 preview = ImTabController
  392.             
  393.             self.notebookPanel = SkinnedNotebookPanel(self, -1, preview = preview)
  394.             self.eventHandler = SkinnedIMFrameEventHandler(self)
  395.         self.notebook.winman = TabWindowManager((lambda pos, size = None: ImFrame(pos = pos, size = size)))
  396.         if placement is not None:
  397.             if not setPos:
  398.                 pass
  399.         if setPos:
  400.             self.Position = pos
  401.         
  402.         if setSize:
  403.             self.Size = size
  404.         
  405.         if not config.nativeIMWindow:
  406.             self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
  407.         
  408.         self.posId = posId
  409.         self.EnsureInScreen()
  410.         if pos is not None:
  411.             wx.CallAfter(self.EnsureNotStacked)
  412.         
  413.         profile.prefs.link(IMWIN_ALWAYS_ON_TOP_PREF, self.on_always_on_top, callnow = not startMinimized)
  414.         snap_pref(self)
  415.         self.iconizecallbacks = set()
  416.         Bind = self.Bind
  417.         Bind(wx.EVT_ICONIZE, self.OnIconize)
  418.         memory_event()
  419.         
  420.         def gainfocus(e):
  421.             if e.Active:
  422.                 self._startengage()
  423.             else:
  424.                 self._endengage()
  425.             e.Skip()
  426.  
  427.         Bind(wx.EVT_ACTIVATE, gainfocus)
  428.         self.register_hooks()
  429.  
  430.     
  431.     def register_hooks(self):
  432.         if getattr(ImFrame, 'did_register_hooks', False):
  433.             return None
  434.         ImFrame.did_register_hooks = True
  435.         ImFrame.engage_is_idle = False
  436.         
  437.         def goidle():
  438.             ImFrame.engage_is_idle = True
  439.             for win in all_imframes():
  440.                 win._endengage()
  441.             
  442.             return True
  443.  
  444.         
  445.         def unidle():
  446.             ImFrame.engage_is_idle = False
  447.             for win in all_imframes():
  448.                 if win.IsActive():
  449.                     win._startengage()
  450.                     continue
  451.             
  452.             return True
  453.  
  454.         
  455.         def idle_ms(ms_idle_time):
  456.             if not (ImFrame.engage_is_idle) and ms_idle_time > IMWIN_STAT_IDLE_TIME:
  457.                 goidle()
  458.             elif ImFrame.engage_is_idle and ms_idle_time < IMWIN_STAT_IDLE_TIME:
  459.                 unidle()
  460.             
  461.             return 15000
  462.  
  463.         hooks.register('digsby.app.idle', idle_ms)
  464.         import cgui
  465.         if config.platform == 'win' and cgui.isWin7OrHigher():
  466.             set_overlay_icon = set_overlay_icon
  467.             get_tab_notebook = get_tab_notebook
  468.             import gui.native.win.taskbar
  469.             
  470.             def icon_updated(imwin):
  471.                 get_tab_notebook(imwin.Top).InvalidateThumbnails(imwin)
  472.                 
  473.                 def later():
  474.                     if wx.IsDestroyed(imwin):
  475.                         return None
  476.                     set_overlay_icon(im_badge(), tlw = imwin.Top)
  477.  
  478.                 wx.CallLater(300, later)
  479.  
  480.             hooks.register('digsby.overlay_icon_updated', icon_updated)
  481.         
  482.  
  483.     
  484.     def _startengage(self):
  485.         self._endengage()
  486.         self.start_time = default_timer()
  487.         self.on_engaged_start()
  488.  
  489.     
  490.     def _endengage(self):
  491.         if hasattr(self, 'start_time'):
  492.             diff = max(int(default_timer() - self.start_time), 0)
  493.             del self.start_time
  494.             hooks.notify('digsby.statistics.imwin.imwin_engage', diff)
  495.             self.on_engaged_end()
  496.         
  497.  
  498.     cycleTitle = prefprop('conversation_window.cycle_unread_ims')
  499.     shouldFlash = prefprop('conversation_window.notify_flash')
  500.     
  501.     def OnIconize(self, event = None):
  502.         if event is not None:
  503.             event.Skip()
  504.         
  505.         if not event.Iconized() and not (self.OnTop) and pref(IMWIN_ALWAYS_ON_TOP_PREF, False):
  506.             self.OnTop = True
  507.         
  508.         for callback in set(self.iconizecallbacks):
  509.             
  510.             try:
  511.                 callback()
  512.             continue
  513.             except PyDeadObjectError:
  514.                 self.iconizecallbacks.remove(callback)
  515.                 continue
  516.             
  517.  
  518.         
  519.  
  520.     
  521.     def notebook(self):
  522.         if hasattr(self, 'notebookPanel') and self.notebookPanel:
  523.             return self.notebookPanel.notebook
  524.  
  525.     notebook = property(notebook)
  526.     
  527.     def AnyNotified(self):
  528.         return any((lambda .0: for iwin in .0:
  529. iwin.Tab.notified)(self))
  530.  
  531.     AnyNotified = property(AnyNotified)
  532.     
  533.     def __iter__(self):
  534.         if config.nativeIMWindow:
  535.             pass
  536.         
  537.         return iter((lambda .0: for p in .0:
  538. p.Content)(self.notebook.Pages()))
  539.  
  540.     
  541.     def __getitem__(self, n):
  542.         if config.nativeIMWindow:
  543.             pass
  544.         
  545.         return self.notebook.Pages()[n].Content
  546.  
  547.     
  548.     def GetTabCount(self):
  549.         return self.notebook.GetTabCount()
  550.  
  551.     
  552.     def AddTab(self, ctrl, focus = None):
  553.         return self.notebook.Add(ctrl, focus = focus)
  554.  
  555.     
  556.     def CloseTabIfNotLast(self):
  557.         if self.notebook.GetTabCount() > 1:
  558.             tab = self.notebook.ActiveTab
  559.             self.notebook.CloseTab(tab)
  560.         
  561.  
  562.     CloseTabIfNotLast = bind('ImFrame.Tabs.CloseIfNotLast')(CloseTabIfNotLast)
  563.     
  564.     def CloseActiveTab(self):
  565.         tab = self.notebook.ActiveTab
  566.         self.notebook.CloseTab(tab)
  567.         if self.notebook.GetTabCount() < 1:
  568.             self.Close()
  569.         
  570.  
  571.     CloseActiveTab = bind('ImFrame.Tabs.CloseActive')(CloseActiveTab)
  572.     
  573.     def NextTab(self):
  574.         self.notebook.NextTab()
  575.  
  576.     NextTab = bind('ImFrame.Tabs.NextTab')(NextTab)
  577.     
  578.     def PrevTab(self):
  579.         self.notebook.PrevTab()
  580.  
  581.     PrevTab = bind('ImFrame.Tabs.PrevTab')(PrevTab)
  582.     
  583.     def IncreaseTextSize(self):
  584.         self.ActiveMessageArea.IncreaseTextSize()
  585.  
  586.     IncreaseTextSize = bind('ImFrame.ChatWindow.IncreaseTextSize')(IncreaseTextSize)
  587.     
  588.     def DescreaseTextSize(self):
  589.         self.ActiveMessageArea.DecreaseTextSize()
  590.  
  591.     DescreaseTextSize = bind('ImFrame.ChatWindow.DecreaseTextSize')(DescreaseTextSize)
  592.     
  593.     def ResetTextSize(self):
  594.         self.ActiveMessageArea.ResetTextSize()
  595.  
  596.     ResetTextSize = bind('ImFrame.ChatWindow.ResetTextSize')(ResetTextSize)
  597.     
  598.     def ActiveMessageArea(self):
  599.         return self.notebook.ActiveTab.page.Content.message_area
  600.  
  601.     ActiveMessageArea = property(ActiveMessageArea)
  602.     
  603.     def CloseAndSaveState(self, e):
  604.         tabcount = self.GetTabCount()
  605.         self.Hide()
  606.         saveWindowPos(self, uniqueId = self.posId)
  607.         if not config.nativeIMWindow:
  608.             for page in self.notebook.Pages():
  609.                 page.Children[0].on_close()
  610.             
  611.         
  612.         memory_event()
  613.         return True
  614.  
  615.     
  616.     def __repr__(self):
  617.         return '<%s %s>' % (self.__class__.__name__, id(self))
  618.  
  619.     
  620.     def on_always_on_top(self, val):
  621.         self.OnTop = val
  622.  
  623.     
  624.     def UpdateSkin(self):
  625.         wx.CallAfter(self.Layout)
  626.  
  627.  
  628.  
  629. def newIMWindow(pos, size):
  630.     win = ImFrame(pos, size)
  631.     win.Show(False)
  632.     fadein(win, 'normal')
  633.     return win
  634.  
  635.  
  636. def all_imframes():
  637.     return _[1]
  638.  
  639.  
  640. def notify_unread_message_hook():
  641.     hooks.notify('digsby.im.unread_messages_changed')
  642.  
  643.  
  644. def all_unread_convos():
  645.     imwins = []
  646.     for imframe in all_imframes():
  647.         imwins.extend((lambda .0: for tab in .0:
  648. tab.page.panel)(imframe.eventHandler.notifiedtabs))
  649.     
  650.     return imwins
  651.  
  652.  
  653. def im_badge(specific_page = None):
  654.     imwins = []
  655.     typing_statuses = dict((lambda .0: for i, s in .0:
  656. (s, i))(enumerate([
  657.         None,
  658.         'typed',
  659.         'typing'])))
  660.     max_typing = None
  661.     unread_count = 0
  662.     needs_bubbles = False
  663.     if specific_page is None:
  664.         for imframe in all_imframes():
  665.             notified_wins = set((lambda .0: for tab in .0:
  666. tab.page.panel)(imframe.eventHandler.notifiedtabs))
  667.             for page in imframe.notebook.Pages():
  668.                 imwin = page.panel
  669.                 if typing_statuses[imwin.typing] > typing_statuses[max_typing]:
  670.                     max_typing = imwin.typing
  671.                 
  672.                 if imwin in notified_wins:
  673.                     unread_count += 1
  674.                     continue
  675.             
  676.         
  677.     else:
  678.         max_typing = specific_page.typing
  679.         needs_bubbles = specific_page.Notified
  680.     bubble_icon = None
  681.     if max_typing is not None:
  682.         bubble_icon = skin.get('statusicons.' + max_typing, None)
  683.     
  684.     if bubble_icon is None:
  685.         if (unread_count or specific_page is not None) and needs_bubbles:
  686.             bubble_icon = skin.get('AppDefaults.UnreadMessageIcon', None)
  687.         
  688.     if bubble_icon is not None:
  689.         bubble_icon = bubble_icon.PIL.ResizeCanvas(16, 16)
  690.     
  691.     if unread_count:
  692.         if bubble_icon is None:
  693.             bubble_icon = Image.new('RGBA', (16, 16))
  694.         
  695.         bubble_icon = draw_tiny_text(bubble_icon, str(unread_count))
  696.     
  697.     if specific_page is None and bubble_icon is not None:
  698.         bubble_icon = bubble_icon.WXB
  699.     
  700.     return bubble_icon
  701.  
  702. from gui.input import add_class_context
  703. add_class_context(_('IM Windows'), 'ImFrame', cls = ImFrame)
  704.