+++ /dev/null
-# --------------------------------------------------------------------------- #
-# FLATNOTEBOOK Widget wxPython IMPLEMENTATION
-#
-# Original C++ Code From Eran. You Can Find It At:
-#
-# http://wxforum.shadonet.com/viewtopic.php?t=5761&start=0
-#
-# License: wxWidgets license
-#
-#
-# Python Code By:
-#
-# Andrea Gavana, @ 02 Oct 2006
-# Latest Revision: 28 Jun 2007, 21.00 GMT
-#
-#
-# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
-# Write To Me At:
-#
-# andrea.gavana@gmail.com
-# gavana@kpo.kz
-#
-# Or, Obviously, To The wxPython Mailing List!!!
-#
-#
-# End Of Comments
-# --------------------------------------------------------------------------- #
-
-"""
-The FlatNotebook is a full implementation of the wx.Notebook, and designed to be
-a drop-in replacement for wx.Notebook. The API functions are similar so one can
-expect the function to behave in the same way.
-
-Some features:
-
- - The buttons are highlighted a la Firefox style
- - 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 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)
- - An option to hide 'X' button or navigation buttons (separately)
- - Gradient coloring of the selected tabs and border
- - Support for drag 'n' drop of tabs, both in the same notebook or to another notebook
- - Possibility to have closing button on the active tab directly
- - Support for disabled tabs
- - Colours for active/inactive tabs, and captions
- - Background of tab area can be painted in gradient (VC8 style only)
- - Colourful tabs - a random gentle colour is generated for each new tab (very cool, VC8 style only)
-
-
-And much more.
-
-
-License And Version:
-
-FlatNotebook Is Freeware And Distributed Under The wxPython License.
-
-Latest Revision: Andrea Gavana @ 28 Jun 2007, 21.00 GMT
-
-Version 2.2.
-
-@undocumented: FNB_HEIGHT_SPACER, VERTICAL_BORDER_PADDING, VC8_SHAPE_LEN,
- wxEVT*, left_arrow_*, right_arrow*, x_button*, down_arrow*,
- FNBDragInfo, FNBDropTarget, GetMondrian*
-"""
-
-__docformat__ = "epytext"
-
-
-#----------------------------------------------------------------------
-# Beginning Of FLATNOTEBOOK wxPython Code
-#----------------------------------------------------------------------
-
-import wx
-import random
-import math
-import weakref
-import cPickle
-
-# Check for the new method in 2.7 (not present in 2.6.3.3)
-if wx.VERSION_STRING < "2.7":
- wx.Rect.Contains = lambda self, point: wx.Rect.Inside(self, point)
-
-FNB_HEIGHT_SPACER = 10
-
-# Use Visual Studio 2003 (VC7.1) style for tabs
-FNB_VC71 = 1
-"""Use Visual Studio 2003 (VC7.1) style for tabs"""
-
-# Use fancy style - square tabs filled with gradient coloring
-FNB_FANCY_TABS = 2
-"""Use fancy style - square tabs filled with gradient coloring"""
-
-# Draw thin border around the page
-FNB_TABS_BORDER_SIMPLE = 4
-"""Draw thin border around the page"""
-
-# Do not display the 'X' button
-FNB_NO_X_BUTTON = 8
-"""Do not display the 'X' button"""
-
-# Do not display the Right / Left arrows
-FNB_NO_NAV_BUTTONS = 16
-"""Do not display the right/left arrows"""
-
-# Use the mouse middle button for cloing tabs
-FNB_MOUSE_MIDDLE_CLOSES_TABS = 32
-"""Use the mouse middle button for cloing tabs"""
-
-# Place tabs at bottom - the default is to place them
-# at top
-FNB_BOTTOM = 64
-"""Place tabs at bottom - the default is to place them at top"""
-
-# Disable dragging of tabs
-FNB_NODRAG = 128
-"""Disable dragging of tabs"""
-
-# Use Visual Studio 2005 (VC8) style for tabs
-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"""
-
-FNB_BACKGROUND_GRADIENT = 1024
-"""Use gradients to paint the tabs background"""
-
-FNB_COLORFUL_TABS = 2048
-"""Use colourful tabs (VC8 style only)"""
-
-# Style to close tab using double click - styles 1024, 2048 are reserved
-FNB_DCLICK_CLOSES_TABS = 4096
-"""Style to close tab using double click"""
-
-FNB_SMART_TABS = 8192
-"""Use Smart Tabbing, like Alt+Tab on Windows"""
-
-FNB_DROPDOWN_TABS_LIST = 16384
-"""Use a dropdown menu on the left in place of the arrows"""
-
-FNB_ALLOW_FOREIGN_DND = 32768
-"""Allows drag 'n' drop operations between different L{FlatNotebook}s"""
-
-FNB_HIDE_ON_SINGLE_TAB = 65536
-"""Hides the Page Container when there is one or fewer tabs"""
-
-VERTICAL_BORDER_PADDING = 4
-
-# Button size is a 16x16 xpm bitmap
-BUTTON_SPACE = 16
-"""Button size is a 16x16 xpm bitmap"""
-
-VC8_SHAPE_LEN = 16
-
-MASK_COLOR = wx.Colour(0, 128, 128)
-"""Mask colour for the arrow bitmaps"""
-
-# Button status
-FNB_BTN_PRESSED = 2
-"""Navigation button is pressed"""
-FNB_BTN_HOVER = 1
-"""Navigation button is hovered"""
-FNB_BTN_NONE = 0
-"""No navigation"""
-
-# Hit Test results
-FNB_TAB = 1 # On a tab
-"""Indicates mouse coordinates inside a tab"""
-FNB_X = 2 # On the X button
-"""Indicates mouse coordinates inside the I{X} region"""
-FNB_TAB_X = 3 # On the 'X' button (tab's X button)
-"""Indicates mouse coordinates inside the I{X} region in a tab"""
-FNB_LEFT_ARROW = 4 # On the rotate left arrow button
-"""Indicates mouse coordinates inside the left arrow region"""
-FNB_RIGHT_ARROW = 5 # On the rotate right arrow button
-"""Indicates mouse coordinates inside the right arrow region"""
-FNB_DROP_DOWN_ARROW = 6 # On the drop down arrow button
-"""Indicates mouse coordinates inside the drop down arrow region"""
-FNB_NOWHERE = 0 # Anywhere else
-"""Indicates mouse coordinates not on any tab of the notebook"""
-
-FNB_DEFAULT_STYLE = FNB_MOUSE_MIDDLE_CLOSES_TABS | FNB_HIDE_ON_SINGLE_TAB
-"""L{FlatNotebook} default style"""
-
-# FlatNotebook Events:
-# wxEVT_FLATNOTEBOOK_PAGE_CHANGED: Event Fired When You Switch Page;
-# wxEVT_FLATNOTEBOOK_PAGE_CHANGING: Event Fired When You Are About To Switch
-# Pages, But You Can Still "Veto" The Page Changing By Avoiding To Call
-# event.Skip() In Your Event Handler;
-# wxEVT_FLATNOTEBOOK_PAGE_CLOSING: Event Fired When A Page Is Closing, But
-# You Can Still "Veto" The Page Changing By Avoiding To Call event.Skip()
-# In Your Event Handler;
-# wxEVT_FLATNOTEBOOK_PAGE_CLOSED: Event Fired When A Page Is Closed.
-# wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU: Event Fired When A Menu Pops-up In A Tab.
-
-wxEVT_FLATNOTEBOOK_PAGE_CHANGED = wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
-wxEVT_FLATNOTEBOOK_PAGE_CHANGING = wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING
-wxEVT_FLATNOTEBOOK_PAGE_CLOSING = wx.NewEventType()
-wxEVT_FLATNOTEBOOK_PAGE_CLOSED = wx.NewEventType()
-wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU = wx.NewEventType()
-
-#-----------------------------------#
-# FlatNotebookEvent
-#-----------------------------------#
-
-EVT_FLATNOTEBOOK_PAGE_CHANGED = wx.EVT_NOTEBOOK_PAGE_CHANGED
-"""Notify client objects when the active page in L{FlatNotebook}
-has changed."""
-EVT_FLATNOTEBOOK_PAGE_CHANGING = wx.EVT_NOTEBOOK_PAGE_CHANGING
-"""Notify client objects when the active page in L{FlatNotebook}
-is about to change."""
-EVT_FLATNOTEBOOK_PAGE_CLOSING = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, 1)
-"""Notify client objects when a page in L{FlatNotebook} is closing."""
-EVT_FLATNOTEBOOK_PAGE_CLOSED = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CLOSED, 1)
-"""Notify client objects when a page in L{FlatNotebook} has been closed."""
-EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU, 1)
-"""Notify client objects when a pop-up menu should appear next to a tab."""
-
-
-# Some icons in XPM format
-
-left_arrow_disabled_xpm = [
- " 16 16 8 1",
- "` c #008080",
- ". c #555555",
- "# c #000000",
- "a c #000000",
- "b c #000000",
- "c c #000000",
- "d c #000000",
- "e c #000000",
- "````````````````",
- "````````````````",
- "````````````````",
- "````````.```````",
- "```````..```````",
- "``````.`.```````",
- "`````.``.```````",
- "````.```.```````",
- "`````.``.```````",
- "``````.`.```````",
- "```````..```````",
- "````````.```````",
- "````````````````",
- "````````````````",
- "````````````````",
- "````````````````"
- ]
-
-x_button_pressed_xpm = [
- " 16 16 8 1",
- "` c #008080",
- ". c #4766e0",
- "# c #9e9ede",
- "a c #000000",
- "b c #000000",
- "c c #000000",
- "d c #000000",
- "e c #000000",
- "````````````````",
- "`..............`",
- "`.############.`",
- "`.############.`",
- "`.############.`",
- "`.###aa####aa#.`",
- "`.####aa##aa##.`",
- "`.#####aaaa###.`",
- "`.######aa####.`",
- "`.#####aaaa###.`",
- "`.####aa##aa##.`",
- "`.###aa####aa#.`",
- "`.############.`",
- "`..............`",
- "````````````````",
- "````````````````"
- ]
-
-
-left_arrow_xpm = [
- " 16 16 8 1",
- "` c #008080",
- ". c #555555",
- "# c #000000",
- "a c #000000",
- "b c #000000",
- "c c #000000",
- "d c #000000",
- "e c #000000",
- "````````````````",
- "````````````````",
- "````````````````",
- "````````.```````",
- "```````..```````",
- "``````...```````",
- "`````....```````",
- "````.....```````",
- "`````....```````",
- "``````...```````",
- "```````..```````",
- "````````.```````",
- "````````````````",
- "````````````````",
- "````````````````",
- "````````````````"
- ]
-
-x_button_hilite_xpm = [
- " 16 16 8 1",
- "` c #008080",
- ". c #4766e0",
- "# c #c9dafb",
- "a c #000000",
- "b c #000000",
- "c c #000000",
- "d c #000000",
- "e c #000000",
- "````````````````",
- "`..............`",
- "`.############.`",
- "`.############.`",
- "`.##aa####aa##.`",
- "`.###aa##aa###.`",
- "`.####aaaa####.`",
- "`.#####aa#####.`",
- "`.####aaaa####.`",
- "`.###aa##aa###.`",
- "`.##aa####aa##.`",
- "`.############.`",
- "`.############.`",
- "`..............`",
- "````````````````",
- "````````````````"
- ]
-
-x_button_xpm = [
- " 16 16 8 1",
- "` c #008080",
- ". c #555555",
- "# c #000000",
- "a c #000000",
- "b c #000000",
- "c c #000000",
- "d c #000000",
- "e c #000000",
- "````````````````",
- "````````````````",
- "````````````````",
- "````````````````",
- "````..````..````",
- "`````..``..`````",
- "``````....``````",
- "```````..```````",
- "``````....``````",
- "`````..``..`````",
- "````..````..````",
- "````````````````",
- "````````````````",
- "````````````````",
- "````````````````",
- "````````````````"
- ]
-
-left_arrow_pressed_xpm = [
- " 16 16 8 1",
- "` c #008080",
- ". c #4766e0",
- "# c #9e9ede",
- "a c #000000",
- "b c #000000",
- "c c #000000",
- "d c #000000",
- "e c #000000",
- "````````````````",
- "`..............`",
- "`.############.`",
- "`.############.`",
- "`.#######a####.`",
- "`.######aa####.`",
- "`.#####aaa####.`",
- "`.####aaaa####.`",
- "`.###aaaaa####.`",
- "`.####aaaa####.`",
- "`.#####aaa####.`",
- "`.######aa####.`",
- "`.#######a####.`",
- "`..............`",
- "````````````````",
- "````````````````"
- ]
-
-left_arrow_hilite_xpm = [
- " 16 16 8 1",
- "` c #008080",
- ". c #4766e0",
- "# c #c9dafb",
- "a c #000000",
- "b c #000000",
- "c c #000000",
- "d c #000000",
- "e c #000000",
- "````````````````",
- "`..............`",
- "`.############.`",
- "`.######a#####.`",
- "`.#####aa#####.`",
- "`.####aaa#####.`",
- "`.###aaaa#####.`",
- "`.##aaaaa#####.`",
- "`.###aaaa#####.`",
- "`.####aaa#####.`",
- "`.#####aa#####.`",
- "`.######a#####.`",
- "`.############.`",
- "`..............`",
- "````````````````",
- "````````````````"
- ]
-
-right_arrow_disabled_xpm = [
- " 16 16 8 1",
- "` c #008080",
- ". c #555555",
- "# c #000000",
- "a c #000000",
- "b c #000000",
- "c c #000000",
- "d c #000000",
- "e c #000000",
- "````````````````",
- "````````````````",
- "````````````````",
- "```````.````````",
- "```````..```````",
- "```````.`.``````",
- "```````.``.`````",
- "```````.```.````",
- "```````.``.`````",
- "```````.`.``````",
- "```````..```````",
- "```````.````````",
- "````````````````",
- "````````````````",
- "````````````````",
- "````````````````"
- ]
-
-right_arrow_hilite_xpm = [
- " 16 16 8 1",
- "` c #008080",
- ". c #4766e0",
- "# c #c9dafb",
- "a c #000000",
- "b c #000000",
- "c c #000000",
- "d c #000000",
- "e c #000000",
- "````````````````",
- "`..............`",
- "`.############.`",
- "`.####a#######.`",
- "`.####aa######.`",
- "`.####aaa#####.`",
- "`.####aaaa####.`",
- "`.####aaaaa###.`",
- "`.####aaaa####.`",
- "`.####aaa#####.`",
- "`.####aa######.`",
- "`.####a#######.`",
- "`.############.`",
- "`..............`",
- "````````````````",
- "````````````````"
- ]
-
-right_arrow_pressed_xpm = [
- " 16 16 8 1",
- "` c #008080",
- ". c #4766e0",
- "# c #9e9ede",
- "a c #000000",
- "b c #000000",
- "c c #000000",
- "d c #000000",
- "e c #000000",
- "````````````````",
- "`..............`",
- "`.############.`",
- "`.############.`",
- "`.#####a######.`",
- "`.#####aa#####.`",
- "`.#####aaa####.`",
- "`.#####aaaa###.`",
- "`.#####aaaaa##.`",
- "`.#####aaaa###.`",
- "`.#####aaa####.`",
- "`.#####aa#####.`",
- "`.#####a######.`",
- "`..............`",
- "````````````````",
- "````````````````"
- ]
-
-
-right_arrow_xpm = [
- " 16 16 8 1",
- "` c #008080",
- ". c #555555",
- "# c #000000",
- "a c #000000",
- "b c #000000",
- "c c #000000",
- "d c #000000",
- "e c #000000",
- "````````````````",
- "````````````````",
- "````````````````",
- "```````.````````",
- "```````..```````",
- "```````...``````",
- "```````....`````",
- "```````.....````",
- "```````....`````",
- "```````...``````",
- "```````..```````",
- "```````.````````",
- "````````````````",
- "````````````````",
- "````````````````",
- "````````````````"
- ]
-
-down_arrow_hilite_xpm = [
- " 16 16 8 1",
- "` c #008080",
- ". c #4766e0",
- "# c #c9dafb",
- "a c #000000",
- "b c #000000",
- "c c #000000",
- "d c #000000",
- "e c #000000",
- "````````````````",
- "``.............`",
- "``.###########.`",
- "``.###########.`",
- "``.###########.`",
- "``.#aaaaaaaaa#.`",
- "``.##aaaaaaa##.`",
- "``.###aaaaa###.`",
- "``.####aaa####.`",
- "``.#####a#####.`",
- "``.###########.`",
- "``.###########.`",
- "``.###########.`",
- "``.............`",
- "````````````````",
- "````````````````"
- ]
-
-down_arrow_pressed_xpm = [
- " 16 16 8 1",
- "` c #008080",
- ". c #4766e0",
- "# c #9e9ede",
- "a c #000000",
- "b c #000000",
- "c c #000000",
- "d c #000000",
- "e c #000000",
- "````````````````",
- "``.............`",
- "``.###########.`",
- "``.###########.`",
- "``.###########.`",
- "``.###########.`",
- "``.###########.`",
- "``.#aaaaaaaaa#.`",
- "``.##aaaaaaa##.`",
- "``.###aaaaa###.`",
- "``.####aaa####.`",
- "``.#####a#####.`",
- "``.###########.`",
- "``.............`",
- "````````````````",
- "````````````````"
- ]
-
-
-down_arrow_xpm = [
- " 16 16 8 1",
- "` c #008080",
- ". c #000000",
- "# c #000000",
- "a c #000000",
- "b c #000000",
- "c c #000000",
- "d c #000000",
- "e c #000000",
- "````````````````",
- "````````````````",
- "````````````````",
- "````````````````",
- "````````````````",
- "````````````````",
- "````.........```",
- "`````.......````",
- "``````.....`````",
- "```````...``````",
- "````````.```````",
- "````````````````",
- "````````````````",
- "````````````````",
- "````````````````",
- "````````````````"
- ]
-
-
-#----------------------------------------------------------------------
-def GetMondrianData():
- return \
-'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\
-\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00qID\
-ATX\x85\xed\xd6;\n\x800\x10E\xd1{\xc5\x8d\xb9r\x97\x16\x0b\xad$\x8a\x82:\x16\
-o\xda\x84pB2\x1f\x81Fa\x8c\x9c\x08\x04Z{\xcf\xa72\xbcv\xfa\xc5\x08 \x80r\x80\
-\xfc\xa2\x0e\x1c\xe4\xba\xfaX\x1d\xd0\xde]S\x07\x02\xd8>\xe1wa-`\x9fQ\xe9\
-\x86\x01\x04\x10\x00\\(Dk\x1b-\x04\xdc\x1d\x07\x14\x98;\x0bS\x7f\x7f\xf9\x13\
-\x04\x10@\xf9X\xbe\x00\xc9 \x14K\xc1<={\x00\x00\x00\x00IEND\xaeB`\x82'
-
-
-def GetMondrianBitmap():
- return wx.BitmapFromImage(GetMondrianImage().Scale(16, 16))
-
-
-def GetMondrianImage():
- import cStringIO
- stream = cStringIO.StringIO(GetMondrianData())
- return wx.ImageFromStream(stream)
-
-
-def GetMondrianIcon():
- icon = wx.EmptyIcon()
- icon.CopyFromBitmap(GetMondrianBitmap())
- return icon
-#----------------------------------------------------------------------
-
-
-def LightColour(color, percent):
- """ Brighten input colour by percent. """
-
- end_color = wx.WHITE
-
- rd = end_color.Red() - color.Red()
- gd = end_color.Green() - color.Green()
- bd = end_color.Blue() - color.Blue()
-
- high = 100
-
- # We take the percent way of the color from color -. white
- i = percent
- r = color.Red() + ((i*rd*100)/high)/100
- g = color.Green() + ((i*gd*100)/high)/100
- b = color.Blue() + ((i*bd*100)/high)/100
- return wx.Colour(r, g, b)
-
-
-def RandomColour():
- """ Creates a random colour. """
-
- r = random.randint(0, 255) # Random value betweem 0-255
- g = random.randint(0, 255) # Random value betweem 0-255
- b = random.randint(0, 255) # Random value betweem 0-255
-
- return wx.Colour(r, g, b)
-
-
-def PaintStraightGradientBox(dc, rect, startColor, endColor, vertical=True):
- """ Draws a gradient colored box from startColor to endColor. """
-
- rd = endColor.Red() - startColor.Red()
- gd = endColor.Green() - startColor.Green()
- bd = endColor.Blue() - startColor.Blue()
-
- # Save the current pen and brush
- savedPen = dc.GetPen()
- savedBrush = dc.GetBrush()
-
- if vertical:
- high = rect.GetHeight()-1
- else:
- high = rect.GetWidth()-1
-
- if high < 1:
- return
-
- for i in xrange(high+1):
-
- r = startColor.Red() + ((i*rd*100)/high)/100
- g = startColor.Green() + ((i*gd*100)/high)/100
- b = startColor.Blue() + ((i*bd*100)/high)/100
-
- p = wx.Pen(wx.Colour(r, g, b))
- dc.SetPen(p)
-
- if vertical:
- dc.DrawLine(rect.x, rect.y+i, rect.x+rect.width, rect.y+i)
- else:
- dc.DrawLine(rect.x+i, rect.y, rect.x+i, rect.y+rect.height)
-
- # Restore the pen and brush
- dc.SetPen(savedPen)
- 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
-# ---------------------------------------------------------------------------- #
-
-class FNBDropSource(wx.DropSource):
- """
- Give some custom UI feedback during the drag and drop operation in this
- function. It is called on each mouse move, so your implementation must
- not be too slow.
- """
-
- def __init__(self, win):
- """ Default class constructor. Used internally. """
-
- wx.DropSource.__init__(self, win)
- self._win = win
-
-
- def GiveFeedback(self, effect):
- """ Provides user with a nice feedback when tab is being dragged. """
-
- self._win.DrawDragHint()
- return False
-
-
-# ---------------------------------------------------------------------------- #
-# Class FNBDragInfo
-# Stores All The Information To Allow Drag And Drop Between Different
-# FlatNotebooks.
-# ---------------------------------------------------------------------------- #
-
-class FNBDragInfo:
-
- _map = weakref.WeakValueDictionary()
-
- def __init__(self, container, pageindex):
- """ Default class constructor. """
-
- self._id = id(container)
- FNBDragInfo._map[self._id] = container
- self._pageindex = pageindex
-
-
- def GetContainer(self):
- """ Returns the L{FlatNotebook} page (usually a panel). """
-
- return FNBDragInfo._map.get(self._id, None)
-
-
- def GetPageIndex(self):
- """ Returns the page index associated with a page. """
-
- return self._pageindex
-
-
-# ---------------------------------------------------------------------------- #
-# Class FNBDropTarget
-# Simply Used To Handle The OnDrop() Method When Dragging And Dropping Between
-# Different FlatNotebooks.
-# ---------------------------------------------------------------------------- #
-
-class FNBDropTarget(wx.DropTarget):
-
- def __init__(self, parent):
- """ Default class constructor. """
-
- wx.DropTarget.__init__(self)
-
- self._parent = parent
- self._dataobject = wx.CustomDataObject(wx.CustomDataFormat("FlatNotebook"))
- self.SetDataObject(self._dataobject)
-
-
- def OnData(self, x, y, dragres):
- """ Handles the OnData() method to call the real DnD routine. """
-
- if not self.GetData():
- return wx.DragNone
-
- draginfo = self._dataobject.GetData()
- drginfo = cPickle.loads(draginfo)
-
- return self._parent.OnDropTarget(x, y, drginfo.GetPageIndex(), drginfo.GetContainer())
-
-
-# ---------------------------------------------------------------------------- #
-# Class PageInfo
-# Contains parameters for every FlatNotebook page
-# ---------------------------------------------------------------------------- #
-
-class PageInfo:
- """
- This class holds all the information (caption, image, etc...) belonging to a
- single tab in L{FlatNotebook}.
- """
-
- def __init__(self, caption="", imageindex=-1, tabangle=0, enabled=True):
- """
- Default Class Constructor.
-
- Parameters:
- @param caption: the tab caption;
- @param imageindex: the tab image index based on the assigned (set) wx.ImageList (if any);
- @param tabangle: the tab angle (only on standard tabs, from 0 to 15 degrees);
- @param enabled: sets enabled or disabled the tab.
- """
-
- self._strCaption = caption
- self._TabAngle = tabangle
- self._ImageIndex = imageindex
- self._bEnabled = enabled
- self._pos = wx.Point(-1, -1)
- self._size = wx.Size(-1, -1)
- self._region = wx.Region()
- self._xRect = wx.Rect()
- self._color = None
- self._hasFocus = False
-
-
- def SetCaption(self, value):
- """ Sets the tab caption. """
-
- self._strCaption = value
-
-
- def GetCaption(self):
- """ Returns the tab caption. """
-
- return self._strCaption
-
-
- def SetPosition(self, value):
- """ Sets the tab position. """
-
- self._pos = value
-
-
- def GetPosition(self):
- """ Returns the tab position. """
-
- return self._pos
-
-
- def SetSize(self, value):
- """ Sets the tab size. """
-
- self._size = value
-
-
- def GetSize(self):
- """ Returns the tab size. """
-
- return self._size
-
-
- def SetTabAngle(self, value):
- """ Sets the tab header angle (0 <= tab <= 15 degrees). """
-
- self._TabAngle = min(45, value)
-
-
- def GetTabAngle(self):
- """ Returns the tab angle. """
-
- return self._TabAngle
-
-
- def SetImageIndex(self, value):
- """ Sets the tab image index. """
-
- self._ImageIndex = value
-
-
- def GetImageIndex(self):
- """ Returns the tab umage index. """
-
- return self._ImageIndex
-
-
- def GetEnabled(self):
- """ Returns whether the tab is enabled or not. """
-
- return self._bEnabled
-
-
- def EnableTab(self, enabled):
- """ Sets the tab enabled or disabled. """
-
- self._bEnabled = enabled
-
-
- def SetRegion(self, points=[]):
- """ Sets the tab region. """
-
- self._region = wx.RegionFromPoints(points)
-
-
- def GetRegion(self):
- """ Returns the tab region. """
-
- return self._region
-
-
- def SetXRect(self, xrect):
- """ Sets the button 'X' area rect. """
-
- self._xRect = xrect
-
-
- def GetXRect(self):
- """ Returns the button 'X' area rect. """
-
- return self._xRect
-
-
- def GetColour(self):
- """ Returns the tab colour. """
-
- return self._color
-
-
- def SetColour(self, color):
- """ Sets the tab colour. """
-
- self._color = color
-
-
-# ---------------------------------------------------------------------------- #
-# Class FlatNotebookEvent
-# ---------------------------------------------------------------------------- #
-
-class FlatNotebookEvent(wx.PyCommandEvent):
- """
- This events will be sent when a EVT_FLATNOTEBOOK_PAGE_CHANGED,
- EVT_FLATNOTEBOOK_PAGE_CHANGING, EVT_FLATNOTEBOOK_PAGE_CLOSING,
- EVT_FLATNOTEBOOK_PAGE_CLOSED and EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU is
- mapped in the parent.
- """
-
- def __init__(self, eventType, id=1, nSel=-1, nOldSel=-1):
- """ Default class constructor. """
-
- wx.PyCommandEvent.__init__(self, eventType, id)
- self._eventType = eventType
-
- self.notify = wx.NotifyEvent(eventType, id)
-
-
- def GetNotifyEvent(self):
- """Returns the actual wx.NotifyEvent."""
-
- return self.notify
-
-
- def IsAllowed(self):
- """Returns whether the event is allowed or not."""
-
- return self.notify.IsAllowed()
-
-
- def Veto(self):
- """Vetos the event."""
-
- self.notify.Veto()
-
-
- def Allow(self):
- """The event is allowed."""
-
- self.notify.Allow()
-
-
- def SetSelection(self, nSel):
- """ Sets event selection. """
-
- self._selection = nSel
-
-
- def SetOldSelection(self, nOldSel):
- """ Sets old event selection. """
-
- self._oldselection = nOldSel
-
-
- def GetSelection(self):
- """ Returns event selection. """
-
- return self._selection
-
-
- def GetOldSelection(self):
- """ Returns old event selection """
-
- return self._oldselection
-
-
-# ---------------------------------------------------------------------------- #
-# Class TabNavigatorWindow
-# ---------------------------------------------------------------------------- #
-
-class TabNavigatorWindow(wx.Dialog):
- """
- This class is used to create a modal dialog that enables "Smart Tabbing",
- similar to what you would get by hitting Alt+Tab on Windows.
- """
-
- def __init__(self, parent=None):
- """ Default class constructor. Used internally."""
-
- wx.Dialog.__init__(self, parent, wx.ID_ANY, "", style=0)
-
- self._selectedItem = -1
- self._indexMap = []
-
- self._bmp = GetMondrianBitmap()
-
- sz = wx.BoxSizer(wx.VERTICAL)
-
- self._listBox = wx.ListBox(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(200, 150), [], wx.LB_SINGLE | wx.NO_BORDER)
-
- mem_dc = wx.MemoryDC()
- mem_dc.SelectObject(wx.EmptyBitmap(1,1))
- font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
- font.SetWeight(wx.BOLD)
- mem_dc.SetFont(font)
-
- panelHeight = mem_dc.GetCharHeight()
- panelHeight += 4 # Place a spacer of 2 pixels
-
- # Out signpost bitmap is 24 pixels
- if panelHeight < 24:
- panelHeight = 24
-
- self._panel = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(200, panelHeight))
-
- sz.Add(self._panel)
- sz.Add(self._listBox, 1, wx.EXPAND)
-
- self.SetSizer(sz)
-
- # Connect events to the list box
- self._listBox.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
- self._listBox.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey)
- self._listBox.Bind(wx.EVT_LISTBOX_DCLICK, self.OnItemSelected)
-
- # Connect paint event to the panel
- self._panel.Bind(wx.EVT_PAINT, self.OnPanelPaint)
- self._panel.Bind(wx.EVT_ERASE_BACKGROUND, self.OnPanelEraseBg)
-
- self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
- self._listBox.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
- self.PopulateListControl(parent)
-
- self.GetSizer().Fit(self)
- self.GetSizer().SetSizeHints(self)
- self.GetSizer().Layout()
- self.Centre()
-
-
- def OnKeyUp(self, event):
- """Handles the wx.EVT_KEY_UP for the L{TabNavigatorWindow}."""
-
- if event.GetKeyCode() == wx.WXK_CONTROL:
- self.CloseDialog()
-
-
- def OnNavigationKey(self, event):
- """Handles the wx.EVT_NAVIGATION_KEY for the L{TabNavigatorWindow}. """
-
- selected = self._listBox.GetSelection()
- bk = self.GetParent()
- maxItems = bk.GetPageCount()
-
- if event.GetDirection():
-
- # Select next page
- if selected == maxItems - 1:
- itemToSelect = 0
- else:
- itemToSelect = selected + 1
-
- else:
-
- # Previous page
- if selected == 0:
- itemToSelect = maxItems - 1
- else:
- itemToSelect = selected - 1
-
- self._listBox.SetSelection(itemToSelect)
-
-
- def PopulateListControl(self, book):
- """Populates the L{TabNavigatorWindow} listbox with a list of tabs."""
-
- selection = book.GetSelection()
- count = book.GetPageCount()
-
- self._listBox.Append(book.GetPageText(selection))
- self._indexMap.append(selection)
-
- prevSel = book.GetPreviousSelection()
-
- if prevSel != wx.NOT_FOUND:
-
- # Insert the previous selection as second entry
- self._listBox.Append(book.GetPageText(prevSel))
- self._indexMap.append(prevSel)
-
- for c in xrange(count):
-
- # Skip selected page
- if c == selection:
- continue
-
- # Skip previous selected page as well
- if c == prevSel:
- continue
-
- self._listBox.Append(book.GetPageText(c))
- self._indexMap.append(c)
-
- # Select the next entry after the current selection
- self._listBox.SetSelection(0)
- dummy = wx.NavigationKeyEvent()
- dummy.SetDirection(True)
- self.OnNavigationKey(dummy)
-
-
- def OnItemSelected(self, event):
- """Handles the wx.EVT_LISTBOX_DCLICK event for the wx.ListBox inside L{TabNavigatorWindow}. """
-
- self.CloseDialog()
-
-
- def CloseDialog(self):
- """Closes the L{TabNavigatorWindow} dialog, setting selection in L{FlatNotebook}."""
-
- bk = self.GetParent()
- self._selectedItem = self._listBox.GetSelection()
- iter = self._indexMap[self._selectedItem]
- bk._pages.FireEvent(iter)
- self.EndModal(wx.ID_OK)
-
-
- def OnPanelPaint(self, event):
- """Handles the wx.EVT_PAINT event for L{TabNavigatorWindow} top panel. """
-
- dc = wx.PaintDC(self._panel)
- rect = self._panel.GetClientRect()
-
- bmp = wx.EmptyBitmap(rect.width, rect.height)
-
- mem_dc = wx.MemoryDC()
- mem_dc.SelectObject(bmp)
-
- endColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
- startColour = LightColour(endColour, 50)
- PaintStraightGradientBox(mem_dc, rect, startColour, endColour)
-
- # Draw the caption title and place the bitmap
- # get the bitmap optimal position, and draw it
- bmpPt, txtPt = wx.Point(), wx.Point()
- bmpPt.y = (rect.height - self._bmp.GetHeight())/2
- bmpPt.x = 3
- mem_dc.DrawBitmap(self._bmp, bmpPt.x, bmpPt.y, True)
-
- # get the text position, and draw it
- font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
- font.SetWeight(wx.BOLD)
- mem_dc.SetFont(font)
- fontHeight = mem_dc.GetCharHeight()
-
- txtPt.x = bmpPt.x + self._bmp.GetWidth() + 4
- txtPt.y = (rect.height - fontHeight)/2
- mem_dc.SetTextForeground(wx.WHITE)
- mem_dc.DrawText("Opened tabs:", txtPt.x, txtPt.y)
- mem_dc.SelectObject(wx.NullBitmap)
-
- dc.DrawBitmap(bmp, 0, 0)
-
-
- def OnPanelEraseBg(self, event):
- """Handles the wx.EVT_ERASE_BACKGROUND event for L{TabNavigatorWindow} top panel. """
-
- pass
-
-
-# ---------------------------------------------------------------------------- #
-# Class FNBRenderer
-# ---------------------------------------------------------------------------- #
-
-class FNBRenderer:
- """
- Parent class for the 4 renderers defined: I{Standard}, I{VC71}, I{Fancy}
- and I{VC8}. This class implements the common methods of all 4 renderers.
- @undocumented: _GetBitmap*
- """
-
- def __init__(self):
- """Default class constructor. """
-
- self._tabXBgBmp = wx.EmptyBitmap(16, 16)
- self._xBgBmp = wx.EmptyBitmap(16, 14)
- self._leftBgBmp = wx.EmptyBitmap(16, 14)
- self._rightBgBmp = wx.EmptyBitmap(16, 14)
- self._tabHeight = None
-
- if wx.Platform == "__WXMAC__":
- self._focusPen = wx.Pen(wx.BLACK, 1, wx.SOLID)
- else:
- self._focusPen = wx.Pen(wx.BLACK, 1, wx.USER_DASH)
- self._focusPen.SetDashes([1, 1])
- self._focusPen.SetCap(wx.CAP_BUTT)
-
-
- def GetLeftButtonPos(self, pageContainer):
- """ Returns the left button position in the navigation area. """
-
- pc = pageContainer
- style = pc.GetParent().GetWindowStyleFlag()
- rect = pc.GetClientRect()
- clientWidth = rect.width
-
- if style & FNB_NO_X_BUTTON:
- return clientWidth - 38
- else:
- return clientWidth - 54
-
-
-
- def GetRightButtonPos(self, pageContainer):
- """ Returns the right button position in the navigation area. """
-
- pc = pageContainer
- style = pc.GetParent().GetWindowStyleFlag()
- rect = pc.GetClientRect()
- clientWidth = rect.width
-
- if style & FNB_NO_X_BUTTON:
- return clientWidth - 22
- else:
- return clientWidth - 38
-
-
- def GetDropArrowButtonPos(self, pageContainer):
- """ Returns the drop down button position in the navigation area. """
-
- return self.GetRightButtonPos(pageContainer)
-
-
- def GetXPos(self, pageContainer):
- """ Returns the 'X' button position in the navigation area. """
-
- pc = pageContainer
- style = pc.GetParent().GetWindowStyleFlag()
- rect = pc.GetClientRect()
- clientWidth = rect.width
-
- if style & FNB_NO_X_BUTTON:
- return clientWidth
- else:
- return clientWidth - 22
-
-
- def GetButtonsAreaLength(self, pageContainer):
- """ Returns the navigation area width. """
-
- pc = pageContainer
- style = pc.GetParent().GetWindowStyleFlag()
-
- # ''
- if style & FNB_NO_NAV_BUTTONS and style & FNB_NO_X_BUTTON and not style & FNB_DROPDOWN_TABS_LIST:
- return 0
-
- # 'x'
- elif style & FNB_NO_NAV_BUTTONS and not style & FNB_NO_X_BUTTON and not style & FNB_DROPDOWN_TABS_LIST:
- return 22
-
- # '<>'
- if not style & FNB_NO_NAV_BUTTONS and style & FNB_NO_X_BUTTON and not style & FNB_DROPDOWN_TABS_LIST:
- return 53 - 16
-
- # 'vx'
- if style & FNB_DROPDOWN_TABS_LIST and not style & FNB_NO_X_BUTTON:
- return 22 + 16
-
- # 'v'
- if style & FNB_DROPDOWN_TABS_LIST and style & FNB_NO_X_BUTTON:
- return 22
-
- # '<>x'
- return 53
-
-
- def DrawLeftArrow(self, pageContainer, dc):
- """ Draw the left navigation arrow. """
-
- pc = pageContainer
-
- style = pc.GetParent().GetWindowStyleFlag()
- if style & FNB_NO_NAV_BUTTONS:
- return
-
- # Make sure that there are pages in the container
- if not pc._pagesInfoVec:
- return
-
- # Set the bitmap according to the button status
- if pc._nLeftButtonStatus == FNB_BTN_HOVER:
- arrowBmp = wx.BitmapFromXPMData(left_arrow_hilite_xpm)
- elif pc._nLeftButtonStatus == FNB_BTN_PRESSED:
- arrowBmp = wx.BitmapFromXPMData(left_arrow_pressed_xpm)
- else:
- arrowBmp = wx.BitmapFromXPMData(left_arrow_xpm)
-
- if pc._nFrom == 0:
- # Handle disabled arrow
- arrowBmp = wx.BitmapFromXPMData(left_arrow_disabled_xpm)
-
- arrowBmp.SetMask(wx.Mask(arrowBmp, MASK_COLOR))
-
- # Erase old bitmap
- posx = self.GetLeftButtonPos(pc)
- dc.DrawBitmap(self._leftBgBmp, posx, 6)
-
- # Draw the new bitmap
- dc.DrawBitmap(arrowBmp, posx, 6, True)
-
-
- def DrawRightArrow(self, pageContainer, dc):
- """ Draw the right navigation arrow. """
-
- pc = pageContainer
-
- style = pc.GetParent().GetWindowStyleFlag()
- if style & FNB_NO_NAV_BUTTONS:
- return
-
- # Make sure that there are pages in the container
- if not pc._pagesInfoVec:
- return
-
- # Set the bitmap according to the button status
- if pc._nRightButtonStatus == FNB_BTN_HOVER:
- arrowBmp = wx.BitmapFromXPMData(right_arrow_hilite_xpm)
- elif pc._nRightButtonStatus == FNB_BTN_PRESSED:
- arrowBmp = wx.BitmapFromXPMData(right_arrow_pressed_xpm)
- else:
- arrowBmp = wx.BitmapFromXPMData(right_arrow_xpm)
-
- # Check if the right most tab is visible, if it is
- # don't rotate right anymore
- if pc._pagesInfoVec[-1].GetPosition() != wx.Point(-1, -1):
- arrowBmp = wx.BitmapFromXPMData(right_arrow_disabled_xpm)
-
- arrowBmp.SetMask(wx.Mask(arrowBmp, MASK_COLOR))
-
- # erase old bitmap
- posx = self.GetRightButtonPos(pc)
- dc.DrawBitmap(self._rightBgBmp, posx, 6)
-
- # Draw the new bitmap
- dc.DrawBitmap(arrowBmp, posx, 6, True)
-
-
- def DrawDropDownArrow(self, pageContainer, dc):
- """ Draws the drop-down arrow in the navigation area. """
-
- pc = pageContainer
-
- # Check if this style is enabled
- style = pc.GetParent().GetWindowStyleFlag()
- if not style & FNB_DROPDOWN_TABS_LIST:
- return
-
- # Make sure that there are pages in the container
- if not pc._pagesInfoVec:
- return
-
- if pc._nArrowDownButtonStatus == FNB_BTN_HOVER:
- downBmp = wx.BitmapFromXPMData(down_arrow_hilite_xpm)
- elif pc._nArrowDownButtonStatus == FNB_BTN_PRESSED:
- downBmp = wx.BitmapFromXPMData(down_arrow_pressed_xpm)
- else:
- downBmp = wx.BitmapFromXPMData(down_arrow_xpm)
-
- downBmp.SetMask(wx.Mask(downBmp, MASK_COLOR))
-
- # erase old bitmap
- posx = self.GetDropArrowButtonPos(pc)
- dc.DrawBitmap(self._rightBgBmp, posx, 6)
-
- # Draw the new bitmap
- dc.DrawBitmap(downBmp, posx, 6, True)
-
-
- def DrawX(self, pageContainer, dc):
- """ Draw the 'X' navigation button in the navigation area. """
-
- pc = pageContainer
-
- # Check if this style is enabled
- style = pc.GetParent().GetWindowStyleFlag()
- if style & FNB_NO_X_BUTTON:
- return
-
- # Make sure that there are pages in the container
- if not pc._pagesInfoVec:
- return
-
- # Set the bitmap according to the button status
- if pc._nXButtonStatus == FNB_BTN_HOVER:
- xbmp = wx.BitmapFromXPMData(x_button_hilite_xpm)
- elif pc._nXButtonStatus == FNB_BTN_PRESSED:
- xbmp = wx.BitmapFromXPMData(x_button_pressed_xpm)
- else:
- xbmp = wx.BitmapFromXPMData(x_button_xpm)
-
- xbmp.SetMask(wx.Mask(xbmp, MASK_COLOR))
-
- # erase old bitmap
- posx = self.GetXPos(pc)
- dc.DrawBitmap(self._xBgBmp, posx, 6)
-
- # Draw the new bitmap
- dc.DrawBitmap(xbmp, posx, 6, True)
-
-
- def DrawTabX(self, pageContainer, dc, rect, tabIdx, btnStatus):
- """ Draws the 'X' in the selected tab. """
-
- pc = pageContainer
- if not pc.HasFlag(FNB_X_ON_TAB):
- return
-
- # We draw the 'x' on the active tab only
- if tabIdx != pc.GetSelection() or tabIdx < 0:
- return
-
- # Set the bitmap according to the button status
-
- if btnStatus == FNB_BTN_HOVER:
- xBmp = wx.BitmapFromXPMData(x_button_hilite_xpm)
- elif btnStatus == FNB_BTN_PRESSED:
- xBmp = wx.BitmapFromXPMData(x_button_pressed_xpm)
- else:
- xBmp = wx.BitmapFromXPMData(x_button_xpm)
-
- # Set the masking
- xBmp.SetMask(wx.Mask(xBmp, MASK_COLOR))
-
- # erase old button
- dc.DrawBitmap(self._tabXBgBmp, rect.x, rect.y)
-
- # Draw the new bitmap
- dc.DrawBitmap(xBmp, rect.x, rect.y, True)
-
- # Update the vector
- rr = wx.Rect(rect.x, rect.y, 14, 13)
- pc._pagesInfoVec[tabIdx].SetXRect(rr)
-
-
- def _GetBitmap(self, dc, rect, bmp):
-
- mem_dc = wx.MemoryDC()
- mem_dc.SelectObject(bmp)
- mem_dc.Blit(0, 0, rect.width, rect.height, dc, rect.x, rect.y)
- mem_dc.SelectObject(wx.NullBitmap)
- return bmp
-
-
- def DrawTabsLine(self, pageContainer, dc, selTabX1=-1, selTabX2=-1):
- """ Draws a line over the tabs. """
-
- pc = pageContainer
-
- clntRect = pc.GetClientRect()
- clientRect3 = wx.Rect(0, 0, clntRect.width, clntRect.height)
-
- 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(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:
-
- 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)
-
- 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, 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):
- """ Calculates the width of the input tab. """
-
- pc = pageContainer
- dc = wx.MemoryDC()
- dc.SelectObject(wx.EmptyBitmap(1,1))
-
- boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
- boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
-
- if pc.IsDefaultTabs():
- shapePoints = int(tabHeight*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
-
- # Calculate the text length using the bold font, so when selecting a tab
- # its width will not change
- dc.SetFont(boldFont)
- width, pom = dc.GetTextExtent(pc.GetPageText(tabIdx))
-
- # Set a minimum size to a tab
- if width < 20:
- width = 20
-
- tabWidth = 2*pc._pParent.GetPadding() + width
-
- # Style to add a small 'x' button on the top right
- # of the tab
- if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
- # The xpm image that contains the 'x' button is 9 pixels
- spacer = 9
- if pc.HasFlag(FNB_VC8):
- spacer = 4
-
- tabWidth += pc._pParent.GetPadding() + spacer
-
- if pc.IsDefaultTabs():
- # Default style
- tabWidth += 2*shapePoints
-
- hasImage = pc._ImageList != None and pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
-
- # For VC71 style, we only add the icon size (16 pixels)
- if hasImage:
-
- if not pc.IsDefaultTabs():
- tabWidth += 16 + pc._pParent.GetPadding()
- else:
- # Default style
- tabWidth += 16 + pc._pParent.GetPadding() + shapePoints/2
-
- return tabWidth
-
-
- def CalcTabHeight(self, pageContainer):
- """ Calculates the height of the input tab. """
-
- if self._tabHeight:
- return self._tabHeight
-
- pc = pageContainer
- dc = wx.MemoryDC()
- dc.SelectObject(wx.EmptyBitmap(1,1))
-
- # For GTK it seems that we must do this steps in order
- # for the tabs will get the proper height on initialization
- # on MSW, preforming these steps yields wierd results
- normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
- boldFont = normalFont
-
- if "__WXGTK__" in wx.PlatformInfo:
- boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
- dc.SetFont(boldFont)
-
- height = dc.GetCharHeight()
-
- tabHeight = height + FNB_HEIGHT_SPACER # We use 8 pixels as padding
- if "__WXGTK__" in wx.PlatformInfo:
- # On GTK the tabs are should be larger
- tabHeight += 6
-
- self._tabHeight = tabHeight
-
- return tabHeight
-
-
- def DrawTabs(self, pageContainer, dc):
- """ Actually draws the tabs in L{FlatNotebook}."""
-
- pc = pageContainer
- if "__WXMAC__" in wx.PlatformInfo:
- # Works well on MSW & GTK, however this lines should be skipped on MAC
- if not pc._pagesInfoVec or pc._nFrom >= len(pc._pagesInfoVec):
- pc.Hide()
- return
-
- # Get the text hight
- tabHeight = self.CalcTabHeight(pageContainer)
- style = pc.GetParent().GetWindowStyleFlag()
-
- # Calculate the number of rows required for drawing the tabs
- rect = pc.GetClientRect()
- clientWidth = rect.width
-
- # Set the maximum client size
- pc.SetSizeHints(self.GetButtonsAreaLength(pc), tabHeight)
- borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
-
- if style & FNB_VC71:
- backBrush = wx.Brush(wx.Colour(247, 243, 233))
- else:
- backBrush = wx.Brush(pc._tabAreaColor)
-
- noselBrush = wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE))
- selBrush = wx.Brush(pc._activeTabColor)
-
- size = pc.GetSize()
-
- # Background
- dc.SetTextBackground((style & FNB_VC71 and [wx.Colour(247, 243, 233)] or [pc.GetBackgroundColour()])[0])
- dc.SetTextForeground(pc._activeTextColor)
- dc.SetBrush(backBrush)
-
- # If border style is set, set the pen to be border pen
- if pc.HasFlag(FNB_TABS_BORDER_SIMPLE):
- dc.SetPen(borderPen)
- 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
-
- mem_dc = wx.MemoryDC()
- #---------------------------------------
- # X button
- #---------------------------------------
- rect = wx.Rect(self.GetXPos(pc), 6, 16, 14)
- mem_dc.SelectObject(self._xBgBmp)
- mem_dc.Blit(0, 0, rect.width, rect.height, dc, rect.x, rect.y)
- mem_dc.SelectObject(wx.NullBitmap)
-
- #---------------------------------------
- # Right button
- #---------------------------------------
- rect = wx.Rect(self.GetRightButtonPos(pc), 6, 16, 14)
- mem_dc.SelectObject(self._rightBgBmp)
- mem_dc.Blit(0, 0, rect.width, rect.height, dc, rect.x, rect.y)
- mem_dc.SelectObject(wx.NullBitmap)
-
- #---------------------------------------
- # Left button
- #---------------------------------------
- rect = wx.Rect(self.GetLeftButtonPos(pc), 6, 16, 14)
- mem_dc.SelectObject(self._leftBgBmp)
- mem_dc.Blit(0, 0, rect.width, rect.height, dc, rect.x, rect.y)
- mem_dc.SelectObject(wx.NullBitmap)
-
- # We always draw the bottom/upper line of the tabs
- # regradless the style
- dc.SetPen(borderPen)
-
- if not pc.HasFlag(FNB_FF2):
- self.DrawTabsLine(pc, dc)
-
- # Restore the pen
- dc.SetPen(borderPen)
-
- if pc.HasFlag(FNB_VC71):
-
- greyLineYVal = (pc.HasFlag(FNB_BOTTOM) and [0] or [size.y - 2])[0]
- whiteLineYVal = (pc.HasFlag(FNB_BOTTOM) and [3] or [size.y - 3])[0]
-
- pen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
- dc.SetPen(pen)
-
- # Draw thik grey line between the windows area and
- # the tab area
- for num in xrange(3):
- dc.DrawLine(0, greyLineYVal + num, size.x, greyLineYVal + num)
-
- wbPen = (pc.HasFlag(FNB_BOTTOM) and [wx.BLACK_PEN] or [wx.WHITE_PEN])[0]
- dc.SetPen(wbPen)
- dc.DrawLine(1, whiteLineYVal, size.x - 1, whiteLineYVal)
-
- # Restore the pen
- dc.SetPen(borderPen)
-
- # Draw labels
- normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
- boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
- boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
- dc.SetFont(boldFont)
-
- posx = pc._pParent.GetPadding()
-
- # Update all the tabs from 0 to 'pc._nFrom' to be non visible
- for i in xrange(pc._nFrom):
-
- pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1))
- pc._pagesInfoVec[i].GetRegion().Clear()
-
- count = pc._nFrom
-
- #----------------------------------------------------------
- # Go over and draw the visible tabs
- #----------------------------------------------------------
- x1 = x2 = -1
- for i in xrange(pc._nFrom, len(pc._pagesInfoVec)):
-
- dc.SetPen(borderPen)
-
- 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])
-
- # Add the padding to the tab width
- # Tab width:
- # +-----------------------------------------------------------+
- # | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING |
- # +-----------------------------------------------------------+
- tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight)
-
- # Check if we can draw more
- if posx + tabWidth + self.GetButtonsAreaLength(pc) >= clientWidth:
- break
-
- count = count + 1
-
- # By default we clean the tab region
- pc._pagesInfoVec[i].GetRegion().Clear()
-
- # Clean the 'x' buttn on the tab.
- # A 'Clean' rectangle, is a rectangle with width or height
- # with values lower than or equal to 0
- pc._pagesInfoVec[i].GetXRect().SetSize(wx.Size(-1, -1))
-
- # 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)
-
- # Update the tab position & size
- posy = (pc.HasFlag(FNB_BOTTOM) and [0] or [VERTICAL_BORDER_PADDING])[0]
-
- pc._pagesInfoVec[i].SetPosition(wx.Point(posx, posy))
- pc._pagesInfoVec[i].SetSize(wx.Size(tabWidth, tabHeight))
- self.DrawFocusRectangle(dc, pc, pc._pagesInfoVec[i])
-
- posx += tabWidth
-
- # Update all tabs that can not fit into the screen as non-visible
- for i in xrange(count, len(pc._pagesInfoVec)):
- pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1))
- pc._pagesInfoVec[i].GetRegion().Clear()
-
- # Draw the left/right/close buttons
- # Left arrow
- self.DrawLeftArrow(pc, dc)
- self.DrawRightArrow(pc, dc)
- self.DrawX(pc, dc)
- self.DrawDropDownArrow(pc, dc)
-
- if pc.HasFlag(FNB_FF2):
- self.DrawTabsLine(pc, dc, x1, x2)
-
-
- def DrawFocusRectangle(self, dc, pageContainer, page):
- """ Draws a focus rectangle like the native Notebooks. """
-
- if not page._hasFocus:
- return
-
- tabPos = page.GetPosition()
- if pageContainer.GetParent().GetWindowStyleFlag() & FNB_VC8:
- vc8ShapeLen = self.CalcTabHeight(pageContainer) - VERTICAL_BORDER_PADDING - 2
- tabPos.x += vc8ShapeLen
-
- rect = wx.RectPS(tabPos, page.GetSize())
- rect = wx.Rect(rect.x+2, rect.y+2, rect.width-4, rect.height-8)
-
- dc.SetBrush(wx.TRANSPARENT_BRUSH)
- dc.SetPen(self._focusPen)
- dc.DrawRoundedRectangleRect(rect, 2)
-
-
- def DrawDragHint(self, pc, tabIdx):
- """
- Draws tab drag hint, the default implementation is to do nothing.
- You can override this function to provide a nice feedback to user.
- """
-
- pass
-
-
- def NumberTabsCanFit(self, pageContainer, fr=-1):
-
- pc = pageContainer
-
- rect = pc.GetClientRect()
- clientWidth = rect.width
-
- vTabInfo = []
-
- tabHeight = self.CalcTabHeight(pageContainer)
-
- # The drawing starts from posx
- posx = pc._pParent.GetPadding()
-
- if fr < 0:
- fr = pc._nFrom
-
- for i in xrange(fr, len(pc._pagesInfoVec)):
-
- tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight)
- if posx + tabWidth + self.GetButtonsAreaLength(pc) >= clientWidth:
- break;
-
- # Add a result to the returned vector
- tabRect = wx.Rect(posx, VERTICAL_BORDER_PADDING, tabWidth , tabHeight)
- vTabInfo.append(tabRect)
-
- # Advance posx
- posx += tabWidth + FNB_HEIGHT_SPACER
-
- return vTabInfo
-
-
-# ---------------------------------------------------------------------------- #
-# Class FNBRendererMgr
-# A manager that handles all the renderers defined below and calls the
-# appropriate one when drawing is needed
-# ---------------------------------------------------------------------------- #
-
-class FNBRendererMgr:
- """
- This class represents a manager that handles all the 4 renderers defined
- and calls the appropriate one when drawing is needed.
- """
-
- def __init__(self):
- """ Default class constructor. """
-
- # register renderers
-
- self._renderers = {}
- self._renderers.update({-1: FNBRendererDefault()})
- 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. """
-
- if style & FNB_VC71:
- return self._renderers[FNB_VC71]
-
- if style & FNB_FANCY_TABS:
- return self._renderers[FNB_FANCY_TABS]
-
- 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]
-
-
-#------------------------------------------
-# Default renderer
-#------------------------------------------
-
-class FNBRendererDefault(FNBRenderer):
- """
- This class handles the drawing of tabs using the I{Standard} 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{Standard} style. """
-
- # Default style
- borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
- pc = pageContainer
-
- tabPoints = [wx.Point() for ii in xrange(7)]
- tabPoints[0].x = posx
- tabPoints[0].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0]
-
- tabPoints[1].x = int(posx+(tabHeight-2)*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
- 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 = int(posx+tabWidth-(tabHeight-2)*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))-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 = int(tabPoints[4].x+(tabHeight-2)*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
- 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
-
- if tabIdx == pc.GetSelection():
-
- # Draw the tab as rounded rectangle
- dc.DrawPolygon(tabPoints)
-
- else:
-
- if tabIdx != pc.GetSelection() - 1:
-
- # Draw a vertical line to the right of the text
- pt1x = tabPoints[5].x
- pt1y = (pc.HasFlag(FNB_BOTTOM) and [4] or [tabHeight - 6])[0]
- pt2x = tabPoints[5].x
- pt2y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - 4] or [4])[0]
- dc.DrawLine(pt1x, pt1y, pt2x, pt2y)
-
- if tabIdx == pc.GetSelection():
-
- savePen = dc.GetPen()
- whitePen = wx.Pen(wx.WHITE)
- whitePen.SetWidth(1)
- dc.SetPen(whitePen)
-
- secPt = wx.Point(tabPoints[5].x + 1, tabPoints[5].y)
- dc.DrawLine(tabPoints[0].x, tabPoints[0].y, secPt.x, secPt.y)
-
- # Restore the pen
- dc.SetPen(savePen)
-
- # -----------------------------------
- # Text and image drawing
- # -----------------------------------
-
- # Text drawing offset from the left border of the
- # rectangle
-
- # 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*pc._pParent._nPadding + 16 + shapePoints/2
- else:
- textOffset = pc._pParent._nPadding + 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)
-
-
-#------------------------------------------
-# 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
-#------------------------------------------------------------------
-
-class FNBRendererVC71(FNBRenderer):
- """
- This class handles the drawing of tabs using the I{VC71} 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{VC71} style. """
-
- # Visual studio 7.1 style
- borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
- pc = pageContainer
-
- dc.SetPen((tabIdx == pc.GetSelection() and [wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))] or [borderPen])[0])
- dc.SetBrush((tabIdx == pc.GetSelection() and [wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))] or [wx.Brush(wx.Colour(247, 243, 233))])[0])
-
- if tabIdx == pc.GetSelection():
-
- posy = (pc.HasFlag(FNB_BOTTOM) and [0] or [VERTICAL_BORDER_PADDING])[0]
- tabH = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - 5] or [tabHeight - 3])[0]
- dc.DrawRectangle(posx, posy, tabWidth, tabH)
-
- # Draw a black line on the left side of the
- # rectangle
- dc.SetPen(wx.BLACK_PEN)
-
- blackLineY1 = VERTICAL_BORDER_PADDING
- blackLineY2 = tabH
- dc.DrawLine(posx + tabWidth, blackLineY1, posx + tabWidth, blackLineY2)
-
- # To give the tab more 3D look we do the following
- # Incase the tab is on top,
- # Draw a thik white line on topof the rectangle
- # Otherwise, draw a thin (1 pixel) black line at the bottom
-
- pen = wx.Pen((pc.HasFlag(FNB_BOTTOM) and [wx.BLACK] or [wx.WHITE])[0])
- dc.SetPen(pen)
- whiteLinePosY = (pc.HasFlag(FNB_BOTTOM) and [blackLineY2] or [VERTICAL_BORDER_PADDING ])[0]
- dc.DrawLine(posx , whiteLinePosY, posx + tabWidth + 1, whiteLinePosY)
-
- # Draw a white vertical line to the left of the tab
- dc.SetPen(wx.WHITE_PEN)
- if not pc.HasFlag(FNB_BOTTOM):
- blackLineY2 += 1
-
- dc.DrawLine(posx, blackLineY1, posx, blackLineY2)
-
- else:
-
- # We dont draw a rectangle for non selected tabs, but only
- # vertical line on the left
-
- blackLineY1 = (pc.HasFlag(FNB_BOTTOM) and [VERTICAL_BORDER_PADDING + 2] or [VERTICAL_BORDER_PADDING + 1])[0]
- blackLineY2 = pc.GetSize().y - 5
- dc.DrawLine(posx + tabWidth, blackLineY1, posx + tabWidth, blackLineY2)
-
- # -----------------------------------
- # Text and image drawing
- # -----------------------------------
-
- # Text drawing offset from the left border of the
- # rectangle
-
- # The width of the images are 16 pixels
- padding = pc.GetParent().GetPadding()
- hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
- imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [5] or [8])[0]
-
- if hasImage:
- textOffset = 2*pc._pParent._nPadding + 16
- else:
- textOffset = pc._pParent._nPadding
-
- 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)
-
-
-#------------------------------------------------------------------
-# Fancy style
-#------------------------------------------------------------------
-
-class FNBRendererFancy(FNBRenderer):
- """
- This class handles the drawing of tabs using the I{Fancy} 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{Fancy} style, similar to VC71 but with gradients. """
-
- # Fancy tabs - like with VC71 but with the following differences:
- # - The Selected tab is colored with gradient color
- borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
- pc = pageContainer
-
- pen = (tabIdx == pc.GetSelection() and [wx.Pen(pc._pParent.GetBorderColour())] or [wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))])[0]
-
- if tabIdx == pc.GetSelection():
-
- posy = (pc.HasFlag(FNB_BOTTOM) and [2] or [VERTICAL_BORDER_PADDING])[0]
- th = tabHeight - 5
-
- rect = wx.Rect(posx, posy, tabWidth, th)
-
- col2 = (pc.HasFlag(FNB_BOTTOM) and [pc._pParent.GetGradientColourTo()] or [pc._pParent.GetGradientColourFrom()])[0]
- col1 = (pc.HasFlag(FNB_BOTTOM) and [pc._pParent.GetGradientColourFrom()] or [pc._pParent.GetGradientColourTo()])[0]
-
- PaintStraightGradientBox(dc, rect, col1, col2)
- dc.SetBrush(wx.TRANSPARENT_BRUSH)
- dc.SetPen(pen)
- dc.DrawRectangleRect(rect)
-
- # erase the bottom/top line of the rectangle
- dc.SetPen(wx.Pen(pc._pParent.GetGradientColourFrom()))
- if pc.HasFlag(FNB_BOTTOM):
- dc.DrawLine(rect.x, 2, rect.x + rect.width, 2)
- else:
- dc.DrawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width, rect.y + rect.height - 1)
-
- else:
-
- # We dont draw a rectangle for non selected tabs, but only
- # vertical line on the left
- dc.SetPen(borderPen)
- dc.DrawLine(posx + tabWidth, VERTICAL_BORDER_PADDING + 3, posx + tabWidth, tabHeight - 4)
-
-
- # -----------------------------------
- # Text and image drawing
- # -----------------------------------
-
- # Text drawing offset from the left border of the
- # rectangle
-
- # The width of the images are 16 pixels
- padding = pc.GetParent().GetPadding()
- hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
- imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0]
-
- if hasImage:
- textOffset = 2*pc._pParent._nPadding + 16
- else:
- textOffset = pc._pParent._nPadding
-
- 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 2005 (VS8)
-#------------------------------------------------------------------
-class FNBRendererVC8(FNBRenderer):
- """
- This class handles the drawing of tabs using the I{VC8} renderer.
- """
-
- def __init__(self):
- """ Default class constructor. """
-
- FNBRenderer.__init__(self)
- self._first = True
- self._factor = 1
-
-
- def DrawTabs(self, pageContainer, dc):
- """ Draws all the tabs using VC8 style. Overloads The DrawTabs method in parent class. """
-
- pc = pageContainer
-
- if "__WXMAC__" in wx.PlatformInfo:
- # Works well on MSW & GTK, however this lines should be skipped on MAC
- if not pc._pagesInfoVec or pc._nFrom >= len(pc._pagesInfoVec):
- pc.Hide()
- return
-
- # Get the text hight
- tabHeight = self.CalcTabHeight(pageContainer)
-
- # Set the font for measuring the tab height
- normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
- boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
- boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
-
- # Calculate the number of rows required for drawing the tabs
- rect = pc.GetClientRect()
-
- # Set the maximum client size
- pc.SetSizeHints(self.GetButtonsAreaLength(pc), tabHeight)
- borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
-
- # Create brushes
- backBrush = wx.Brush(pc._tabAreaColor)
- noselBrush = wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE))
- selBrush = wx.Brush(pc._activeTabColor)
- size = pc.GetSize()
-
- # Background
- dc.SetTextBackground(pc.GetBackgroundColour())
- dc.SetTextForeground(pc._activeTextColor)
-
- # If border style is set, set the pen to be border pen
- if pc.HasFlag(FNB_TABS_BORDER_SIMPLE):
- dc.SetPen(borderPen)
- else:
- dc.SetPen(wx.TRANSPARENT_PEN)
-
- lightFactor = (pc.HasFlag(FNB_BACKGROUND_GRADIENT) and [70] or [0])[0]
-
- # For VC8 style, we color the tab area in gradient coloring
- lightcolour = LightColour(pc._tabAreaColor, lightFactor)
- PaintStraightGradientBox(dc, pc.GetClientRect(), pc._tabAreaColor, lightcolour)
-
- dc.SetBrush(wx.TRANSPARENT_BRUSH)
- dc.DrawRectangle(0, 0, size.x, size.y)
-
- # Take 3 bitmaps for the background for the buttons
-
- mem_dc = wx.MemoryDC()
- #---------------------------------------
- # X button
- #---------------------------------------
- rect = wx.Rect(self.GetXPos(pc), 6, 16, 14)
- mem_dc.SelectObject(self._xBgBmp)
- mem_dc.Blit(0, 0, rect.width, rect.height, dc, rect.x, rect.y)
- mem_dc.SelectObject(wx.NullBitmap)
-
- #---------------------------------------
- # Right button
- #---------------------------------------
- rect = wx.Rect(self.GetRightButtonPos(pc), 6, 16, 14)
- mem_dc.SelectObject(self._rightBgBmp)
- mem_dc.Blit(0, 0, rect.width, rect.height, dc, rect.x, rect.y)
- mem_dc.SelectObject(wx.NullBitmap)
-
- #---------------------------------------
- # Left button
- #---------------------------------------
- rect = wx.Rect(self.GetLeftButtonPos(pc), 6, 16, 14)
- mem_dc.SelectObject(self._leftBgBmp)
- mem_dc.Blit(0, 0, rect.width, rect.height, dc, rect.x, rect.y)
- mem_dc.SelectObject(wx.NullBitmap)
-
- # We always draw the bottom/upper line of the tabs
- # regradless the style
- dc.SetPen(borderPen)
- self.DrawTabsLine(pc, dc)
-
- # Restore the pen
- dc.SetPen(borderPen)
-
- # Draw labels
- dc.SetFont(boldFont)
-
- # Update all the tabs from 0 to 'pc.self._nFrom' to be non visible
- for i in xrange(pc._nFrom):
-
- pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1))
- pc._pagesInfoVec[i].GetRegion().Clear()
-
- # Draw the visible tabs, in VC8 style, we draw them from right to left
- vTabsInfo = self.NumberTabsCanFit(pc)
-
- activeTabPosx = 0
- activeTabWidth = 0
- activeTabHeight = 0
-
- for cur in xrange(len(vTabsInfo)-1, -1, -1):
-
- # 'i' points to the index of the currently drawn tab
- # in pc.GetPageInfoVector() vector
- i = pc._nFrom + cur
- dc.SetPen(borderPen)
- 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])
-
- # Add the padding to the tab width
- # Tab width:
- # +-----------------------------------------------------------+
- # | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING |
- # +-----------------------------------------------------------+
-
- tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight)
- posx = vTabsInfo[cur].x
-
- # By default we clean the tab region
- # incase we use the VC8 style which requires
- # the region, it will be filled by the function
- # drawVc8Tab
- pc._pagesInfoVec[i].GetRegion().Clear()
-
- # Clean the 'x' buttn on the tab
- # 'Clean' rectanlge is a rectangle with width or height
- # with values lower than or equal to 0
- pc._pagesInfoVec[i].GetXRect().SetSize(wx.Size(-1, -1))
-
- # Draw the tab
- # Incase we are drawing the active tab
- # we need to redraw so it will appear on top
- # of all other tabs
-
- # when using the vc8 style, we keep the position of the active tab so we will draw it again later
- if i == pc.GetSelection() and pc.HasFlag(FNB_VC8):
-
- activeTabPosx = posx
- activeTabWidth = tabWidth
- activeTabHeight = tabHeight
-
- else:
-
- self.DrawTab(pc, dc, posx, i, tabWidth, tabHeight, pc._nTabXButtonStatus)
-
- # Restore the text forground
- dc.SetTextForeground(pc._activeTextColor)
-
- # Update the tab position & size
- pc._pagesInfoVec[i].SetPosition(wx.Point(posx, VERTICAL_BORDER_PADDING))
- pc._pagesInfoVec[i].SetSize(wx.Size(tabWidth, tabHeight))
-
- # Incase we are in VC8 style, redraw the active tab (incase it is visible)
- if pc.GetSelection() >= pc._nFrom and pc.GetSelection() < pc._nFrom + len(vTabsInfo):
-
- self.DrawTab(pc, dc, activeTabPosx, pc.GetSelection(), activeTabWidth, activeTabHeight, pc._nTabXButtonStatus)
-
- # Update all tabs that can not fit into the screen as non-visible
- for xx in xrange(pc._nFrom + len(vTabsInfo), len(pc._pagesInfoVec)):
-
- pc._pagesInfoVec[xx].SetPosition(wx.Point(-1, -1))
- pc._pagesInfoVec[xx].GetRegion().Clear()
-
- # Draw the left/right/close buttons
- # Left arrow
- self.DrawLeftArrow(pc, dc)
- self.DrawRightArrow(pc, dc)
- self.DrawX(pc, dc)
- self.DrawDropDownArrow(pc, dc)
-
-
- def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
- """ Draws a tab using VC8 style. """
-
- pc = pageContainer
- borderPen = wx.Pen(pc._pParent.GetBorderColour())
- tabPoints = [wx.Point() for ii in xrange(8)]
-
- # If we draw the first tab or the active tab,
- # we draw a full tab, else we draw a truncated tab
- #
- # X(2) X(3)
- # X(1) X(4)
- #
- # X(5)
- #
- # X(0),(7) X(6)
- #
- #
-
- tabPoints[0].x = (pc.HasFlag(FNB_BOTTOM) and [posx] or [posx+self._factor])[0]
- tabPoints[0].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 3])[0]
-
- tabPoints[1].x = tabPoints[0].x + tabHeight - VERTICAL_BORDER_PADDING - 3 - self._factor
- 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 + 4
- tabPoints[2].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
-
- tabPoints[3].x = tabPoints[2].x + 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 + 1
- tabPoints[4].y = (pc.HasFlag(FNB_BOTTOM) and [tabPoints[3].y - 1] or [tabPoints[3].y + 1])[0]
-
- tabPoints[5].x = tabPoints[4].x + 1
- tabPoints[5].y = (pc.HasFlag(FNB_BOTTOM) and [(tabPoints[4].y - 1)] or [tabPoints[4].y + 1])[0]
-
- tabPoints[6].x = tabPoints[2].x + tabWidth
- tabPoints[6].y = tabPoints[0].y
-
- tabPoints[7].x = tabPoints[0].x
- tabPoints[7].y = tabPoints[0].y
-
- pc._pagesInfoVec[tabIdx].SetRegion(tabPoints)
-
- # Draw the polygon
- br = dc.GetBrush()
- dc.SetBrush(wx.Brush((tabIdx == pc.GetSelection() and [pc._activeTabColor] or [pc._colorTo])[0]))
- dc.SetPen(wx.Pen((tabIdx == pc.GetSelection() and [wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)] or [pc._colorBorder])[0]))
- dc.DrawPolygon(tabPoints)
-
- # Restore the brush
- dc.SetBrush(br)
- rect = pc.GetClientRect()
-
- if tabIdx != pc.GetSelection() and not pc.HasFlag(FNB_BOTTOM):
-
- # Top default tabs
- dc.SetPen(wx.Pen(pc._pParent.GetBorderColour()))
- lineY = rect.height
- curPen = dc.GetPen()
- curPen.SetWidth(1)
- dc.SetPen(curPen)
- dc.DrawLine(posx, lineY, posx+rect.width, lineY)
-
- # Incase we are drawing the selected tab, we draw the border of it as well
- # but without the bottom (upper line incase of wxBOTTOM)
- if tabIdx == pc.GetSelection():
-
- borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
- dc.SetPen(borderPen)
- dc.SetBrush(wx.TRANSPARENT_BRUSH)
- dc.DrawPolygon(tabPoints)
-
- # Delete the bottom line (or the upper one, incase we use wxBOTTOM)
- dc.SetPen(wx.WHITE_PEN)
- dc.DrawLine(tabPoints[0].x, tabPoints[0].y, tabPoints[6].x, tabPoints[6].y)
-
- self.FillVC8GradientColour(pc, dc, tabPoints, tabIdx == pc.GetSelection(), tabIdx)
-
- # Draw a thin line to the right of the non-selected tab
- if tabIdx != pc.GetSelection():
-
- dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)))
- dc.DrawLine(tabPoints[4].x-1, tabPoints[4].y, tabPoints[5].x-1, tabPoints[5].y)
- dc.DrawLine(tabPoints[5].x-1, tabPoints[5].y, tabPoints[6].x-1, tabPoints[6].y)
-
- # Text drawing offset from the left border of the
- # rectangle
-
- # The width of the images are 16 pixels
- vc8ShapeLen = tabHeight - VERTICAL_BORDER_PADDING - 2
- if pc.TabHasImage(tabIdx):
- textOffset = 2*pc._pParent.GetPadding() + 16 + vc8ShapeLen
- else:
- textOffset = pc._pParent.GetPadding() + vc8ShapeLen
-
- # Draw the image for the tab if any
- imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0]
-
- if pc.TabHasImage(tabIdx):
-
- imageXOffset = textOffset - 16 - pc._pParent.GetPadding()
- pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
- posx + imageXOffset, imageYCoord,
- wx.IMAGELIST_DRAW_TRANSPARENT, True)
-
- boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
-
- # if selected tab, draw text in bold
- if tabIdx == pc.GetSelection():
- boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
-
- dc.SetFont(boldFont)
- 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)
-
- self.DrawFocusRectangle(dc, pc, pc._pagesInfoVec[tabIdx])
-
-
- def FillVC8GradientColour(self, pageContainer, dc, tabPoints, bSelectedTab, tabIdx):
- """ Fills a tab with a gradient shading. """
-
- # calculate gradient coefficients
- pc = pageContainer
-
- if self._first:
- self._first = False
- pc._colorTo = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 0)
- pc._colorFrom = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 60)
-
- col2 = pc._pParent.GetGradientColourTo()
- col1 = pc._pParent.GetGradientColourFrom()
-
- # If colorful tabs style is set, override the tab color
- if pc.HasFlag(FNB_COLORFUL_TABS):
-
- if not pc._pagesInfoVec[tabIdx].GetColour():
-
- # First time, generate color, and keep it in the vector
- tabColor = RandomColour()
- pc._pagesInfoVec[tabIdx].SetColour(tabColor)
-
- if pc.HasFlag(FNB_BOTTOM):
-
- col2 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 50)
- col1 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 80)
-
- else:
-
- col1 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 50)
- col2 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 80)
-
- size = abs(tabPoints[2].y - tabPoints[0].y) - 1
-
- rf, gf, bf = 0, 0, 0
- rstep = float(col2.Red() - col1.Red())/float(size)
- gstep = float(col2.Green() - col1.Green())/float(size)
- bstep = float(col2.Blue() - col1.Blue())/float(size)
-
- y = tabPoints[0].y
-
- # If we are drawing the selected tab, we need also to draw a line
- # from 0.tabPoints[0].x and tabPoints[6].x . end, we achieve this
- # by drawing the rectangle with transparent brush
- # the line under the selected tab will be deleted by the drwaing loop
- if bSelectedTab:
- self.DrawTabsLine(pc, dc)
-
- while 1:
-
- if pc.HasFlag(FNB_BOTTOM):
-
- if y > tabPoints[0].y + size:
- break
-
- else:
-
- if y < tabPoints[0].y - size:
- break
-
- currCol = wx.Colour(col1.Red() + rf, col1.Green() + gf, col1.Blue() + bf)
-
- dc.SetPen((bSelectedTab and [wx.Pen(pc._activeTabColor)] or [wx.Pen(currCol)])[0])
- startX = self.GetStartX(tabPoints, y, pc.GetParent().GetWindowStyleFlag())
- endX = self.GetEndX(tabPoints, y, pc.GetParent().GetWindowStyleFlag())
- dc.DrawLine(startX, y, endX, y)
-
- # Draw the border using the 'edge' point
- dc.SetPen(wx.Pen((bSelectedTab and [wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)] or [pc._colorBorder])[0]))
-
- dc.DrawPoint(startX, y)
- dc.DrawPoint(endX, y)
-
- # Progress the color
- rf += rstep
- gf += gstep
- bf += bstep
-
- if pc.HasFlag(FNB_BOTTOM):
- y = y + 1
- else:
- y = y - 1
-
-
- def GetStartX(self, tabPoints, y, style):
- """ Returns the x start position of a tab. """
-
- x1, x2, y1, y2 = 0.0, 0.0, 0.0, 0.0
-
- # We check the 3 points to the left
-
- bBottomStyle = (style & FNB_BOTTOM and [True] or [False])[0]
- match = False
-
- if bBottomStyle:
-
- for i in xrange(3):
-
- if y >= tabPoints[i].y and y < tabPoints[i+1].y:
-
- x1 = tabPoints[i].x
- x2 = tabPoints[i+1].x
- y1 = tabPoints[i].y
- y2 = tabPoints[i+1].y
- match = True
- break
-
- else:
-
- for i in xrange(3):
-
- if y <= tabPoints[i].y and y > tabPoints[i+1].y:
-
- x1 = tabPoints[i].x
- x2 = tabPoints[i+1].x
- y1 = tabPoints[i].y
- y2 = tabPoints[i+1].y
- match = True
- break
-
- if not match:
- return tabPoints[2].x
-
- # According to the equation y = ax + b => x = (y-b)/a
- # We know the first 2 points
-
- if x2 == x1:
- return x2
- else:
- a = (y2 - y1)/(x2 - x1)
-
- b = y1 - ((y2 - y1)/(x2 - x1))*x1
-
- if a == 0:
- return int(x1)
-
- x = (y - b)/a
-
- return int(x)
-
-
- def GetEndX(self, tabPoints, y, style):
- """ Returns the x end position of a tab. """
-
- x1, x2, y1, y2 = 0.0, 0.0, 0.0, 0.0
-
- # We check the 3 points to the left
- bBottomStyle = (style & FNB_BOTTOM and [True] or [False])[0]
- match = False
-
- if bBottomStyle:
-
- for i in xrange(7, 3, -1):
-
- if y >= tabPoints[i].y and y < tabPoints[i-1].y:
-
- x1 = tabPoints[i].x
- x2 = tabPoints[i-1].x
- y1 = tabPoints[i].y
- y2 = tabPoints[i-1].y
- match = True
- break
-
- else:
-
- for i in xrange(7, 3, -1):
-
- if y <= tabPoints[i].y and y > tabPoints[i-1].y:
-
- x1 = tabPoints[i].x
- x2 = tabPoints[i-1].x
- y1 = tabPoints[i].y
- y2 = tabPoints[i-1].y
- match = True
- break
-
- if not match:
- return tabPoints[3].x
-
- # According to the equation y = ax + b => x = (y-b)/a
- # We know the first 2 points
-
- # Vertical line
- if x1 == x2:
- return int(x1)
-
- a = (y2 - y1)/(x2 - x1)
- b = y1 - ((y2 - y1)/(x2 - x1))*x1
-
- if a == 0:
- return int(x1)
-
- x = (y - b)/a
-
- return int(x)
-
-
- def NumberTabsCanFit(self, pageContainer, fr=-1):
- """ Returns the number of tabs that can fit in the visible area. """
-
- pc = pageContainer
-
- rect = pc.GetClientRect()
- clientWidth = rect.width
-
- # Empty results
- vTabInfo = []
- tabHeight = self.CalcTabHeight(pageContainer)
-
- # The drawing starts from posx
- posx = pc._pParent.GetPadding()
-
- if fr < 0:
- fr = pc._nFrom
-
- for i in xrange(fr, len(pc._pagesInfoVec)):
-
- vc8glitch = tabHeight + FNB_HEIGHT_SPACER
- tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight)
-
- if posx + tabWidth + vc8glitch + self.GetButtonsAreaLength(pc) >= clientWidth:
- break
-
- # Add a result to the returned vector
- tabRect = wx.Rect(posx, VERTICAL_BORDER_PADDING, tabWidth, tabHeight)
- vTabInfo.append(tabRect)
-
- # Advance posx
- posx += tabWidth + FNB_HEIGHT_SPACER
-
- return vTabInfo
-
-
-# ---------------------------------------------------------------------------- #
-# Class FlatNotebook
-# ---------------------------------------------------------------------------- #
-
-class FlatNotebook(wx.PyPanel):
- """
- Display one or more windows in a notebook.
-
- B{Events}:
- - B{EVT_FLATNOTEBOOK_PAGE_CHANGING}: sent when the active
- page in the notebook is changing
- - B{EVT_FLATNOTEBOOK_PAGE_CHANGED}: sent when the active
- page in the notebook has changed
- - B{EVT_FLATNOTEBOOK_PAGE_CLOSING}: sent when a page in the
- notebook is closing
- - B{EVT_FLATNOTEBOOK_PAGE_CLOSED}: sent when a page in the
- notebook has been closed
- - B{EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU}: sent when the user
- clicks a tab in the notebook with the right mouse
- button
- """
-
- def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
- style=0, name="FlatNotebook"):
- """
- Default class constructor.
-
- All the parameters are as in wxPython class construction, except the
- 'style': this can be assigned to whatever combination of FNB_* styles.
-
- """
-
- self._bForceSelection = False
- self._nPadding = 6
- self._nFrom = 0
- style |= wx.TAB_TRAVERSAL
- self._pages = None
- self._windows = []
- self._popupWin = None
-
- wx.PyPanel.__init__(self, parent, id, pos, size, style)
-
- self._pages = PageContainer(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, style)
-
- self.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey)
-
- self.Init()
-
-
- def Init(self):
- """ Initializes all the class attributes. """
-
- self._pages._colorBorder = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
-
- self._mainSizer = wx.BoxSizer(wx.VERTICAL)
- self.SetSizer(self._mainSizer)
-
- # The child panels will inherit this bg color, so leave it at the default value
- #self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_APPWORKSPACE))
-
- # Set default page height
- dc = wx.ClientDC(self)
-
- if "__WXGTK__" in wx.PlatformInfo:
- # For GTK it seems that we must do this steps in order
- # for the tabs will get the proper height on initialization
- # on MSW, preforming these steps yields wierd results
- 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 8 pixels as padding
-
- if "__WXGTK__" in wx.PlatformInfo:
- tabHeight += 6
-
- self._pages.SetSizeHints(-1, tabHeight)
- # Add the tab container to the sizer
- self._mainSizer.Insert(0, self._pages, 0, wx.EXPAND)
- self._mainSizer.Layout()
-
- self._pages._nFrom = self._nFrom
- self._pDropTarget = FNBDropTarget(self)
- self.SetDropTarget(self._pDropTarget)
-
-
- def DoGetBestSize(self):
- """ Overrides DoGetBestSize to handle sizers nicely. """
-
- if not self._windows:
- # Something is better than nothing... no pages!
- return wx.Size(20, 20)
-
- maxWidth = maxHeight = 0
- tabHeight = self.GetPageBestSize().height
-
- for win in self._windows:
- # Loop over all the windows to get their best size
- width, height = win.GetBestSize()
- maxWidth, maxHeight = max(maxWidth, width), max(maxHeight, height)
-
- return wx.Size(maxWidth, maxHeight+tabHeight)
-
-
- def SetActiveTabTextColour(self, textColour):
- """ Sets the text colour for the active tab. """
-
- self._pages._activeTextColor = textColour
-
-
- def OnDropTarget(self, x, y, nTabPage, wnd_oldContainer):
- """ Handles the drop action from a DND operation. """
-
- return self._pages.OnDropTarget(x, y, nTabPage, wnd_oldContainer)
-
-
- def GetPreviousSelection(self):
- """ Returns the previous selection. """
-
- return self._pages._iPreviousActivePage
-
-
- def AddPage(self, page, text, select=True, imageId=-1):
- """
- Add a page to the L{FlatNotebook}.
-
- @param page: Specifies the new page.
- @param text: Specifies the text for the new page.
- @param select: Specifies whether the page should be selected.
- @param imageId: Specifies the optional image index for the new page.
-
- Return value:
- True if successful, False otherwise.
- """
-
- # sanity check
- if not page:
- return False
-
- # reparent the window to us
- page.Reparent(self)
-
- # Add tab
- bSelected = select or len(self._windows) == 0
-
- if bSelected:
-
- bSelected = False
-
- # Check for selection and send events
- oldSelection = self._pages._iActivePage
- tabIdx = len(self._windows)
-
- event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetId())
- event.SetSelection(tabIdx)
- event.SetOldSelection(oldSelection)
- event.SetEventObject(self)
-
- if not self.GetEventHandler().ProcessEvent(event) or event.IsAllowed() or len(self._windows) == 0:
- bSelected = True
-
- curSel = self._pages.GetSelection()
-
- if not self._pages.IsShown():
- self._pages.Show()
-
- self._pages.AddPage(text, bSelected, imageId)
- self._windows.append(page)
-
- self.Freeze()
-
- # Check if a new selection was made
- if bSelected:
-
- if curSel >= 0:
-
- # Remove the window from the main sizer
- self._mainSizer.Detach(self._windows[curSel])
- self._windows[curSel].Hide()
-
- if self.GetWindowStyleFlag() & FNB_BOTTOM:
-
- self._mainSizer.Insert(0, page, 1, wx.EXPAND)
-
- else:
-
- # We leave a space of 1 pixel around the window
- self._mainSizer.Add(page, 1, wx.EXPAND)
-
- # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
- event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
- event.SetOldSelection(oldSelection)
- self.GetEventHandler().ProcessEvent(event)
-
- else:
-
- # Hide the page
- page.Hide()
-
- self.Thaw()
- self._mainSizer.Layout()
- self.Refresh()
-
- return True
-
-
- def SetImageList(self, imageList):
- """ Sets the image list for the page control. """
-
- self._pages.SetImageList(imageList)
-
-
- def AssignImageList(self, imageList):
- """ Assigns the image list for the page control. """
-
- self._pages.AssignImageList(imageList)
-
-
- def GetImageList(self):
- """ Returns the associated image list. """
-
- return self._pages.GetImageList()
-
-
- def InsertPage(self, indx, page, text, select=True, imageId=-1):
- """
- Inserts a new page at the specified position.
-
- @param indx: Specifies the position of the new page.
- @param page: Specifies the new page.
- @param text: Specifies the text for the new page.
- @param select: Specifies whether the page should be selected.
- @param imageId: Specifies the optional image index for the new page.
-
- Return value:
- True if successful, False otherwise.
- """
-
- # sanity check
- if not page:
- return False
-
- # reparent the window to us
- page.Reparent(self)
-
- if not self._windows:
-
- self.AddPage(page, text, select, imageId)
- return True
-
- # Insert tab
- bSelected = select or not self._windows
- curSel = self._pages.GetSelection()
-
- indx = max(0, min(indx, len(self._windows)))
-
- if indx <= len(self._windows):
-
- self._windows.insert(indx, page)
-
- else:
-
- self._windows.append(page)
-
- if bSelected:
-
- bSelected = False
-
- # Check for selection and send events
- oldSelection = self._pages._iActivePage
-
- event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetId())
- event.SetSelection(indx)
- event.SetOldSelection(oldSelection)
- event.SetEventObject(self)
-
- if not self.GetEventHandler().ProcessEvent(event) or event.IsAllowed() or len(self._windows) == 0:
- bSelected = True
-
- self._pages.InsertPage(indx, text, bSelected, imageId)
-
- if indx <= curSel:
- curSel = curSel + 1
-
- self.Freeze()
-
- # Check if a new selection was made
- if bSelected:
-
- if curSel >= 0:
-
- # Remove the window from the main sizer
- self._mainSizer.Detach(self._windows[curSel])
- self._windows[curSel].Hide()
-
- self._pages.SetSelection(indx)
-
- # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
- event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
- event.SetOldSelection(oldSelection)
- self.GetEventHandler().ProcessEvent(event)
-
- else:
-
- # Hide the page
- page.Hide()
-
- self.Thaw()
- self._mainSizer.Layout()
- self.Refresh()
-
- return True
-
-
- def SetSelection(self, page):
- """
- Sets the selection for the given page.
- The call to this function generates the page changing events
- """
-
- if page >= len(self._windows) or not self._windows:
- return
-
- # Support for disabed tabs
- if not self._pages.GetEnabled(page) and len(self._windows) > 1 and not self._bForceSelection:
- return
-
- curSel = self._pages.GetSelection()
-
- # program allows the page change
- self.Freeze()
- if curSel >= 0:
-
- # Remove the window from the main sizer
- self._mainSizer.Detach(self._windows[curSel])
- self._windows[curSel].Hide()
-
- if self.GetWindowStyleFlag() & FNB_BOTTOM:
-
- self._mainSizer.Insert(0, self._windows[page], 1, wx.EXPAND)
-
- else:
-
- # We leave a space of 1 pixel around the window
- self._mainSizer.Add(self._windows[page], 1, wx.EXPAND)
-
- self._windows[page].Show()
- self.Thaw()
-
- self._mainSizer.Layout()
-
- if page != self._pages._iActivePage:
- # there is a real page changing
- self._pages._iPreviousActivePage = self._pages._iActivePage
-
- self._pages._iActivePage = page
- self._pages.DoSetSelection(page)
-
-
- def DeletePage(self, page):
- """
- Deletes the specified page, and the associated window.
- The call to this function generates the page changing events.
- """
-
- if page >= len(self._windows) or page < 0:
- return
-
- # Fire a closing event
- event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, self.GetId())
- event.SetSelection(page)
- event.SetEventObject(self)
- self.GetEventHandler().ProcessEvent(event)
-
- # The event handler allows it?
- if not event.IsAllowed():
- return
-
- self.Freeze()
-
- # Delete the requested page
- pageRemoved = self._windows[page]
-
- # If the page is the current window, remove it from the sizer
- # as well
- if page == self._pages.GetSelection():
- self._mainSizer.Detach(pageRemoved)
-
- # Remove it from the array as well
- self._windows.pop(page)
-
- # Now we can destroy it in wxWidgets use Destroy instead of delete
- pageRemoved.Destroy()
-
- self.Thaw()
-
- self._pages.DoDeletePage(page)
- self.Refresh()
- self.Update()
-
- # Fire a closed event
- closedEvent = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSED, self.GetId())
- closedEvent.SetSelection(page)
- closedEvent.SetEventObject(self)
- self.GetEventHandler().ProcessEvent(closedEvent)
-
-
- def DeleteAllPages(self):
- """ Deletes all the pages. """
-
- if not self._windows:
- return False
-
- self.Freeze()
-
- for page in self._windows:
- page.Destroy()
-
- self._windows = []
- self.Thaw()
-
- # Clear the container of the tabs as well
- self._pages.DeleteAllPages()
- return True
-
-
- def GetCurrentPage(self):
- """ Returns the currently selected notebook page or None. """
-
- sel = self._pages.GetSelection()
- if sel < 0:
- return None
-
- return self._windows[sel]
-
-
- def GetPage(self, page):
- """ Returns the window at the given page position, or None. """
-
- if page >= len(self._windows):
- return None
-
- return self._windows[page]
-
-
- def GetPageIndex(self, win):
- """ Returns the index at which the window is found. """
-
- try:
- return self._windows.index(win)
- except:
- return -1
-
-
- def GetSelection(self):
- """ Returns the currently selected page, or -1 if none was selected. """
-
- return self._pages.GetSelection()
-
-
- def AdvanceSelection(self, forward=True):
- """
- Cycles through the tabs.
- The call to this function generates the page changing events.
- """
-
- self._pages.AdvanceSelection(forward)
-
-
- def GetPageCount(self):
- """ Returns the number of pages in the L{FlatNotebook} control. """
-
- return self._pages.GetPageCount()
-
-
- def OnNavigationKey(self, event):
- """ Handles the wx.EVT_NAVIGATION_KEY event for L{FlatNotebook}. """
-
- if event.IsWindowChange():
- if len(self._windows) == 0:
- return
- # change pages
- if self.HasFlag(FNB_SMART_TABS):
- if not self._popupWin:
- self._popupWin = TabNavigatorWindow(self)
- self._popupWin.SetReturnCode(wx.ID_OK)
- self._popupWin.ShowModal()
- self._popupWin.Destroy()
- self._popupWin = None
- else:
- # a dialog is already opened
- self._popupWin.OnNavigationKey(event)
- return
- else:
- # change pages
- self.AdvanceSelection(event.GetDirection())
-
- else:
- event.Skip()
-
-
- def GetPageShapeAngle(self, page_index):
- """ Returns the angle associated to a tab. """
-
- if page_index < 0 or page_index >= len(self._pages._pagesInfoVec):
- return None, False
-
- result = self._pages._pagesInfoVec[page_index].GetTabAngle()
- return result, True
-
-
- def SetPageShapeAngle(self, page_index, angle):
- """ Sets the angle associated to a tab. """
-
- if page_index < 0 or page_index >= len(self._pages._pagesInfoVec):
- return
-
- if angle > 15:
- return
-
- self._pages._pagesInfoVec[page_index].SetTabAngle(angle)
-
-
- def SetAllPagesShapeAngle(self, angle):
- """ Sets the angle associated to all the tab. """
-
- if angle > 15:
- return
-
- for ii in xrange(len(self._pages._pagesInfoVec)):
- self._pages._pagesInfoVec[ii].SetTabAngle(angle)
-
- self.Refresh()
-
-
- def GetPageBestSize(self):
- """ Return the page best size. """
-
- return self._pages.GetClientSize()
-
-
- def SetPageText(self, page, text):
- """ Sets the text for the given page. """
-
- bVal = self._pages.SetPageText(page, text)
- self._pages.Refresh()
-
- return bVal
-
-
- def SetPadding(self, padding):
- """
- Sets the amount of space around each page's icon and label, in pixels.
- NB: only the horizontal padding is considered.
- """
-
- self._nPadding = padding.GetWidth()
-
-
- def GetTabArea(self):
- """ Returns the associated page. """
-
- return self._pages
-
-
- def GetPadding(self):
- """ Returns the amount of space around each page's icon and label, in pixels. """
-
- return self._nPadding
-
-
- def SetWindowStyleFlag(self, style):
- """ Sets the L{FlatNotebook} window style flags. """
-
- wx.PyPanel.SetWindowStyleFlag(self, style)
- renderer = self._pages._mgr.GetRenderer(self.GetWindowStyleFlag())
- renderer._tabHeight = None
-
- if self._pages:
-
- # For changing the tab position (i.e. placing them top/bottom)
- # refreshing the tab container is not enough
- self.SetSelection(self._pages._iActivePage)
-
- if not self._pages.HasFlag(FNB_HIDE_ON_SINGLE_TAB):
- #For Redrawing the Tabs once you remove the Hide tyle
- self._pages._ReShow()
-
-
- def RemovePage(self, page):
- """ Deletes the specified page, without deleting the associated window. """
-
- if page >= len(self._windows):
- return False
-
- # Fire a closing event
- event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, self.GetId())
- event.SetSelection(page)
- event.SetEventObject(self)
- self.GetEventHandler().ProcessEvent(event)
-
- # The event handler allows it?
- if not event.IsAllowed():
- return False
-
- self.Freeze()
-
- # Remove the requested page
- pageRemoved = self._windows[page]
-
- # If the page is the current window, remove it from the sizer
- # as well
- if page == self._pages.GetSelection():
- self._mainSizer.Detach(pageRemoved)
-
- # Remove it from the array as well
- self._windows.pop(page)
- self.Thaw()
-
- self._pages.DoDeletePage(page)
-
- return True
-
-
- def SetRightClickMenu(self, menu):
- """ Sets the popup menu associated to a right click on a tab. """
-
- self._pages._pRightClickMenu = menu
-
-
- def GetPageText(self, nPage):
- """ Returns the tab caption. """
-
- return self._pages.GetPageText(nPage)
-
-
- def SetGradientColours(self, fr, to, border):
- """ Sets the gradient colours for the tab. """
-
- self._pages._colorFrom = fr
- self._pages._colorTo = to
- self._pages._colorBorder = border
-
-
- def SetGradientColourFrom(self, fr):
- """ Sets the starting colour for the gradient. """
-
- self._pages._colorFrom = fr
-
-
- def SetGradientColourTo(self, to):
- """ Sets the ending colour for the gradient. """
-
- self._pages._colorTo = to
-
-
- def SetGradientColourBorder(self, border):
- """ Sets the tab border colour. """
-
- self._pages._colorBorder = border
-
-
- def GetGradientColourFrom(self):
- """ Gets first gradient colour. """
-
- return self._pages._colorFrom
-
-
- def GetGradientColourTo(self):
- """ Gets second gradient colour. """
-
- return self._pages._colorTo
-
-
- def GetGradientColourBorder(self):
- """ Gets the tab border colour. """
-
- return self._pages._colorBorder
-
-
- def GetBorderColour(self):
- """ Returns the border colour. """
-
- return self._pages._colorBorder
-
-
- def GetActiveTabTextColour(self):
- """ Get the active tab text colour. """
-
- return self._pages._activeTextColor
-
-
- def SetPageImage(self, page, image):
- """
- Sets the image index for the given page. Image is an index into the
- image list which was set with SetImageList.
- """
-
- self._pages.SetPageImage(page, image)
-
-
- def GetPageImage(self, nPage):
- """
- Returns the image index for the given page. Image is an index into the
- image list which was set with SetImageList.
- """
-
- return self._pages.GetPageImage(nPage)
-
-
- def GetEnabled(self, page):
- """ Returns whether a tab is enabled or not. """
-
- return self._pages.GetEnabled(page)
-
-
- def EnableTab(self, page, enabled=True):
- """ Enables or disables a tab. """
-
- if page >= len(self._windows):
- return
-
- self._windows[page].Enable(enabled)
- self._pages.EnableTab(page, enabled)
-
-
- def GetNonActiveTabTextColour(self):
- """ Returns the non active tabs text colour. """
-
- return self._pages._nonActiveTextColor
-
-
- def SetNonActiveTabTextColour(self, color):
- """ Sets the non active tabs text colour. """
-
- self._pages._nonActiveTextColor = color
-
-
- def SetTabAreaColour(self, color):
- """ Sets the area behind the tabs colour. """
-
- self._pages._tabAreaColor = color
-
-
- def GetTabAreaColour(self):
- """ Returns the area behind the tabs colour. """
-
- return self._pages._tabAreaColor
-
-
- def SetActiveTabColour(self, color):
- """ Sets the active tab colour. """
-
- self._pages._activeTabColor = color
-
-
- def GetActiveTabColour(self):
- """ Returns the active tab colour. """
-
- return self._pages._activeTabColor
-
-
-# ---------------------------------------------------------------------------- #
-# Class PageContainer
-# Acts as a container for the pages you add to FlatNotebook
-# ---------------------------------------------------------------------------- #
-
-class PageContainer(wx.Panel):
- """
- This class acts as a container for the pages you add to L{FlatNotebook}.
- """
-
- def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
- size=wx.DefaultSize, style=0):
- """ Default class constructor. """
-
- self._ImageList = None
- self._iActivePage = -1
- self._pDropTarget = None
- self._nLeftClickZone = FNB_NOWHERE
- self._iPreviousActivePage = -1
-
- self._pRightClickMenu = None
- self._nXButtonStatus = FNB_BTN_NONE
- self._nArrowDownButtonStatus = FNB_BTN_NONE
- self._pParent = parent
- self._nRightButtonStatus = FNB_BTN_NONE
- self._nLeftButtonStatus = FNB_BTN_NONE
- self._nTabXButtonStatus = FNB_BTN_NONE
-
- self._pagesInfoVec = []
-
- self._colorTo = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
- 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_BTNTEXT)
- self._tabAreaColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)
-
- self._nFrom = 0
- self._isdragging = False
-
- # Set default page height, this is done according to the system font
- memDc = wx.MemoryDC()
- memDc.SelectObject(wx.EmptyBitmap(1,1))
-
- if "__WXGTK__" in wx.PlatformInfo:
- boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
- boldFont.SetWeight(wx.BOLD)
- memDc.SetFont(boldFont)
-
- height = memDc.GetCharHeight()
- tabHeight = height + FNB_HEIGHT_SPACER # We use 10 pixels as padding
-
- wx.Panel.__init__(self, parent, id, pos, wx.Size(size.x, tabHeight),
- style|wx.NO_BORDER|wx.NO_FULL_REPAINT_ON_RESIZE|wx.WANTS_CHARS)
-
- self._pDropTarget = FNBDropTarget(self)
- self.SetDropTarget(self._pDropTarget)
- self._mgr = FNBRendererMgr()
-
- self.Bind(wx.EVT_PAINT, self.OnPaint)
- self.Bind(wx.EVT_SIZE, self.OnSize)
- self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
- self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
- self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
- self.Bind(wx.EVT_MIDDLE_DOWN, self.OnMiddleDown)
- self.Bind(wx.EVT_MOTION, self.OnMouseMove)
- self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
- self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
- self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnterWindow)
- self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
- self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
- self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
- self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
-
-
- def OnEraseBackground(self, event):
- """ Handles the wx.EVT_ERASE_BACKGROUND event for L{PageContainer} (does nothing)."""
-
- pass
-
-
- def _ReShow(self):
- """ Handles the Redraw of the tabs when the FNB_HIDE_ON_SINGLE_TAB has been removed """
- self.Show()
- self.GetParent()._mainSizer.Layout()
- self.Refresh()
-
-
- def OnPaint(self, event):
- """ Handles the wx.EVT_PAINT event for L{PageContainer}."""
-
- dc = wx.BufferedPaintDC(self)
- renderer = self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag())
- renderer.DrawTabs(self, dc)
-
- if self.HasFlag(FNB_HIDE_ON_SINGLE_TAB) and len(self._pagesInfoVec) <= 1:
- self.Hide()
- self.GetParent()._mainSizer.Layout()
- self.Refresh()
-
-
- def AddPage(self, caption, selected=True, imgindex=-1):
- """
- Add a page to the L{FlatNotebook}.
-
- @param window: Specifies the new page.
- @param caption: Specifies the text for the new page.
- @param selected: Specifies whether the page should be selected.
- @param imgindex: Specifies the optional image index for the new page.
-
- Return value:
- True if successful, False otherwise.
- """
-
- if selected:
-
- self._iPreviousActivePage = self._iActivePage
- self._iActivePage = len(self._pagesInfoVec)
-
- # Create page info and add it to the vector
- pageInfo = PageInfo(caption, imgindex)
- self._pagesInfoVec.append(pageInfo)
- self.Refresh()
-
-
- def InsertPage(self, indx, text, selected=True, imgindex=-1):
- """
- Inserts a new page at the specified position.
-
- @param indx: Specifies the position of the new page.
- @param page: Specifies the new page.
- @param text: Specifies the text for the new page.
- @param select: Specifies whether the page should be selected.
- @param imgindex: Specifies the optional image index for the new page.
-
- Return value:
- True if successful, False otherwise.
- """
-
- if selected:
-
- self._iPreviousActivePage = self._iActivePage
- self._iActivePage = len(self._pagesInfoVec)
-
- self._pagesInfoVec.insert(indx, PageInfo(text, imgindex))
-
- self.Refresh()
- return True
-
-
- def OnSize(self, event):
- """ Handles the wx.EVT_SIZE events for L{PageContainer}. """
-
- # When resizing the control, try to fit to screen as many tabs as we can
- style = self.GetParent().GetWindowStyleFlag()
- renderer = self._mgr.GetRenderer(style)
-
- fr = 0
- page = self.GetSelection()
-
- for fr in xrange(self._nFrom):
- vTabInfo = renderer.NumberTabsCanFit(self, fr)
- if page - fr >= len(vTabInfo):
- continue
- break
-
- self._nFrom = fr
-
- self.Refresh() # Call on paint
- event.Skip()
-
-
- def OnMiddleDown(self, event):
- """ Handles the wx.EVT_MIDDLE_DOWN events for L{PageContainer}. """
-
- # Test if this style is enabled
- style = self.GetParent().GetWindowStyleFlag()
-
- if not style & FNB_MOUSE_MIDDLE_CLOSES_TABS:
- return
-
- where, tabIdx = self.HitTest(event.GetPosition())
-
- if where == FNB_TAB:
- self.DeletePage(tabIdx)
-
- event.Skip()
-
-
- def OnRightDown(self, event):
- """ Handles the wx.EVT_RIGHT_DOWN events for L{PageContainer}. """
-
- where, tabIdx = self.HitTest(event.GetPosition())
-
- if where in [FNB_TAB, FNB_TAB_X]:
-
- if self._pagesInfoVec[tabIdx].GetEnabled():
- # Fire events and eventually (if allowed) change selection
- self.FireEvent(tabIdx)
-
- # send a message to popup a custom menu
- event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU, self.GetParent().GetId())
- event.SetSelection(tabIdx)
- event.SetOldSelection(self._iActivePage)
- event.SetEventObject(self.GetParent())
- self.GetParent().GetEventHandler().ProcessEvent(event)
-
- if self._pRightClickMenu:
- self.PopupMenu(self._pRightClickMenu)
-
- event.Skip()
-
-
- def OnLeftDown(self, event):
- """ Handles the wx.EVT_LEFT_DOWN events for L{PageContainer}. """
-
- # Reset buttons status
- self._nXButtonStatus = FNB_BTN_NONE
- self._nLeftButtonStatus = FNB_BTN_NONE
- self._nRightButtonStatus = FNB_BTN_NONE
- self._nTabXButtonStatus = FNB_BTN_NONE
- self._nArrowDownButtonStatus = FNB_BTN_NONE
-
- self._nLeftClickZone, tabIdx = self.HitTest(event.GetPosition())
-
- if self._nLeftClickZone == FNB_DROP_DOWN_ARROW:
- self._nArrowDownButtonStatus = FNB_BTN_PRESSED
- self.Refresh()
- elif self._nLeftClickZone == FNB_LEFT_ARROW:
- self._nLeftButtonStatus = FNB_BTN_PRESSED
- self.Refresh()
- elif self._nLeftClickZone == FNB_RIGHT_ARROW:
- self._nRightButtonStatus = FNB_BTN_PRESSED
- self.Refresh()
- elif self._nLeftClickZone == FNB_X:
- self._nXButtonStatus = FNB_BTN_PRESSED
- self.Refresh()
- elif self._nLeftClickZone == FNB_TAB_X:
- self._nTabXButtonStatus = FNB_BTN_PRESSED
- self.Refresh()
-
- elif self._nLeftClickZone == FNB_TAB:
-
- if self._iActivePage != tabIdx:
-
- # In case the tab is disabled, we dont allow to choose it
- if self._pagesInfoVec[tabIdx].GetEnabled():
- 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):
- """ 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:
-
- # Make sure that the button was pressed before
- if self._nXButtonStatus != FNB_BTN_PRESSED:
- return
-
- self._nXButtonStatus = FNB_BTN_HOVER
-
- self.DeletePage(self._iActivePage)
-
- elif where == FNB_TAB_X:
-
- # Make sure that the button was pressed before
- if self._nTabXButtonStatus != FNB_BTN_PRESSED:
- return
-
- self._nTabXButtonStatus = FNB_BTN_HOVER
-
- self.DeletePage(self._iActivePage)
-
- elif where == FNB_DROP_DOWN_ARROW:
-
- # Make sure that the button was pressed before
- if self._nArrowDownButtonStatus != FNB_BTN_PRESSED:
- return
-
- self._nArrowDownButtonStatus = FNB_BTN_NONE
-
- # Refresh the button status
- renderer = self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag())
- dc = wx.ClientDC(self)
- renderer.DrawDropDownArrow(self, dc)
-
- self.PopupTabsMenu()
-
- event.Skip()
-
-
- def HitTest(self, pt):
- """
- HitTest method for L{PageContainer}.
- Returns the flag (if any) and the hit page (if any).
- """
-
- style = self.GetParent().GetWindowStyleFlag()
- render = self._mgr.GetRenderer(style)
-
- fullrect = self.GetClientRect()
- btnLeftPos = render.GetLeftButtonPos(self)
- btnRightPos = render.GetRightButtonPos(self)
- btnXPos = render.GetXPos(self)
-
- tabIdx = -1
-
- if len(self._pagesInfoVec) == 0:
- return FNB_NOWHERE, tabIdx
-
- rect = wx.Rect(btnXPos, 8, 16, 16)
- if rect.Contains(pt):
- return (style & FNB_NO_X_BUTTON and [FNB_NOWHERE] or [FNB_X])[0], tabIdx
-
- rect = wx.Rect(btnRightPos, 8, 16, 16)
- if style & FNB_DROPDOWN_TABS_LIST:
- rect = wx.Rect(render.GetDropArrowButtonPos(self), 8, 16, 16)
- if rect.Contains(pt):
- return FNB_DROP_DOWN_ARROW, tabIdx
-
- if rect.Contains(pt):
- return (style & FNB_NO_NAV_BUTTONS and [FNB_NOWHERE] or [FNB_RIGHT_ARROW])[0], tabIdx
-
- rect = wx.Rect(btnLeftPos, 8, 16, 16)
- if rect.Contains(pt):
- return (style & FNB_NO_NAV_BUTTONS and [FNB_NOWHERE] or [FNB_LEFT_ARROW])[0], tabIdx
-
- # Test whether a left click was made on a tab
- bFoundMatch = False
-
- for cur in xrange(self._nFrom, len(self._pagesInfoVec)):
-
- pgInfo = self._pagesInfoVec[cur]
-
- if pgInfo.GetPosition() == wx.Point(-1, -1):
- continue
-
- if style & FNB_X_ON_TAB and cur == self.GetSelection():
- # 'x' button exists on a tab
- if self._pagesInfoVec[cur].GetXRect().Contains(pt):
- return FNB_TAB_X, cur
-
- if style & FNB_VC8:
-
- if self._pagesInfoVec[cur].GetRegion().Contains(pt.x, pt.y):
- if bFoundMatch or cur == self.GetSelection():
- return FNB_TAB, cur
-
- tabIdx = cur
- bFoundMatch = True
-
- else:
-
- tabRect = wx.Rect(pgInfo.GetPosition().x, pgInfo.GetPosition().y,
- pgInfo.GetSize().x, pgInfo.GetSize().y)
-
- if tabRect.Contains(pt):
- # We have a match
- return FNB_TAB, cur
-
- if bFoundMatch:
- return FNB_TAB, tabIdx
-
- if self._isdragging:
- # We are doing DND, so check also the region outside the tabs
- # try before the first tab
- pgInfo = self._pagesInfoVec[0]
- tabRect = wx.Rect(0, pgInfo.GetPosition().y, pgInfo.GetPosition().x, self.GetParent().GetSize().y)
- if tabRect.Contains(pt):
- return FNB_TAB, 0
-
- # try after the last tab
- pgInfo = self._pagesInfoVec[-1]
- startpos = pgInfo.GetPosition().x+pgInfo.GetSize().x
- tabRect = wx.Rect(startpos, pgInfo.GetPosition().y, fullrect.width-startpos, self.GetParent().GetSize().y)
-
- if tabRect.Contains(pt):
- return FNB_TAB, len(self._pagesInfoVec)
-
- # Default
- return FNB_NOWHERE, -1
-
-
- def SetSelection(self, page):
- """ Sets the selected page. """
-
- book = self.GetParent()
- book.SetSelection(page)
- self.DoSetSelection(page)
-
-
- def DoSetSelection(self, page):
- """ Does the actual selection of a page. """
-
- if page < len(self._pagesInfoVec):
- #! fix for tabfocus
- da_page = self._pParent.GetPage(page)
-
- if da_page != None:
- da_page.SetFocus()
-
- if not self.IsTabVisible(page):
- # Try to remove one tab from start and try again
-
- if not self.CanFitToScreen(page):
-
- if self._nFrom > page:
- self._nFrom = page
- else:
- while self._nFrom < page:
- self._nFrom += 1
- if self.CanFitToScreen(page):
- break
-
- self.Refresh()
-
-
- def DeletePage(self, page):
- """ Delete the specified page from L{FlatNotebook}. """
-
- book = self.GetParent()
- book.DeletePage(page)
- book.Refresh()
-
-
- def IsTabVisible(self, page):
- """ Returns whether a tab is visible or not. """
-
- iLastVisiblePage = self.GetLastVisibleTab()
- return page <= iLastVisiblePage and page >= self._nFrom
-
-
- def DoDeletePage(self, page):
- """ Does the actual page deletion. """
-
- # Remove the page from the vector
- book = self.GetParent()
- self._pagesInfoVec.pop(page)
-
- # Thanks to Yiaanis AKA Mandrav
- if self._iActivePage >= page:
- self._iActivePage = self._iActivePage - 1
- self._iPreviousActivePage = -1
-
- # The delete page was the last first on the array,
- # but the book still has more pages, so we set the
- # active page to be the first one (0)
- if self._iActivePage < 0 and len(self._pagesInfoVec) > 0:
- self._iActivePage = 0
- self._iPreviousActivePage = -1
-
- # Refresh the tabs
- if self._iActivePage >= 0:
-
- book._bForceSelection = True
-
- # Check for selection and send event
- event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetParent().GetId())
- event.SetSelection(self._iActivePage)
- event.SetOldSelection(self._iPreviousActivePage)
- event.SetEventObject(self.GetParent())
-
- book.SetSelection(self._iActivePage)
- book._bForceSelection = False
-
- # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
- event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
- event.SetOldSelection(self._iPreviousActivePage)
- self.GetParent().GetEventHandler().ProcessEvent(event)
-
- if not self._pagesInfoVec:
- # Erase the page container drawings
- dc = wx.ClientDC(self)
- dc.Clear()
-
-
- def DeleteAllPages(self):
- """ Deletes all the pages. """
-
- self._iActivePage = -1
- self._iPreviousActivePage = -1
- self._nFrom = 0
- self._pagesInfoVec = []
-
- # Erase the page container drawings
- dc = wx.ClientDC(self)
- dc.Clear()
-
-
- def OnMouseMove(self, event):
- """ Handles the wx.EVT_MOTION for L{PageContainer}. """
-
- if self._pagesInfoVec and self.IsShown():
-
- xButtonStatus = self._nXButtonStatus
- xTabButtonStatus = self._nTabXButtonStatus
- rightButtonStatus = self._nRightButtonStatus
- leftButtonStatus = self._nLeftButtonStatus
- dropDownButtonStatus = self._nArrowDownButtonStatus
-
- style = self.GetParent().GetWindowStyleFlag()
-
- self._nXButtonStatus = FNB_BTN_NONE
- self._nRightButtonStatus = FNB_BTN_NONE
- self._nLeftButtonStatus = FNB_BTN_NONE
- self._nTabXButtonStatus = FNB_BTN_NONE
- self._nArrowDownButtonStatus = FNB_BTN_NONE
-
- where, tabIdx = self.HitTest(event.GetPosition())
-
- if where == FNB_X:
- if event.LeftIsDown():
-
- self._nXButtonStatus = (self._nLeftClickZone==FNB_X and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
-
- else:
-
- self._nXButtonStatus = FNB_BTN_HOVER
-
- elif where == FNB_DROP_DOWN_ARROW:
- if event.LeftIsDown():
-
- self._nArrowDownButtonStatus = (self._nLeftClickZone==FNB_DROP_DOWN_ARROW and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
-
- else:
-
- self._nArrowDownButtonStatus = FNB_BTN_HOVER
-
- elif where == FNB_TAB_X:
- if event.LeftIsDown():
-
- self._nTabXButtonStatus = (self._nLeftClickZone==FNB_TAB_X and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
-
- else:
-
- self._nTabXButtonStatus = FNB_BTN_HOVER
-
- elif where == FNB_RIGHT_ARROW:
- if event.LeftIsDown():
-
- self._nRightButtonStatus = (self._nLeftClickZone==FNB_RIGHT_ARROW and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
-
- else:
-
- self._nRightButtonStatus = FNB_BTN_HOVER
-
- elif where == FNB_LEFT_ARROW:
- if event.LeftIsDown():
-
- self._nLeftButtonStatus = (self._nLeftClickZone==FNB_LEFT_ARROW and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
-
- else:
-
- self._nLeftButtonStatus = FNB_BTN_HOVER
-
- elif where == FNB_TAB:
- # Call virtual method for showing tooltip
- self.ShowTabTooltip(tabIdx)
-
- if not self.GetEnabled(tabIdx):
- # Set the cursor to be 'No-entry'
- wx.SetCursor(wx.StockCursor(wx.CURSOR_NO_ENTRY))
-
- # Support for drag and drop
- if event.Dragging() and not (style & FNB_NODRAG):
-
- self._isdragging = True
- draginfo = FNBDragInfo(self, tabIdx)
- drginfo = cPickle.dumps(draginfo)
- dataobject = wx.CustomDataObject(wx.CustomDataFormat("FlatNotebook"))
- dataobject.SetData(drginfo)
- dragSource = FNBDropSource(self)
- dragSource.SetData(dataobject)
- dragSource.DoDragDrop(wx.Drag_DefaultMove)
-
- bRedrawX = self._nXButtonStatus != xButtonStatus
- bRedrawRight = self._nRightButtonStatus != rightButtonStatus
- bRedrawLeft = self._nLeftButtonStatus != leftButtonStatus
- bRedrawTabX = self._nTabXButtonStatus != xTabButtonStatus
- bRedrawDropArrow = self._nArrowDownButtonStatus != dropDownButtonStatus
-
- render = self._mgr.GetRenderer(style)
-
- if (bRedrawX or bRedrawRight or bRedrawLeft or bRedrawTabX or bRedrawDropArrow):
-
- dc = wx.ClientDC(self)
-
- if bRedrawX:
-
- render.DrawX(self, dc)
-
- if bRedrawLeft:
-
- render.DrawLeftArrow(self, dc)
-
- if bRedrawRight:
-
- render.DrawRightArrow(self, dc)
-
- if bRedrawTabX:
-
- self.Refresh()
-
- if bRedrawDropArrow:
-
- render.DrawDropDownArrow(self, dc)
-
- event.Skip()
-
-
- def GetLastVisibleTab(self):
- """ Returns the last visible tab. """
-
- if self._nFrom < 0:
- return -1
-
- ii = 0
-
- for ii in xrange(self._nFrom, len(self._pagesInfoVec)):
-
- if self._pagesInfoVec[ii].GetPosition() == wx.Point(-1, -1):
- break
-
- return ii-1
-
-
- def GetNumTabsCanScrollLeft(self):
- """ Returns the number of tabs than can be scrolled left. """
-
- if self._nFrom - 1 >= 0:
- return 1
-
- return 0
-
-
- def IsDefaultTabs(self):
- """ Returns whether a tab has a default style. """
-
- style = self.GetParent().GetWindowStyleFlag()
- res = (style & FNB_VC71) or (style & FNB_FANCY_TABS) or (style & FNB_VC8)
- return not res
-
-
- def AdvanceSelection(self, bForward=True):
- """
- Cycles through the tabs.
- The call to this function generates the page changing events.
- """
-
- nSel = self.GetSelection()
-
- if nSel < 0:
- return
-
- nMax = self.GetPageCount() - 1
-
- if bForward:
- newSelection = (nSel == nMax and [0] or [nSel + 1])[0]
- else:
- newSelection = (nSel == 0 and [nMax] or [nSel - 1])[0]
-
- if not self._pagesInfoVec[newSelection].GetEnabled():
- return
-
- self.FireEvent(newSelection)
-
-
- def OnMouseLeave(self, event):
- """ Handles the wx.EVT_LEAVE_WINDOW event for L{PageContainer}. """
-
- self._nLeftButtonStatus = FNB_BTN_NONE
- self._nXButtonStatus = FNB_BTN_NONE
- self._nRightButtonStatus = FNB_BTN_NONE
- self._nTabXButtonStatus = FNB_BTN_NONE
- self._nArrowDownButtonStatus = FNB_BTN_NONE
-
- style = self.GetParent().GetWindowStyleFlag()
- render = self._mgr.GetRenderer(style)
-
- dc = wx.ClientDC(self)
-
- render.DrawX(self, dc)
- render.DrawLeftArrow(self, dc)
- render.DrawRightArrow(self, dc)
-
- selection = self.GetSelection()
-
- if selection == -1:
- event.Skip()
- return
-
- if not self.IsTabVisible(selection):
- if selection == len(self._pagesInfoVec) - 1:
- if not self.CanFitToScreen(selection):
- event.Skip()
- return
- else:
- event.Skip()
- return
-
- render.DrawTabX(self, dc, self._pagesInfoVec[selection].GetXRect(), selection, self._nTabXButtonStatus)
-
- event.Skip()
-
-
- def OnMouseEnterWindow(self, event):
- """ Handles the wx.EVT_ENTER_WINDOW event for L{PageContainer}. """
-
- self._nLeftButtonStatus = FNB_BTN_NONE
- self._nXButtonStatus = FNB_BTN_NONE
- self._nRightButtonStatus = FNB_BTN_NONE
- self._nLeftClickZone = FNB_BTN_NONE
- self._nArrowDownButtonStatus = FNB_BTN_NONE
-
- event.Skip()
-
-
- def ShowTabTooltip(self, tabIdx):
- """ Shows a tab tooltip. """
-
- pWindow = self._pParent.GetPage(tabIdx)
-
- if pWindow:
- pToolTip = pWindow.GetToolTip()
- if pToolTip and pToolTip.GetWindow() == pWindow:
- self.SetToolTipString(pToolTip.GetTip())
-
-
- def SetPageImage(self, page, imgindex):
- """ Sets the image index associated to a page. """
-
- if page < len(self._pagesInfoVec):
-
- self._pagesInfoVec[page].SetImageIndex(imgindex)
- self.Refresh()
-
-
- def GetPageImage(self, page):
- """ Returns the image index associated to a page. """
-
- if page < len(self._pagesInfoVec):
-
- return self._pagesInfoVec[page].GetImageIndex()
-
- return -1
-
-
- def OnDropTarget(self, x, y, nTabPage, wnd_oldContainer):
- """ Handles the drop action from a DND operation. """
-
- # Disable drag'n'drop for disabled tab
- if not wnd_oldContainer._pagesInfoVec[nTabPage].GetEnabled():
- return wx.DragCancel
-
- self._isdragging = True
- oldContainer = wnd_oldContainer
- nIndex = -1
-
- where, nIndex = self.HitTest(wx.Point(x, y))
-
- oldNotebook = oldContainer.GetParent()
- newNotebook = self.GetParent()
-
- if oldNotebook == newNotebook:
-
- if nTabPage >= 0:
-
- if where == FNB_TAB:
- self.MoveTabPage(nTabPage, nIndex)
-
- elif self.GetParent().GetWindowStyleFlag() & FNB_ALLOW_FOREIGN_DND:
-
- if wx.Platform in ["__WXMSW__", "__WXGTK__", "__WXMAC__"]:
- if nTabPage >= 0:
-
- window = oldNotebook.GetPage(nTabPage)
-
- if window:
- where, nIndex = newNotebook._pages.HitTest(wx.Point(x, y))
- caption = oldContainer.GetPageText(nTabPage)
- imageindex = oldContainer.GetPageImage(nTabPage)
- oldNotebook.RemovePage(nTabPage)
- window.Reparent(newNotebook)
-
- if imageindex >= 0:
-
- bmp = oldNotebook.GetImageList().GetIcon(imageindex)
- newImageList = newNotebook.GetImageList()
-
- if not newImageList:
- xbmp, ybmp = bmp.GetWidth(), bmp.GetHeight()
- newImageList = wx.ImageList(xbmp, ybmp)
- imageindex = 0
- else:
- imageindex = newImageList.GetImageCount()
-
- newImageList.AddIcon(bmp)
- newNotebook.SetImageList(newImageList)
-
- newNotebook.InsertPage(nIndex, window, caption, True, imageindex)
-
- self._isdragging = False
-
- return wx.DragMove
-
-
- def MoveTabPage(self, nMove, nMoveTo):
- """ Moves a tab inside the same L{FlatNotebook}. """
-
- if nMove == nMoveTo:
- return
-
- elif nMoveTo < len(self._pParent._windows):
- nMoveTo = nMoveTo + 1
-
- self._pParent.Freeze()
-
- # Remove the window from the main sizer
- nCurSel = self._pParent._pages.GetSelection()
- self._pParent._mainSizer.Detach(self._pParent._windows[nCurSel])
- self._pParent._windows[nCurSel].Hide()
-
- pWindow = self._pParent._windows[nMove]
- self._pParent._windows.pop(nMove)
- self._pParent._windows.insert(nMoveTo-1, pWindow)
-
- pgInfo = self._pagesInfoVec[nMove]
-
- self._pagesInfoVec.pop(nMove)
- self._pagesInfoVec.insert(nMoveTo - 1, pgInfo)
-
- # Add the page according to the style
- pSizer = self._pParent._mainSizer
- style = self.GetParent().GetWindowStyleFlag()
-
- if style & FNB_BOTTOM:
-
- pSizer.Insert(0, pWindow, 1, wx.EXPAND)
-
- else:
-
- # We leave a space of 1 pixel around the window
- pSizer.Add(pWindow, 1, wx.EXPAND)
-
- pWindow.Show()
-
- pSizer.Layout()
- self._iActivePage = nMoveTo - 1
- self._iPreviousActivePage = -1
- self.DoSetSelection(self._iActivePage)
- self.Refresh()
- self._pParent.Thaw()
-
-
- def CanFitToScreen(self, page):
- """ Returns wheter a tab can fit in the left space in the screen or not. """
-
- # Incase the from is greater than page,
- # we need to reset the self._nFrom, so in order
- # to force the caller to do so, we return false
- if self._nFrom > page:
- return False
-
- style = self.GetParent().GetWindowStyleFlag()
- render = self._mgr.GetRenderer(style)
-
- vTabInfo = render.NumberTabsCanFit(self)
-
- if page - self._nFrom >= len(vTabInfo):
- return False
-
- return True
-
-
- def GetNumOfVisibleTabs(self):
- """ Returns the number of visible tabs. """
-
- count = 0
- for ii in xrange(self._nFrom, len(self._pagesInfoVec)):
- if self._pagesInfoVec[ii].GetPosition() == wx.Point(-1, -1):
- break
- count = count + 1
-
- return count
-
-
- def GetEnabled(self, page):
- """ Returns whether a tab is enabled or not. """
-
- if page >= len(self._pagesInfoVec):
- return True # Seems strange, but this is the default
-
- return self._pagesInfoVec[page].GetEnabled()
-
-
- def EnableTab(self, page, enabled=True):
- """ Enables or disables a tab. """
-
- if page >= len(self._pagesInfoVec):
- return
-
- self._pagesInfoVec[page].EnableTab(enabled)
-
-
- def GetSingleLineBorderColour(self):
- """ Returns the colour for the single line border. """
-
- if self.HasFlag(FNB_FANCY_TABS):
- return self._colorFrom
-
- return wx.WHITE
-
-
- def HasFlag(self, flag):
- """ Returns whether a flag is present in the L{FlatNotebook} style. """
-
- style = self.GetParent().GetWindowStyleFlag()
- res = (style & flag and [True] or [False])[0]
- return res
-
-
- def ClearFlag(self, flag):
- """ Deletes a flag from the L{FlatNotebook} style. """
-
- style = self.GetParent().GetWindowStyleFlag()
- style &= ~flag
- self.SetWindowStyleFlag(style)
-
-
- def TabHasImage(self, tabIdx):
- """ Returns whether a tab has an associated image index or not. """
-
- if self._ImageList:
- return self._pagesInfoVec[tabIdx].GetImageIndex() != -1
-
- return False
-
-
- def OnLeftDClick(self, event):
- """ Handles the wx.EVT_LEFT_DCLICK event for L{PageContainer}. """
-
- 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):
-
- if where == FNB_TAB:
- self.DeletePage(tabIdx)
-
- else:
-
- event.Skip()
-
-
- def OnSetFocus(self, event):
- """ Handles the wx.EVT_SET_FOCUS event for L{PageContainer}. """
-
- if self._iActivePage < 0:
- event.Skip()
- return
-
- self.SetFocusedPage(self._iActivePage)
-
-
- def OnKillFocus(self, event):
- """ Handles the wx.EVT_KILL_FOCUS event for L{PageContainer}. """
-
- self.SetFocusedPage()
-
-
- def OnKeyDown(self, event):
- """
- When the PageContainer has the focus tabs can be changed with
- the left/right arrow keys.
- """
- key = event.GetKeyCode()
- print key
- if key == wx.WXK_LEFT:
- self.GetParent().AdvanceSelection(False)
- elif key == wx.WXK_RIGHT:
- self.GetParent().AdvanceSelection(True)
- elif key == wx.WXK_TAB:
- flags = 0
- if not event.ShiftDown(): flags |= wx.NavigationKeyEvent.IsForward
- if event.CmdDown(): flags |= wx.NavigationKeyEvent.WinChange
- self.Navigate(flags)
- else:
- event.Skip()
-
-
- def SetFocusedPage(self, pageIndex=-1):
- """
- Sets/Unsets the focus on the appropriate page.
- If pageIndex is defaulted, we have lost focus and no focus indicator is drawn.
- """
-
- for indx, page in enumerate(self._pagesInfoVec):
- if indx == pageIndex:
- page._hasFocus = True
- else:
- page._hasFocus = False
-
- self.Refresh()
-
-
- def PopupTabsMenu(self):
- """ Pops up the menu activated with the drop down arrow in the navigation area. """
-
- popupMenu = wx.Menu()
-
- for i in xrange(len(self._pagesInfoVec)):
- pi = self._pagesInfoVec[i]
- item = wx.MenuItem(popupMenu, i+1, pi.GetCaption(), pi.GetCaption(), wx.ITEM_NORMAL)
- self.Bind(wx.EVT_MENU, self.OnTabMenuSelection, item)
-
- # There is an alignment problem with wx2.6.3 & Menus so only use
- # images for versions above 2.6.3
- if wx.VERSION > (2, 6, 3, 0) and self.TabHasImage(i):
- item.SetBitmap(self.GetImageList().GetBitmap(pi.GetImageIndex()))
-
- popupMenu.AppendItem(item)
- item.EnableTab(pi.GetEnabled())
-
- self.PopupMenu(popupMenu)
-
-
- def OnTabMenuSelection(self, event):
- """ Handles the wx.EVT_MENU event for L{PageContainer}. """
-
- selection = event.GetId() - 1
- self.FireEvent(selection)
-
-
- def FireEvent(self, selection):
- """
- Fires the wxEVT_FLATNOTEBOOK_PAGE_CHANGING and wxEVT_FLATNOTEBOOK_PAGE_CHANGED events
- called from other methods (from menu selection or Smart Tabbing).
- Utility function.
- """
-
- if selection == self._iActivePage:
- # No events for the same selection
- return
-
- oldSelection = self._iActivePage
-
- event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetParent().GetId())
- event.SetSelection(selection)
- event.SetOldSelection(oldSelection)
- event.SetEventObject(self.GetParent())
-
- if not self.GetParent().GetEventHandler().ProcessEvent(event) or event.IsAllowed():
-
- self.SetSelection(selection)
-
- # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
- event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
- event.SetOldSelection(oldSelection)
- self.GetParent().GetEventHandler().ProcessEvent(event)
- self.SetFocus()
-
-
- def SetImageList(self, imglist):
- """ Sets the image list for the page control. """
-
- self._ImageList = imglist
-
-
- def AssignImageList(self, imglist):
- """ Assigns the image list for the page control. """
-
- self._ImageList = imglist
-
-
- def GetImageList(self):
- """ Returns the image list for the page control. """
-
- return self._ImageList
-
-
- def GetSelection(self):
- """ Returns the current selected page. """
-
- return self._iActivePage
-
-
- def GetPageCount(self):
- """ Returns the number of tabs in the L{FlatNotebook} control. """
-
- return len(self._pagesInfoVec)
-
-
- def GetPageText(self, page):
- """ Returns the tab caption of the page. """
-
- return self._pagesInfoVec[page].GetCaption()
-
-
- def SetPageText(self, page, text):
- """ Sets the tab caption of the page. """
-
- self._pagesInfoVec[page].SetCaption(text)
- return True
-
-
- def DrawDragHint(self):
- """ Draws small arrow at the place that the tab will be placed. """
-
- # get the index of tab that will be replaced with the dragged tab
- pt = wx.GetMousePosition()
- client_pt = self.ScreenToClient(pt)
- where, tabIdx = self.HitTest(client_pt)
- self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag()).DrawDragHint(self, tabIdx)
-
-