X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ec873c943d71f0d5f13e3398557071448cda6c23..a4027e74873007e3430af3bd77019bcab76f6c04:/wxPython/wx/lib/flatnotebook.py diff --git a/wxPython/wx/lib/flatnotebook.py b/wxPython/wx/lib/flatnotebook.py deleted file mode 100644 index 214f6821c3..0000000000 --- a/wxPython/wx/lib/flatnotebook.py +++ /dev/null @@ -1,4940 +0,0 @@ -# --------------------------------------------------------------------------- # -# 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) - -