From aba5d43fc78011353dd6759993a7dd4f9132a711 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Sun, 14 Sep 2014 21:17:35 -0400 Subject: [PATCH] Added some docs ChromeTabs and did some cleaning --- gui/chromeTabs.py | 517 +++++++++++++++++++++++++++------------------- 1 file changed, 304 insertions(+), 213 deletions(-) diff --git a/gui/chromeTabs.py b/gui/chromeTabs.py index 2d9570d2e..91be9ed60 100644 --- a/gui/chromeTabs.py +++ b/gui/chromeTabs.py @@ -1,17 +1,24 @@ -#!/usr/bin/env python - -# --------------------------------------------------------------------------------- # -# Pyfa's custom Notebook core python IMPLEMENTATION +#=============================================================================== +# Copyright (C) 2010 Darriele # -# Darriele (homeworld using gmail point com) - 10/27/2010 -# Updated: 11/11/2010 +# This file is part of pyfa. # -# --------------------------------------------------------------------------------- # +# pyfa is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# pyfa is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with pyfa. If not, see . +#=============================================================================== import wx import wx.lib.newevent -import copy -import time import gui.utils.colorUtils as colorUtils import gui.utils.drawUtils as drawUtils from gui import bitmapLoader @@ -33,8 +40,8 @@ class VetoAble(): def isVetoed(self): return self.__vetoed -class NotebookTabChangeEvent(): +class NotebookTabChangeEvent(): def __init__(self, old, new): self.__old = old self.__new = new @@ -48,17 +55,20 @@ class NotebookTabChangeEvent(): OldSelection = property(GetOldSelection) Selection = property(GetSelection) + class PageChanging(_PageChanging, NotebookTabChangeEvent, VetoAble): def __init__(self, old, new): NotebookTabChangeEvent.__init__(self, old, new) _PageChanging.__init__(self) VetoAble.__init__(self) + class PageChanged(_PageChanged, NotebookTabChangeEvent): def __init__(self, old, new): NotebookTabChangeEvent.__init__(self, old, new) _PageChanged.__init__(self) + class PageClosing(_PageClosing, VetoAble): def __init__(self, i): self.__index = i @@ -69,43 +79,50 @@ class PageClosing(_PageClosing, VetoAble): def GetSelection(self): return self.__index + class PageAdding(_PageAdding, VetoAble): def __init__(self): _PageAdding.__init__(self) VetoAble.__init__(self) + class PFNotebook(wx.Panel): - def __init__(self, parent, canAdd = True): - wx.Panel.__init__(self, parent, wx.ID_ANY,size = (-1,-1)) + + def __init__(self, parent, canAdd=True): + """ + Instance of Pyfa Notebook. Initializes general layout, includes methods + for setting current page, replacing pages, etc + + parent - wx parent element + canAdd - True if tabs be deleted and added, passed directly to + PFTabsContainer + + """ + wx.Panel.__init__(self, parent, wx.ID_ANY, size=(-1, -1)) self.pages = [] self.activePage = None - mainSizer = wx.BoxSizer( wx.VERTICAL ) + mainSizer = wx.BoxSizer(wx.VERTICAL) - tabsSizer = wx.BoxSizer( wx.VERTICAL ) + tabsSizer = wx.BoxSizer(wx.VERTICAL) + self.tabsContainer = PFTabsContainer(self, canAdd=canAdd) + tabsSizer.Add(self.tabsContainer, 0, wx.EXPAND) - self.tabsContainer = PFTabsContainer(self, canAdd = canAdd) - tabsSizer.Add( self.tabsContainer, 0, wx.EXPAND ) + style = wx.DOUBLE_BORDER if 'wxMSW' in wx.PlatformInfo else wx.SIMPLE_BORDER - mainSizer.Add( tabsSizer, 0, wx.EXPAND, 5 ) - - contentSizer = wx.BoxSizer( wx.VERTICAL ) - if 'wxMSW' in wx.PlatformInfo: - style = wx.DOUBLE_BORDER - else: - style = wx.SIMPLE_BORDER - self.pageContainer = wx.Panel(self, style = style) + contentSizer = wx.BoxSizer(wx.VERTICAL) + self.pageContainer = wx.Panel(self, style=style) self.pageContainer.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)) - contentSizer.Add( self.pageContainer, 1, wx.EXPAND, 5 ) + contentSizer.Add(self.pageContainer, 1, wx.EXPAND, 5) - mainSizer.Add( contentSizer, 1, wx.EXPAND | wx.BOTTOM, 2 ) + mainSizer.Add(tabsSizer, 0, wx.EXPAND, 5) + mainSizer.Add(contentSizer, 1, wx.EXPAND | wx.BOTTOM, 2) - self.SetSizer( mainSizer ) + self.SetSizer(mainSizer) self.Bind(wx.EVT_SIZE, self.OnSize) self.Layout() - def GetPage(self, i): return self.pages[i] @@ -120,20 +137,24 @@ class PFNotebook(wx.Panel): self.activePage = page else: oldPage.Destroy() + page.Reparent(self.pageContainer) if self.activePage == page: self.ShowActive() - def GetBorders(self): + """Gets border widths to better determine page size in ShowActive()""" + bx = wx.SystemSettings_GetMetric(wx.SYS_BORDER_X) by = wx.SystemSettings_GetMetric(wx.SYS_BORDER_Y) - if bx<0: + + if bx < 0: bx = 1 - if by<0: + if by < 0: by = 1 - return (bx,by) + + return bx, by def ReplaceActivePage(self, page): self.SetPage(self.GetSelection(), page) @@ -154,6 +175,7 @@ class PFNotebook(wx.Panel): return len(self.pages) def NextPage(self): + """Used with keyboard shortcut for next page navigation""" cpage = self.GetSelection() if cpage is None: @@ -161,7 +183,7 @@ class PFNotebook(wx.Panel): if cpage < self.GetPageCount() - 1: self.SetSelection(cpage + 1) - npage = cpage +1 + npage = cpage + 1 else: self.SetSelection(0) npage = 0 @@ -169,6 +191,7 @@ class PFNotebook(wx.Panel): wx.PostEvent(self, PageChanged(cpage, npage)) def PrevPage(self): + """Used with keyboard shortcut for previous page navigation""" cpage = self.GetSelection() if cpage is None: @@ -176,19 +199,22 @@ class PFNotebook(wx.Panel): if cpage > 0: self.SetSelection(cpage - 1) - npage = cpage -1 + npage = cpage - 1 else: self.SetSelection(self.GetPageCount() - 1) npage = self.GetPageCount() - 1 wx.PostEvent(self, PageChanged(cpage, npage)) - def AddPage(self, tabWnd = None, tabTitle ="Empty Tab", tabImage = None, showClose = True): + def AddPage(self, tabWnd=None, tabTitle="Empty Tab", tabImage=None, showClose=True): if self.activePage: self.activePage.Hide() + if not tabWnd: tabWnd = wx.Panel(self) + tabWnd.Reparent(self.pageContainer) + self.pageContainer.Layout() self.pages.append(tabWnd) @@ -197,7 +223,6 @@ class PFNotebook(wx.Panel): self.activePage = tabWnd self.ShowActive(True) - def SetSelection(self, page): oldsel = self.GetSelection() if oldsel != page: @@ -206,14 +231,20 @@ class PFNotebook(wx.Panel): self.tabsContainer.SetSelected(page) self.ShowActive() - def DeletePage(self, n, internal = False): + def DeletePage(self, n, internal=False): + """ + Deletes page. + + n -- index of page to be deleted + internal -- True if we're deleting the page from the PFTabsContainer + """ page = self.pages[n] - self.pages.remove(page) - page.Destroy() if not internal: + # If we're not deleting from the tab, delete the tab + # (deleting from the tab automatically deletes itself) self.tabsContainer.DeleteTab(n, True) sel = self.tabsContainer.GetSelected() @@ -224,27 +255,37 @@ class PFNotebook(wx.Panel): else: self.activePage = None - - def SwitchPages(self, src, dest, internal = False): + def SwitchPages(self, src, dest): self.pages[src], self.pages[dest] = self.pages[dest], self.pages[src] - def ShowActive(self, resizeOnly = False): - size = self.pageContainer.GetSize() + def ShowActive(self, resizeOnly=False): + """ + Sets the size of the page and shows. The sizing logic adjusts for some + minor sizing errors (scrollbars going beyond bounds) + + resizeOnly -- if we are not interested in showing the page, only setting + the size + + @todo: is resizeOnly still needed? Was introduced with 8b8b97 in mid 2011 + to fix a resizing bug with blank pages, cannot reproduce 13Sept2014 + """ + + ww, wh = self.pageContainer.GetSize() bx, by = self.GetBorders() - ww,wh = size ww -= bx * 4 wh -= by * 4 - self.activePage.SetSize((ww,wh)) - self.activePage.SetPosition((0,0)) + self.activePage.SetSize((ww, wh)) + self.activePage.SetPosition((0, 0)) + if not resizeOnly: self.activePage.Show() - self.Layout() + self.Layout() def IsActive(self, page): return self.activePage == page - def SetPageText(self, i, text, refresh=True): + def SetPageTitle(self, i, text, refresh=True): tab = self.tabsContainer.tabs[i] tab.text = text if refresh: @@ -259,7 +300,7 @@ class PFNotebook(wx.Panel): self.Refresh() def SetPageTextIcon(self, i, text=wx.EmptyString, icon=None): - self.SetPageText(i, text, False) + self.SetPageTitle(i, text, False) self.SetPageIcon(i, icon, False) self.tabsContainer.AdjustTabsSize() self.Refresh() @@ -268,7 +309,7 @@ class PFNotebook(wx.Panel): self.tabsContainer.Refresh() def OnSize(self, event): - w,h= self.GetSize() + w, h = self.GetSize() self.tabsContainer.SetSize((w, -1)) self.tabsContainer.UpdateSize() self.tabsContainer.Refresh() @@ -278,9 +319,18 @@ class PFNotebook(wx.Panel): self.ShowActive() event.Skip() -class PFTabRenderer: - def __init__(self, size = (36,24), text = wx.EmptyString, img = None, inclination = 6 , closeButton = True, fontSize = 14): +class PFTabRenderer: + def __init__(self, size=(36, 24), text=wx.EmptyString, img=None, inclination=6 , closeButton=True, fontSize=14): + """ + Renders a new tab + + text -- tab label + img -- wxImage of tab icon + inclination -- does not seem to affect class, maybe used to be a variable + for custom drawn tab inclinations before there were bitmaps? + closeButton -- True if tab can be closed + """ # tab left/right zones inclination self.ctabLeft = bitmapLoader.getImage("ctableft", "icons") self.ctabMiddle = bitmapLoader.getImage("ctabmiddle", "icons") @@ -290,7 +340,7 @@ class PFTabRenderer: self.leftWidth = self.ctabLeft.GetWidth() self.rightWidth = self.ctabRight.GetWidth() self.middleWidth = self.ctabMiddle.GetWidth() - self.closeBtnWidth = self.ctabClose.GetWidth() + self.closeBtnWidth = self.ctabClose.GetWidth() width, height = size if width < self.leftWidth + self.rightWidth + self.middleWidth: @@ -312,7 +362,7 @@ class PFTabRenderer: self.font = wx.FontFromPixelSize((0, self.fontSize), wx.SWISS, wx.NORMAL, wx.NORMAL, False) self.tabImg = img - self.position = (0, 0) # Not used internaly for rendering - helper for tab container + self.position = (0, 0) # Not used internally for rendering - helper for tab container self.InitTab() def SetPosition(self, position): @@ -325,18 +375,16 @@ class PFTabRenderer: return self.tabSize def SetSize(self, size): - otw,oth = self.tabSize - w,h = size - if w< self.leftWidth + self.rightWidth + self.middleWidth: + w, h = size + if w < self.leftWidth + self.rightWidth + self.middleWidth: w = self.leftWidth + self.rightWidth + self.middleWidth if h < self.ctabMiddle.GetHeight(): h = self.ctabMiddle.GetHeight() - self.tabSize = (w,h) - + self.tabSize = (w, h) self.InitTab() - def SetSelected(self, sel = True): + def SetSelected(self, sel=True): self.selected = sel self.InitTab() @@ -346,7 +394,7 @@ class PFTabRenderer: def IsSelected(self): return self.selected - def ShowCloseButtonHovering(self, hover = True): + def ShowCloseButtonHovering(self, hover=True): if self.closeBtnHovering != hover: self.closeBtnHovering = hover self._Render() @@ -363,14 +411,14 @@ class PFTabRenderer: return self.CopyRegion(self.closeBtnRegion) def GetMinSize(self): - ebmp = wx.EmptyBitmap(1,1) + ebmp = wx.EmptyBitmap(1, 1) mdc = wx.MemoryDC() mdc.SelectObject(ebmp) mdc.SetFont(self.font) textSizeX, textSizeY = mdc.GetTextExtent(self.text) totalSize = self.leftWidth + self.rightWidth + textSizeX + self.closeBtnWidth/2 + 16 + self.padding*2 mdc.SelectObject(wx.NullBitmap) - return (totalSize, self.tabHeight) + return totalSize, self.tabHeight def SetTabImage(self, img): self.tabImg = img @@ -383,11 +431,9 @@ class PFTabRenderer: return newRegion - def InitTab(self, skipLRzones = False): + def InitTab(self): self.tabWidth, self.tabHeight = self.tabSize - # content width is tabWidth - (left+right) zones - self.contentWidth = self.tabWidth - self.leftWidth - self.rightWidth self.tabRegion = None self.closeBtnRegion = None @@ -400,57 +446,75 @@ class PFTabRenderer: self._Render() def InitBitmaps(self): + """ + Creates bitmap for tab + Takes the bitmaps already set and replaces a known color (black) with + the needed color, while also considering selected state. Color dependant + on platform -- see InitColors(). + """ if self.selected: - tr,tg,tb = self.selectedColor + tr, tg, tb = self.selectedColor else: - tr,tg,tb = self.inactiveColor + tr, tg, tb = self.inactiveColor ctabLeft = self.ctabLeft.Copy() ctabRight = self.ctabRight.Copy() ctabMiddle = self.ctabMiddle.Copy() - ctabLeft.Replace(0,0,0,tr, tg, tb) - ctabRight.Replace(0,0,0,tr, tg, tb) - ctabMiddle.Replace(0,0,0,tr, tg, tb) + ctabLeft.Replace(0, 0, 0, tr, tg, tb) + ctabRight.Replace(0, 0, 0, tr, tg, tb) + ctabMiddle.Replace(0, 0, 0, tr, tg, tb) self.ctabLeftBmp = wx.BitmapFromImage(ctabLeft) self.ctabRightBmp = wx.BitmapFromImage(ctabRight) self.ctabMiddleBmp = wx.BitmapFromImage(ctabMiddle) self.ctabCloseBmp = wx.BitmapFromImage(self.ctabClose) - - def ComposeTabBack(self): - + """ + Creates the tab background bitmap based upon calculated dimension values + and modified bitmaps via InitBitmaps() + """ bkbmp = wx.EmptyBitmap(self.tabWidth, self.tabHeight) mdc = wx.MemoryDC() mdc.SelectObject(bkbmp) - mdc.SetBackground( wx.Brush((0x12,0x23,0x32))) + #mdc.SetBackground(wx.Brush((0x12, 0x23, 0x32))) mdc.Clear() - mdc.DrawBitmap(self.ctabLeftBmp, 0, 0) + mdc.DrawBitmap(self.ctabLeftBmp, 0, 0) # set the left bitmap + + # convert middle bitmap and scale to tab width cm = self.ctabMiddleBmp.ConvertToImage() mimg = cm.Scale(self.contentWidth, self.ctabMiddle.GetHeight(), wx.IMAGE_QUALITY_NORMAL) mbmp = wx.BitmapFromImage(mimg) - mdc.DrawBitmap(mbmp, self.leftWidth, 0 ) - mdc.DrawBitmap(self.ctabRightBmp, self.contentWidth + self.leftWidth, 0 ) + mdc.DrawBitmap(mbmp, self.leftWidth, 0 ) # set middle bitmap, offset by left + + # set right bitmap offset by left + middle + mdc.DrawBitmap(self.ctabRightBmp, self.contentWidth + self.leftWidth, 0) + mdc.SelectObject(wx.NullBitmap) - bkbmp.SetMaskColour( (0x12, 0x23, 0x32) ) + + #bkbmp.SetMaskColour((0x12, 0x23, 0x32)) + if self.tabBackBitmap: del self.tabBackBitmap self.tabBackBitmap = bkbmp def InitTabRegions(self): + """ + Initializes regions for tab, which makes it easier to determine if + given coordinates are incluced in a region + """ self.tabRegion = wx.RegionFromBitmap(self.tabBackBitmap) self.closeBtnRegion = wx.RegionFromBitmap(self.ctabCloseBmp) - self.closeBtnRegion.Offset(self.contentWidth+self.leftWidth - self.ctabCloseBmp.GetWidth()/2, (self.tabHeight - self.ctabCloseBmp.GetHeight())/2) - + self.closeBtnRegion.Offset(self.contentWidth + self.leftWidth - self.ctabCloseBmp.GetWidth()/2, (self.tabHeight - self.ctabCloseBmp.GetHeight())/2) def InitColors(self): + """Determines colors used for tab, based on system settings""" self.tabColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE) self.inactiveColor = colorUtils.GetSuitableColor(self.tabColor, 0.25) self.selectedColor = colorUtils.GetSuitableColor(self.tabColor, 0.10) @@ -459,34 +523,32 @@ class PFTabRenderer: return self.tabBitmap def _Render(self): + """Renders the tab, complete with the icon, text, and close button""" if self.tabBitmap: del self.tabBitmap - inc = 6 height = self.tabHeight - width = self.tabWidth - contentWidth = self.contentWidth - rect = wx.Rect(0,0,self.tabWidth, self.tabHeight) + #rect = wx.Rect(0, 0, self.tabWidth, self.tabHeight) - canvas = wx.EmptyBitmap(rect.width, rect.height) + canvas = wx.EmptyBitmap(self.tabWidth, self.tabHeight, 24) mdc = wx.MemoryDC() mdc.SelectObject(canvas) - mdc.SetBackground(wx.Brush ((0x12,0x23,0x32))) + #mdc.SetBackground(wx.Brush ((0x12,0x23,0x32))) mdc.Clear() - - r = copy.copy(rect) - r.top = r.left = 0 - r.height = height + #r = copy.copy(rect) + #r.top = r.left = 0 + #r.height = height mdc.DrawBitmap(self.tabBackBitmap, 0, 0, True) if self.tabImg: bmp = wx.BitmapFromImage(self.tabImg) - if self.contentWidth > 16: - mdc.DrawBitmap(bmp, self.leftWidth + self.padding - bmp.GetWidth()/2, (height - bmp.GetHeight())/2) + if self.contentWidth > 16: # @todo: is this conditional relevant anymore? + # Draw tab icon + mdc.DrawBitmap(bmp, self.leftWidth + self.padding - bmp.GetWidth()/2, (height - bmp.GetHeight())/2) textStart = self.leftWidth + self.padding + bmp.GetWidth()/2 else: textStart = self.leftWidth @@ -494,42 +556,42 @@ class PFTabRenderer: mdc.SetFont(self.font) maxsize = self.tabWidth - textStart - self.rightWidth - self.padding*4 - - if self.selected: - color = self.selectedColor - else: - color = self.inactiveColor + color = self.selectedColor if self.selected else self.inactiveColor mdc.SetTextForeground(colorUtils.GetSuitableColor(color, 1)) text = drawUtils.GetPartialText(mdc, self.text, maxsize, "") - - tx,ty = mdc.GetTextExtent(text) - - mdc.DrawText(text, textStart + self.padding , height / 2 - ty / 2) + tx, ty = mdc.GetTextExtent(text) + mdc.DrawText(text, textStart + self.padding, height / 2 - ty / 2) if self.closeButton: if self.closeBtnHovering: - mdc.DrawBitmap(self.ctabCloseBmp,self.contentWidth+self.leftWidth - self.ctabCloseBmp.GetWidth()/2,(height - self.ctabCloseBmp.GetHeight())/2) + cbmp = self.ctabCloseBmp else: cimg = self.ctabCloseBmp.ConvertToImage() - cimg = cimg.AdjustChannels(0.7,0.7,0.7,0.3) + cimg = cimg.AdjustChannels(0.7, 0.7, 0.7, 0.3) cbmp = wx.BitmapFromImage(cimg) - mdc.DrawBitmap(cbmp,self.contentWidth+self.leftWidth - self.ctabCloseBmp.GetWidth()/2,(height - self.ctabCloseBmp.GetHeight())/2) + + mdc.DrawBitmap( + cbmp, + self.contentWidth + self.leftWidth - self.ctabCloseBmp.GetWidth()/2, + (height - self.ctabCloseBmp.GetHeight())/2) mdc.SelectObject(wx.NullBitmap) - - canvas.SetMaskColour((0x12,0x23,0x32)) + canvas.SetMaskColour((0x12, 0x23, 0x32)) img = canvas.ConvertToImage() + if not img.HasAlpha(): img.InitAlpha() + bmp = wx.BitmapFromImage(img) self.tabBitmap = bmp + class PFAddRenderer: def __init__(self): - + """Renders the add tab button""" self.addImg = bitmapLoader.getImage("ctabadd", "icons") self.width = self.addImg.GetWidth() self.height = self.addImg.GetHeight() @@ -538,7 +600,7 @@ class PFAddRenderer: self.tbmp = wx.BitmapFromImage(self.addImg) self.addBitmap = None - self.position = (0,0) + self.position = (0, 0) self.highlighted = False self.InitRenderer() @@ -550,7 +612,7 @@ class PFAddRenderer: self.position = pos def GetSize(self): - return (self.width, self.height) + return self.width, self.height def GetHeight(self): return self.height @@ -559,11 +621,9 @@ class PFAddRenderer: return self.width def InitRenderer(self): - self.region = self.CreateRegion() self._Render() - def CreateRegion(self): region = wx.RegionFromBitmap(self.tbmp) return region @@ -579,7 +639,7 @@ class PFAddRenderer: def GetRegion(self): return self.CopyRegion(self.region) - def Highlight(self, highlight = False): + def Highlight(self, highlight=False): self.highlighted = highlight self._Render() @@ -590,29 +650,29 @@ class PFAddRenderer: return self.addBitmap def _Render(self): - - rect = wx.Rect(0 ,0 ,self.width, self.height) - if self.addBitmap: del self.addBitmap - if self.highlighted: - alpha = 1 - else: - alpha = 0.3 - img = self.addImg.AdjustChannels(1, 1, 1, alpha) + alpha = 1 if self.highlighted else 0.3 + img = self.addImg.AdjustChannels(1, 1, 1, alpha) bbmp = wx.BitmapFromImage(img) self.addBitmap = bbmp - class PFTabsContainer(wx.Panel): - def __init__(self, parent, pos = (0,0), size = (100,22), id = wx.ID_ANY, canAdd = True): - wx.Panel.__init__(self, parent, id , pos, size) + def __init__(self, parent, pos=(0, 0), size=(100, 22), id=wx.ID_ANY, canAdd=True): + """ + Defines the tab container. Handles functions such as tab selection and + dragging, and defines minimum width of tabs (all tabs are of equal width, + which is determined via widest tab). Also handles the tab preview, if any. + """ + + wx.Panel.__init__(self, parent, id, pos, size) + self.tabs = [] width, height = size - self.width = width + self.width = width self.height = height self.containerHeight = height self.startDrag = False @@ -624,8 +684,7 @@ class PFTabsContainer(wx.Panel): else: self.reserved = self.inclination * 4 - - self.dragTrail = 3 + self.dragTrail = 3 # pixel distance to drag before we actually start dragging self.dragx = 0 self.dragy = 0 self.draggedTab = None @@ -657,7 +716,7 @@ class PFTabsContainer(wx.Panel): self.Bind(wx.EVT_MOTION, self.OnMotion) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_SYS_COLOUR_CHANGED, self.OnSysColourChanged) - self.tabShadow = PFTabRenderer((self.tabMinWidth, self.height + 1), inclination = self.inclination) + self.tabShadow = PFTabRenderer((self.tabMinWidth, self.height + 1), inclination=self.inclination) def OnSysColourChanged(self, event): for tab in self.tabs: @@ -669,21 +728,23 @@ class PFTabsContainer(wx.Panel): event.Skip() def UpdateSize(self): - width, dummy = self.GetSize() + width, _ = self.GetSize() if width != self.width: self.width = width self.tabContainerWidth = self.width - self.reserved self.AdjustTabsSize() def OnLeftDown(self, event): - mposx,mposy = event.GetPosition() + """Determines what happens when user left clicks (down)""" + mposx, mposy = event.GetPosition() if not self.startDrag: tab = self.FindTabAtPos(mposx, mposy) if tab: self.CheckTabSelected(tab, mposx, mposy) if self.showAddButton: + # If we can add tabs, we can drag them. Set flag self.startDrag = True - tx,ty = tab.GetPosition() + tx, ty = tab.GetPosition() self.dragx = mposx - tx self.dragy = self.containerHeight - self.height self.Refresh() @@ -691,7 +752,8 @@ class PFTabsContainer(wx.Panel): self.draggedTab = tab def OnLeftUp(self, event): - mposx,mposy = event.GetPosition() + """Determines what happens when user left clicks (up)""" + mposx, mposy = event.GetPosition() if self.startDrag and self.dragging: self.dragging = False self.startDrag = False @@ -708,18 +770,23 @@ class PFTabsContainer(wx.Panel): self.startDrag = False self.dragTrigger = self.dragTrail + # Checks if we selected the add button and, if True, returns if self.CheckAddButton(mposx, mposy): return + # If there are no tabs, don't waste time if self.GetTabsCount() == 0: return + + # Gets selected tab (was set when user down clicked) selTab = self.GetSelectedTab() + # Check if we selected close button for selected tab if self.CheckTabClose(selTab, mposx, mposy): return + # Check if we selected close button for all others for tab in self.tabs: - if self.CheckTabClose(tab, mposx, mposy): return @@ -741,22 +808,27 @@ class PFTabsContainer(wx.Panel): self.tabs[tabIndex].SetSelected(True) self.Refresh() - def CheckTabSelected(self,tab, mposx, mposy): + def CheckTabSelected(self, tab, x, y): + """ + Selects the tab at x, y. If the tab at x, y is already selected, simply + return true. Otherwise, perform TabHitTest and set tab at position to + selected + """ oldSelTab = self.GetSelectedTab() if oldSelTab == tab: return True - if self.TabHitTest(tab, mposx, mposy): + if self.TabHitTest(tab, x, y): tab.SetSelected(True) oldSelTab.SetSelected(False) ev = PageChanging(self.tabs.index(oldSelTab), self.tabs.index(tab)) wx.PostEvent(self.Parent, ev) + if ev.isVetoed(): return False self.Refresh() - selTab = self.tabs.index(tab) self.Parent.SetSelection(selTab) @@ -766,16 +838,16 @@ class PFTabsContainer(wx.Panel): return False - def CheckTabClose(self, tab, mposx, mposy): - if not tab.closeButton: + def CheckTabClose(self, tab, x, y): + """Determines if close button was selected for the given tab.""" + if not tab.closeButton: # if not able to close, return False return False closeBtnReg = tab.GetCloseButtonRegion() tabPosX, tabPosY = tab.GetPosition() + closeBtnReg.Offset(tabPosX, tabPosY) - closeBtnReg.Offset(tabPosX,tabPosY) - - if closeBtnReg.Contains(mposx, mposy): + if closeBtnReg.Contains(x, y): index = self.tabs.index(tab) ev = PageClosing(index) wx.PostEvent(self.Parent, ev) @@ -786,18 +858,23 @@ class PFTabsContainer(wx.Panel): self.DeleteTab(index) wx.PostEvent(self.Parent, PageClosed(index=index)) sel = self.GetSelected() - if sel is not None: + + if sel is not None: wx.PostEvent(self.Parent, PageChanged(-1, sel)) + return True return False - def CheckAddButton(self, mposx,mposy): - if not self.showAddButton: + def CheckAddButton(self, x, y): + """Determines if add button was selected.""" + if not self.showAddButton: # if not able to add, return False return + reg = self.addButton.GetRegion() - ax,ay = self.addButton.GetPosition() - reg.Offset(ax,ay) - if reg.Contains(mposx, mposy): + ax, ay = self.addButton.GetPosition() + reg.Offset(ax, ay) + + if reg.Contains(x, y): ev = PageAdding() wx.PostEvent(self.Parent, ev) if ev.isVetoed(): @@ -807,15 +884,20 @@ class PFTabsContainer(wx.Panel): wx.PostEvent(self.Parent, PageAdded()) return True - def CheckCloseButtons(self, mposx, mposy): + def CheckCloseButtons(self, x, y): + """ + Checks if mouse pos at x, y is over a close button. If so, set the + close hovering flag for that tab + """ dirty = False - + # @todo: maybe change to for...else for tab in self.tabs: closeBtnReg = tab.GetCloseButtonRegion() tabPos = tab.GetPosition() tabPosX, tabPosY = tabPos closeBtnReg.Offset(tabPosX,tabPosY) - if closeBtnReg.Contains(mposx,mposy): + + if closeBtnReg.Contains(x, y): if not tab.GetCloseButtonHoverStatus(): tab.ShowCloseButtonHovering(True) dirty = True @@ -829,6 +911,7 @@ class PFTabsContainer(wx.Panel): def FindTabAtPos(self, x, y): if self.GetTabsCount() == 0: return None + selTab = self.GetSelectedTab() if self.TabHitTest(selTab, x, y): return selTab @@ -843,35 +926,36 @@ class PFTabsContainer(wx.Panel): tabPos = tab.GetPosition() tabPosX, tabPosY = tabPos tabRegion.Offset(tabPosX, tabPosY) + if tabRegion.Contains(x, y): return True + return False def GetTabAtLeft(self, tabIndex): - if tabIndex>0: - return self.tabs[tabIndex - 1] - else: - return None + return self.tabs[tabIndex - 1] if tabIndex > 0 else None def GetTabAtRight(self, tabIndex): - if tabIndex < self.GetTabsCount() - 1: - return self.tabs[tabIndex + 1] - else: - return None + return self.tabs[tabIndex + 1] if tabIndex < self.GetTabsCount() - 1 else None - def SwitchTabs(self, src, dest, draggedTab = None): + + def SwitchTabs(self, src, dest, draggedTab=None): self.tabs[src], self.tabs[dest] = self.tabs[dest], self.tabs[src] self.UpdateTabsPosition(draggedTab) - - self.Parent.SwitchPages(src,dest, True) - + self.Parent.SwitchPages(src, dest) self.Refresh() def GetTabIndex(self, tab): return self.tabs.index(tab) def OnMotion(self, event): - mposx,mposy = event.GetPosition() + """ + Determines what happens when the mouse moves. This handles primarily + dragging (region tab can be dragged) as well as checking if we are over + an actionable button. + """ + mposx, mposy = event.GetPosition() + if self.startDrag: if not self.dragging: if self.dragTrigger < 0: @@ -882,13 +966,13 @@ class PFTabsContainer(wx.Panel): self.dragTrigger -= 1 if self.dragging: dtx = mposx - self.dragx - w,h = self.draggedTab.GetSize() + w, h = self.draggedTab.GetSize() if dtx < 0: dtx = 0 if dtx + w > self.tabContainerWidth + self.inclination * 2: dtx = self.tabContainerWidth - w + self.inclination * 2 - self.draggedTab.SetPosition( (dtx, self.dragy)) + self.draggedTab.SetPosition((dtx, self.dragy)) index = self.GetTabIndex(self.draggedTab) @@ -896,32 +980,36 @@ class PFTabsContainer(wx.Panel): rightTab = self.GetTabAtRight(index) if leftTab: - lw,lh = leftTab.GetSize() - lx,ly = leftTab.GetPosition() + lw, lh = leftTab.GetSize() + lx, ly = leftTab.GetPosition() if lx + lw / 2 - self.inclination * 2 > dtx: - self.SwitchTabs(index - 1 , index, self.draggedTab) + self.SwitchTabs(index - 1, index, self.draggedTab) return if rightTab: - rw,rh = rightTab.GetSize() - rx,ry = rightTab.GetPosition() + rw, rh = rightTab.GetSize() + rx, ry = rightTab.GetPosition() if rx + rw / 2 + self.inclination * 2 < dtx + w: - self.SwitchTabs(index + 1 , index, self.draggedTab) + self.SwitchTabs(index + 1, index, self.draggedTab) return self.UpdateTabsPosition(self.draggedTab) self.Refresh() return return - self.CheckCloseButtons(mposx, mposy) - self.CheckAddHighlighted(mposx,mposy) + self.CheckCloseButtons(mposx, mposy) + self.CheckAddHighlighted(mposx, mposy) self.CheckTabPreview(mposx, mposy) + event.Skip() def CheckTabPreview(self, mposx, mposy): - + """ + Checks to see if we have a tab preview and sets up the timer for it + to display + """ if self.previewTimer: if self.previewTimer.IsRunning(): if self.previewWnd: @@ -943,19 +1031,24 @@ class PFTabsContainer(wx.Panel): self.previewTimer = wx.Timer(self, self.previewTimerID) self.previewTab = tab - self.previewTimer.Start(1500, True) + self.previewTimer.Start(500, True) break except: pass - - def CheckAddHighlighted(self, mposx, mposy): + def CheckAddHighlighted(self, x, y): + """ + Checks to see if x, y are in add button region, and sets the highlight + flag + """ if not self.showAddButton: return + reg = self.addButton.GetRegion() - ax,ay = self.addButton.GetPosition() - reg.Offset(ax,ay) - if reg.Contains(mposx, mposy): + ax, ay = self.addButton.GetPosition() + reg.Offset(ax, ay) + + if reg.Contains(x, y): if not self.addButton.IsHighlighted(): self.addButton.Highlight(True) self.Refresh() @@ -965,13 +1058,11 @@ class PFTabsContainer(wx.Panel): self.Refresh() def OnPaint(self, event): - if "wxGTK" in wx.PlatformInfo: mdc = wx.AutoBufferedPaintDC(self) else: rect = self.GetRect() - mdc = wx.BufferedPaintDC(self) selected = 0 @@ -1007,7 +1098,7 @@ class PFTabsContainer(wx.Panel): for i in xrange(len(self.tabs) - 1, -1, -1): tab = self.tabs[i] width = tab.tabWidth - 6 - posx, posy = tab.GetPosition() + posx, posy = tab.GetPosition() if not tab.IsSelected(): mdc.DrawBitmap(self.efxBmp, posx, posy, True ) @@ -1021,7 +1112,7 @@ class PFTabsContainer(wx.Panel): selected = tab if selected: - posx, posy = selected.GetPosition() + posx, posy = selected.GetPosition() mdc.DrawBitmap(self.efxBmp, posx, posy, True) bmp = selected.Render() @@ -1037,7 +1128,7 @@ class PFTabsContainer(wx.Panel): pass def UpdateTabFX(self): - w,h = self.tabShadow.GetSize() + w, h = self.tabShadow.GetSize() if w != self.tabMinWidth: self.tabShadow.SetSize((self.tabMinWidth, self.height + 1)) fxBmp = self.tabShadow.Render() @@ -1046,17 +1137,17 @@ class PFTabsContainer(wx.Panel): if not simg.HasAlpha(): simg.InitAlpha() simg = simg.Blur(2) - simg = simg.AdjustChannels(0.3,0.3,0.3,0.35) + simg = simg.AdjustChannels(0.3, 0.3, 0.3, 0.35) self.efxBmp = wx.BitmapFromImage(simg) - def AddTab(self, title = wx.EmptyString, img = None, showClose = False): + def AddTab(self, title=wx.EmptyString, img=None, showClose=False): self.ClearTabsSelected() - tabRenderer = PFTabRenderer( (120,self.height), title, img, self.inclination, closeButton = showClose) + tabRenderer = PFTabRenderer((120, self.height), title, img, self.inclination, closeButton=showClose) tabRenderer.SetSelected(True) - self.tabs.append( tabRenderer ) + self.tabs.append(tabRenderer) self.AdjustTabsSize() self.Refresh() @@ -1064,7 +1155,7 @@ class PFTabsContainer(wx.Panel): for tab in self.tabs: tab.SetSelected(False) - def DeleteTab(self, tab, external = False): + def DeleteTab(self, tab, external=False): tabRenderer = self.tabs[tab] wasSelected = tabRenderer.GetSelected() self.tabs.remove(tabRenderer) @@ -1073,10 +1164,11 @@ class PFTabsContainer(wx.Panel): del tabRenderer if wasSelected and self.GetTabsCount() > 0: - if tab > self.GetTabsCount() -1: + if tab > self.GetTabsCount() - 1: self.tabs[self.GetTabsCount() - 1].SetSelected(True) else: self.tabs[tab].SetSelected(True) + if not external: self.Parent.DeletePage(tab, True) @@ -1087,35 +1179,34 @@ class PFTabsContainer(wx.Panel): return len(self.tabs) def AdjustTabsSize(self): - - tabMinWidth = 9000000 # Really, it should be over 9000 + tabMinWidth = 9000000 # Really, it should be over 9000 tabMaxWidth = 0 for tab in self.tabs: - mw,mh = tab.GetMinSize() + mw, mh = tab.GetMinSize() if tabMinWidth > mw: tabMinWidth = mw if tabMaxWidth < mw: tabMaxWidth = mw if tabMaxWidth < 100: tabMaxWidth = 100 - if self.GetTabsCount() >0: + if self.GetTabsCount() > 0: if (self.GetTabsCount()) * (tabMaxWidth - self.inclination * 2) > self.tabContainerWidth: self.tabMinWidth = float(self.tabContainerWidth) / float(self.GetTabsCount()) + self.inclination * 2 else: self.tabMinWidth = tabMaxWidth - if self.tabMinWidth <1: + if self.tabMinWidth < 1: self.tabMinWidth = 1 for tab in self.tabs: - w,h = tab.GetSize() - tab.SetSize( (self.tabMinWidth, self.height) ) + w, h = tab.GetSize() + tab.SetSize((self.tabMinWidth, self.height)) if self.GetTabsCount() > 0: self.UpdateTabFX() self.UpdateTabsPosition() - def UpdateTabsPosition(self, skipTab = None): + def UpdateTabsPosition(self, skipTab=None): tabsWidth = 0 for tab in self.tabs: tabsWidth += tab.tabWidth - self.inclination*2 @@ -1158,14 +1249,14 @@ class PFTabsContainer(wx.Panel): if not self.previewTab.GetSelected(): page = self.Parent.GetPage(self.GetTabIndex(self.previewTab)) if page.Snapshot(): - self.previewWnd = PFNotebookPagePreview(self,(mposx+3,mposy+3), page.Snapshot(), self.previewTab.text) + self.previewWnd = PFNotebookPagePreview(self, (mposx+3, mposy+3), page.Snapshot(), self.previewTab.text) self.previewWnd.Show() event.Skip() class PFNotebookPagePreview(wx.Frame): def __init__ (self,parent, pos, bitmap, title): - wx.Frame.__init__(self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = pos, size = wx.DefaultSize, style = + wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=pos, size=wx.DefaultSize, style= wx.NO_BORDER | wx.FRAME_NO_TASKBAR | wx.STAY_ON_TOP) @@ -1173,22 +1264,22 @@ class PFNotebookPagePreview(wx.Frame): self.title = title self.bitmap = bitmap self.SetSize((bitmap.GetWidth(), bitmap.GetHeight())) - self.Bind(wx.EVT_PAINT,self.OnWindowPaint) + self.Bind(wx.EVT_PAINT, self.OnWindowPaint) self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnWindowEraseBk) self.Bind(wx.EVT_TIMER, self.OnTimer) - self.timer = wx.Timer(self,wx.ID_ANY) + self.timer = wx.Timer(self, wx.ID_ANY) self.timerSleep = None self.timerSleepId = wx.NewId() self.direction = 1 self.padding = 15 self.transp = 0 - hfont = wx.FontFromPixelSize((0,14), wx.SWISS, wx.NORMAL,wx.NORMAL, False) + hfont = wx.FontFromPixelSize((0, 14), wx.SWISS, wx.NORMAL, wx.NORMAL, False) self.SetFont(hfont) tx, ty = self.GetTextExtent(self.title) - tx += self.padding * 2 + tx += self.padding * 2 if bitmap.GetWidth() < tx: width = tx @@ -1224,7 +1315,7 @@ class PFNotebookPagePreview(wx.Frame): if lastwnd: lastwnd.Raise() - def Show(self, showWnd = True): + def Show(self, showWnd=True): if showWnd: wx.Frame.Show(self, showWnd) self.RaiseParent() @@ -1238,7 +1329,7 @@ class PFNotebookPagePreview(wx.Frame): def OnWindowEraseBk(self,event): pass - def OnWindowPaint(self,event): + def OnWindowPaint(self, event): rect = self.GetRect() canvas = wx.EmptyBitmap(rect.width, rect.height) mdc = wx.BufferedPaintDC(self) @@ -1247,21 +1338,21 @@ class PFNotebookPagePreview(wx.Frame): mdc.SetBackground(wx.Brush(color)) mdc.Clear() - font = wx.FontFromPixelSize((0,14), wx.SWISS, wx.NORMAL,wx.NORMAL, False) + font = wx.FontFromPixelSize((0, 14), wx.SWISS, wx.NORMAL,wx.NORMAL, False) mdc.SetFont(font) x,y = mdc.GetTextExtent(self.title) mdc.SetBrush(wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT))) - mdc.DrawRectangle(0,0,rect.width,16) + mdc.DrawRectangle(0, 0, rect.width, 16) mdc.SetTextForeground(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)) - mdc.DrawText(self.title, (rect.width - x)/2, (16 -y)/2) + mdc.DrawText(self.title, (rect.width - x)/2, (16 - y)/2) mdc.DrawBitmap(self.bitmap, 0, 16) - mdc.SetPen( wx.Pen("#000000", width = 1 ) ) - mdc.SetBrush( wx.TRANSPARENT_BRUSH ) + mdc.SetPen(wx.Pen("#000000", width=1)) + mdc.SetBrush(wx.TRANSPARENT_BRUSH) - mdc.DrawRectangle( 0, 16, rect.width,rect.height - 16) + mdc.DrawRectangle(0, 16, rect.width, rect.height - 16)