1 # --------------------------------------------------------------------------- #
2 # FLATNOTEBOOK Widget wxPython IMPLEMENTATION
4 # Original C++ Code From Eran. You Can Find It At:
6 # http://wxforum.shadonet.com/viewtopic.php?t=5761&start=0
8 # License: wxWidgets license
13 # Andrea Gavana, @ 02 Oct 2006
14 # Latest Revision: 12 Oct 2006, 20.00 GMT
17 # For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
20 # andrea.gavana@gmail.com
23 # Or, Obviously, To The wxPython Mailing List!!!
27 # --------------------------------------------------------------------------- #
30 The FlatNotebook is a full implementation of the wx.Notebook, and designed to be
31 a drop-in replacement for wx.Notebook. The API functions are similar so one can
32 expect the function to behave in the same way.
36 - The buttons are highlighted a la Firefox style
37 - The scrolling is done for bulks of tabs (so, the scrolling is faster and better)
38 - The buttons area is never overdrawn by tabs (unlike many other implementations I saw)
39 - It is a generic control
40 - Currently there are 4 differnt styles - VC8, VC 71, Standard and Fancy
41 - Mouse middle click can be used to close tabs
42 - A function to add right click menu for tabs (simple as SetRightClickMenu)
43 - All styles has bottom style as well (they can be drawn in the bottom of screen)
44 - An option to hide 'X' button or navigation buttons (separately)
45 - Gradient coloring of the selected tabs and border
46 - Support for drag 'n' drop of tabs, both in the same notebook or to another notebook
47 - Possibility to have closing button on the active tab directly
48 - Support for disabled tabs
49 - Colours for active/inactive tabs, and captions
50 - Background of tab area can be painted in gradient (VC8 style only)
51 - Colourful tabs - a random gentle colour is generated for each new tab (very cool, VC8 style only)
59 FlatNotebook Is Freeware And Distributed Under The wxPython License.
61 Latest Revision: Andrea Gavana @ 12 Oct 2006, 20.00 GMT
65 @undocumented: FNB_HEIGHT_SPACER, VERTICAL_BORDER_PADDING, VC8_SHAPE_LEN,
66 wxEVT*, left_arrow_*, right_arrow*, x_button*, down_arrow*,
67 FNBDragInfo, FNBDropTarget, GetMondrian*
70 __docformat__
= "epytext"
73 #----------------------------------------------------------------------
74 # Beginning Of FLATNOTEBOOK wxPython Code
75 #----------------------------------------------------------------------
83 # Check for the new method in 2.7 (not present in 2.6.3.3)
84 if wx
.VERSION_STRING
< "2.7":
85 wx
.Rect
.Contains
= lambda self
, point
: wx
.Rect
.Inside(self
, point
)
87 FNB_HEIGHT_SPACER
= 10
89 # Use Visual Studio 2003 (VC7.1) style for tabs
91 """Use Visual Studio 2003 (VC7.1) style for tabs"""
93 # Use fancy style - square tabs filled with gradient coloring
95 """Use fancy style - square tabs filled with gradient coloring"""
97 # Draw thin border around the page
98 FNB_TABS_BORDER_SIMPLE
= 4
99 """Draw thin border around the page"""
101 # Do not display the 'X' button
103 """Do not display the 'X' button"""
105 # Do not display the Right / Left arrows
106 FNB_NO_NAV_BUTTONS
= 16
107 """Do not display the right/left arrows"""
109 # Use the mouse middle button for cloing tabs
110 FNB_MOUSE_MIDDLE_CLOSES_TABS
= 32
111 """Use the mouse middle button for cloing tabs"""
113 # Place tabs at bottom - the default is to place them
116 """Place tabs at bottom - the default is to place them at top"""
118 # Disable dragging of tabs
120 """Disable dragging of tabs"""
122 # Use Visual Studio 2005 (VC8) style for tabs
124 """Use Visual Studio 2005 (VC8) style for tabs"""
128 """Place 'X' close button on the active tab"""
130 FNB_BACKGROUND_GRADIENT
= 1024
131 """Use gradients to paint the tabs background"""
133 FNB_COLORFUL_TABS
= 2048
134 """Use colourful tabs (VC8 style only)"""
136 # Style to close tab using double click - styles 1024, 2048 are reserved
137 FNB_DCLICK_CLOSES_TABS
= 4096
138 """Style to close tab using double click"""
140 FNB_SMART_TABS
= 8192
141 """Use Smart Tabbing, like Alt+Tab on Windows"""
143 FNB_DROPDOWN_TABS_LIST
= 16384
144 """Use a dropdown menu on the left in place of the arrows"""
146 FNB_ALLOW_FOREIGN_DND
= 32768
147 """Allows drag 'n' drop operations between different L{FlatNotebook}s"""
149 VERTICAL_BORDER_PADDING
= 4
151 # Button size is a 16x16 xpm bitmap
153 """Button size is a 16x16 xpm bitmap"""
157 MASK_COLOR
= wx
.Colour(0, 128, 128)
158 """Mask colour for the arrow bitmaps"""
162 """Navigation button is pressed"""
164 """Navigation button is hovered"""
169 FNB_TAB
= 1 # On a tab
170 """Indicates mouse coordinates inside a tab"""
171 FNB_X
= 2 # On the X button
172 """Indicates mouse coordinates inside the I{X} region"""
173 FNB_TAB_X
= 3 # On the 'X' button (tab's X button)
174 """Indicates mouse coordinates inside the I{X} region in a tab"""
175 FNB_LEFT_ARROW
= 4 # On the rotate left arrow button
176 """Indicates mouse coordinates inside the left arrow region"""
177 FNB_RIGHT_ARROW
= 5 # On the rotate right arrow button
178 """Indicates mouse coordinates inside the right arrow region"""
179 FNB_DROP_DOWN_ARROW
= 6 # On the drop down arrow button
180 """Indicates mouse coordinates inside the drop down arrow region"""
181 FNB_NOWHERE
= 0 # Anywhere else
182 """Indicates mouse coordinates not on any tab of the notebook"""
184 FNB_DEFAULT_STYLE
= FNB_MOUSE_MIDDLE_CLOSES_TABS
185 """L{FlatNotebook} default style"""
187 # FlatNotebook Events:
188 # wxEVT_FLATNOTEBOOK_PAGE_CHANGED: Event Fired When You Switch Page;
189 # wxEVT_FLATNOTEBOOK_PAGE_CHANGING: Event Fired When You Are About To Switch
190 # Pages, But You Can Still "Veto" The Page Changing By Avoiding To Call
191 # event.Skip() In Your Event Handler;
192 # wxEVT_FLATNOTEBOOK_PAGE_CLOSING: Event Fired When A Page Is Closing, But
193 # You Can Still "Veto" The Page Changing By Avoiding To Call event.Skip()
194 # In Your Event Handler;
195 # wxEVT_FLATNOTEBOOK_PAGE_CLOSED: Event Fired When A Page Is Closed.
196 # wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU: Event Fired When A Menu Pops-up In A Tab.
198 wxEVT_FLATNOTEBOOK_PAGE_CHANGED
= wx
.NewEventType()
199 wxEVT_FLATNOTEBOOK_PAGE_CHANGING
= wx
.NewEventType()
200 wxEVT_FLATNOTEBOOK_PAGE_CLOSING
= wx
.NewEventType()
201 wxEVT_FLATNOTEBOOK_PAGE_CLOSED
= wx
.NewEventType()
202 wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU
= wx
.NewEventType()
204 #-----------------------------------#
206 #-----------------------------------#
208 EVT_FLATNOTEBOOK_PAGE_CHANGED
= wx
.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
, 1)
209 """Notify client objects when the active page in L{FlatNotebook}
211 EVT_FLATNOTEBOOK_PAGE_CHANGING
= wx
.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, 1)
212 """Notify client objects when the active page in L{FlatNotebook}
213 is about to change."""
214 EVT_FLATNOTEBOOK_PAGE_CLOSING
= wx
.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CLOSING
, 1)
215 """Notify client objects when a page in L{FlatNotebook} is closing."""
216 EVT_FLATNOTEBOOK_PAGE_CLOSED
= wx
.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CLOSED
, 1)
217 """Notify client objects when a page in L{FlatNotebook} has been closed."""
218 EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU
= wx
.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU
, 1)
219 """Notify client objects when a pop-up menu should appear next to a tab."""
222 # Some icons in XPM format
224 left_arrow_disabled_xpm
= [
252 x_button_pressed_xpm
= [
309 x_button_hilite_xpm
= [
365 left_arrow_pressed_xpm
= [
393 left_arrow_hilite_xpm
= [
421 right_arrow_disabled_xpm
= [
449 right_arrow_hilite_xpm
= [
477 right_arrow_pressed_xpm
= [
534 down_arrow_hilite_xpm
= [
562 down_arrow_pressed_xpm
= [
620 #----------------------------------------------------------------------
621 def GetMondrianData():
623 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\
624 \x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00qID\
625 ATX\x85\xed\xd6;\n\x800\x10E\xd1{\xc5\x8d\xb9r\x97\x16\x0b\xad$\x8a\x82:\x16\
626 o\xda\x84pB2\x1f\x81Fa\x8c\x9c\x08\x04Z{\xcf\xa72\xbcv\xfa\xc5\x08 \x80r\x80\
627 \xfc\xa2\x0e\x1c\xe4\xba\xfaX\x1d\xd0\xde]S\x07\x02\xd8>\xe1wa-`\x9fQ\xe9\
628 \x86\x01\x04\x10\x00\\(Dk\x1b-\x04\xdc\x1d\x07\x14\x98;\x0bS\x7f\x7f\xf9\x13\
629 \x04\x10@\xf9X\xbe\x00\xc9 \x14K\xc1<={\x00\x00\x00\x00IEND\xaeB`\x82'
632 def GetMondrianBitmap():
633 return wx
.BitmapFromImage(GetMondrianImage().Scale(16, 16))
636 def GetMondrianImage():
638 stream
= cStringIO
.StringIO(GetMondrianData())
639 return wx
.ImageFromStream(stream
)
642 def GetMondrianIcon():
643 icon
= wx
.EmptyIcon()
644 icon
.CopyFromBitmap(GetMondrianBitmap())
646 #----------------------------------------------------------------------
649 def LightColour(color
, percent
):
650 """ Brighten input colour by percent. """
654 rd
= end_color
.Red() - color
.Red()
655 gd
= end_color
.Green() - color
.Green()
656 bd
= end_color
.Blue() - color
.Blue()
660 # We take the percent way of the color from color -. white
662 r
= color
.Red() + ((i
*rd
*100)/high
)/100
663 g
= color
.Green() + ((i
*gd
*100)/high
)/100
664 b
= color
.Blue() + ((i
*bd
*100)/high
)/100
665 return wx
.Colour(r
, g
, b
)
669 """ Creates a random colour. """
671 r
= random
.randint(0, 255) # Random value betweem 0-255
672 g
= random
.randint(0, 255) # Random value betweem 0-255
673 b
= random
.randint(0, 255) # Random value betweem 0-255
675 return wx
.Colour(r
, g
, b
)
678 def PaintStraightGradientBox(dc
, rect
, startColor
, endColor
, vertical
=True):
679 """ Draws a gradient colored box from startColor to endColor. """
681 rd
= endColor
.Red() - startColor
.Red()
682 gd
= endColor
.Green() - startColor
.Green()
683 bd
= endColor
.Blue() - startColor
.Blue()
685 # Save the current pen and brush
686 savedPen
= dc
.GetPen()
687 savedBrush
= dc
.GetBrush()
690 high
= rect
.GetHeight()-1
692 high
= rect
.GetWidth()-1
697 for i
in xrange(high
+1):
699 r
= startColor
.Red() + ((i
*rd
*100)/high
)/100
700 g
= startColor
.Green() + ((i
*gd
*100)/high
)/100
701 b
= startColor
.Blue() + ((i
*bd
*100)/high
)/100
703 p
= wx
.Pen(wx
.Colour(r
, g
, b
))
707 dc
.DrawLine(rect
.x
, rect
.y
+i
, rect
.x
+rect
.width
, rect
.y
+i
)
709 dc
.DrawLine(rect
.x
+i
, rect
.y
, rect
.x
+i
, rect
.y
+rect
.height
)
711 # Restore the pen and brush
713 dc
.SetBrush(savedBrush
)
716 # ---------------------------------------------------------------------------- #
717 # Class FNBDropSource
718 # Gives Some Custom UI Feedback during the DnD Operations
719 # ---------------------------------------------------------------------------- #
721 class FNBDropSource(wx
.DropSource
):
723 Give some custom UI feedback during the drag and drop operation in this
724 function. It is called on each mouse move, so your implementation must
728 def __init__(self
, win
):
729 """ Default class constructor. Used internally. """
731 wx
.DropSource
.__init
__(self
, win
)
735 def GiveFeedback(self
, effect
):
736 """ Provides user with a nice feedback when tab is being dragged. """
738 self
._win
.DrawDragHint()
742 # ---------------------------------------------------------------------------- #
744 # Stores All The Information To Allow Drag And Drop Between Different
746 # ---------------------------------------------------------------------------- #
750 _map
= weakref
.WeakValueDictionary()
752 def __init__(self
, container
, pageindex
):
753 """ Default class constructor. """
755 self
._id
= id(container
)
756 FNBDragInfo
._map
[self
._id
] = container
757 self
._pageindex
= pageindex
760 def GetContainer(self
):
761 """ Returns the L{FlatNotebook} page (usually a panel). """
763 return FNBDragInfo
._map
.get(self
._id
, None)
766 def GetPageIndex(self
):
767 """ Returns the page index associated with a page. """
769 return self
._pageindex
772 # ---------------------------------------------------------------------------- #
773 # Class FNBDropTarget
774 # Simply Used To Handle The OnDrop() Method When Dragging And Dropping Between
775 # Different FlatNotebooks.
776 # ---------------------------------------------------------------------------- #
778 class FNBDropTarget(wx
.DropTarget
):
780 def __init__(self
, parent
):
781 """ Default class constructor. """
783 wx
.DropTarget
.__init
__(self
)
785 self
._parent
= parent
786 self
._dataobject
= wx
.CustomDataObject(wx
.CustomDataFormat("FlatNotebook"))
787 self
.SetDataObject(self
._dataobject
)
790 def OnData(self
, x
, y
, dragres
):
791 """ Handles the OnData() method to call the real DnD routine. """
793 if not self
.GetData():
796 draginfo
= self
._dataobject
.GetData()
797 drginfo
= cPickle
.loads(draginfo
)
799 return self
._parent
.OnDropTarget(x
, y
, drginfo
.GetPageIndex(), drginfo
.GetContainer())
802 # ---------------------------------------------------------------------------- #
804 # Contains parameters for every FlatNotebook page
805 # ---------------------------------------------------------------------------- #
809 This class holds all the information (caption, image, etc...) belonging to a
810 single tab in L{FlatNotebook}.
813 def __init__(self
, caption
="", imageindex
=-1, tabangle
=0, enabled
=True):
815 Default Class Constructor.
818 @param caption: the tab caption;
819 @param imageindex: the tab image index based on the assigned (set) wx.ImageList (if any);
820 @param tabangle: the tab angle (only on standard tabs, from 0 to 15 degrees);
821 @param enabled: sets enabled or disabled the tab.
824 self
._strCaption
= caption
825 self
._TabAngle
= tabangle
826 self
._ImageIndex
= imageindex
827 self
._bEnabled
= enabled
828 self
._pos
= wx
.Point(-1, -1)
829 self
._size
= wx
.Size(-1, -1)
830 self
._region
= wx
.Region()
831 self
._xRect
= wx
.Rect()
835 def SetCaption(self
, value
):
836 """ Sets the tab caption. """
838 self
._strCaption
= value
841 def GetCaption(self
):
842 """ Returns the tab caption. """
844 return self
._strCaption
847 def SetPosition(self
, value
):
848 """ Sets the tab position. """
853 def GetPosition(self
):
854 """ Returns the tab position. """
859 def SetSize(self
, value
):
860 """ Sets the tab size. """
866 """ Returns the tab size. """
871 def SetTabAngle(self
, value
):
872 """ Sets the tab header angle (0 <= tab <= 15 degrees). """
874 self
._TabAngle
= min(45, value
)
877 def GetTabAngle(self
):
878 """ Returns the tab angle. """
880 return self
._TabAngle
883 def SetImageIndex(self
, value
):
884 """ Sets the tab image index. """
886 self
._ImageIndex
= value
889 def GetImageIndex(self
):
890 """ Returns the tab umage index. """
892 return self
._ImageIndex
895 def GetEnabled(self
):
896 """ Returns whether the tab is enabled or not. """
898 return self
._bEnabled
901 def Enable(self
, enabled
):
902 """ Sets the tab enabled or disabled. """
904 self
._bEnabled
= enabled
907 def SetRegion(self
, points
=[]):
908 """ Sets the tab region. """
910 self
._region
= wx
.RegionFromPoints(points
)
914 """ Returns the tab region. """
919 def SetXRect(self
, xrect
):
920 """ Sets the button 'X' area rect. """
926 """ Returns the button 'X' area rect. """
932 """ Returns the tab colour. """
937 def SetColour(self
, color
):
938 """ Sets the tab colour. """
943 # ---------------------------------------------------------------------------- #
944 # Class FlatNotebookEvent
945 # ---------------------------------------------------------------------------- #
947 class FlatNotebookEvent(wx
.PyCommandEvent
):
949 This events will be sent when a EVT_FLATNOTEBOOK_PAGE_CHANGED,
950 EVT_FLATNOTEBOOK_PAGE_CHANGING, EVT_FLATNOTEBOOK_PAGE_CLOSING,
951 EVT_FLATNOTEBOOK_PAGE_CLOSED and EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU is
952 mapped in the parent.
955 def __init__(self
, eventType
, id=1, nSel
=-1, nOldSel
=-1):
956 """ Default class constructor. """
958 wx
.PyCommandEvent
.__init
__(self
, eventType
, id)
959 self
._eventType
= eventType
961 self
.notify
= wx
.NotifyEvent(eventType
, id)
964 def GetNotifyEvent(self
):
965 """Returns the actual wx.NotifyEvent."""
971 """Returns whether the event is allowed or not."""
973 return self
.notify
.IsAllowed()
977 """Vetos the event."""
983 """The event is allowed."""
988 def SetSelection(self
, nSel
):
989 """ Sets event selection. """
991 self
._selection
= nSel
994 def SetOldSelection(self
, nOldSel
):
995 """ Sets old event selection. """
997 self
._oldselection
= nOldSel
1000 def GetSelection(self
):
1001 """ Returns event selection. """
1003 return self
._selection
1006 def GetOldSelection(self
):
1007 """ Returns old event selection """
1009 return self
._oldselection
1012 # ---------------------------------------------------------------------------- #
1013 # Class TabNavigatorWindow
1014 # ---------------------------------------------------------------------------- #
1016 class TabNavigatorWindow(wx
.Dialog
):
1018 This class is used to create a modal dialog that enables "Smart Tabbing",
1019 similar to what you would get by hitting Alt+Tab on Windows.
1022 def __init__(self
, parent
=None):
1023 """ Default class constructor. Used internally."""
1025 wx
.Dialog
.__init
__(self
, parent
, wx
.ID_ANY
, "", style
=0)
1027 self
._selectedItem
= -1
1030 self
._bmp
= GetMondrianBitmap()
1032 sz
= wx
.BoxSizer(wx
.VERTICAL
)
1034 self
._listBox
= wx
.ListBox(self
, wx
.ID_ANY
, wx
.DefaultPosition
, wx
.Size(200, 150), [], wx
.LB_SINGLE | wx
.NO_BORDER
)
1036 mem_dc
= wx
.MemoryDC()
1037 mem_dc
.SelectObject(wx
.EmptyBitmap(1,1))
1038 font
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
1039 font
.SetWeight(wx
.BOLD
)
1040 mem_dc
.SetFont(font
)
1042 panelHeight
= mem_dc
.GetCharHeight()
1043 panelHeight
+= 4 # Place a spacer of 2 pixels
1045 # Out signpost bitmap is 24 pixels
1046 if panelHeight
< 24:
1049 self
._panel
= wx
.Panel(self
, wx
.ID_ANY
, wx
.DefaultPosition
, wx
.Size(200, panelHeight
))
1052 sz
.Add(self
._listBox
, 1, wx
.EXPAND
)
1056 # Connect events to the list box
1057 self
._listBox
.Bind(wx
.EVT_KEY_UP
, self
.OnKeyUp
)
1058 self
._listBox
.Bind(wx
.EVT_NAVIGATION_KEY
, self
.OnNavigationKey
)
1059 self
._listBox
.Bind(wx
.EVT_LISTBOX_DCLICK
, self
.OnItemSelected
)
1061 # Connect paint event to the panel
1062 self
._panel
.Bind(wx
.EVT_PAINT
, self
.OnPanelPaint
)
1063 self
._panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, self
.OnPanelEraseBg
)
1065 self
.SetBackgroundColour(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
))
1066 self
._listBox
.SetBackgroundColour(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
))
1067 self
.PopulateListControl(parent
)
1069 self
.GetSizer().Fit(self
)
1070 self
.GetSizer().SetSizeHints(self
)
1071 self
.GetSizer().Layout()
1075 def OnKeyUp(self
, event
):
1076 """Handles the wx.EVT_KEY_UP for the L{TabNavigatorWindow}."""
1078 if event
.GetKeyCode() == wx
.WXK_CONTROL
:
1082 def OnNavigationKey(self
, event
):
1083 """Handles the wx.EVT_NAVIGATION_KEY for the L{TabNavigatorWindow}. """
1085 selected
= self
._listBox
.GetSelection()
1086 bk
= self
.GetParent()
1087 maxItems
= bk
.GetPageCount()
1089 if event
.GetDirection():
1092 if selected
== maxItems
- 1:
1095 itemToSelect
= selected
+ 1
1101 itemToSelect
= maxItems
- 1
1103 itemToSelect
= selected
- 1
1105 self
._listBox
.SetSelection(itemToSelect
)
1108 def PopulateListControl(self
, book
):
1109 """Populates the L{TabNavigatorWindow} listbox with a list of tabs."""
1111 selection
= book
.GetSelection()
1112 count
= book
.GetPageCount()
1114 self
._listBox
.Append(book
.GetPageText(selection
))
1115 self
._indexMap
.append(selection
)
1117 prevSel
= book
.GetPreviousSelection()
1119 if prevSel
!= wx
.NOT_FOUND
:
1121 # Insert the previous selection as second entry
1122 self
._listBox
.Append(book
.GetPageText(prevSel
))
1123 self
._indexMap
.append(prevSel
)
1125 for c
in xrange(count
):
1127 # Skip selected page
1131 # Skip previous selected page as well
1135 self
._listBox
.Append(book
.GetPageText(c
))
1136 self
._indexMap
.append(c
)
1138 # Select the next entry after the current selection
1139 self
._listBox
.SetSelection(0)
1140 dummy
= wx
.NavigationKeyEvent()
1141 dummy
.SetDirection(True)
1142 self
.OnNavigationKey(dummy
)
1145 def OnItemSelected(self
, event
):
1146 """Handles the wx.EVT_LISTBOX_DCLICK event for the wx.ListBox inside L{TabNavigatorWindow}. """
1151 def CloseDialog(self
):
1152 """Closes the L{TabNavigatorWindow} dialog, setting selection in L{FlatNotebook}."""
1154 bk
= self
.GetParent()
1155 self
._selectedItem
= self
._listBox
.GetSelection()
1156 iter = self
._indexMap
[self
._selectedItem
]
1157 bk
._pages
.FireEvent(iter)
1158 self
.EndModal(wx
.ID_OK
)
1161 def OnPanelPaint(self
, event
):
1162 """Handles the wx.EVT_PAINT event for L{TabNavigatorWindow} top panel. """
1164 dc
= wx
.PaintDC(self
._panel
)
1165 rect
= self
._panel
.GetClientRect()
1167 bmp
= wx
.EmptyBitmap(rect
.width
, rect
.height
)
1169 mem_dc
= wx
.MemoryDC()
1170 mem_dc
.SelectObject(bmp
)
1172 endColour
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)
1173 startColour
= LightColour(endColour
, 50)
1174 PaintStraightGradientBox(mem_dc
, rect
, startColour
, endColour
)
1176 # Draw the caption title and place the bitmap
1177 # get the bitmap optimal position, and draw it
1178 bmpPt
, txtPt
= wx
.Point(), wx
.Point()
1179 bmpPt
.y
= (rect
.height
- self
._bmp
.GetHeight())/2
1181 mem_dc
.DrawBitmap(self
._bmp
, bmpPt
.x
, bmpPt
.y
, True)
1183 # get the text position, and draw it
1184 font
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
1185 font
.SetWeight(wx
.BOLD
)
1186 mem_dc
.SetFont(font
)
1187 fontHeight
= mem_dc
.GetCharHeight()
1189 txtPt
.x
= bmpPt
.x
+ self
._bmp
.GetWidth() + 4
1190 txtPt
.y
= (rect
.height
- fontHeight
)/2
1191 mem_dc
.SetTextForeground(wx
.WHITE
)
1192 mem_dc
.DrawText("Opened tabs:", txtPt
.x
, txtPt
.y
)
1193 mem_dc
.SelectObject(wx
.NullBitmap
)
1195 dc
.DrawBitmap(bmp
, 0, 0)
1198 def OnPanelEraseBg(self
, event
):
1199 """Handles the wx.EVT_ERASE_BACKGROUND event for L{TabNavigatorWindow} top panel. """
1204 # ---------------------------------------------------------------------------- #
1206 # ---------------------------------------------------------------------------- #
1210 Parent class for the 4 renderers defined: I{Standard}, I{VC71}, I{Fancy}
1211 and I{VC8}. This class implements the common methods of all 4 renderers.
1212 @undocumented: _GetBitmap*
1216 """Default class constructor. """
1218 self
._tabXBgBmp
= wx
.EmptyBitmap(16, 16)
1219 self
._xBgBmp
= wx
.EmptyBitmap(16, 14)
1220 self
._leftBgBmp
= wx
.EmptyBitmap(16, 14)
1221 self
._rightBgBmp
= wx
.EmptyBitmap(16, 14)
1222 self
._tabHeight
= None
1225 def GetLeftButtonPos(self
, pageContainer
):
1226 """ Returns the left button position in the navigation area. """
1229 style
= pc
.GetParent().GetWindowStyleFlag()
1230 rect
= pc
.GetClientRect()
1231 clientWidth
= rect
.width
1233 if style
& FNB_NO_X_BUTTON
:
1234 return clientWidth
- 38
1236 return clientWidth
- 54
1240 def GetRightButtonPos(self
, pageContainer
):
1241 """ Returns the right button position in the navigation area. """
1244 style
= pc
.GetParent().GetWindowStyleFlag()
1245 rect
= pc
.GetClientRect()
1246 clientWidth
= rect
.width
1248 if style
& FNB_NO_X_BUTTON
:
1249 return clientWidth
- 22
1251 return clientWidth
- 38
1254 def GetDropArrowButtonPos(self
, pageContainer
):
1255 """ Returns the drop down button position in the navigation area. """
1257 return self
.GetRightButtonPos(pageContainer
)
1260 def GetXPos(self
, pageContainer
):
1261 """ Returns the 'X' button position in the navigation area. """
1264 style
= pc
.GetParent().GetWindowStyleFlag()
1265 rect
= pc
.GetClientRect()
1266 clientWidth
= rect
.width
1268 if style
& FNB_NO_X_BUTTON
:
1271 return clientWidth
- 22
1274 def GetButtonsAreaLength(self
, pageContainer
):
1275 """ Returns the navigation area width. """
1278 style
= pc
.GetParent().GetWindowStyleFlag()
1281 if style
& FNB_NO_NAV_BUTTONS
and style
& FNB_NO_X_BUTTON
and not style
& FNB_DROPDOWN_TABS_LIST
:
1285 elif style
& FNB_NO_NAV_BUTTONS
and not style
& FNB_NO_X_BUTTON
and not style
& FNB_DROPDOWN_TABS_LIST
:
1289 if not style
& FNB_NO_NAV_BUTTONS
and style
& FNB_NO_X_BUTTON
and not style
& FNB_DROPDOWN_TABS_LIST
:
1293 if style
& FNB_DROPDOWN_TABS_LIST
and not style
& FNB_NO_X_BUTTON
:
1297 if style
& FNB_DROPDOWN_TABS_LIST
and style
& FNB_NO_X_BUTTON
:
1304 def DrawLeftArrow(self
, pageContainer
, dc
):
1305 """ Draw the left navigation arrow. """
1309 style
= pc
.GetParent().GetWindowStyleFlag()
1310 if style
& FNB_NO_NAV_BUTTONS
:
1313 # Make sure that there are pages in the container
1314 if not pc
._pagesInfoVec
:
1317 # Set the bitmap according to the button status
1318 if pc
._nLeftButtonStatus
== FNB_BTN_HOVER
:
1319 arrowBmp
= wx
.BitmapFromXPMData(left_arrow_hilite_xpm
)
1320 elif pc
._nLeftButtonStatus
== FNB_BTN_PRESSED
:
1321 arrowBmp
= wx
.BitmapFromXPMData(left_arrow_pressed_xpm
)
1323 arrowBmp
= wx
.BitmapFromXPMData(left_arrow_xpm
)
1326 # Handle disabled arrow
1327 arrowBmp
= wx
.BitmapFromXPMData(left_arrow_disabled_xpm
)
1329 arrowBmp
.SetMask(wx
.Mask(arrowBmp
, MASK_COLOR
))
1332 posx
= self
.GetLeftButtonPos(pc
)
1333 dc
.DrawBitmap(self
._leftBgBmp
, posx
, 6)
1335 # Draw the new bitmap
1336 dc
.DrawBitmap(arrowBmp
, posx
, 6, True)
1339 def DrawRightArrow(self
, pageContainer
, dc
):
1340 """ Draw the right navigation arrow. """
1344 style
= pc
.GetParent().GetWindowStyleFlag()
1345 if style
& FNB_NO_NAV_BUTTONS
:
1348 # Make sure that there are pages in the container
1349 if not pc
._pagesInfoVec
:
1352 # Set the bitmap according to the button status
1353 if pc
._nRightButtonStatus
== FNB_BTN_HOVER
:
1354 arrowBmp
= wx
.BitmapFromXPMData(right_arrow_hilite_xpm
)
1355 elif pc
._nRightButtonStatus
== FNB_BTN_PRESSED
:
1356 arrowBmp
= wx
.BitmapFromXPMData(right_arrow_pressed_xpm
)
1358 arrowBmp
= wx
.BitmapFromXPMData(right_arrow_xpm
)
1360 # Check if the right most tab is visible, if it is
1361 # don't rotate right anymore
1362 if pc
._pagesInfoVec
[-1].GetPosition() != wx
.Point(-1, -1):
1363 arrowBmp
= wx
.BitmapFromXPMData(right_arrow_disabled_xpm
)
1365 arrowBmp
.SetMask(wx
.Mask(arrowBmp
, MASK_COLOR
))
1368 posx
= self
.GetRightButtonPos(pc
)
1369 dc
.DrawBitmap(self
._rightBgBmp
, posx
, 6)
1371 # Draw the new bitmap
1372 dc
.DrawBitmap(arrowBmp
, posx
, 6, True)
1375 def DrawDropDownArrow(self
, pageContainer
, dc
):
1376 """ Draws the drop-down arrow in the navigation area. """
1380 # Check if this style is enabled
1381 style
= pc
.GetParent().GetWindowStyleFlag()
1382 if not style
& FNB_DROPDOWN_TABS_LIST
:
1385 # Make sure that there are pages in the container
1386 if not pc
._pagesInfoVec
:
1389 if pc
._nArrowDownButtonStatus
== FNB_BTN_HOVER
:
1390 downBmp
= wx
.BitmapFromXPMData(down_arrow_hilite_xpm
)
1391 elif pc
._nArrowDownButtonStatus
== FNB_BTN_PRESSED
:
1392 downBmp
= wx
.BitmapFromXPMData(down_arrow_pressed_xpm
)
1394 downBmp
= wx
.BitmapFromXPMData(down_arrow_xpm
)
1396 downBmp
.SetMask(wx
.Mask(downBmp
, MASK_COLOR
))
1399 posx
= self
.GetDropArrowButtonPos(pc
)
1400 dc
.DrawBitmap(self
._xBgBmp
, posx
, 6)
1402 # Draw the new bitmap
1403 dc
.DrawBitmap(downBmp
, posx
, 6, True)
1406 def DrawX(self
, pageContainer
, dc
):
1407 """ Draw the 'X' navigation button in the navigation area. """
1411 # Check if this style is enabled
1412 style
= pc
.GetParent().GetWindowStyleFlag()
1413 if style
& FNB_NO_X_BUTTON
:
1416 # Make sure that there are pages in the container
1417 if not pc
._pagesInfoVec
:
1420 # Set the bitmap according to the button status
1421 if pc
._nXButtonStatus
== FNB_BTN_HOVER
:
1422 xbmp
= wx
.BitmapFromXPMData(x_button_hilite_xpm
)
1423 elif pc
._nXButtonStatus
== FNB_BTN_PRESSED
:
1424 xbmp
= wx
.BitmapFromXPMData(x_button_pressed_xpm
)
1426 xbmp
= wx
.BitmapFromXPMData(x_button_xpm
)
1428 xbmp
.SetMask(wx
.Mask(xbmp
, MASK_COLOR
))
1431 posx
= self
.GetXPos(pc
)
1432 dc
.DrawBitmap(self
._xBgBmp
, posx
, 6)
1434 # Draw the new bitmap
1435 dc
.DrawBitmap(xbmp
, posx
, 6, True)
1438 def DrawTabX(self
, pageContainer
, dc
, rect
, tabIdx
, btnStatus
):
1439 """ Draws the 'X' in the selected tab. """
1442 if not pc
.HasFlag(FNB_X_ON_TAB
):
1445 # We draw the 'x' on the active tab only
1446 if tabIdx
!= pc
.GetSelection() or tabIdx
< 0:
1449 # Set the bitmap according to the button status
1451 if btnStatus
== FNB_BTN_HOVER
:
1452 xBmp
= wx
.BitmapFromXPMData(x_button_hilite_xpm
)
1453 elif btnStatus
== FNB_BTN_PRESSED
:
1454 xBmp
= wx
.BitmapFromXPMData(x_button_pressed_xpm
)
1456 xBmp
= wx
.BitmapFromXPMData(x_button_xpm
)
1459 xBmp
.SetMask(wx
.Mask(xBmp
, MASK_COLOR
))
1462 dc
.DrawBitmap(self
._tabXBgBmp
, rect
.x
, rect
.y
)
1464 # Draw the new bitmap
1465 dc
.DrawBitmap(xBmp
, rect
.x
, rect
.y
, True)
1468 rr
= wx
.Rect(rect
.x
, rect
.y
, 14, 13)
1469 pc
._pagesInfoVec
[tabIdx
].SetXRect(rr
)
1472 def _GetBitmap(self
, dc
, rect
, bmp
):
1474 mem_dc
= wx
.MemoryDC()
1475 mem_dc
.SelectObject(bmp
)
1476 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
1477 mem_dc
.SelectObject(wx
.NullBitmap
)
1481 def DrawTabsLine(self
, pageContainer
, dc
):
1482 """ Draws a line over the tabs. """
1486 clntRect
= pc
.GetClientRect()
1487 clientRect3
= wx
.Rect(0, 0, clntRect
.width
, clntRect
.height
)
1489 if pc
.HasFlag(FNB_BOTTOM
):
1491 clientRect
= wx
.Rect(0, 2, clntRect
.width
, clntRect
.height
- 2)
1492 clientRect2
= wx
.Rect(0, 1, clntRect
.width
, clntRect
.height
- 1)
1496 clientRect
= wx
.Rect(0, 0, clntRect
.width
, clntRect
.height
- 2)
1497 clientRect2
= wx
.Rect(0, 0, clntRect
.width
, clntRect
.height
- 1)
1499 dc
.SetBrush(wx
.TRANSPARENT_BRUSH
)
1500 dc
.SetPen(wx
.Pen(pc
.GetSingleLineBorderColour()))
1501 dc
.DrawRectangleRect(clientRect2
)
1502 dc
.DrawRectangleRect(clientRect3
)
1504 dc
.SetPen(wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)))
1505 dc
.DrawRectangleRect(clientRect
)
1507 if not pc
.HasFlag(FNB_TABS_BORDER_SIMPLE
):
1509 dc
.SetPen(wx
.Pen((pc
.HasFlag(FNB_VC71
) and [wx
.Colour(247, 243, 233)] or [pc
._tabAreaColor
])[0]))
1510 dc
.DrawLine(0, 0, 0, clientRect
.height
+1)
1512 if pc
.HasFlag(FNB_BOTTOM
):
1514 dc
.DrawLine(0, clientRect
.height
+1, clientRect
.width
, clientRect
.height
+1)
1518 dc
.DrawLine(0, 0, clientRect
.width
, 0)
1520 dc
.DrawLine(clientRect
.width
- 1, 0, clientRect
.width
- 1, clientRect
.height
+1)
1523 def CalcTabWidth(self
, pageContainer
, tabIdx
, tabHeight
):
1524 """ Calculates the width of the input tab. """
1528 dc
.SelectObject(wx
.EmptyBitmap(1,1))
1530 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
1531 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
1533 if pc
.IsDefaultTabs():
1534 shapePoints
= int(tabHeight
*math
.tan(float(pc
._pagesInfoVec
[tabIdx
].GetTabAngle())/180.0*math
.pi
))
1536 # Calculate the text length using the bold font, so when selecting a tab
1537 # its width will not change
1538 dc
.SetFont(boldFont
)
1539 width
, pom
= dc
.GetTextExtent(pc
.GetPageText(tabIdx
))
1541 # Set a minimum size to a tab
1545 tabWidth
= 2*pc
._pParent
.GetPadding() + width
1547 # Style to add a small 'x' button on the top right
1549 if pc
.HasFlag(FNB_X_ON_TAB
) and tabIdx
== pc
.GetSelection():
1550 # The xpm image that contains the 'x' button is 9 pixels
1552 if pc
.HasFlag(FNB_VC8
):
1555 tabWidth
+= pc
._pParent
.GetPadding() + spacer
1557 if pc
.IsDefaultTabs():
1559 tabWidth
+= 2*shapePoints
1561 hasImage
= pc
._ImageList
!= None and pc
._pagesInfoVec
[tabIdx
].GetImageIndex() != -1
1563 # For VC71 style, we only add the icon size (16 pixels)
1566 if not pc
.IsDefaultTabs():
1567 tabWidth
+= 16 + pc
._pParent
.GetPadding()
1570 tabWidth
+= 16 + pc
._pParent
.GetPadding() + shapePoints
/2
1575 def CalcTabHeight(self
, pageContainer
):
1576 """ Calculates the height of the input tab. """
1579 return self
._tabHeight
1583 dc
.SelectObject(wx
.EmptyBitmap(1,1))
1585 # For GTK it seems that we must do this steps in order
1586 # for the tabs will get the proper height on initialization
1587 # on MSW, preforming these steps yields wierd results
1588 normalFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
1589 boldFont
= normalFont
1591 if "__WXGTK__" in wx
.PlatformInfo
:
1592 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
1593 dc
.SetFont(boldFont
)
1595 height
= dc
.GetCharHeight()
1597 tabHeight
= height
+ FNB_HEIGHT_SPACER
# We use 8 pixels as padding
1598 if "__WXGTK__" in wx
.PlatformInfo
:
1599 # On GTK the tabs are should be larger
1602 self
._tabHeight
= tabHeight
1607 def DrawTabs(self
, pageContainer
, dc
):
1608 """ Actually draws the tabs in L{FlatNotebook}."""
1611 if "__WXMAC__" in wx
.PlatformInfo
:
1612 # Works well on MSW & GTK, however this lines should be skipped on MAC
1613 if not pc
._pagesInfoVec
or pc
._nFrom
>= len(pc
._pagesInfoVec
):
1617 # Get the text hight
1618 tabHeight
= self
.CalcTabHeight(pageContainer
)
1619 style
= pc
.GetParent().GetWindowStyleFlag()
1621 # Calculate the number of rows required for drawing the tabs
1622 rect
= pc
.GetClientRect()
1623 clientWidth
= rect
.width
1625 # Set the maximum client size
1626 pc
.SetSizeHints(self
.GetButtonsAreaLength(pc
), tabHeight
)
1627 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
1629 if style
& FNB_VC71
:
1630 backBrush
= wx
.Brush(wx
.Colour(247, 243, 233))
1632 backBrush
= wx
.Brush(pc
._tabAreaColor
)
1634 noselBrush
= wx
.Brush(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNFACE
))
1635 selBrush
= wx
.Brush(pc
._activeTabColor
)
1640 dc
.SetTextBackground((style
& FNB_VC71
and [wx
.Colour(247, 243, 233)] or [pc
.GetBackgroundColour()])[0])
1641 dc
.SetTextForeground(pc
._activeTextColor
)
1642 dc
.SetBrush(backBrush
)
1644 # If border style is set, set the pen to be border pen
1645 if pc
.HasFlag(FNB_TABS_BORDER_SIMPLE
):
1646 dc
.SetPen(borderPen
)
1648 colr
= (pc
.HasFlag(FNB_VC71
) and [wx
.Colour(247, 243, 233)] or [pc
.GetBackgroundColour()])[0]
1649 dc
.SetPen(wx
.Pen(colr
))
1651 dc
.DrawRectangle(0, 0, size
.x
, size
.y
)
1653 # Take 3 bitmaps for the background for the buttons
1655 mem_dc
= wx
.MemoryDC()
1656 #---------------------------------------
1658 #---------------------------------------
1659 rect
= wx
.Rect(self
.GetXPos(pc
), 6, 16, 14)
1660 mem_dc
.SelectObject(self
._xBgBmp
)
1661 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
1662 mem_dc
.SelectObject(wx
.NullBitmap
)
1664 #---------------------------------------
1666 #---------------------------------------
1667 rect
= wx
.Rect(self
.GetRightButtonPos(pc
), 6, 16, 14)
1668 mem_dc
.SelectObject(self
._rightBgBmp
)
1669 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
1670 mem_dc
.SelectObject(wx
.NullBitmap
)
1672 #---------------------------------------
1674 #---------------------------------------
1675 rect
= wx
.Rect(self
.GetLeftButtonPos(pc
), 6, 16, 14)
1676 mem_dc
.SelectObject(self
._leftBgBmp
)
1677 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
1678 mem_dc
.SelectObject(wx
.NullBitmap
)
1680 # We always draw the bottom/upper line of the tabs
1681 # regradless the style
1682 dc
.SetPen(borderPen
)
1683 self
.DrawTabsLine(pc
, dc
)
1686 dc
.SetPen(borderPen
)
1688 if pc
.HasFlag(FNB_VC71
):
1690 greyLineYVal
= (pc
.HasFlag(FNB_BOTTOM
) and [0] or [size
.y
- 2])[0]
1691 whiteLineYVal
= (pc
.HasFlag(FNB_BOTTOM
) and [3] or [size
.y
- 3])[0]
1693 pen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
))
1696 # Draw thik grey line between the windows area and
1698 for num
in xrange(3):
1699 dc
.DrawLine(0, greyLineYVal
+ num
, size
.x
, greyLineYVal
+ num
)
1701 wbPen
= (pc
.HasFlag(FNB_BOTTOM
) and [wx
.BLACK_PEN
] or [wx
.WHITE_PEN
])[0]
1703 dc
.DrawLine(1, whiteLineYVal
, size
.x
- 1, whiteLineYVal
)
1706 dc
.SetPen(borderPen
)
1709 normalFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
1710 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
1711 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
1712 dc
.SetFont(boldFont
)
1714 posx
= pc
._pParent
.GetPadding()
1716 # Update all the tabs from 0 to 'pc._nFrom' to be non visible
1717 for i
in xrange(pc
._nFrom
):
1719 pc
._pagesInfoVec
[i
].SetPosition(wx
.Point(-1, -1))
1720 pc
._pagesInfoVec
[i
].GetRegion().Clear()
1724 #----------------------------------------------------------
1725 # Go over and draw the visible tabs
1726 #----------------------------------------------------------
1727 for i
in xrange(pc
._nFrom
, len(pc
._pagesInfoVec
)):
1729 dc
.SetPen(borderPen
)
1730 dc
.SetBrush((i
==pc
.GetSelection() and [selBrush
] or [noselBrush
])[0])
1732 # Now set the font to the correct font
1733 dc
.SetFont((i
==pc
.GetSelection() and [boldFont
] or [normalFont
])[0])
1735 # Add the padding to the tab width
1737 # +-----------------------------------------------------------+
1738 # | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING |
1739 # +-----------------------------------------------------------+
1740 tabWidth
= self
.CalcTabWidth(pageContainer
, i
, tabHeight
)
1742 # Check if we can draw more
1743 if posx
+ tabWidth
+ self
.GetButtonsAreaLength(pc
) >= clientWidth
:
1748 # By default we clean the tab region
1749 pc
._pagesInfoVec
[i
].GetRegion().Clear()
1751 # Clean the 'x' buttn on the tab.
1752 # A 'Clean' rectangle, is a rectangle with width or height
1753 # with values lower than or equal to 0
1754 pc
._pagesInfoVec
[i
].GetXRect().SetSize(wx
.Size(-1, -1))
1756 # Draw the tab (border, text, image & 'x' on tab)
1757 self
.DrawTab(pc
, dc
, posx
, i
, tabWidth
, tabHeight
, pc
._nTabXButtonStatus
)
1759 # Restore the text forground
1760 dc
.SetTextForeground(pc
._activeTextColor
)
1762 # Update the tab position & size
1763 posy
= (pc
.HasFlag(FNB_BOTTOM
) and [0] or [VERTICAL_BORDER_PADDING
])[0]
1765 pc
._pagesInfoVec
[i
].SetPosition(wx
.Point(posx
, posy
))
1766 pc
._pagesInfoVec
[i
].SetSize(wx
.Size(tabWidth
, tabHeight
))
1769 # Update all tabs that can not fit into the screen as non-visible
1770 for i
in xrange(count
, len(pc
._pagesInfoVec
)):
1771 pc
._pagesInfoVec
[i
].SetPosition(wx
.Point(-1, -1))
1772 pc
._pagesInfoVec
[i
].GetRegion().Clear()
1774 # Draw the left/right/close buttons
1776 self
.DrawLeftArrow(pc
, dc
)
1777 self
.DrawRightArrow(pc
, dc
)
1779 self
.DrawDropDownArrow(pc
, dc
)
1782 def DrawDragHint(self
, pc
, tabIdx
):
1784 Draws tab drag hint, the default implementation is to do nothing.
1785 You can override this function to provide a nice feedback to user.
1791 # ---------------------------------------------------------------------------- #
1792 # Class FNBRendererMgr
1793 # A manager that handles all the renderers defined below and calls the
1794 # appropriate one when drawing is needed
1795 # ---------------------------------------------------------------------------- #
1797 class FNBRendererMgr
:
1799 This class represents a manager that handles all the 4 renderers defined
1800 and calls the appropriate one when drawing is needed.
1804 """ Default class constructor. """
1806 # register renderers
1808 self
._renderers
= {}
1809 self
._renderers
.update({-1: FNBRendererDefault()}
)
1810 self
._renderers
.update({FNB_VC71: FNBRendererVC71()}
)
1811 self
._renderers
.update({FNB_FANCY_TABS: FNBRendererFancy()}
)
1812 self
._renderers
.update({FNB_VC8: FNBRendererVC8()}
)
1815 def GetRenderer(self
, style
):
1816 """ Returns the current renderer based on the style selected. """
1818 # since we dont have a style for default tabs, we
1819 # test for all others - FIXME: add style for default tabs
1820 if not style
& FNB_VC71
and not style
& FNB_VC8
and not style
& FNB_FANCY_TABS
:
1821 return self
._renderers
[-1]
1823 if style
& FNB_VC71
:
1824 return self
._renderers
[FNB_VC71
]
1826 if style
& FNB_FANCY_TABS
:
1827 return self
._renderers
[FNB_FANCY_TABS
]
1830 return self
._renderers
[FNB_VC8
]
1832 # the default is to return the default renderer
1833 return self
._renderers
[-1]
1836 #------------------------------------------
1838 #------------------------------------------
1840 class FNBRendererDefault(FNBRenderer
):
1842 This class handles the drawing of tabs using the I{Standard} renderer.
1846 """ Default class constructor. """
1848 FNBRenderer
.__init
__(self
)
1851 def DrawTab(self
, pageContainer
, dc
, posx
, tabIdx
, tabWidth
, tabHeight
, btnStatus
):
1852 """ Draws a tab using the I{Standard} style. """
1855 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
1858 tabPoints
= [wx
.Point() for ii
in xrange(7)]
1859 tabPoints
[0].x
= posx
1860 tabPoints
[0].y
= (pc
.HasFlag(FNB_BOTTOM
) and [2] or [tabHeight
- 2])[0]
1862 tabPoints
[1].x
= int(posx
+(tabHeight
-2)*math
.tan(float(pc
._pagesInfoVec
[tabIdx
].GetTabAngle())/180.0*math
.pi
))
1863 tabPoints
[1].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- (VERTICAL_BORDER_PADDING
+2)] or [(VERTICAL_BORDER_PADDING
+2)])[0]
1865 tabPoints
[2].x
= tabPoints
[1].x
+2
1866 tabPoints
[2].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- VERTICAL_BORDER_PADDING
] or [VERTICAL_BORDER_PADDING
])[0]
1868 tabPoints
[3].x
= int(posx
+tabWidth
-(tabHeight
-2)*math
.tan(float(pc
._pagesInfoVec
[tabIdx
].GetTabAngle())/180.0*math
.pi
))-2
1869 tabPoints
[3].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- VERTICAL_BORDER_PADDING
] or [VERTICAL_BORDER_PADDING
])[0]
1871 tabPoints
[4].x
= tabPoints
[3].x
+2
1872 tabPoints
[4].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- (VERTICAL_BORDER_PADDING
+2)] or [(VERTICAL_BORDER_PADDING
+2)])[0]
1874 tabPoints
[5].x
= int(tabPoints
[4].x
+(tabHeight
-2)*math
.tan(float(pc
._pagesInfoVec
[tabIdx
].GetTabAngle())/180.0*math
.pi
))
1875 tabPoints
[5].y
= (pc
.HasFlag(FNB_BOTTOM
) and [2] or [tabHeight
- 2])[0]
1877 tabPoints
[6].x
= tabPoints
[0].x
1878 tabPoints
[6].y
= tabPoints
[0].y
1880 if tabIdx
== pc
.GetSelection():
1882 # Draw the tab as rounded rectangle
1883 dc
.DrawPolygon(tabPoints
)
1887 if tabIdx
!= pc
.GetSelection() - 1:
1889 # Draw a vertical line to the right of the text
1890 pt1x
= tabPoints
[5].x
1891 pt1y
= (pc
.HasFlag(FNB_BOTTOM
) and [4] or [tabHeight
- 6])[0]
1892 pt2x
= tabPoints
[5].x
1893 pt2y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- 4] or [4])[0]
1894 dc
.DrawLine(pt1x
, pt1y
, pt2x
, pt2y
)
1896 if tabIdx
== pc
.GetSelection():
1898 savePen
= dc
.GetPen()
1899 whitePen
= wx
.Pen(wx
.WHITE
)
1900 whitePen
.SetWidth(1)
1903 secPt
= wx
.Point(tabPoints
[5].x
+ 1, tabPoints
[5].y
)
1904 dc
.DrawLine(tabPoints
[0].x
, tabPoints
[0].y
, secPt
.x
, secPt
.y
)
1909 # -----------------------------------
1910 # Text and image drawing
1911 # -----------------------------------
1913 # Text drawing offset from the left border of the
1916 # The width of the images are 16 pixels
1917 padding
= pc
.GetParent().GetPadding()
1918 shapePoints
= int(tabHeight
*math
.tan(float(pc
._pagesInfoVec
[tabIdx
].GetTabAngle())/180.0*math
.pi
))
1919 hasImage
= pc
._pagesInfoVec
[tabIdx
].GetImageIndex() != -1
1920 imageYCoord
= (pc
.HasFlag(FNB_BOTTOM
) and [6] or [8])[0]
1923 textOffset
= 2*pc
._pParent
._nPadding
+ 16 + shapePoints
/2
1925 textOffset
= pc
._pParent
._nPadding
+ shapePoints
/2
1929 if tabIdx
!= pc
.GetSelection():
1931 # Set the text background to be like the vertical lines
1932 dc
.SetTextForeground(pc
._pParent
.GetNonActiveTabTextColour())
1936 imageXOffset
= textOffset
- 16 - padding
1937 pc
._ImageList
.Draw(pc
._pagesInfoVec
[tabIdx
].GetImageIndex(), dc
,
1938 posx
+ imageXOffset
, imageYCoord
,
1939 wx
.IMAGELIST_DRAW_TRANSPARENT
, True)
1941 dc
.DrawText(pc
.GetPageText(tabIdx
), posx
+ textOffset
, imageYCoord
)
1943 # draw 'x' on tab (if enabled)
1944 if pc
.HasFlag(FNB_X_ON_TAB
) and tabIdx
== pc
.GetSelection():
1946 textWidth
, textHeight
= dc
.GetTextExtent(pc
.GetPageText(tabIdx
))
1947 tabCloseButtonXCoord
= posx
+ textOffset
+ textWidth
+ 1
1949 # take a bitmap from the position of the 'x' button (the x on tab button)
1950 # this bitmap will be used later to delete old buttons
1951 tabCloseButtonYCoord
= imageYCoord
1952 x_rect
= wx
.Rect(tabCloseButtonXCoord
, tabCloseButtonYCoord
, 16, 16)
1953 self
._tabXBgBmp
= self
._GetBitmap
(dc
, x_rect
, self
._tabXBgBmp
)
1956 self
.DrawTabX(pc
, dc
, x_rect
, tabIdx
, btnStatus
)
1959 #------------------------------------------------------------------
1961 #------------------------------------------------------------------
1963 class FNBRendererVC71(FNBRenderer
):
1965 This class handles the drawing of tabs using the I{VC71} renderer.
1969 """ Default class constructor. """
1971 FNBRenderer
.__init
__(self
)
1974 def DrawTab(self
, pageContainer
, dc
, posx
, tabIdx
, tabWidth
, tabHeight
, btnStatus
):
1975 """ Draws a tab using the I{VC71} style. """
1977 # Visual studio 7.1 style
1978 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
1981 dc
.SetPen((tabIdx
== pc
.GetSelection() and [wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
))] or [borderPen
])[0])
1982 dc
.SetBrush((tabIdx
== pc
.GetSelection() and [wx
.Brush(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
))] or [wx
.Brush(wx
.Colour(247, 243, 233))])[0])
1984 if tabIdx
== pc
.GetSelection():
1986 posy
= (pc
.HasFlag(FNB_BOTTOM
) and [0] or [VERTICAL_BORDER_PADDING
])[0]
1987 tabH
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- 5] or [tabHeight
- 3])[0]
1988 dc
.DrawRectangle(posx
, posy
, tabWidth
, tabH
)
1990 # Draw a black line on the left side of the
1992 dc
.SetPen(wx
.BLACK_PEN
)
1994 blackLineY1
= VERTICAL_BORDER_PADDING
1996 dc
.DrawLine(posx
+ tabWidth
, blackLineY1
, posx
+ tabWidth
, blackLineY2
)
1998 # To give the tab more 3D look we do the following
1999 # Incase the tab is on top,
2000 # Draw a thik white line on topof the rectangle
2001 # Otherwise, draw a thin (1 pixel) black line at the bottom
2003 pen
= wx
.Pen((pc
.HasFlag(FNB_BOTTOM
) and [wx
.BLACK
] or [wx
.WHITE
])[0])
2005 whiteLinePosY
= (pc
.HasFlag(FNB_BOTTOM
) and [blackLineY2
] or [VERTICAL_BORDER_PADDING
])[0]
2006 dc
.DrawLine(posx
, whiteLinePosY
, posx
+ tabWidth
+ 1, whiteLinePosY
)
2008 # Draw a white vertical line to the left of the tab
2009 dc
.SetPen(wx
.WHITE_PEN
)
2010 if not pc
.HasFlag(FNB_BOTTOM
):
2013 dc
.DrawLine(posx
, blackLineY1
, posx
, blackLineY2
)
2017 # We dont draw a rectangle for non selected tabs, but only
2018 # vertical line on the left
2020 blackLineY1
= (pc
.HasFlag(FNB_BOTTOM
) and [VERTICAL_BORDER_PADDING
+ 2] or [VERTICAL_BORDER_PADDING
+ 1])[0]
2021 blackLineY2
= pc
.GetSize().y
- 5
2022 dc
.DrawLine(posx
+ tabWidth
, blackLineY1
, posx
+ tabWidth
, blackLineY2
)
2024 # -----------------------------------
2025 # Text and image drawing
2026 # -----------------------------------
2028 # Text drawing offset from the left border of the
2031 # The width of the images are 16 pixels
2032 padding
= pc
.GetParent().GetPadding()
2033 hasImage
= pc
._pagesInfoVec
[tabIdx
].GetImageIndex() != -1
2034 imageYCoord
= (pc
.HasFlag(FNB_BOTTOM
) and [5] or [8])[0]
2037 textOffset
= 2*pc
._pParent
._nPadding
+ 16
2039 textOffset
= pc
._pParent
._nPadding
2041 if tabIdx
!= pc
.GetSelection():
2043 # Set the text background to be like the vertical lines
2044 dc
.SetTextForeground(pc
._pParent
.GetNonActiveTabTextColour())
2048 imageXOffset
= textOffset
- 16 - padding
2049 pc
._ImageList
.Draw(pc
._pagesInfoVec
[tabIdx
].GetImageIndex(), dc
,
2050 posx
+ imageXOffset
, imageYCoord
,
2051 wx
.IMAGELIST_DRAW_TRANSPARENT
, True)
2053 dc
.DrawText(pc
.GetPageText(tabIdx
), posx
+ textOffset
, imageYCoord
)
2055 # draw 'x' on tab (if enabled)
2056 if pc
.HasFlag(FNB_X_ON_TAB
) and tabIdx
== pc
.GetSelection():
2058 textWidth
, textHeight
= dc
.GetTextExtent(pc
.GetPageText(tabIdx
))
2059 tabCloseButtonXCoord
= posx
+ textOffset
+ textWidth
+ 1
2061 # take a bitmap from the position of the 'x' button (the x on tab button)
2062 # this bitmap will be used later to delete old buttons
2063 tabCloseButtonYCoord
= imageYCoord
2064 x_rect
= wx
.Rect(tabCloseButtonXCoord
, tabCloseButtonYCoord
, 16, 16)
2065 self
._tabXBgBmp
= self
._GetBitmap
(dc
, x_rect
, self
._tabXBgBmp
)
2068 self
.DrawTabX(pc
, dc
, x_rect
, tabIdx
, btnStatus
)
2071 #------------------------------------------------------------------
2073 #------------------------------------------------------------------
2075 class FNBRendererFancy(FNBRenderer
):
2077 This class handles the drawing of tabs using the I{Fancy} renderer.
2081 """ Default class constructor. """
2083 FNBRenderer
.__init
__(self
)
2086 def DrawTab(self
, pageContainer
, dc
, posx
, tabIdx
, tabWidth
, tabHeight
, btnStatus
):
2087 """ Draws a tab using the I{Fancy} style, similar to VC71 but with gradients. """
2089 # Fancy tabs - like with VC71 but with the following differences:
2090 # - The Selected tab is colored with gradient color
2091 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
2094 pen
= (tabIdx
== pc
.GetSelection() and [wx
.Pen(pc
._pParent
.GetBorderColour())] or [wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
))])[0]
2096 if tabIdx
== pc
.GetSelection():
2098 posy
= (pc
.HasFlag(FNB_BOTTOM
) and [2] or [VERTICAL_BORDER_PADDING
])[0]
2101 rect
= wx
.Rect(posx
, posy
, tabWidth
, th
)
2103 col2
= (pc
.HasFlag(FNB_BOTTOM
) and [pc
._pParent
.GetGradientColourTo()] or [pc
._pParent
.GetGradientColourFrom()])[0]
2104 col1
= (pc
.HasFlag(FNB_BOTTOM
) and [pc
._pParent
.GetGradientColourFrom()] or [pc
._pParent
.GetGradientColourTo()])[0]
2106 PaintStraightGradientBox(dc
, rect
, col1
, col2
)
2107 dc
.SetBrush(wx
.TRANSPARENT_BRUSH
)
2109 dc
.DrawRectangleRect(rect
)
2111 # erase the bottom/top line of the rectangle
2112 dc
.SetPen(wx
.Pen(pc
._pParent
.GetGradientColourFrom()))
2113 if pc
.HasFlag(FNB_BOTTOM
):
2114 dc
.DrawLine(rect
.x
, 2, rect
.x
+ rect
.width
, 2)
2116 dc
.DrawLine(rect
.x
, rect
.y
+ rect
.height
- 1, rect
.x
+ rect
.width
, rect
.y
+ rect
.height
- 1)
2120 # We dont draw a rectangle for non selected tabs, but only
2121 # vertical line on the left
2122 dc
.SetPen(borderPen
)
2123 dc
.DrawLine(posx
+ tabWidth
, VERTICAL_BORDER_PADDING
+ 3, posx
+ tabWidth
, tabHeight
- 4)
2126 # -----------------------------------
2127 # Text and image drawing
2128 # -----------------------------------
2130 # Text drawing offset from the left border of the
2133 # The width of the images are 16 pixels
2134 padding
= pc
.GetParent().GetPadding()
2135 hasImage
= pc
._pagesInfoVec
[tabIdx
].GetImageIndex() != -1
2136 imageYCoord
= (pc
.HasFlag(FNB_BOTTOM
) and [6] or [8])[0]
2139 textOffset
= 2*pc
._pParent
._nPadding
+ 16
2141 textOffset
= pc
._pParent
._nPadding
2145 if tabIdx
!= pc
.GetSelection():
2147 # Set the text background to be like the vertical lines
2148 dc
.SetTextForeground(pc
._pParent
.GetNonActiveTabTextColour())
2152 imageXOffset
= textOffset
- 16 - padding
2153 pc
._ImageList
.Draw(pc
._pagesInfoVec
[tabIdx
].GetImageIndex(), dc
,
2154 posx
+ imageXOffset
, imageYCoord
,
2155 wx
.IMAGELIST_DRAW_TRANSPARENT
, True)
2157 dc
.DrawText(pc
.GetPageText(tabIdx
), posx
+ textOffset
, imageYCoord
)
2159 # draw 'x' on tab (if enabled)
2160 if pc
.HasFlag(FNB_X_ON_TAB
) and tabIdx
== pc
.GetSelection():
2162 textWidth
, textHeight
= dc
.GetTextExtent(pc
.GetPageText(tabIdx
))
2163 tabCloseButtonXCoord
= posx
+ textOffset
+ textWidth
+ 1
2165 # take a bitmap from the position of the 'x' button (the x on tab button)
2166 # this bitmap will be used later to delete old buttons
2167 tabCloseButtonYCoord
= imageYCoord
2168 x_rect
= wx
.Rect(tabCloseButtonXCoord
, tabCloseButtonYCoord
, 16, 16)
2169 self
._tabXBgBmp
= self
._GetBitmap
(dc
, x_rect
, self
._tabXBgBmp
)
2172 self
.DrawTabX(pc
, dc
, x_rect
, tabIdx
, btnStatus
)
2175 #------------------------------------------------------------------
2176 # Visual studio 2005 (VS8)
2177 #------------------------------------------------------------------
2178 class FNBRendererVC8(FNBRenderer
):
2180 This class handles the drawing of tabs using the I{VC8} renderer.
2184 """ Default class constructor. """
2186 FNBRenderer
.__init
__(self
)
2191 def DrawTabs(self
, pageContainer
, dc
):
2192 """ Draws all the tabs using VC8 style. Overloads The DrawTabs method in parent class. """
2196 if "__WXMAC__" in wx
.PlatformInfo
:
2197 # Works well on MSW & GTK, however this lines should be skipped on MAC
2198 if not pc
._pagesInfoVec
or pc
._nFrom
>= len(pc
._pagesInfoVec
):
2202 # Get the text hight
2203 tabHeight
= self
.CalcTabHeight(pageContainer
)
2205 # Set the font for measuring the tab height
2206 normalFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
2207 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
2208 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
2210 # Calculate the number of rows required for drawing the tabs
2211 rect
= pc
.GetClientRect()
2213 # Set the maximum client size
2214 pc
.SetSizeHints(self
.GetButtonsAreaLength(pc
), tabHeight
)
2215 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
2218 backBrush
= wx
.Brush(pc
._tabAreaColor
)
2219 noselBrush
= wx
.Brush(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNFACE
))
2220 selBrush
= wx
.Brush(pc
._activeTabColor
)
2224 dc
.SetTextBackground(pc
.GetBackgroundColour())
2225 dc
.SetTextForeground(pc
._activeTextColor
)
2227 # If border style is set, set the pen to be border pen
2228 if pc
.HasFlag(FNB_TABS_BORDER_SIMPLE
):
2229 dc
.SetPen(borderPen
)
2231 dc
.SetPen(wx
.TRANSPARENT_PEN
)
2233 lightFactor
= (pc
.HasFlag(FNB_BACKGROUND_GRADIENT
) and [70] or [0])[0]
2235 # For VC8 style, we color the tab area in gradient coloring
2236 lightcolour
= LightColour(pc
._tabAreaColor
, lightFactor
)
2237 PaintStraightGradientBox(dc
, pc
.GetClientRect(), pc
._tabAreaColor
, lightcolour
)
2239 dc
.SetBrush(wx
.TRANSPARENT_BRUSH
)
2240 dc
.DrawRectangle(0, 0, size
.x
, size
.y
)
2242 # Take 3 bitmaps for the background for the buttons
2244 mem_dc
= wx
.MemoryDC()
2245 #---------------------------------------
2247 #---------------------------------------
2248 rect
= wx
.Rect(self
.GetXPos(pc
), 6, 16, 14)
2249 mem_dc
.SelectObject(self
._xBgBmp
)
2250 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
2251 mem_dc
.SelectObject(wx
.NullBitmap
)
2253 #---------------------------------------
2255 #---------------------------------------
2256 rect
= wx
.Rect(self
.GetRightButtonPos(pc
), 6, 16, 14)
2257 mem_dc
.SelectObject(self
._rightBgBmp
)
2258 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
2259 mem_dc
.SelectObject(wx
.NullBitmap
)
2261 #---------------------------------------
2263 #---------------------------------------
2264 rect
= wx
.Rect(self
.GetLeftButtonPos(pc
), 6, 16, 14)
2265 mem_dc
.SelectObject(self
._leftBgBmp
)
2266 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
2267 mem_dc
.SelectObject(wx
.NullBitmap
)
2269 # We always draw the bottom/upper line of the tabs
2270 # regradless the style
2271 dc
.SetPen(borderPen
)
2272 self
.DrawTabsLine(pc
, dc
)
2275 dc
.SetPen(borderPen
)
2278 dc
.SetFont(boldFont
)
2280 # Update all the tabs from 0 to 'pc.self._nFrom' to be non visible
2281 for i
in xrange(pc
._nFrom
):
2283 pc
._pagesInfoVec
[i
].SetPosition(wx
.Point(-1, -1))
2284 pc
._pagesInfoVec
[i
].GetRegion().Clear()
2286 # Draw the visible tabs, in VC8 style, we draw them from right to left
2287 vTabsInfo
= self
.NumberTabsCanFit(pc
)
2293 for cur
in xrange(len(vTabsInfo
)-1, -1, -1):
2295 # 'i' points to the index of the currently drawn tab
2296 # in pc.GetPageInfoVector() vector
2298 dc
.SetPen(borderPen
)
2299 dc
.SetBrush((i
==pc
.GetSelection() and [selBrush
] or [noselBrush
])[0])
2301 # Now set the font to the correct font
2302 dc
.SetFont((i
==pc
.GetSelection() and [boldFont
] or [normalFont
])[0])
2304 # Add the padding to the tab width
2306 # +-----------------------------------------------------------+
2307 # | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING |
2308 # +-----------------------------------------------------------+
2310 tabWidth
= self
.CalcTabWidth(pageContainer
, i
, tabHeight
)
2311 posx
= vTabsInfo
[cur
].x
2313 # By default we clean the tab region
2314 # incase we use the VC8 style which requires
2315 # the region, it will be filled by the function
2317 pc
._pagesInfoVec
[i
].GetRegion().Clear()
2319 # Clean the 'x' buttn on the tab
2320 # 'Clean' rectanlge is a rectangle with width or height
2321 # with values lower than or equal to 0
2322 pc
._pagesInfoVec
[i
].GetXRect().SetSize(wx
.Size(-1, -1))
2325 # Incase we are drawing the active tab
2326 # we need to redraw so it will appear on top
2329 # when using the vc8 style, we keep the position of the active tab so we will draw it again later
2330 if i
== pc
.GetSelection() and pc
.HasFlag(FNB_VC8
):
2332 activeTabPosx
= posx
2333 activeTabWidth
= tabWidth
2334 activeTabHeight
= tabHeight
2338 self
.DrawTab(pc
, dc
, posx
, i
, tabWidth
, tabHeight
, pc
._nTabXButtonStatus
)
2340 # Restore the text forground
2341 dc
.SetTextForeground(pc
._activeTextColor
)
2343 # Update the tab position & size
2344 pc
._pagesInfoVec
[i
].SetPosition(wx
.Point(posx
, VERTICAL_BORDER_PADDING
))
2345 pc
._pagesInfoVec
[i
].SetSize(wx
.Size(tabWidth
, tabHeight
))
2347 # Incase we are in VC8 style, redraw the active tab (incase it is visible)
2348 if pc
.GetSelection() >= pc
._nFrom
and pc
.GetSelection() < pc
._nFrom
+ len(vTabsInfo
):
2350 self
.DrawTab(pc
, dc
, activeTabPosx
, pc
.GetSelection(), activeTabWidth
, activeTabHeight
, pc
._nTabXButtonStatus
)
2352 # Update all tabs that can not fit into the screen as non-visible
2353 for xx
in xrange(pc
._nFrom
+ len(vTabsInfo
), len(pc
._pagesInfoVec
)):
2355 pc
._pagesInfoVec
[xx
].SetPosition(wx
.Point(-1, -1))
2356 pc
._pagesInfoVec
[xx
].GetRegion().Clear()
2358 # Draw the left/right/close buttons
2360 self
.DrawLeftArrow(pc
, dc
)
2361 self
.DrawRightArrow(pc
, dc
)
2363 self
.DrawDropDownArrow(pc
, dc
)
2366 def DrawTab(self
, pageContainer
, dc
, posx
, tabIdx
, tabWidth
, tabHeight
, btnStatus
):
2367 """ Draws a tab using VC8 style. """
2370 borderPen
= wx
.Pen(pc
._pParent
.GetBorderColour())
2371 tabPoints
= [wx
.Point() for ii
in xrange(8)]
2373 # If we draw the first tab or the active tab,
2374 # we draw a full tab, else we draw a truncated tab
2385 tabPoints
[0].x
= (pc
.HasFlag(FNB_BOTTOM
) and [posx
] or [posx
+self
._factor
])[0]
2386 tabPoints
[0].y
= (pc
.HasFlag(FNB_BOTTOM
) and [2] or [tabHeight
- 3])[0]
2388 tabPoints
[1].x
= tabPoints
[0].x
+ tabHeight
- VERTICAL_BORDER_PADDING
- 3 - self
._factor
2389 tabPoints
[1].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- (VERTICAL_BORDER_PADDING
+2)] or [(VERTICAL_BORDER_PADDING
+2)])[0]
2391 tabPoints
[2].x
= tabPoints
[1].x
+ 4
2392 tabPoints
[2].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- VERTICAL_BORDER_PADDING
] or [VERTICAL_BORDER_PADDING
])[0]
2394 tabPoints
[3].x
= tabPoints
[2].x
+ tabWidth
- 2
2395 tabPoints
[3].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- VERTICAL_BORDER_PADDING
] or [VERTICAL_BORDER_PADDING
])[0]
2397 tabPoints
[4].x
= tabPoints
[3].x
+ 1
2398 tabPoints
[4].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabPoints
[3].y
- 1] or [tabPoints
[3].y
+ 1])[0]
2400 tabPoints
[5].x
= tabPoints
[4].x
+ 1
2401 tabPoints
[5].y
= (pc
.HasFlag(FNB_BOTTOM
) and [(tabPoints
[4].y
- 1)] or [tabPoints
[4].y
+ 1])[0]
2403 tabPoints
[6].x
= tabPoints
[2].x
+ tabWidth
2404 tabPoints
[6].y
= tabPoints
[0].y
2406 tabPoints
[7].x
= tabPoints
[0].x
2407 tabPoints
[7].y
= tabPoints
[0].y
2409 pc
._pagesInfoVec
[tabIdx
].SetRegion(tabPoints
)
2413 dc
.SetBrush(wx
.Brush((tabIdx
== pc
.GetSelection() and [pc
._activeTabColor
] or [pc
._colorTo
])[0]))
2414 dc
.SetPen(wx
.Pen((tabIdx
== pc
.GetSelection() and [wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)] or [pc
._colorBorder
])[0]))
2415 dc
.DrawPolygon(tabPoints
)
2419 rect
= pc
.GetClientRect()
2421 if tabIdx
!= pc
.GetSelection() and not pc
.HasFlag(FNB_BOTTOM
):
2424 dc
.SetPen(wx
.Pen(pc
._pParent
.GetBorderColour()))
2426 curPen
= dc
.GetPen()
2429 dc
.DrawLine(posx
, lineY
, posx
+rect
.width
, lineY
)
2431 # Incase we are drawing the selected tab, we draw the border of it as well
2432 # but without the bottom (upper line incase of wxBOTTOM)
2433 if tabIdx
== pc
.GetSelection():
2435 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
2436 dc
.SetPen(borderPen
)
2437 dc
.SetBrush(wx
.TRANSPARENT_BRUSH
)
2438 dc
.DrawPolygon(tabPoints
)
2440 # Delete the bottom line (or the upper one, incase we use wxBOTTOM)
2441 dc
.SetPen(wx
.WHITE_PEN
)
2442 dc
.DrawLine(tabPoints
[0].x
, tabPoints
[0].y
, tabPoints
[6].x
, tabPoints
[6].y
)
2444 self
.FillVC8GradientColour(pc
, dc
, tabPoints
, tabIdx
== pc
.GetSelection(), tabIdx
)
2446 # Draw a thin line to the right of the non-selected tab
2447 if tabIdx
!= pc
.GetSelection():
2449 dc
.SetPen(wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
)))
2450 dc
.DrawLine(tabPoints
[4].x
-1, tabPoints
[4].y
, tabPoints
[5].x
-1, tabPoints
[5].y
)
2451 dc
.DrawLine(tabPoints
[5].x
-1, tabPoints
[5].y
, tabPoints
[6].x
-1, tabPoints
[6].y
)
2453 # Text drawing offset from the left border of the
2456 # The width of the images are 16 pixels
2457 vc8ShapeLen
= tabHeight
- VERTICAL_BORDER_PADDING
- 2
2458 if pc
.TabHasImage(tabIdx
):
2459 textOffset
= 2*pc
._pParent
.GetPadding() + 16 + vc8ShapeLen
2461 textOffset
= pc
._pParent
.GetPadding() + vc8ShapeLen
2463 # Draw the image for the tab if any
2464 imageYCoord
= (pc
.HasFlag(FNB_BOTTOM
) and [6] or [8])[0]
2466 if pc
.TabHasImage(tabIdx
):
2468 imageXOffset
= textOffset
- 16 - pc
._pParent
.GetPadding()
2469 pc
._ImageList
.Draw(pc
._pagesInfoVec
[tabIdx
].GetImageIndex(), dc
,
2470 posx
+ imageXOffset
, imageYCoord
,
2471 wx
.IMAGELIST_DRAW_TRANSPARENT
, True)
2473 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
2475 # if selected tab, draw text in bold
2476 if tabIdx
== pc
.GetSelection():
2477 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
2479 dc
.SetFont(boldFont
)
2480 dc
.DrawText(pc
.GetPageText(tabIdx
), posx
+ textOffset
, imageYCoord
)
2482 # draw 'x' on tab (if enabled)
2483 if pc
.HasFlag(FNB_X_ON_TAB
) and tabIdx
== pc
.GetSelection():
2485 textWidth
, textHeight
= dc
.GetTextExtent(pc
.GetPageText(tabIdx
))
2486 tabCloseButtonXCoord
= posx
+ textOffset
+ textWidth
+ 1
2488 # take a bitmap from the position of the 'x' button (the x on tab button)
2489 # this bitmap will be used later to delete old buttons
2490 tabCloseButtonYCoord
= imageYCoord
2491 x_rect
= wx
.Rect(tabCloseButtonXCoord
, tabCloseButtonYCoord
, 16, 16)
2492 self
._tabXBgBmp
= self
._GetBitmap
(dc
, x_rect
, self
._tabXBgBmp
)
2494 self
.DrawTabX(pc
, dc
, x_rect
, tabIdx
, btnStatus
)
2497 def FillVC8GradientColour(self
, pageContainer
, dc
, tabPoints
, bSelectedTab
, tabIdx
):
2498 """ Fills a tab with a gradient shading. """
2500 # calculate gradient coefficients
2505 pc
._colorTo
= LightColour(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
), 0)
2506 pc
._colorFrom
= LightColour(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
), 60)
2508 col2
= (pc
.HasFlag(FNB_BOTTOM
) and [pc
._pParent
.GetGradientColourTo()] or [pc
._pParent
.GetGradientColourFrom()])[0]
2509 col1
= (pc
.HasFlag(FNB_BOTTOM
) and [pc
._pParent
.GetGradientColourFrom()] or [pc
._pParent
.GetGradientColourTo()])[0]
2511 # If colorful tabs style is set, override the tab color
2512 if pc
.HasFlag(FNB_COLORFUL_TABS
):
2514 if not pc
._pagesInfoVec
[tabIdx
].GetColour():
2516 # First time, generate color, and keep it in the vector
2517 tabColor
= RandomColour()
2518 pc
._pagesInfoVec
[tabIdx
].SetColour(tabColor
)
2520 if pc
.HasFlag(FNB_BOTTOM
):
2522 col2
= LightColour(pc
._pagesInfoVec
[tabIdx
].GetColour(), 50)
2523 col1
= LightColour(pc
._pagesInfoVec
[tabIdx
].GetColour(), 80)
2527 col1
= LightColour(pc
._pagesInfoVec
[tabIdx
].GetColour(), 50)
2528 col2
= LightColour(pc
._pagesInfoVec
[tabIdx
].GetColour(), 80)
2530 size
= abs(tabPoints
[2].y
- tabPoints
[0].y
) - 1
2532 rf
, gf
, bf
= 0, 0, 0
2533 rstep
= float(col2
.Red() - col1
.Red())/float(size
)
2534 gstep
= float(col2
.Green() - col1
.Green())/float(size
)
2535 bstep
= float(col2
.Blue() - col1
.Blue())/float(size
)
2539 # If we are drawing the selected tab, we need also to draw a line
2540 # from 0.tabPoints[0].x and tabPoints[6].x . end, we achieve this
2541 # by drawing the rectangle with transparent brush
2542 # the line under the selected tab will be deleted by the drwaing loop
2544 self
.DrawTabsLine(pc
, dc
)
2548 if pc
.HasFlag(FNB_BOTTOM
):
2550 if y
> tabPoints
[0].y
+ size
:
2555 if y
< tabPoints
[0].y
- size
:
2558 currCol
= wx
.Colour(col1
.Red() + rf
, col1
.Green() + gf
, col1
.Blue() + bf
)
2560 dc
.SetPen((bSelectedTab
and [wx
.Pen(pc
._activeTabColor
)] or [wx
.Pen(currCol
)])[0])
2561 startX
= self
.GetStartX(tabPoints
, y
, pc
.GetParent().GetWindowStyleFlag())
2562 endX
= self
.GetEndX(tabPoints
, y
, pc
.GetParent().GetWindowStyleFlag())
2563 dc
.DrawLine(startX
, y
, endX
, y
)
2565 # Draw the border using the 'edge' point
2566 dc
.SetPen(wx
.Pen((bSelectedTab
and [wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)] or [pc
._colorBorder
])[0]))
2568 dc
.DrawPoint(startX
, y
)
2569 dc
.DrawPoint(endX
, y
)
2571 # Progress the color
2576 if pc
.HasFlag(FNB_BOTTOM
):
2582 def GetStartX(self
, tabPoints
, y
, style
):
2583 """ Returns the x start position of a tab. """
2585 x1
, x2
, y1
, y2
= 0.0, 0.0, 0.0, 0.0
2587 # We check the 3 points to the left
2589 bBottomStyle
= (style
& FNB_BOTTOM
and [True] or [False])[0]
2596 if y
>= tabPoints
[i
].y
and y
< tabPoints
[i
+1].y
:
2599 x2
= tabPoints
[i
+1].x
2601 y2
= tabPoints
[i
+1].y
2609 if y
<= tabPoints
[i
].y
and y
> tabPoints
[i
+1].y
:
2612 x2
= tabPoints
[i
+1].x
2614 y2
= tabPoints
[i
+1].y
2619 return tabPoints
[2].x
2621 # According to the equation y = ax + b => x = (y-b)/a
2622 # We know the first 2 points
2627 a
= (y2
- y1
)/(x2
- x1
)
2629 b
= y1
- ((y2
- y1
)/(x2
- x1
))*x1
2639 def GetEndX(self
, tabPoints
, y
, style
):
2640 """ Returns the x end position of a tab. """
2642 x1
, x2
, y1
, y2
= 0.0, 0.0, 0.0, 0.0
2644 # We check the 3 points to the left
2645 bBottomStyle
= (style
& FNB_BOTTOM
and [True] or [False])[0]
2650 for i
in xrange(7, 3, -1):
2652 if y
>= tabPoints
[i
].y
and y
< tabPoints
[i
-1].y
:
2655 x2
= tabPoints
[i
-1].x
2657 y2
= tabPoints
[i
-1].y
2663 for i
in xrange(7, 3, -1):
2665 if y
<= tabPoints
[i
].y
and y
> tabPoints
[i
-1].y
:
2668 x2
= tabPoints
[i
-1].x
2670 y2
= tabPoints
[i
-1].y
2675 return tabPoints
[3].x
2677 # According to the equation y = ax + b => x = (y-b)/a
2678 # We know the first 2 points
2684 a
= (y2
- y1
)/(x2
- x1
)
2685 b
= y1
- ((y2
- y1
)/(x2
- x1
))*x1
2695 def NumberTabsCanFit(self
, pageContainer
, fr
=-1):
2696 """ Returns the number of tabs that can fit in the visible area. """
2700 rect
= pc
.GetClientRect()
2701 clientWidth
= rect
.width
2705 tabHeight
= self
.CalcTabHeight(pageContainer
)
2707 # The drawing starts from posx
2708 posx
= pc
._pParent
.GetPadding()
2713 for i
in xrange(fr
, len(pc
._pagesInfoVec
)):
2715 vc8glitch
= tabHeight
+ FNB_HEIGHT_SPACER
2716 tabWidth
= self
.CalcTabWidth(pageContainer
, i
, tabHeight
)
2718 if posx
+ tabWidth
+ vc8glitch
+ self
.GetButtonsAreaLength(pc
) >= clientWidth
:
2721 # Add a result to the returned vector
2722 tabRect
= wx
.Rect(posx
, VERTICAL_BORDER_PADDING
, tabWidth
, tabHeight
)
2723 vTabInfo
.append(tabRect
)
2726 posx
+= tabWidth
+ FNB_HEIGHT_SPACER
2731 # ---------------------------------------------------------------------------- #
2732 # Class FlatNotebook
2733 # ---------------------------------------------------------------------------- #
2735 class FlatNotebook(wx
.Panel
):
2737 Display one or more windows in a notebook.
2740 - B{EVT_FLATNOTEBOOK_PAGE_CHANGING}: sent when the active
2741 page in the notebook is changing
2742 - B{EVT_FLATNOTEBOOK_PAGE_CHANGED}: sent when the active
2743 page in the notebook has changed
2744 - B{EVT_FLATNOTEBOOK_PAGE_CLOSING}: sent when a page in the
2746 - B{EVT_FLATNOTEBOOK_PAGE_CLOSED}: sent when a page in the
2747 notebook has been closed
2748 - B{EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU}: sent when the user
2749 clicks a tab in the notebook with the right mouse
2753 def __init__(self
, parent
, id=wx
.ID_ANY
, pos
=wx
.DefaultPosition
, size
=wx
.DefaultSize
,
2754 style
=0, name
="FlatNotebook"):
2756 Default class constructor.
2758 All the parameters are as in wxPython class construction, except the
2759 'style': this can be assigned to whatever combination of FNB_* styles.
2763 self
._bForceSelection
= False
2766 style |
= wx
.TAB_TRAVERSAL
2769 self
._popupWin
= None
2771 wx
.Panel
.__init
__(self
, parent
, id, pos
, size
, style
)
2773 self
._pages
= PageContainer(self
, wx
.ID_ANY
, wx
.DefaultPosition
, wx
.DefaultSize
, style
)
2775 self
.Bind(wx
.EVT_NAVIGATION_KEY
, self
.OnNavigationKey
)
2781 """ Initializes all the class attributes. """
2783 self
._pages
._colorBorder
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)
2785 self
._mainSizer
= wx
.BoxSizer(wx
.VERTICAL
)
2786 self
.SetSizer(self
._mainSizer
)
2788 # The child panels will inherit this bg color, so leave it at the default value
2789 #self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_APPWORKSPACE))
2791 # Set default page height
2792 dc
= wx
.ClientDC(self
)
2794 if "__WXGTK__" in wx
.PlatformInfo
:
2795 # For GTK it seems that we must do this steps in order
2796 # for the tabs will get the proper height on initialization
2797 # on MSW, preforming these steps yields wierd results
2798 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
2799 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
2800 dc
.SetFont(boldFont
)
2802 height
= dc
.GetCharHeight()
2804 tabHeight
= height
+ FNB_HEIGHT_SPACER
# We use 8 pixels as padding
2806 if "__WXGTK__" in wx
.PlatformInfo
:
2809 self
._pages
.SetSizeHints(-1, tabHeight
)
2810 # Add the tab container to the sizer
2811 self
._mainSizer
.Insert(0, self
._pages
, 0, wx
.EXPAND
)
2812 self
._mainSizer
.Layout()
2814 self
._pages
._nFrom
= self
._nFrom
2815 self
._pDropTarget
= FNBDropTarget(self
)
2816 self
.SetDropTarget(self
._pDropTarget
)
2819 def SetActiveTabTextColour(self
, textColour
):
2820 """ Sets the text colour for the active tab. """
2822 self
._pages
._activeTextColor
= textColour
2825 def OnDropTarget(self
, x
, y
, nTabPage
, wnd_oldContainer
):
2826 """ Handles the drop action from a DND operation. """
2828 return self
._pages
.OnDropTarget(x
, y
, nTabPage
, wnd_oldContainer
)
2831 def GetPreviousSelection(self
):
2832 """ Returns the previous selection. """
2834 return self
._pages
._iPreviousActivePage
2837 def AddPage(self
, page
, text
, select
=True, imageId
=-1):
2839 Add a page to the L{FlatNotebook}.
2841 @param page: Specifies the new page.
2842 @param text: Specifies the text for the new page.
2843 @param select: Specifies whether the page should be selected.
2844 @param imageId: Specifies the optional image index for the new page.
2847 True if successful, False otherwise.
2854 # reparent the window to us
2858 bSelected
= select
or len(self
._windows
) == 0
2864 # Check for selection and send events
2865 oldSelection
= self
._pages
._iActivePage
2866 tabIdx
= len(self
._windows
)
2868 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, self
.GetId())
2869 event
.SetSelection(tabIdx
)
2870 event
.SetOldSelection(oldSelection
)
2871 event
.SetEventObject(self
)
2873 if not self
.GetEventHandler().ProcessEvent(event
) or event
.IsAllowed() or len(self
._windows
) == 0:
2876 curSel
= self
._pages
.GetSelection()
2878 if not self
._pages
.IsShown():
2881 self
._pages
.AddPage(text
, bSelected
, imageId
)
2882 self
._windows
.append(page
)
2886 # Check if a new selection was made
2891 # Remove the window from the main sizer
2892 self
._mainSizer
.Detach(self
._windows
[curSel
])
2893 self
._windows
[curSel
].Hide()
2895 if self
.GetWindowStyleFlag() & FNB_BOTTOM
:
2897 self
._mainSizer
.Insert(0, page
, 1, wx
.EXPAND
)
2901 # We leave a space of 1 pixel around the window
2902 self
._mainSizer
.Add(page
, 1, wx
.EXPAND
)
2904 # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
2905 event
.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
)
2906 event
.SetOldSelection(oldSelection
)
2907 self
.GetEventHandler().ProcessEvent(event
)
2915 self
._mainSizer
.Layout()
2921 def SetImageList(self
, imageList
):
2923 Sets the image list for the page control. It does not take ownership
2924 of the image list, you must delete it yourself.
2927 self
._pages
.SetImageList(imageList
)
2930 def GetImageList(self
):
2931 """ Returns the associated image list. """
2933 return self
._pages
.GetImageList()
2936 def InsertPage(self
, indx
, page
, text
, select
=True, imageId
=-1):
2938 Inserts a new page at the specified position.
2940 @param indx: Specifies the position of the new page.
2941 @param page: Specifies the new page.
2942 @param text: Specifies the text for the new page.
2943 @param select: Specifies whether the page should be selected.
2944 @param imageId: Specifies the optional image index for the new page.
2947 True if successful, False otherwise.
2954 # reparent the window to us
2957 if not self
._windows
:
2959 self
.AddPage(page
, text
, select
, imageId
)
2963 bSelected
= select
or not self
._windows
2964 curSel
= self
._pages
.GetSelection()
2966 indx
= max(0, min(indx
, len(self
._windows
)))
2968 if indx
<= len(self
._windows
):
2970 self
._windows
.insert(indx
, page
)
2974 self
._windows
.append(page
)
2980 # Check for selection and send events
2981 oldSelection
= self
._pages
._iActivePage
2983 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, self
.GetId())
2984 event
.SetSelection(indx
)
2985 event
.SetOldSelection(oldSelection
)
2986 event
.SetEventObject(self
)
2988 if not self
.GetEventHandler().ProcessEvent(event
) or event
.IsAllowed() or len(self
._windows
) == 0:
2991 self
._pages
.InsertPage(indx
, text
, bSelected
, imageId
)
2998 # Check if a new selection was made
3003 # Remove the window from the main sizer
3004 self
._mainSizer
.Detach(self
._windows
[curSel
])
3005 self
._windows
[curSel
].Hide()
3007 self
._pages
.SetSelection(indx
)
3009 # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
3010 event
.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
)
3011 event
.SetOldSelection(oldSelection
)
3012 self
.GetEventHandler().ProcessEvent(event
)
3020 self
._mainSizer
.Layout()
3026 def SetSelection(self
, page
):
3028 Sets the selection for the given page.
3029 The call to this function generates the page changing events
3032 if page
>= len(self
._windows
) or not self
._windows
:
3035 # Support for disabed tabs
3036 if not self
._pages
.GetEnabled(page
) and len(self
._windows
) > 1 and not self
._bForceSelection
:
3039 curSel
= self
._pages
.GetSelection()
3041 # program allows the page change
3045 # Remove the window from the main sizer
3046 self
._mainSizer
.Detach(self
._windows
[curSel
])
3047 self
._windows
[curSel
].Hide()
3049 if self
.GetWindowStyleFlag() & FNB_BOTTOM
:
3051 self
._mainSizer
.Insert(0, self
._windows
[page
], 1, wx
.EXPAND
)
3055 # We leave a space of 1 pixel around the window
3056 self
._mainSizer
.Add(self
._windows
[page
], 1, wx
.EXPAND
)
3058 self
._windows
[page
].Show()
3061 self
._mainSizer
.Layout()
3063 if page
!= self
._pages
._iActivePage
:
3064 # there is a real page changing
3065 self
._pages
._iPreviousActivePage
= self
._pages
._iActivePage
3067 self
._pages
._iActivePage
= page
3068 self
._pages
.DoSetSelection(page
)
3071 def DeletePage(self
, page
):
3073 Deletes the specified page, and the associated window.
3074 The call to this function generates the page changing events.
3077 if page
>= len(self
._windows
) or page
< 0:
3080 # Fire a closing event
3081 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING
, self
.GetId())
3082 event
.SetSelection(page
)
3083 event
.SetEventObject(self
)
3084 self
.GetEventHandler().ProcessEvent(event
)
3086 # The event handler allows it?
3087 if not event
.IsAllowed():
3092 # Delete the requested page
3093 pageRemoved
= self
._windows
[page
]
3095 # If the page is the current window, remove it from the sizer
3097 if page
== self
._pages
.GetSelection():
3098 self
._mainSizer
.Detach(pageRemoved
)
3100 # Remove it from the array as well
3101 self
._windows
.pop(page
)
3103 # Now we can destroy it in wxWidgets use Destroy instead of delete
3104 pageRemoved
.Destroy()
3108 self
._pages
.DoDeletePage(page
)
3111 # Fire a closed event
3112 closedEvent
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSED
, self
.GetId())
3113 closedEvent
.SetSelection(page
)
3114 closedEvent
.SetEventObject(self
)
3115 self
.GetEventHandler().ProcessEvent(closedEvent
)
3118 def DeleteAllPages(self
):
3119 """ Deletes all the pages. """
3121 if not self
._windows
:
3126 for page
in self
._windows
:
3132 # Clear the container of the tabs as well
3133 self
._pages
.DeleteAllPages()
3137 def GetCurrentPage(self
):
3138 """ Returns the currently selected notebook page or None. """
3140 sel
= self
._pages
.GetSelection()
3144 return self
._windows
[sel
]
3147 def GetPage(self
, page
):
3148 """ Returns the window at the given page position, or None. """
3150 if page
>= len(self
._windows
):
3153 return self
._windows
[page
]
3156 def GetPageIndex(self
, win
):
3157 """ Returns the index at which the window is found. """
3160 return self
._windows
.index(win
)
3165 def GetSelection(self
):
3166 """ Returns the currently selected page, or -1 if none was selected. """
3168 return self
._pages
.GetSelection()
3171 def AdvanceSelection(self
, forward
=True):
3173 Cycles through the tabs.
3174 The call to this function generates the page changing events.
3177 self
._pages
.AdvanceSelection(forward
)
3180 def GetPageCount(self
):
3181 """ Returns the number of pages in the L{FlatNotebook} control. """
3183 return self
._pages
.GetPageCount()
3186 def OnNavigationKey(self
, event
):
3187 """ Handles the wx.EVT_NAVIGATION_KEY event for L{FlatNotebook}. """
3189 if event
.IsWindowChange():
3190 if len(self
._windows
) == 0:
3193 if self
.HasFlag(FNB_SMART_TABS
):
3194 if not self
._popupWin
:
3195 self
._popupWin
= TabNavigatorWindow(self
)
3196 self
._popupWin
.SetReturnCode(wx
.ID_OK
)
3197 self
._popupWin
.ShowModal()
3198 self
._popupWin
.Destroy()
3199 self
._popupWin
= None
3201 # a dialog is already opened
3202 self
._popupWin
.OnNavigationKey(event
)
3206 self
.AdvanceSelection(event
.GetDirection())
3208 # pass to the parent
3209 if self
.GetParent():
3210 event
.SetCurrentFocus(self
)
3211 self
.GetParent().ProcessEvent(event
)
3214 def GetPageShapeAngle(self
, page_index
):
3215 """ Returns the angle associated to a tab. """
3217 if page_index
< 0 or page_index
>= len(self
._pages
._pagesInfoVec
):
3220 result
= self
._pages
._pagesInfoVec
[page_index
].GetTabAngle()
3224 def SetPageShapeAngle(self
, page_index
, angle
):
3225 """ Sets the angle associated to a tab. """
3227 if page_index
< 0 or page_index
>= len(self
._pages
._pagesInfoVec
):
3233 self
._pages
._pagesInfoVec
[page_index
].SetTabAngle(angle
)
3236 def SetAllPagesShapeAngle(self
, angle
):
3237 """ Sets the angle associated to all the tab. """
3242 for ii
in xrange(len(self
._pages
._pagesInfoVec
)):
3243 self
._pages
._pagesInfoVec
[ii
].SetTabAngle(angle
)
3248 def GetPageBestSize(self
):
3249 """ Return the page best size. """
3251 return self
._pages
.GetClientSize()
3254 def SetPageText(self
, page
, text
):
3255 """ Sets the text for the given page. """
3257 bVal
= self
._pages
.SetPageText(page
, text
)
3258 self
._pages
.Refresh()
3263 def SetPadding(self
, padding
):
3265 Sets the amount of space around each page's icon and label, in pixels.
3266 NB: only the horizontal padding is considered.
3269 self
._nPadding
= padding
.GetWidth()
3272 def GetTabArea(self
):
3273 """ Returns the associated page. """
3278 def GetPadding(self
):
3279 """ Returns the amount of space around each page's icon and label, in pixels. """
3281 return self
._nPadding
3284 def SetWindowStyleFlag(self
, style
):
3285 """ Sets the L{FlatNotebook} window style flags. """
3287 wx
.Panel
.SetWindowStyleFlag(self
, style
)
3288 renderer
= self
._pages
._mgr
.GetRenderer(self
.GetWindowStyleFlag())
3289 renderer
._tabHeight
= None
3293 # For changing the tab position (i.e. placing them top/bottom)
3294 # refreshing the tab container is not enough
3295 self
.SetSelection(self
._pages
._iActivePage
)
3298 def RemovePage(self
, page
):
3299 """ Deletes the specified page, without deleting the associated window. """
3301 if page
>= len(self
._windows
):
3304 # Fire a closing event
3305 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING
, self
.GetId())
3306 event
.SetSelection(page
)
3307 event
.SetEventObject(self
)
3308 self
.GetEventHandler().ProcessEvent(event
)
3310 # The event handler allows it?
3311 if not event
.IsAllowed():
3316 # Remove the requested page
3317 pageRemoved
= self
._windows
[page
]
3319 # If the page is the current window, remove it from the sizer
3321 if page
== self
._pages
.GetSelection():
3322 self
._mainSizer
.Detach(pageRemoved
)
3324 # Remove it from the array as well
3325 self
._windows
.pop(page
)
3328 self
._pages
.DoDeletePage(page
)
3333 def SetRightClickMenu(self
, menu
):
3334 """ Sets the popup menu associated to a right click on a tab. """
3336 self
._pages
._pRightClickMenu
= menu
3339 def GetPageText(self
, nPage
):
3340 """ Returns the tab caption. """
3342 return self
._pages
.GetPageText(nPage
)
3345 def SetGradientColours(self
, fr
, to
, border
):
3346 """ Sets the gradient colours for the tab. """
3348 self
._pages
._colorFrom
= fr
3349 self
._pages
._colorTo
= to
3350 self
._pages
._colorBorder
= border
3353 def SetGradientColourFrom(self
, fr
):
3354 """ Sets the starting colour for the gradient. """
3356 self
._pages
._colorFrom
= fr
3359 def SetGradientColourTo(self
, to
):
3360 """ Sets the ending colour for the gradient. """
3362 self
._pages
._colorTo
= to
3365 def SetGradientColourBorder(self
, border
):
3366 """ Sets the tab border colour. """
3368 self
._pages
._colorBorder
= border
3371 def GetGradientColourFrom(self
):
3372 """ Gets first gradient colour. """
3374 return self
._pages
._colorFrom
3377 def GetGradientColourTo(self
):
3378 """ Gets second gradient colour. """
3380 return self
._pages
._colorTo
3383 def GetGradientColourBorder(self
):
3384 """ Gets the tab border colour. """
3386 return self
._pages
._colorBorder
3389 def GetBorderColour(self
):
3390 """ Returns the border colour. """
3392 return self
._pages
._colorBorder
3395 def GetActiveTabTextColour(self
):
3396 """ Get the active tab text colour. """
3398 return self
._pages
._activeTextColor
3401 def SetPageImage(self
, page
, image
):
3403 Sets the image index for the given page. Image is an index into the
3404 image list which was set with SetImageList.
3407 self
._pages
.SetPageImage(page
, image
)
3410 def GetPageImage(self
, nPage
):
3412 Returns the image index for the given page. Image is an index into the
3413 image list which was set with SetImageList.
3416 return self
._pages
.GetPageImage(nPage
)
3419 def GetEnabled(self
, page
):
3420 """ Returns whether a tab is enabled or not. """
3422 return self
._pages
.GetEnabled(page
)
3425 def Enable(self
, page
, enabled
=True):
3426 """ Enables or disables a tab. """
3428 if page
>= len(self
._windows
):
3431 self
._windows
[page
].Enable(enabled
)
3432 self
._pages
.Enable(page
, enabled
)
3435 def GetNonActiveTabTextColour(self
):
3436 """ Returns the non active tabs text colour. """
3438 return self
._pages
._nonActiveTextColor
3441 def SetNonActiveTabTextColour(self
, color
):
3442 """ Sets the non active tabs text colour. """
3444 self
._pages
._nonActiveTextColor
= color
3447 def SetTabAreaColour(self
, color
):
3448 """ Sets the area behind the tabs colour. """
3450 self
._pages
._tabAreaColor
= color
3453 def GetTabAreaColour(self
):
3454 """ Returns the area behind the tabs colour. """
3456 return self
._pages
._tabAreaColor
3459 def SetActiveTabColour(self
, color
):
3460 """ Sets the active tab colour. """
3462 self
._pages
._activeTabColor
= color
3465 def GetActiveTabColour(self
):
3466 """ Returns the active tab colour. """
3468 return self
._pages
._activeTabColor
3471 # ---------------------------------------------------------------------------- #
3472 # Class PageContainer
3473 # Acts as a container for the pages you add to FlatNotebook
3474 # ---------------------------------------------------------------------------- #
3476 class PageContainer(wx
.Panel
):
3478 This class acts as a container for the pages you add to L{FlatNotebook}.
3481 def __init__(self
, parent
, id=wx
.ID_ANY
, pos
=wx
.DefaultPosition
,
3482 size
=wx
.DefaultSize
, style
=0):
3483 """ Default class constructor. """
3485 self
._ImageList
= None
3486 self
._iActivePage
= -1
3487 self
._pDropTarget
= None
3488 self
._nLeftClickZone
= FNB_NOWHERE
3489 self
._iPreviousActivePage
= -1
3491 self
._pRightClickMenu
= None
3492 self
._nXButtonStatus
= FNB_BTN_NONE
3493 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
3494 self
._pParent
= parent
3495 self
._nRightButtonStatus
= FNB_BTN_NONE
3496 self
._nLeftButtonStatus
= FNB_BTN_NONE
3497 self
._nTabXButtonStatus
= FNB_BTN_NONE
3499 self
._pagesInfoVec
= []
3501 self
._colorTo
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_ACTIVECAPTION
)
3502 self
._colorFrom
= wx
.WHITE
3503 self
._activeTabColor
= wx
.WHITE
3504 self
._activeTextColor
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNTEXT
)
3505 self
._nonActiveTextColor
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)
3506 self
._tabAreaColor
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNFACE
)
3509 self
._isdragging
= False
3511 # Set default page height, this is done according to the system font
3512 memDc
= wx
.MemoryDC()
3513 memDc
.SelectObject(wx
.EmptyBitmap(1,1))
3515 if "__WXGTK__" in wx
.PlatformInfo
:
3516 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
3517 boldFont
.SetWeight(wx
.BOLD
)
3518 memDc
.SetFont(boldFont
)
3520 height
= memDc
.GetCharHeight()
3521 tabHeight
= height
+ FNB_HEIGHT_SPACER
# We use 10 pixels as padding
3523 wx
.Panel
.__init
__(self
, parent
, id, pos
, wx
.Size(size
.x
, tabHeight
),
3524 style|wx
.NO_BORDER|wx
.NO_FULL_REPAINT_ON_RESIZE
)
3526 self
._pDropTarget
= FNBDropTarget(self
)
3527 self
.SetDropTarget(self
._pDropTarget
)
3528 self
._mgr
= FNBRendererMgr()
3530 self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
)
3531 self
.Bind(wx
.EVT_SIZE
, self
.OnSize
)
3532 self
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnLeftDown
)
3533 self
.Bind(wx
.EVT_LEFT_UP
, self
.OnLeftUp
)
3534 self
.Bind(wx
.EVT_RIGHT_DOWN
, self
.OnRightDown
)
3535 self
.Bind(wx
.EVT_MIDDLE_DOWN
, self
.OnMiddleDown
)
3536 self
.Bind(wx
.EVT_MOTION
, self
.OnMouseMove
)
3537 self
.Bind(wx
.EVT_ERASE_BACKGROUND
, self
.OnEraseBackground
)
3538 self
.Bind(wx
.EVT_LEAVE_WINDOW
, self
.OnMouseLeave
)
3539 self
.Bind(wx
.EVT_ENTER_WINDOW
, self
.OnMouseEnterWindow
)
3540 self
.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnLeftDClick
)
3543 def OnEraseBackground(self
, event
):
3544 """ Handles the wx.EVT_ERASE_BACKGROUND event for L{PageContainer} (does nothing)."""
3549 def OnPaint(self
, event
):
3550 """ Handles the wx.EVT_PAINT event for L{PageContainer}."""
3552 # Currently having problems with buffered DCs because of
3553 # recent changes. Just do the buffering ourselves instead.
3554 dc
= wx
.BufferedPaintDC(self
)
3555 #dc = wx.AutoBufferedPaintDC(self)
3556 #dc = wx.AutoBufferedPaintDCFactory(self)
3557 ## size = self.GetSize()
3558 ## bmp = wx.EmptyBitmap(*size)
3559 ## dc = wx.MemoryDC()
3560 ## dc.SelectObject(bmp)
3562 renderer
= self
._mgr
.GetRenderer(self
.GetParent().GetWindowStyleFlag())
3563 renderer
.DrawTabs(self
, dc
)
3565 ## pdc = wx.PaintDC(self)
3566 ## pdc.Blit(0,0, size.width, size.height, dc, 0,0)
3569 def AddPage(self
, caption
, selected
=True, imgindex
=-1):
3571 Add a page to the L{FlatNotebook}.
3573 @param window: Specifies the new page.
3574 @param caption: Specifies the text for the new page.
3575 @param selected: Specifies whether the page should be selected.
3576 @param imgindex: Specifies the optional image index for the new page.
3579 True if successful, False otherwise.
3584 self
._iPreviousActivePage
= self
._iActivePage
3585 self
._iActivePage
= len(self
._pagesInfoVec
)
3587 # Create page info and add it to the vector
3588 pageInfo
= PageInfo(caption
, imgindex
)
3589 self
._pagesInfoVec
.append(pageInfo
)
3593 def InsertPage(self
, indx
, text
, selected
=True, imgindex
=-1):
3595 Inserts a new page at the specified position.
3597 @param indx: Specifies the position of the new page.
3598 @param page: Specifies the new page.
3599 @param text: Specifies the text for the new page.
3600 @param select: Specifies whether the page should be selected.
3601 @param imgindex: Specifies the optional image index for the new page.
3604 True if successful, False otherwise.
3609 self
._iPreviousActivePage
= self
._iActivePage
3610 self
._iActivePage
= len(self
._pagesInfoVec
)
3612 self
._pagesInfoVec
.insert(indx
, PageInfo(text
, imgindex
))
3618 def OnSize(self
, event
):
3619 """ Handles the wx.EVT_SIZE events for L{PageContainer}. """
3621 self
.Refresh() # Call on paint
3625 def OnMiddleDown(self
, event
):
3626 """ Handles the wx.EVT_MIDDLE_DOWN events for L{PageContainer}. """
3628 # Test if this style is enabled
3629 style
= self
.GetParent().GetWindowStyleFlag()
3631 if not style
& FNB_MOUSE_MIDDLE_CLOSES_TABS
:
3634 where
, tabIdx
= self
.HitTest(event
.GetPosition())
3636 if where
== FNB_TAB
:
3637 self
.DeletePage(tabIdx
)
3642 def OnRightDown(self
, event
):
3643 """ Handles the wx.EVT_RIGHT_DOWN events for L{PageContainer}. """
3645 if self
._pRightClickMenu
:
3647 where
, tabIdx
= self
.HitTest(event
.GetPosition())
3649 if where
in [FNB_TAB
, FNB_TAB_X
]:
3651 if self
._pagesInfoVec
[tabIdx
].GetEnabled():
3652 # Set the current tab to be active
3653 self
.SetSelection(tabIdx
)
3655 # If the owner has defined a context menu for the tabs,
3656 # popup the right click menu
3657 if self
._pRightClickMenu
:
3658 self
.PopupMenu(self
._pRightClickMenu
)
3660 # send a message to popup a custom menu
3661 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU
, self
.GetParent().GetId())
3662 event
.SetSelection(tabIdx
)
3663 event
.SetOldSelection(self
._iActivePage
)
3664 event
.SetEventObject(self
.GetParent())
3665 self
.GetParent().GetEventHandler().ProcessEvent(event
)
3670 def OnLeftDown(self
, event
):
3671 """ Handles the wx.EVT_LEFT_DOWN events for L{PageContainer}. """
3673 # Reset buttons status
3674 self
._nXButtonStatus
= FNB_BTN_NONE
3675 self
._nLeftButtonStatus
= FNB_BTN_NONE
3676 self
._nRightButtonStatus
= FNB_BTN_NONE
3677 self
._nTabXButtonStatus
= FNB_BTN_NONE
3678 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
3680 self
._nLeftClickZone
, tabIdx
= self
.HitTest(event
.GetPosition())
3682 if self
._nLeftClickZone
== FNB_DROP_DOWN_ARROW
:
3683 self
._nArrowDownButtonStatus
= FNB_BTN_PRESSED
3685 elif self
._nLeftClickZone
== FNB_LEFT_ARROW
:
3686 self
._nLeftButtonStatus
= FNB_BTN_PRESSED
3688 elif self
._nLeftClickZone
== FNB_RIGHT_ARROW
:
3689 self
._nRightButtonStatus
= FNB_BTN_PRESSED
3691 elif self
._nLeftClickZone
== FNB_X
:
3692 self
._nXButtonStatus
= FNB_BTN_PRESSED
3694 elif self
._nLeftClickZone
== FNB_TAB_X
:
3695 self
._nTabXButtonStatus
= FNB_BTN_PRESSED
3698 elif self
._nLeftClickZone
== FNB_TAB
:
3700 if self
._iActivePage
!= tabIdx
:
3702 # In case the tab is disabled, we dont allow to choose it
3703 if self
._pagesInfoVec
[tabIdx
].GetEnabled():
3704 self
.FireEvent(tabIdx
)
3707 def OnLeftUp(self
, event
):
3708 """ Handles the wx.EVT_LEFT_UP events for L{PageContainer}. """
3710 # forget the zone that was initially clicked
3711 self
._nLeftClickZone
= FNB_NOWHERE
3713 where
, tabIdx
= self
.HitTest(event
.GetPosition())
3715 if where
== FNB_LEFT_ARROW
:
3717 if self
._nFrom
== 0:
3720 # Make sure that the button was pressed before
3721 if self
._nLeftButtonStatus
!= FNB_BTN_PRESSED
:
3724 self
._nLeftButtonStatus
= FNB_BTN_HOVER
3726 # We scroll left with bulks of 5
3727 scrollLeft
= self
.GetNumTabsCanScrollLeft()
3729 self
._nFrom
-= scrollLeft
3735 elif where
== FNB_RIGHT_ARROW
:
3737 if self
._nFrom
>= len(self
._pagesInfoVec
) - 1:
3740 # Make sure that the button was pressed before
3741 if self
._nRightButtonStatus
!= FNB_BTN_PRESSED
:
3744 self
._nRightButtonStatus
= FNB_BTN_HOVER
3746 # Check if the right most tab is visible, if it is
3747 # don't rotate right anymore
3748 if self
._pagesInfoVec
[-1].GetPosition() != wx
.Point(-1, -1):
3751 lastVisibleTab
= self
.GetLastVisibleTab()
3752 if lastVisibleTab
< 0:
3753 # Probably the screen is too small for displaying even a single
3754 # tab, in this case we do nothing
3757 self
._nFrom
+= self
.GetNumOfVisibleTabs()
3760 elif where
== FNB_X
:
3762 # Make sure that the button was pressed before
3763 if self
._nXButtonStatus
!= FNB_BTN_PRESSED
:
3766 self
._nXButtonStatus
= FNB_BTN_HOVER
3768 self
.DeletePage(self
._iActivePage
)
3770 elif where
== FNB_TAB_X
:
3772 # Make sure that the button was pressed before
3773 if self
._nTabXButtonStatus
!= FNB_BTN_PRESSED
:
3776 self
._nTabXButtonStatus
= FNB_BTN_HOVER
3778 self
.DeletePage(self
._iActivePage
)
3780 elif where
== FNB_DROP_DOWN_ARROW
:
3782 # Make sure that the button was pressed before
3783 if self
._nArrowDownButtonStatus
!= FNB_BTN_PRESSED
:
3786 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
3788 # Refresh the button status
3789 renderer
= self
._mgr
.GetRenderer(self
.GetParent().GetWindowStyleFlag())
3790 dc
= wx
.ClientDC(self
)
3791 renderer
.DrawDropDownArrow(self
, dc
)
3793 self
.PopupTabsMenu()
3796 def HitTest(self
, pt
):
3798 HitTest method for L{PageContainer}.
3799 Returns the flag (if any) and the hit page (if any).
3802 style
= self
.GetParent().GetWindowStyleFlag()
3803 render
= self
._mgr
.GetRenderer(style
)
3805 fullrect
= self
.GetClientRect()
3806 btnLeftPos
= render
.GetLeftButtonPos(self
)
3807 btnRightPos
= render
.GetRightButtonPos(self
)
3808 btnXPos
= render
.GetXPos(self
)
3812 if len(self
._pagesInfoVec
) == 0:
3813 return FNB_NOWHERE
, tabIdx
3815 rect
= wx
.Rect(btnXPos
, 8, 16, 16)
3816 if rect
.Contains(pt
):
3817 return (style
& FNB_NO_X_BUTTON
and [FNB_NOWHERE
] or [FNB_X
])[0], tabIdx
3819 rect
= wx
.Rect(btnRightPos
, 8, 16, 16)
3820 if style
& FNB_DROPDOWN_TABS_LIST
:
3821 rect
= wx
.Rect(render
.GetDropArrowButtonPos(self
), 8, 16, 16)
3822 if rect
.Contains(pt
):
3823 return FNB_DROP_DOWN_ARROW
, tabIdx
3825 if rect
.Contains(pt
):
3826 return (style
& FNB_NO_NAV_BUTTONS
and [FNB_NOWHERE
] or [FNB_RIGHT_ARROW
])[0], tabIdx
3828 rect
= wx
.Rect(btnLeftPos
, 8, 16, 16)
3829 if rect
.Contains(pt
):
3830 return (style
& FNB_NO_NAV_BUTTONS
and [FNB_NOWHERE
] or [FNB_LEFT_ARROW
])[0], tabIdx
3832 # Test whether a left click was made on a tab
3835 for cur
in xrange(self
._nFrom
, len(self
._pagesInfoVec
)):
3837 pgInfo
= self
._pagesInfoVec
[cur
]
3839 if pgInfo
.GetPosition() == wx
.Point(-1, -1):
3842 if style
& FNB_X_ON_TAB
and cur
== self
.GetSelection():
3843 # 'x' button exists on a tab
3844 if self
._pagesInfoVec
[cur
].GetXRect().Contains(pt
):
3845 return FNB_TAB_X
, cur
3849 if self
._pagesInfoVec
[cur
].GetRegion().Contains(pt
.x
, pt
.y
):
3850 if bFoundMatch
or cur
== self
.GetSelection():
3858 tabRect
= wx
.Rect(pgInfo
.GetPosition().x
, pgInfo
.GetPosition().y
,
3859 pgInfo
.GetSize().x
, pgInfo
.GetSize().y
)
3861 if tabRect
.Contains(pt
):
3866 return FNB_TAB
, tabIdx
3868 if self
._isdragging
:
3869 # We are doing DND, so check also the region outside the tabs
3870 # try before the first tab
3871 pgInfo
= self
._pagesInfoVec
[0]
3872 tabRect
= wx
.Rect(0, pgInfo
.GetPosition().y
, pgInfo
.GetPosition().x
, self
.GetParent().GetSize().y
)
3873 if tabRect
.Contains(pt
):
3876 # try after the last tab
3877 pgInfo
= self
._pagesInfoVec
[-1]
3878 startpos
= pgInfo
.GetPosition().x
+pgInfo
.GetSize().x
3879 tabRect
= wx
.Rect(startpos
, pgInfo
.GetPosition().y
, fullrect
.width
-startpos
, self
.GetParent().GetSize().y
)
3881 if tabRect
.Contains(pt
):
3882 return FNB_TAB
, len(self
._pagesInfoVec
)
3885 return FNB_NOWHERE
, -1
3888 def SetSelection(self
, page
):
3889 """ Sets the selected page. """
3891 book
= self
.GetParent()
3892 book
.SetSelection(page
)
3893 self
.DoSetSelection(page
)
3896 def DoSetSelection(self
, page
):
3897 """ Does the actual selection of a page. """
3899 if page
< len(self
._pagesInfoVec
):
3901 da_page
= self
._pParent
.GetPage(page
)
3906 if not self
.IsTabVisible(page
):
3908 if page
== len(self
._pagesInfoVec
) - 1:
3909 # Incase the added tab is last,
3910 # the function IsTabVisible() will always return False
3911 # and thus will cause an evil behaviour that the new
3912 # tab will hide all other tabs, we need to check if the
3913 # new selected tab can fit to the current screen
3914 if not self
.CanFitToScreen(page
):
3919 if not self
.CanFitToScreen(page
):
3920 # Redraw the tabs starting from page
3926 def DeletePage(self
, page
):
3927 """ Delete the specified page from L{FlatNotebook}. """
3929 book
= self
.GetParent()
3930 book
.DeletePage(page
)
3934 def IsTabVisible(self
, page
):
3935 """ Returns whether a tab is visible or not. """
3937 iLastVisiblePage
= self
.GetLastVisibleTab()
3938 return page
<= iLastVisiblePage
and page
>= self
._nFrom
3941 def DoDeletePage(self
, page
):
3942 """ Does the actual page deletion. """
3944 # Remove the page from the vector
3945 book
= self
.GetParent()
3946 self
._pagesInfoVec
.pop(page
)
3948 # Thanks to Yiaanis AKA Mandrav
3949 if self
._iActivePage
>= page
:
3950 self
._iActivePage
= self
._iActivePage
- 1
3951 self
._iPreviousActivePage
= -1
3953 # The delete page was the last first on the array,
3954 # but the book still has more pages, so we set the
3955 # active page to be the first one (0)
3956 if self
._iActivePage
< 0 and len(self
._pagesInfoVec
) > 0:
3957 self
._iActivePage
= 0
3958 self
._iPreviousActivePage
= -1
3961 if self
._iActivePage
>= 0:
3963 book
._bForceSelection
= True
3965 # Check for selection and send event
3966 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, self
.GetParent().GetId())
3967 event
.SetSelection(self
._iActivePage
)
3968 event
.SetOldSelection(self
._iPreviousActivePage
)
3969 event
.SetEventObject(self
.GetParent())
3971 book
.SetSelection(self
._iActivePage
)
3972 book
._bForceSelection
= False
3974 # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
3975 event
.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
)
3976 event
.SetOldSelection(self
._iPreviousActivePage
)
3977 self
.GetParent().GetEventHandler().ProcessEvent(event
)
3979 if not self
._pagesInfoVec
:
3980 # Erase the page container drawings
3981 dc
= wx
.ClientDC(self
)
3985 def DeleteAllPages(self
):
3986 """ Deletes all the pages. """
3988 self
._iActivePage
= -1
3989 self
._iPreviousActivePage
= -1
3991 self
._pagesInfoVec
= []
3993 # Erase the page container drawings
3994 dc
= wx
.ClientDC(self
)
3998 def OnMouseMove(self
, event
):
3999 """ Handles the wx.EVT_MOTION for L{PageContainer}. """
4001 if self
._pagesInfoVec
and self
.IsShown():
4003 xButtonStatus
= self
._nXButtonStatus
4004 xTabButtonStatus
= self
._nTabXButtonStatus
4005 rightButtonStatus
= self
._nRightButtonStatus
4006 leftButtonStatus
= self
._nLeftButtonStatus
4007 dropDownButtonStatus
= self
._nArrowDownButtonStatus
4009 style
= self
.GetParent().GetWindowStyleFlag()
4011 self
._nXButtonStatus
= FNB_BTN_NONE
4012 self
._nRightButtonStatus
= FNB_BTN_NONE
4013 self
._nLeftButtonStatus
= FNB_BTN_NONE
4014 self
._nTabXButtonStatus
= FNB_BTN_NONE
4015 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
4017 where
, tabIdx
= self
.HitTest(event
.GetPosition())
4020 if event
.LeftIsDown():
4022 self
._nXButtonStatus
= (self
._nLeftClickZone
==FNB_X
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4026 self
._nXButtonStatus
= FNB_BTN_HOVER
4028 elif where
== FNB_DROP_DOWN_ARROW
:
4029 if event
.LeftIsDown():
4031 self
._nArrowDownButtonStatus
= (self
._nLeftClickZone
==FNB_DROP_DOWN_ARROW
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4035 self
._nArrowDownButtonStatus
= FNB_BTN_HOVER
4037 elif where
== FNB_TAB_X
:
4038 if event
.LeftIsDown():
4040 self
._nTabXButtonStatus
= (self
._nLeftClickZone
==FNB_TAB_X
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4044 self
._nTabXButtonStatus
= FNB_BTN_HOVER
4046 elif where
== FNB_RIGHT_ARROW
:
4047 if event
.LeftIsDown():
4049 self
._nRightButtonStatus
= (self
._nLeftClickZone
==FNB_RIGHT_ARROW
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4053 self
._nRightButtonStatus
= FNB_BTN_HOVER
4055 elif where
== FNB_LEFT_ARROW
:
4056 if event
.LeftIsDown():
4058 self
._nLeftButtonStatus
= (self
._nLeftClickZone
==FNB_LEFT_ARROW
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4062 self
._nLeftButtonStatus
= FNB_BTN_HOVER
4064 elif where
== FNB_TAB
:
4065 # Call virtual method for showing tooltip
4066 self
.ShowTabTooltip(tabIdx
)
4068 if not self
.GetEnabled(tabIdx
):
4069 # Set the cursor to be 'No-entry'
4070 wx
.SetCursor(wx
.StockCursor(wx
.CURSOR_NO_ENTRY
))
4072 # Support for drag and drop
4073 if event
.Dragging() and not (style
& FNB_NODRAG
):
4075 self
._isdragging
= True
4076 draginfo
= FNBDragInfo(self
, tabIdx
)
4077 drginfo
= cPickle
.dumps(draginfo
)
4078 dataobject
= wx
.CustomDataObject(wx
.CustomDataFormat("FlatNotebook"))
4079 dataobject
.SetData(drginfo
)
4080 dragSource
= FNBDropSource(self
)
4081 dragSource
.SetData(dataobject
)
4082 dragSource
.DoDragDrop(wx
.Drag_DefaultMove
)
4084 bRedrawX
= self
._nXButtonStatus
!= xButtonStatus
4085 bRedrawRight
= self
._nRightButtonStatus
!= rightButtonStatus
4086 bRedrawLeft
= self
._nLeftButtonStatus
!= leftButtonStatus
4087 bRedrawTabX
= self
._nTabXButtonStatus
!= xTabButtonStatus
4088 bRedrawDropArrow
= self
._nArrowDownButtonStatus
!= dropDownButtonStatus
4090 render
= self
._mgr
.GetRenderer(style
)
4092 if (bRedrawX
or bRedrawRight
or bRedrawLeft
or bRedrawTabX
or bRedrawDropArrow
):
4094 dc
= wx
.ClientDC(self
)
4098 render
.DrawX(self
, dc
)
4102 render
.DrawLeftArrow(self
, dc
)
4106 render
.DrawRightArrow(self
, dc
)
4110 render
.DrawTabX(self
, dc
, self
._pagesInfoVec
[tabIdx
].GetXRect(), tabIdx
, self
._nTabXButtonStatus
)
4112 if bRedrawDropArrow
:
4114 render
.DrawDropDownArrow(self
, dc
)
4119 def GetLastVisibleTab(self
):
4120 """ Returns the last visible tab. """
4124 for ii
in xrange(self
._nFrom
, len(self
._pagesInfoVec
)):
4126 if self
._pagesInfoVec
[ii
].GetPosition() == wx
.Point(-1, -1):
4132 def GetNumTabsCanScrollLeft(self
):
4133 """ Returns the number of tabs than can be scrolled left. """
4135 # Reserved area for the buttons (<>x)
4136 rect
= self
.GetClientRect()
4137 clientWidth
= rect
.width
4138 posx
= self
._pParent
._nPadding
4142 # In case we have error prevent crash
4146 dc
= wx
.ClientDC(self
)
4148 style
= self
.GetParent().GetWindowStyleFlag()
4149 render
= self
._mgr
.GetRenderer(style
)
4151 for ii
in xrange(self
._nFrom
, -1, -1):
4153 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
4154 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
4155 dc
.SetFont(boldFont
)
4157 height
= dc
.GetCharHeight()
4159 tabHeight
= height
+ FNB_HEIGHT_SPACER
# We use 6 pixels as padding
4160 if style
& FNB_VC71
:
4161 tabHeight
= (style
& FNB_BOTTOM
and [tabHeight
- 4] or [tabHeight
])[0]
4162 elif style
& FNB_FANCY_TABS
:
4163 tabHeight
= (style
& FNB_BOTTOM
and [tabHeight
- 3] or [tabHeight
])[0]
4165 width
, pom
= dc
.GetTextExtent(self
.GetPageText(ii
))
4166 if style
!= FNB_VC71
:
4167 shapePoints
= int(tabHeight
*math
.tan(float(self
._pagesInfoVec
[ii
].GetTabAngle())/180.0*math
.pi
))
4171 tabWidth
= 2*self
._pParent
._nPadding
+ width
4173 if not (style
& FNB_VC71
):
4175 tabWidth
+= 2*shapePoints
4177 hasImage
= self
._ImageList
!= None and self
._pagesInfoVec
[ii
].GetImageIndex() != -1
4179 # For VC71 style, we only add the icon size (16 pixels)
4182 if not self
.IsDefaultTabs():
4183 tabWidth
+= 16 + self
._pParent
._nPadding
4186 tabWidth
+= 16 + self
._pParent
._nPadding
+ shapePoints
/2
4188 if posx
+ tabWidth
+ render
.GetButtonsAreaLength(self
) >= clientWidth
:
4191 numTabs
= numTabs
+ 1
4197 def IsDefaultTabs(self
):
4198 """ Returns whether a tab has a default style. """
4200 style
= self
.GetParent().GetWindowStyleFlag()
4201 res
= (style
& FNB_VC71
) or (style
& FNB_FANCY_TABS
) or (style
& FNB_VC8
)
4205 def AdvanceSelection(self
, bForward
=True):
4207 Cycles through the tabs.
4208 The call to this function generates the page changing events.
4211 nSel
= self
.GetSelection()
4216 nMax
= self
.GetPageCount() - 1
4219 newSelection
= (nSel
== nMax
and [0] or [nSel
+ 1])[0]
4221 newSelection
= (nSel
== 0 and [nMax
] or [nSel
- 1])[0]
4223 if not self
._pagesInfoVec
[newSelection
].GetEnabled():
4226 self
.FireEvent(newSelection
)
4229 def OnMouseLeave(self
, event
):
4230 """ Handles the wx.EVT_LEAVE_WINDOW event for L{PageContainer}. """
4232 self
._nLeftButtonStatus
= FNB_BTN_NONE
4233 self
._nXButtonStatus
= FNB_BTN_NONE
4234 self
._nRightButtonStatus
= FNB_BTN_NONE
4235 self
._nTabXButtonStatus
= FNB_BTN_NONE
4236 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
4238 style
= self
.GetParent().GetWindowStyleFlag()
4239 render
= self
._mgr
.GetRenderer(style
)
4241 dc
= wx
.ClientDC(self
)
4243 render
.DrawX(self
, dc
)
4244 render
.DrawLeftArrow(self
, dc
)
4245 render
.DrawRightArrow(self
, dc
)
4247 selection
= self
.GetSelection()
4253 if not self
.IsTabVisible(selection
):
4254 if selection
== len(self
._pagesInfoVec
) - 1:
4255 if not self
.CanFitToScreen(selection
):
4262 render
.DrawTabX(self
, dc
, self
._pagesInfoVec
[selection
].GetXRect(), selection
, self
._nTabXButtonStatus
)
4267 def OnMouseEnterWindow(self
, event
):
4268 """ Handles the wx.EVT_ENTER_WINDOW event for L{PageContainer}. """
4270 self
._nLeftButtonStatus
= FNB_BTN_NONE
4271 self
._nXButtonStatus
= FNB_BTN_NONE
4272 self
._nRightButtonStatus
= FNB_BTN_NONE
4273 self
._nLeftClickZone
= FNB_BTN_NONE
4274 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
4279 def ShowTabTooltip(self
, tabIdx
):
4280 """ Shows a tab tooltip. """
4282 pWindow
= self
._pParent
.GetPage(tabIdx
)
4285 pToolTip
= pWindow
.GetToolTip()
4286 if pToolTip
and pToolTip
.GetWindow() == pWindow
:
4287 self
.SetToolTipString(pToolTip
.GetTip())
4290 def SetPageImage(self
, page
, imgindex
):
4291 """ Sets the image index associated to a page. """
4293 if page
< len(self
._pagesInfoVec
):
4295 self
._pagesInfoVec
[page
].SetImageIndex(imgindex
)
4299 def GetPageImage(self
, page
):
4300 """ Returns the image index associated to a page. """
4302 if page
< len(self
._pagesInfoVec
):
4304 return self
._pagesInfoVec
[page
].GetImageIndex()
4309 def OnDropTarget(self
, x
, y
, nTabPage
, wnd_oldContainer
):
4310 """ Handles the drop action from a DND operation. """
4312 # Disable drag'n'drop for disabled tab
4313 if not wnd_oldContainer
._pagesInfoVec
[nTabPage
].GetEnabled():
4314 return wx
.DragCancel
4316 self
._isdragging
= True
4317 oldContainer
= wnd_oldContainer
4320 where
, nIndex
= self
.HitTest(wx
.Point(x
, y
))
4322 oldNotebook
= oldContainer
.GetParent()
4323 newNotebook
= self
.GetParent()
4325 if oldNotebook
== newNotebook
:
4329 if where
== FNB_TAB
:
4330 self
.MoveTabPage(nTabPage
, nIndex
)
4332 elif self
.GetParent().GetWindowStyleFlag() & FNB_ALLOW_FOREIGN_DND
:
4334 if wx
.Platform
in ["__WXMSW__", "__WXGTK__"]:
4337 window
= oldNotebook
.GetPage(nTabPage
)
4340 where
, nIndex
= newNotebook
._pages
.HitTest(wx
.Point(x
, y
))
4341 caption
= oldContainer
.GetPageText(nTabPage
)
4342 imageindex
= oldContainer
.GetPageImage(nTabPage
)
4343 oldNotebook
.RemovePage(nTabPage
)
4344 window
.Reparent(newNotebook
)
4348 bmp
= oldNotebook
.GetImageList().GetIcon(imageindex
)
4349 newImageList
= newNotebook
.GetImageList()
4351 if not newImageList
:
4352 xbmp
, ybmp
= bmp
.GetWidth(), bmp
.GetHeight()
4353 newImageList
= wx
.ImageList(xbmp
, ybmp
)
4356 imageindex
= newImageList
.GetImageCount()
4358 newImageList
.AddIcon(bmp
)
4359 newNotebook
.SetImageList(newImageList
)
4361 newNotebook
.InsertPage(nIndex
, window
, caption
, True, imageindex
)
4363 self
._isdragging
= False
4368 def MoveTabPage(self
, nMove
, nMoveTo
):
4369 """ Moves a tab inside the same L{FlatNotebook}. """
4371 if nMove
== nMoveTo
:
4374 elif nMoveTo
< len(self
._pParent
._windows
):
4375 nMoveTo
= nMoveTo
+ 1
4377 self
._pParent
.Freeze()
4379 # Remove the window from the main sizer
4380 nCurSel
= self
._pParent
._pages
.GetSelection()
4381 self
._pParent
._mainSizer
.Detach(self
._pParent
._windows
[nCurSel
])
4382 self
._pParent
._windows
[nCurSel
].Hide()
4384 pWindow
= self
._pParent
._windows
[nMove
]
4385 self
._pParent
._windows
.pop(nMove
)
4386 self
._pParent
._windows
.insert(nMoveTo
-1, pWindow
)
4388 pgInfo
= self
._pagesInfoVec
[nMove
]
4390 self
._pagesInfoVec
.pop(nMove
)
4391 self
._pagesInfoVec
.insert(nMoveTo
- 1, pgInfo
)
4393 # Add the page according to the style
4394 pSizer
= self
._pParent
._mainSizer
4395 style
= self
.GetParent().GetWindowStyleFlag()
4397 if style
& FNB_BOTTOM
:
4399 pSizer
.Insert(0, pWindow
, 1, wx
.EXPAND
)
4403 # We leave a space of 1 pixel around the window
4404 pSizer
.Add(pWindow
, 1, wx
.EXPAND
)
4409 self
._iActivePage
= nMoveTo
- 1
4410 self
._iPreviousActivePage
= -1
4411 self
.DoSetSelection(self
._iActivePage
)
4413 self
._pParent
.Thaw()
4416 def CanFitToScreen(self
, page
):
4417 """ Returns wheter a tab can fit in the left space in the screen or not. """
4419 # Incase the from is greater than page,
4420 # we need to reset the self._nFrom, so in order
4421 # to force the caller to do so, we return false
4422 if self
._nFrom
> page
:
4425 style
= self
.GetParent().GetWindowStyleFlag()
4426 render
= self
._mgr
.GetRenderer(style
)
4428 if not self
.HasFlag(FNB_VC8
):
4429 rect
= self
.GetClientRect();
4430 clientWidth
= rect
.width
;
4431 tabHeight
= render
.CalcTabHeight(self
)
4432 tabWidth
= render
.CalcTabWidth(self
, page
, tabHeight
)
4434 posx
= self
._pParent
._nPadding
4436 if self
._nFrom
>= 0:
4438 for i
in xrange(self
._nFrom
, len(self
._pagesInfoVec
)):
4440 if self
._pagesInfoVec
[i
].GetPosition() == wx
.Point(-1, -1):
4443 posx
+= self
._pagesInfoVec
[i
].GetSize().x
4445 if posx
+ tabWidth
+ render
.GetButtonsAreaLength(self
) >= clientWidth
:
4452 # TODO:: this is ugly and should be improved, we should *never* access the
4453 # raw pointer directly like we do here (render.Get())
4455 vTabInfo
= vc8_render
.NumberTabsCanFit(self
)
4457 if page
- self
._nFrom
>= len(vTabInfo
):
4463 def GetNumOfVisibleTabs(self
):
4464 """ Returns the number of visible tabs. """
4467 for ii
in xrange(self
._nFrom
, len(self
._pagesInfoVec
)):
4468 if self
._pagesInfoVec
[ii
].GetPosition() == wx
.Point(-1, -1):
4475 def GetEnabled(self
, page
):
4476 """ Returns whether a tab is enabled or not. """
4478 if page
>= len(self
._pagesInfoVec
):
4479 return True # Seems strange, but this is the default
4481 return self
._pagesInfoVec
[page
].GetEnabled()
4484 def Enable(self
, page
, enabled
=True):
4485 """ Enables or disables a tab. """
4487 if page
>= len(self
._pagesInfoVec
):
4490 self
._pagesInfoVec
[page
].Enable(enabled
)
4493 def GetSingleLineBorderColour(self
):
4494 """ Returns the colour for the single line border. """
4496 if self
.HasFlag(FNB_FANCY_TABS
):
4497 return self
._colorFrom
4502 def HasFlag(self
, flag
):
4503 """ Returns whether a flag is present in the L{FlatNotebook} style. """
4505 style
= self
.GetParent().GetWindowStyleFlag()
4506 res
= (style
& flag
and [True] or [False])[0]
4510 def ClearFlag(self
, flag
):
4511 """ Deletes a flag from the L{FlatNotebook} style. """
4513 style
= self
.GetParent().GetWindowStyleFlag()
4515 self
.SetWindowStyleFlag(style
)
4518 def TabHasImage(self
, tabIdx
):
4519 """ Returns whether a tab has an associated image index or not. """
4522 return self
._pagesInfoVec
[tabIdx
].GetImageIndex() != -1
4527 def OnLeftDClick(self
, event
):
4528 """ Handles the wx.EVT_LEFT_DCLICK event for L{PageContainer}. """
4530 if self
.HasFlag(FNB_DCLICK_CLOSES_TABS
):
4532 where
, tabIdx
= self
.HitTest(event
.GetPosition())
4534 if where
== FNB_TAB
:
4535 self
.DeletePage(tabIdx
)
4542 def PopupTabsMenu(self
):
4543 """ Pops up the menu activated with the drop down arrow in the navigation area. """
4545 popupMenu
= wx
.Menu()
4547 for i
in xrange(len(self
._pagesInfoVec
)):
4548 pi
= self
._pagesInfoVec
[i
]
4549 item
= wx
.MenuItem(popupMenu
, i
, pi
.GetCaption(), pi
.GetCaption(), wx
.ITEM_NORMAL
)
4550 self
.Bind(wx
.EVT_MENU
, self
.OnTabMenuSelection
, item
)
4552 # This code is commented, since there is an alignment problem with wx2.6.3 & Menus
4553 # if self.TabHasImage(ii):
4554 # item.SetBitmaps( (*m_ImageList)[pi.GetImageIndex()] );
4556 popupMenu
.AppendItem(item
)
4557 item
.Enable(pi
.GetEnabled())
4559 self
.PopupMenu(popupMenu
)
4562 def OnTabMenuSelection(self
, event
):
4563 """ Handles the wx.EVT_MENU event for L{PageContainer}. """
4565 selection
= event
.GetId()
4566 self
.FireEvent(selection
)
4569 def FireEvent(self
, selection
):
4571 Fires the wxEVT_FLATNOTEBOOK_PAGE_CHANGING and wxEVT_FLATNOTEBOOK_PAGE_CHANGED events
4572 called from other methods (from menu selection or Smart Tabbing).
4576 if selection
== self
._iActivePage
:
4577 # No events for the same selection
4580 oldSelection
= self
._iActivePage
4582 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, self
.GetParent().GetId())
4583 event
.SetSelection(selection
)
4584 event
.SetOldSelection(oldSelection
)
4585 event
.SetEventObject(self
.GetParent())
4587 if not self
.GetParent().GetEventHandler().ProcessEvent(event
) or event
.IsAllowed():
4589 self
.SetSelection(selection
)
4591 # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
4592 event
.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
)
4593 event
.SetOldSelection(oldSelection
)
4594 self
.GetParent().GetEventHandler().ProcessEvent(event
)
4597 def SetImageList(self
, imglist
):
4598 """ Sets the image list for the page control. """
4600 self
._ImageList
= imglist
4603 def GetImageList(self
):
4604 """ Returns the image list for the page control. """
4606 return self
._ImageList
4609 def GetSelection(self
):
4610 """ Returns the current selected page. """
4612 return self
._iActivePage
4615 def GetPageCount(self
):
4616 """ Returns the number of tabs in the L{FlatNotebook} control. """
4618 return len(self
._pagesInfoVec
)
4621 def GetPageText(self
, page
):
4622 """ Returns the tab caption of the page. """
4624 return self
._pagesInfoVec
[page
].GetCaption()
4627 def SetPageText(self
, page
, text
):
4628 """ Sets the tab caption of the page. """
4630 self
._pagesInfoVec
[page
].SetCaption(text
)
4634 def DrawDragHint(self
):
4635 """ Draws small arrow at the place that the tab will be placed. """
4637 # get the index of tab that will be replaced with the dragged tab
4638 pt
= wx
.GetMousePosition()
4639 client_pt
= self
.ScreenToClient(pt
)
4640 where
, tabIdx
= self
.HitTest(client_pt
)
4641 self
._mgr
.GetRenderer(self
.GetParent().GetWindowStyleFlag()).DrawDragHint(self
, tabIdx
)