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/branches/WX_2_8_BRANCH@45521 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2007-04-17 16:40:05 +00:00
parent bf2481b9cf
commit ce7feab06b
2 changed files with 325 additions and 145 deletions

View File

@@ -58,6 +58,7 @@ MENU_DISABLE_TAB = wx.NewId()
MENU_ENABLE_DRAG_N_DROP = wx.NewId() MENU_ENABLE_DRAG_N_DROP = wx.NewId()
MENU_DCLICK_CLOSES_TAB = wx.NewId() MENU_DCLICK_CLOSES_TAB = wx.NewId()
MENU_USE_VC8_STYLE = wx.NewId() MENU_USE_VC8_STYLE = wx.NewId()
MENU_USE_FF2_STYLE = wx.NewId()
MENU_HIDE_ON_SINGLE_TAB = wx.NewId() MENU_HIDE_ON_SINGLE_TAB = wx.NewId()
MENU_SET_ACTIVE_TEXT_COLOR = 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) self.Bind(wx.EVT_MENU, self.OnFancyStyle, item)
styleMenu.AppendItem(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) 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", 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() 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): def OnVC71Style(self, event):
style = self.book.GetWindowStyleFlag() style = self.book.GetWindowStyleFlag()
# remove old tabs style # 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 &= mirror
style |= fnb.FNB_VC71 style |= fnb.FNB_VC71
@@ -461,7 +479,7 @@ class FlatNotebookDemo(wx.Frame):
style = self.book.GetWindowStyleFlag() style = self.book.GetWindowStyleFlag()
# remove old tabs style # 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 &= mirror
# set new style # set new style
@@ -475,7 +493,7 @@ class FlatNotebookDemo(wx.Frame):
style = self.book.GetWindowStyleFlag() style = self.book.GetWindowStyleFlag()
# remove old tabs style # 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 &= mirror
self.book.SetWindowStyleFlag(style) self.book.SetWindowStyleFlag(style)
@@ -486,7 +504,7 @@ class FlatNotebookDemo(wx.Frame):
style = self.book.GetWindowStyleFlag() style = self.book.GetWindowStyleFlag()
# remove old tabs style # 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 &= mirror
style |= fnb.FNB_FANCY_TABS style |= fnb.FNB_FANCY_TABS

View File

@@ -11,7 +11,7 @@
# Python Code By: # Python Code By:
# #
# Andrea Gavana, @ 02 Oct 2006 # 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 # 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 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) - The buttons area is never overdrawn by tabs (unlike many other implementations I saw)
- It is a generic control - 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 - Mouse middle click can be used to close tabs
- A function to add right click menu for tabs (simple as SetRightClickMenu) - 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) - 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. 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. Version 2.0.
@@ -123,6 +123,10 @@ FNB_NODRAG = 128
FNB_VC8 = 256 FNB_VC8 = 256
"""Use Visual Studio 2005 (VC8) style for tabs""" """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 # Place 'X' on a tab
FNB_X_ON_TAB = 512 FNB_X_ON_TAB = 512
"""Place 'X' close button on the active tab""" """Place 'X' close button on the active tab"""
@@ -716,6 +720,61 @@ def PaintStraightGradientBox(dc, rect, startColor, endColor, vertical=True):
dc.SetBrush(savedBrush) 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 # Class FNBDropSource
# Gives Some Custom UI Feedback during the DnD Operations # Gives Some Custom UI Feedback during the DnD Operations
@@ -1148,7 +1207,7 @@ class TabNavigatorWindow(wx.Dialog):
def OnItemSelected(self, event): def OnItemSelected(self, event):
"""Handles the wx.EVT_LISTBOX_DCLICK event for the wx.ListBox inside L{TabNavigatorWindow}. """ """Handles the wx.EVT_LISTBOX_DCLICK event for the wx.ListBox inside L{TabNavigatorWindow}. """
self.CloseDialog() self.CloseDialog()
def CloseDialog(self): def CloseDialog(self):
@@ -1481,7 +1540,7 @@ class FNBRenderer:
return bmp return bmp
def DrawTabsLine(self, pageContainer, dc): def DrawTabsLine(self, pageContainer, dc, selTabX1=-1, selTabX2=-1):
""" Draws a line over the tabs. """ """ Draws a line over the tabs. """
pc = pageContainer pc = pageContainer
@@ -1489,38 +1548,70 @@ class FNBRenderer:
clntRect = pc.GetClientRect() clntRect = pc.GetClientRect()
clientRect3 = wx.Rect(0, 0, clntRect.width, clntRect.height) clientRect3 = wx.Rect(0, 0, clntRect.width, clntRect.height)
if pc.HasFlag(FNB_BOTTOM): if pc.HasFlag(FNB_FF2):
if not pc.HasFlag(FNB_BOTTOM):
clientRect = wx.Rect(0, 2, clntRect.width, clntRect.height - 2) fillColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
clientRect2 = wx.Rect(0, 1, clntRect.width, clntRect.height - 1) else:
fillColor = wx.WHITE
dc.SetPen(wx.Pen(fillColor))
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: 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): 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: 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)
dc.DrawLine(0, 0, clientRect.width, 0) if pc.HasFlag(FNB_BOTTOM):
dc.DrawLine(clientRect.width - 1, 0, clientRect.width - 1, clientRect.height+1) dc.DrawLine(0, clientRect.height+1, clientRect.width, 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): def CalcTabWidth(self, pageContainer, tabIdx, tabHeight):
@@ -1650,7 +1741,12 @@ class FNBRenderer:
else: else:
colr = (pc.HasFlag(FNB_VC71) and [wx.Colour(247, 243, 233)] or [pc.GetBackgroundColour()])[0] colr = (pc.HasFlag(FNB_VC71) and [wx.Colour(247, 243, 233)] or [pc.GetBackgroundColour()])[0]
dc.SetPen(wx.Pen(colr)) 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) dc.DrawRectangle(0, 0, size.x, size.y)
# Take 3 bitmaps for the background for the buttons # 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 # We always draw the bottom/upper line of the tabs
# regradless the style # regradless the style
dc.SetPen(borderPen) dc.SetPen(borderPen)
self.DrawTabsLine(pc, dc)
if not pc.HasFlag(FNB_FF2):
self.DrawTabsLine(pc, dc)
# Restore the pen # Restore the pen
dc.SetPen(borderPen) dc.SetPen(borderPen)
@@ -1727,10 +1825,13 @@ class FNBRenderer:
#---------------------------------------------------------- #----------------------------------------------------------
# Go over and draw the visible tabs # Go over and draw the visible tabs
#---------------------------------------------------------- #----------------------------------------------------------
x1 = x2 = -1
for i in xrange(pc._nFrom, len(pc._pagesInfoVec)): for i in xrange(pc._nFrom, len(pc._pagesInfoVec)):
dc.SetPen(borderPen) 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 # Now set the font to the correct font
dc.SetFont((i==pc.GetSelection() and [boldFont] or [normalFont])[0]) 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) # Draw the tab (border, text, image & 'x' on tab)
self.DrawTab(pc, dc, posx, i, tabWidth, tabHeight, pc._nTabXButtonStatus) self.DrawTab(pc, dc, posx, i, tabWidth, tabHeight, pc._nTabXButtonStatus)
if pc.GetSelection() == i:
x1 = posx
x2 = posx + tabWidth + 2
# Restore the text forground # Restore the text forground
dc.SetTextForeground(pc._activeTextColor) dc.SetTextForeground(pc._activeTextColor)
@@ -1781,6 +1886,9 @@ class FNBRenderer:
self.DrawX(pc, dc) self.DrawX(pc, dc)
self.DrawDropDownArrow(pc, dc) self.DrawDropDownArrow(pc, dc)
if pc.HasFlag(FNB_FF2):
self.DrawTabsLine(pc, dc, x1, x2)
def DrawDragHint(self, pc, tabIdx): def DrawDragHint(self, pc, tabIdx):
""" """
@@ -1846,16 +1954,12 @@ class FNBRendererMgr:
self._renderers.update({FNB_VC71: FNBRendererVC71()}) self._renderers.update({FNB_VC71: FNBRendererVC71()})
self._renderers.update({FNB_FANCY_TABS: FNBRendererFancy()}) self._renderers.update({FNB_FANCY_TABS: FNBRendererFancy()})
self._renderers.update({FNB_VC8: FNBRendererVC8()}) self._renderers.update({FNB_VC8: FNBRendererVC8()})
self._renderers.update({FNB_FF2: FNBRendererFirefox2()})
def GetRenderer(self, style): def GetRenderer(self, style):
""" Returns the current renderer based on the style selected. """ """ 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: if style & FNB_VC71:
return self._renderers[FNB_VC71] return self._renderers[FNB_VC71]
@@ -1865,6 +1969,9 @@ class FNBRendererMgr:
if style & FNB_VC8: if style & FNB_VC8:
return self._renderers[FNB_VC8] return self._renderers[FNB_VC8]
if style & FNB_FF2:
return self._renderers[FNB_FF2]
# the default is to return the default renderer # the default is to return the default renderer
return self._renderers[-1] return self._renderers[-1]
@@ -1992,6 +2099,106 @@ class FNBRendererDefault(FNBRenderer):
self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus) 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 # Visual studio 7.1
#------------------------------------------------------------------ #------------------------------------------------------------------
@@ -3545,7 +3752,7 @@ class PageContainer(wx.Panel):
self._colorFrom = wx.WHITE self._colorFrom = wx.WHITE
self._activeTabColor = wx.WHITE self._activeTabColor = wx.WHITE
self._activeTextColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNTEXT) 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._tabAreaColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)
self._nFrom = 0 self._nFrom = 0
@@ -3758,6 +3965,47 @@ class PageContainer(wx.Panel):
self.FireEvent(tabIdx) self.FireEvent(tabIdx)
def RotateLeft(self):
if self._nFrom == 0:
return
# Make sure that the button was pressed before
if self._nLeftButtonStatus != FNB_BTN_PRESSED:
return
self._nLeftButtonStatus = FNB_BTN_HOVER
# We scroll left with bulks of 5
scrollLeft = self.GetNumTabsCanScrollLeft()
self._nFrom -= scrollLeft
if self._nFrom < 0:
self._nFrom = 0
self.Refresh()
def RotateRight(self):
if self._nFrom >= len(self._pagesInfoVec) - 1:
return
# Make sure that the button was pressed before
if self._nRightButtonStatus != FNB_BTN_PRESSED:
return
self._nRightButtonStatus = FNB_BTN_HOVER
# 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): def OnLeftUp(self, event):
""" Handles the wx.EVT_LEFT_UP events for L{PageContainer}. """ """ Handles the wx.EVT_LEFT_UP events for L{PageContainer}. """
@@ -3767,49 +4015,10 @@ class PageContainer(wx.Panel):
where, tabIdx = self.HitTest(event.GetPosition()) where, tabIdx = self.HitTest(event.GetPosition())
if where == FNB_LEFT_ARROW: if where == FNB_LEFT_ARROW:
self.RotateLeft()
if self._nFrom == 0:
return
# Make sure that the button was pressed before
if self._nLeftButtonStatus != FNB_BTN_PRESSED:
return
self._nLeftButtonStatus = FNB_BTN_HOVER
# We scroll left with bulks of 5
scrollLeft = self.GetNumTabsCanScrollLeft()
self._nFrom -= scrollLeft
if self._nFrom < 0:
self._nFrom = 0
self.Refresh()
elif where == FNB_RIGHT_ARROW: elif where == FNB_RIGHT_ARROW:
self.RotateRight()
if self._nFrom >= len(self._pagesInfoVec) - 1:
return
# Make sure that the button was pressed before
if self._nRightButtonStatus != FNB_BTN_PRESSED:
return
self._nRightButtonStatus = FNB_BTN_HOVER
# 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
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._nFrom += self.GetNumOfVisibleTabs()
self.Refresh()
elif where == FNB_X: elif where == FNB_X:
@@ -3846,6 +4055,8 @@ class PageContainer(wx.Panel):
self.PopupTabsMenu() self.PopupTabsMenu()
event.Skip()
def HitTest(self, pt): def HitTest(self, pt):
""" """
@@ -4185,66 +4396,10 @@ class PageContainer(wx.Panel):
def GetNumTabsCanScrollLeft(self): def GetNumTabsCanScrollLeft(self):
""" Returns the number of tabs than can be scrolled left. """ """ Returns the number of tabs than can be scrolled left. """
# Reserved area for the buttons (<>x) if self._nFrom - 1 >= 0:
rect = self.GetClientRect() return 1
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) return 0
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
# 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
def IsDefaultTabs(self): def IsDefaultTabs(self):
@@ -4553,10 +4708,16 @@ class PageContainer(wx.Panel):
def OnLeftDClick(self, event): def OnLeftDClick(self, event):
""" Handles the wx.EVT_LEFT_DCLICK event for L{PageContainer}. """ """ 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: if where == FNB_TAB:
self.DeletePage(tabIdx) self.DeletePage(tabIdx)
@@ -4672,3 +4833,4 @@ class PageContainer(wx.Panel):
where, tabIdx = self.HitTest(client_pt) where, tabIdx = self.HitTest(client_pt)
self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag()).DrawDragHint(self, tabIdx) self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag()).DrawDragHint(self, tabIdx)