From 5cc18d798620a029753083b3c9dff9312f703a8a Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Tue, 17 Apr 2007 16:40:05 +0000 Subject: [PATCH] wx.lib.flatnotebook: Patch from Andrea that implements the following: * A new style FNB_FF2: my intentions were to make it like Firefox 2, however it turned out to be an hybrid between wxAUI notebook glose style & FF2 ...I still think it looks OK. The main purpose for making it more like wxAUI is to allow applications that uses both to have same look and feel (or as close as it can get...); * Changed the behavior of the left/right rotation arrows to rotate single tab at a time and not bulk of tabs; * Updated the demo module. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45521 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- wxPython/demo/FlatNotebook.py | 26 +- wxPython/wx/lib/flatnotebook.py | 440 ++++++++++++++++++++++---------- 2 files changed, 323 insertions(+), 143 deletions(-) diff --git a/wxPython/demo/FlatNotebook.py b/wxPython/demo/FlatNotebook.py index 18b5ee0d37..0de95de359 100644 --- a/wxPython/demo/FlatNotebook.py +++ b/wxPython/demo/FlatNotebook.py @@ -58,6 +58,7 @@ MENU_DISABLE_TAB = wx.NewId() MENU_ENABLE_DRAG_N_DROP = wx.NewId() MENU_DCLICK_CLOSES_TAB = wx.NewId() MENU_USE_VC8_STYLE = wx.NewId() +MENU_USE_FF2_STYLE = wx.NewId() MENU_HIDE_ON_SINGLE_TAB = wx.NewId() MENU_SET_ACTIVE_TEXT_COLOR = wx.NewId() @@ -179,6 +180,10 @@ class FlatNotebookDemo(wx.Frame): self.Bind(wx.EVT_MENU, self.OnFancyStyle, item) styleMenu.AppendItem(item) + item = wx.MenuItem(styleMenu, MENU_USE_FF2_STYLE, "Use Firefox 2 Style", "Use Firefox 2 Style", wx.ITEM_RADIO) + self.Bind(wx.EVT_MENU, self.OnFF2Style, item) + styleMenu.AppendItem(item) + self._visualMenu.AppendMenu(wx.ID_ANY, "Tabs Style", styleMenu) item = wx.MenuItem(self._visualMenu, MENU_SELECT_GRADIENT_COLOR_FROM, "Select fancy tab style 'from' color", @@ -443,12 +448,25 @@ class FlatNotebookDemo(wx.Frame): self._bShowImages = event.IsChecked() + def OnFF2Style(self, event): + + style = self.book.GetWindowStyleFlag() + + # remove old tabs style + mirror = ~(fnb.FNB_VC71 | fnb.FNB_VC8 | fnb.FNB_FANCY_TABS | fnb.FNB_FF2) + style &= mirror + + style |= fnb.FNB_FF2 + + self.book.SetWindowStyleFlag(style) + + def OnVC71Style(self, event): style = self.book.GetWindowStyleFlag() # remove old tabs style - mirror = ~(fnb.FNB_VC71 | fnb.FNB_VC8 | fnb.FNB_FANCY_TABS) + mirror = ~(fnb.FNB_VC71 | fnb.FNB_VC8 | fnb.FNB_FANCY_TABS | fnb.FNB_FF2) style &= mirror style |= fnb.FNB_VC71 @@ -461,7 +479,7 @@ class FlatNotebookDemo(wx.Frame): style = self.book.GetWindowStyleFlag() # remove old tabs style - mirror = ~(fnb.FNB_VC71 | fnb.FNB_VC8 | fnb.FNB_FANCY_TABS) + mirror = ~(fnb.FNB_VC71 | fnb.FNB_VC8 | fnb.FNB_FANCY_TABS | fnb.FNB_FF2) style &= mirror # set new style @@ -475,7 +493,7 @@ class FlatNotebookDemo(wx.Frame): style = self.book.GetWindowStyleFlag() # remove old tabs style - mirror = ~(fnb.FNB_VC71 | fnb.FNB_VC8 | fnb.FNB_FANCY_TABS) + mirror = ~(fnb.FNB_VC71 | fnb.FNB_VC8 | fnb.FNB_FANCY_TABS | fnb.FNB_FF2) style &= mirror self.book.SetWindowStyleFlag(style) @@ -486,7 +504,7 @@ class FlatNotebookDemo(wx.Frame): style = self.book.GetWindowStyleFlag() # remove old tabs style - mirror = ~(fnb.FNB_VC71 | fnb.FNB_VC8 | fnb.FNB_FANCY_TABS) + mirror = ~(fnb.FNB_VC71 | fnb.FNB_VC8 | fnb.FNB_FANCY_TABS | fnb.FNB_FF2) style &= mirror style |= fnb.FNB_FANCY_TABS diff --git a/wxPython/wx/lib/flatnotebook.py b/wxPython/wx/lib/flatnotebook.py index a5daebcdeb..7b259ad4f7 100644 --- a/wxPython/wx/lib/flatnotebook.py +++ b/wxPython/wx/lib/flatnotebook.py @@ -11,7 +11,7 @@ # Python Code By: # # Andrea Gavana, @ 02 Oct 2006 -# Latest Revision: 12 Oct 2006, 20.00 GMT +# Latest Revision: 16 Apr 2007, 11.00 GMT # # # For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please @@ -37,7 +37,7 @@ Some features: - The scrolling is done for bulks of tabs (so, the scrolling is faster and better) - The buttons area is never overdrawn by tabs (unlike many other implementations I saw) - It is a generic control - - Currently there are 4 differnt styles - VC8, VC 71, Standard and Fancy + - Currently there are 5 differnt styles - VC8, VC 71, Standard, Fancy and Firefox 2; - Mouse middle click can be used to close tabs - A function to add right click menu for tabs (simple as SetRightClickMenu) - All styles has bottom style as well (they can be drawn in the bottom of screen) @@ -58,7 +58,7 @@ License And Version: FlatNotebook Is Freeware And Distributed Under The wxPython License. -Latest Revision: Andrea Gavana @ 12 Oct 2006, 20.00 GMT +Latest Revision: Andrea Gavana @ 16 Apr 2007, 11.00 GMT Version 2.0. @@ -123,6 +123,10 @@ FNB_NODRAG = 128 FNB_VC8 = 256 """Use Visual Studio 2005 (VC8) style for tabs""" +# Firefox 2 tabs style +FNB_FF2 = 131072 +"""Use Firefox 2 style for tabs""" + # Place 'X' on a tab FNB_X_ON_TAB = 512 """Place 'X' close button on the active tab""" @@ -716,6 +720,61 @@ def PaintStraightGradientBox(dc, rect, startColor, endColor, vertical=True): dc.SetBrush(savedBrush) + +# ----------------------------------------------------------------------------- +# Util functions +# ----------------------------------------------------------------------------- + +def DrawButton(dc, rect, focus, upperTabs): + + # Define the rounded rectangle base on the given rect + # we need an array of 9 points for it + regPts = [wx.Point() for indx in xrange(9)] + + if focus: + if upperTabs: + leftPt = wx.Point(rect.x, rect.y + (rect.height / 10)*8) + rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 10)*8) + else: + leftPt = wx.Point(rect.x, rect.y + (rect.height / 10)*5) + rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 10)*5) + else: + leftPt = wx.Point(rect.x, rect.y + (rect.height / 2)) + rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 2)) + + # Define the top region + top = wx.RectPP(rect.GetTopLeft(), rightPt) + bottom = wx.RectPP(leftPt, rect.GetBottomRight()) + + topStartColor = wx.WHITE + + if not focus: + topStartColor = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 50) + + topEndColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE) + bottomStartColor = topEndColor + bottomEndColor = topEndColor + + # Incase we use bottom tabs, switch the colors + if upperTabs: + if focus: + PaintStraightGradientBox(dc, top, topStartColor, topEndColor) + PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor) + else: + PaintStraightGradientBox(dc, top, topEndColor , topStartColor) + PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor) + + else: + if focus: + PaintStraightGradientBox(dc, bottom, topEndColor, bottomEndColor) + PaintStraightGradientBox(dc, top,topStartColor, topStartColor) + else: + PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor) + PaintStraightGradientBox(dc, top, topEndColor, topStartColor) + + dc.SetBrush(wx.TRANSPARENT_BRUSH) + + # ---------------------------------------------------------------------------- # # Class FNBDropSource # Gives Some Custom UI Feedback during the DnD Operations @@ -1148,7 +1207,7 @@ class TabNavigatorWindow(wx.Dialog): def OnItemSelected(self, event): """Handles the wx.EVT_LISTBOX_DCLICK event for the wx.ListBox inside L{TabNavigatorWindow}. """ - self.CloseDialog() + self.CloseDialog() def CloseDialog(self): @@ -1481,7 +1540,7 @@ class FNBRenderer: return bmp - def DrawTabsLine(self, pageContainer, dc): + def DrawTabsLine(self, pageContainer, dc, selTabX1=-1, selTabX2=-1): """ Draws a line over the tabs. """ pc = pageContainer @@ -1489,38 +1548,70 @@ class FNBRenderer: clntRect = pc.GetClientRect() clientRect3 = wx.Rect(0, 0, clntRect.width, clntRect.height) - if pc.HasFlag(FNB_BOTTOM): - - clientRect = wx.Rect(0, 2, clntRect.width, clntRect.height - 2) - clientRect2 = wx.Rect(0, 1, clntRect.width, clntRect.height - 1) - - else: - - clientRect = wx.Rect(0, 0, clntRect.width, clntRect.height - 2) - clientRect2 = wx.Rect(0, 0, clntRect.width, clntRect.height - 1) - - dc.SetBrush(wx.TRANSPARENT_BRUSH) - dc.SetPen(wx.Pen(pc.GetSingleLineBorderColour())) - dc.DrawRectangleRect(clientRect2) - dc.DrawRectangleRect(clientRect3) + if pc.HasFlag(FNB_FF2): + if not pc.HasFlag(FNB_BOTTOM): + fillColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE) + else: + fillColor = wx.WHITE - dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))) - dc.DrawRectangleRect(clientRect) + dc.SetPen(wx.Pen(fillColor)) - if not pc.HasFlag(FNB_TABS_BORDER_SIMPLE): - - dc.SetPen(wx.Pen((pc.HasFlag(FNB_VC71) and [wx.Colour(247, 243, 233)] or [pc._tabAreaColor])[0])) - dc.DrawLine(0, 0, 0, clientRect.height+1) + if pc.HasFlag(FNB_BOTTOM): + + dc.DrawLine(1, 0, clntRect.width-1, 0) + dc.DrawLine(1, 1, clntRect.width-1, 1) + + dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))) + dc.DrawLine(1, 2, clntRect.width-1, 2) + + dc.SetPen(wx.Pen(fillColor)) + dc.DrawLine(selTabX1 + 2, 2, selTabX2 - 1, 2) + + else: + + dc.DrawLine(1, clntRect.height, clntRect.width-1, clntRect.height) + dc.DrawLine(1, clntRect.height-1, clntRect.width-1, clntRect.height-1) + + dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))) + dc.DrawLine(1, clntRect.height-2, clntRect.width-1, clntRect.height-2) + + dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))) + dc.DrawLine(selTabX1 + 2, clntRect.height-2, selTabX2-1, clntRect.height-2) + + else: if pc.HasFlag(FNB_BOTTOM): - dc.DrawLine(0, clientRect.height+1, clientRect.width, clientRect.height+1) + clientRect = wx.Rect(0, 2, clntRect.width, clntRect.height - 2) + clientRect2 = wx.Rect(0, 1, clntRect.width, clntRect.height - 1) else: + + clientRect = wx.Rect(0, 0, clntRect.width, clntRect.height - 2) + clientRect2 = wx.Rect(0, 0, clntRect.width, clntRect.height - 1) + + dc.SetBrush(wx.TRANSPARENT_BRUSH) + dc.SetPen(wx.Pen(pc.GetSingleLineBorderColour())) + dc.DrawRectangleRect(clientRect2) + dc.DrawRectangleRect(clientRect3) + + dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))) + dc.DrawRectangleRect(clientRect) + + if not pc.HasFlag(FNB_TABS_BORDER_SIMPLE): + + dc.SetPen(wx.Pen((pc.HasFlag(FNB_VC71) and [wx.Colour(247, 243, 233)] or [pc._tabAreaColor])[0])) + dc.DrawLine(0, 0, 0, clientRect.height+1) + + if pc.HasFlag(FNB_BOTTOM): - dc.DrawLine(0, 0, clientRect.width, 0) + dc.DrawLine(0, clientRect.height+1, clientRect.width, clientRect.height+1) - dc.DrawLine(clientRect.width - 1, 0, clientRect.width - 1, clientRect.height+1) + else: + + dc.DrawLine(0, 0, clientRect.width, 0) + + dc.DrawLine(clientRect.width - 1, 0, clientRect.width - 1, clientRect.height+1) def CalcTabWidth(self, pageContainer, tabIdx, tabHeight): @@ -1650,7 +1741,12 @@ class FNBRenderer: else: colr = (pc.HasFlag(FNB_VC71) and [wx.Colour(247, 243, 233)] or [pc.GetBackgroundColour()])[0] dc.SetPen(wx.Pen(colr)) - + + if pc.HasFlag(FNB_FF2): + lightFactor = (pc.HasFlag(FNB_BACKGROUND_GRADIENT) and [70] or [0])[0] + PaintStraightGradientBox(dc, pc.GetClientRect(), pc._tabAreaColor, LightColour(pc._tabAreaColor, lightFactor)) + dc.SetBrush(wx.TRANSPARENT_BRUSH) + dc.DrawRectangle(0, 0, size.x, size.y) # Take 3 bitmaps for the background for the buttons @@ -1683,7 +1779,9 @@ class FNBRenderer: # We always draw the bottom/upper line of the tabs # regradless the style dc.SetPen(borderPen) - self.DrawTabsLine(pc, dc) + + if not pc.HasFlag(FNB_FF2): + self.DrawTabsLine(pc, dc) # Restore the pen dc.SetPen(borderPen) @@ -1727,10 +1825,13 @@ class FNBRenderer: #---------------------------------------------------------- # Go over and draw the visible tabs #---------------------------------------------------------- + x1 = x2 = -1 for i in xrange(pc._nFrom, len(pc._pagesInfoVec)): dc.SetPen(borderPen) - dc.SetBrush((i==pc.GetSelection() and [selBrush] or [noselBrush])[0]) + + if not pc.HasFlag(FNB_FF2): + dc.SetBrush((i==pc.GetSelection() and [selBrush] or [noselBrush])[0]) # Now set the font to the correct font dc.SetFont((i==pc.GetSelection() and [boldFont] or [normalFont])[0]) @@ -1759,6 +1860,10 @@ class FNBRenderer: # Draw the tab (border, text, image & 'x' on tab) self.DrawTab(pc, dc, posx, i, tabWidth, tabHeight, pc._nTabXButtonStatus) + if pc.GetSelection() == i: + x1 = posx + x2 = posx + tabWidth + 2 + # Restore the text forground dc.SetTextForeground(pc._activeTextColor) @@ -1781,6 +1886,9 @@ class FNBRenderer: self.DrawX(pc, dc) self.DrawDropDownArrow(pc, dc) + if pc.HasFlag(FNB_FF2): + self.DrawTabsLine(pc, dc, x1, x2) + def DrawDragHint(self, pc, tabIdx): """ @@ -1846,16 +1954,12 @@ class FNBRendererMgr: self._renderers.update({FNB_VC71: FNBRendererVC71()}) self._renderers.update({FNB_FANCY_TABS: FNBRendererFancy()}) self._renderers.update({FNB_VC8: FNBRendererVC8()}) + self._renderers.update({FNB_FF2: FNBRendererFirefox2()}) def GetRenderer(self, style): """ Returns the current renderer based on the style selected. """ - # since we dont have a style for default tabs, we - # test for all others - FIXME: add style for default tabs - if not style & FNB_VC71 and not style & FNB_VC8 and not style & FNB_FANCY_TABS: - return self._renderers[-1] - if style & FNB_VC71: return self._renderers[FNB_VC71] @@ -1865,6 +1969,9 @@ class FNBRendererMgr: if style & FNB_VC8: return self._renderers[FNB_VC8] + if style & FNB_FF2: + return self._renderers[FNB_FF2] + # the default is to return the default renderer return self._renderers[-1] @@ -1992,6 +2099,106 @@ class FNBRendererDefault(FNBRenderer): self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus) +#------------------------------------------ +# Firefox2 renderer +#------------------------------------------ +class FNBRendererFirefox2(FNBRenderer): + """ + This class handles the drawing of tabs using the I{Firefox 2} renderer. + """ + + def __init__(self): + """ Default class constructor. """ + + FNBRenderer.__init__(self) + + + def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus): + """ Draws a tab using the I{Firefox 2} style. """ + + borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)) + pc = pageContainer + + tabPoints = [wx.Point() for indx in xrange(7)] + tabPoints[0].x = posx + 2 + tabPoints[0].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0] + + tabPoints[1].x = tabPoints[0].x + tabPoints[1].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0] + + tabPoints[2].x = tabPoints[1].x+2 + tabPoints[2].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0] + + tabPoints[3].x = posx + tabWidth - 2 + tabPoints[3].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0] + + tabPoints[4].x = tabPoints[3].x + 2 + tabPoints[4].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0] + + tabPoints[5].x = tabPoints[4].x + tabPoints[5].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0] + + tabPoints[6].x = tabPoints[0].x + tabPoints[6].y = tabPoints[0].y + + #------------------------------------ + # Paint the tab with gradient + #------------------------------------ + rr = wx.RectPP(tabPoints[2], tabPoints[5]) + DrawButton(dc, rr, pc.GetSelection() == tabIdx , not pc.HasFlag(FNB_BOTTOM)) + + dc.SetBrush(wx.TRANSPARENT_BRUSH) + dc.SetPen(borderPen) + + # Draw the tab as rounded rectangle + dc.DrawPolygon(tabPoints) + + # ----------------------------------- + # Text and image drawing + # ----------------------------------- + + # The width of the images are 16 pixels + padding = pc.GetParent().GetPadding() + shapePoints = int(tabHeight*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi)) + hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1 + imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0] + + if hasImage: + textOffset = 2*padding + 16 + shapePoints/2 + else: + textOffset = padding + shapePoints/2 + + textOffset += 2 + + if tabIdx != pc.GetSelection(): + + # Set the text background to be like the vertical lines + dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour()) + + if hasImage: + imageXOffset = textOffset - 16 - padding + pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc, + posx + imageXOffset, imageYCoord, + wx.IMAGELIST_DRAW_TRANSPARENT, True) + + dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord) + + # draw 'x' on tab (if enabled) + if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection(): + + textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx)) + tabCloseButtonXCoord = posx + textOffset + textWidth + 1 + + # take a bitmap from the position of the 'x' button (the x on tab button) + # this bitmap will be used later to delete old buttons + tabCloseButtonYCoord = imageYCoord + x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16) + self._tabXBgBmp = self._GetBitmap(dc, x_rect, self._tabXBgBmp) + + # Draw the tab + self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus) + + #------------------------------------------------------------------ # Visual studio 7.1 #------------------------------------------------------------------ @@ -3545,7 +3752,7 @@ class PageContainer(wx.Panel): self._colorFrom = wx.WHITE self._activeTabColor = wx.WHITE self._activeTextColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNTEXT) - self._nonActiveTextColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW) + self._nonActiveTextColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNTEXT) self._tabAreaColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE) self._nFrom = 0 @@ -3758,58 +3965,60 @@ class PageContainer(wx.Panel): self.FireEvent(tabIdx) - def OnLeftUp(self, event): - """ Handles the wx.EVT_LEFT_UP events for L{PageContainer}. """ + def RotateLeft(self): - # forget the zone that was initially clicked - self._nLeftClickZone = FNB_NOWHERE + if self._nFrom == 0: + return - where, tabIdx = self.HitTest(event.GetPosition()) - - if where == FNB_LEFT_ARROW: - - if self._nFrom == 0: - return + # Make sure that the button was pressed before + if self._nLeftButtonStatus != FNB_BTN_PRESSED: + return - # Make sure that the button was pressed before - if self._nLeftButtonStatus != FNB_BTN_PRESSED: - return + self._nLeftButtonStatus = FNB_BTN_HOVER - self._nLeftButtonStatus = FNB_BTN_HOVER + # We scroll left with bulks of 5 + scrollLeft = self.GetNumTabsCanScrollLeft() - # We scroll left with bulks of 5 - scrollLeft = self.GetNumTabsCanScrollLeft() + self._nFrom -= scrollLeft + if self._nFrom < 0: + self._nFrom = 0 - self._nFrom -= scrollLeft - if self._nFrom < 0: - self._nFrom = 0 + self.Refresh() - self.Refresh() - - elif where == FNB_RIGHT_ARROW: - - if self._nFrom >= len(self._pagesInfoVec) - 1: - return - # Make sure that the button was pressed before - if self._nRightButtonStatus != FNB_BTN_PRESSED: - return + def RotateRight(self): - self._nRightButtonStatus = FNB_BTN_HOVER + if self._nFrom >= len(self._pagesInfoVec) - 1: + return - # Check if the right most tab is visible, if it is - # don't rotate right anymore - if self._pagesInfoVec[-1].GetPosition() != wx.Point(-1, -1): - return + # Make sure that the button was pressed before + if self._nRightButtonStatus != FNB_BTN_PRESSED: + return - lastVisibleTab = self.GetLastVisibleTab() - if lastVisibleTab < 0: - # Probably the screen is too small for displaying even a single - # tab, in this case we do nothing - return + self._nRightButtonStatus = FNB_BTN_HOVER - self._nFrom += self.GetNumOfVisibleTabs() - self.Refresh() + # Check if the right most tab is visible, if it is + # don't rotate right anymore + if self._pagesInfoVec[len(self._pagesInfoVec)-1].GetPosition() != wx.Point(-1, -1): + return + + self._nFrom += 1 + self.Refresh() + + + def OnLeftUp(self, event): + """ Handles the wx.EVT_LEFT_UP events for L{PageContainer}. """ + + # forget the zone that was initially clicked + self._nLeftClickZone = FNB_NOWHERE + + where, tabIdx = self.HitTest(event.GetPosition()) + + if where == FNB_LEFT_ARROW: + self.RotateLeft() + + elif where == FNB_RIGHT_ARROW: + self.RotateRight() elif where == FNB_X: @@ -3846,6 +4055,8 @@ class PageContainer(wx.Panel): self.PopupTabsMenu() + event.Skip() + def HitTest(self, pt): """ @@ -4185,66 +4396,10 @@ class PageContainer(wx.Panel): def GetNumTabsCanScrollLeft(self): """ Returns the number of tabs than can be scrolled left. """ - # Reserved area for the buttons (<>x) - rect = self.GetClientRect() - clientWidth = rect.width - posx = self._pParent._nPadding - numTabs = 0 - pom = 0 - - # In case we have error prevent crash - if self._nFrom < 0: - return 0 - - dc = wx.ClientDC(self) - - style = self.GetParent().GetWindowStyleFlag() - render = self._mgr.GetRenderer(style) - - for ii in xrange(self._nFrom, -1, -1): - - boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) - boldFont.SetWeight(wx.FONTWEIGHT_BOLD) - dc.SetFont(boldFont) - - height = dc.GetCharHeight() - - tabHeight = height + FNB_HEIGHT_SPACER # We use 6 pixels as padding - if style & FNB_VC71: - tabHeight = (style & FNB_BOTTOM and [tabHeight - 4] or [tabHeight])[0] - elif style & FNB_FANCY_TABS: - tabHeight = (style & FNB_BOTTOM and [tabHeight - 3] or [tabHeight])[0] - - width, pom = dc.GetTextExtent(self.GetPageText(ii)) - if style != FNB_VC71: - shapePoints = int(tabHeight*math.tan(float(self._pagesInfoVec[ii].GetTabAngle())/180.0*math.pi)) - else: - shapePoints = 0 - - tabWidth = 2*self._pParent._nPadding + width - - if not (style & FNB_VC71): - # Default style - tabWidth += 2*shapePoints - - hasImage = self._ImageList != None and self._pagesInfoVec[ii].GetImageIndex() != -1 + if self._nFrom - 1 >= 0: + return 1 - # For VC71 style, we only add the icon size (16 pixels) - if hasImage: - - if not self.IsDefaultTabs(): - tabWidth += 16 + self._pParent._nPadding - else: - # Default style - tabWidth += 16 + self._pParent._nPadding + shapePoints/2 - - if posx + tabWidth + render.GetButtonsAreaLength(self) >= clientWidth: - break - - numTabs = numTabs + 1 - posx += tabWidth - - return numTabs + return 0 def IsDefaultTabs(self): @@ -4553,10 +4708,16 @@ class PageContainer(wx.Panel): def OnLeftDClick(self, event): """ Handles the wx.EVT_LEFT_DCLICK event for L{PageContainer}. """ - if self.HasFlag(FNB_DCLICK_CLOSES_TABS): + where, tabIdx = self.HitTest(event.GetPosition()) + + if where == FNB_RIGHT_ARROW: + self.RotateRight() + + elif where == FNB_LEFT_ARROW: + self.RotateLeft() + + elif self.HasFlag(FNB_DCLICK_CLOSES_TABS): - where, tabIdx = self.HitTest(event.GetPosition()) - if where == FNB_TAB: self.DeletePage(tabIdx) @@ -4672,3 +4833,4 @@ class PageContainer(wx.Panel): where, tabIdx = self.HitTest(client_pt) self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag()).DrawDragHint(self, tabIdx) + -- 2.45.2