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 def NumberTabsCanFit(self
, pageContainer
, fr
=-1):
1795 rect
= pc
.GetClientRect()
1796 clientWidth
= rect
.width
1800 tabHeight
= self
.CalcTabHeight(pageContainer
)
1802 # The drawing starts from posx
1803 posx
= pc
._pParent
.GetPadding()
1808 for i
in xrange(fr
, len(pc
._pagesInfoVec
)):
1810 tabWidth
= self
.CalcTabWidth(pageContainer
, i
, tabHeight
)
1811 if posx
+ tabWidth
+ self
.GetButtonsAreaLength(pc
) >= clientWidth
:
1814 # Add a result to the returned vector
1815 tabRect
= wx
.Rect(posx
, VERTICAL_BORDER_PADDING
, tabWidth
, tabHeight
)
1816 vTabInfo
.append(tabRect
)
1819 posx
+= tabWidth
+ FNB_HEIGHT_SPACER
1824 # ---------------------------------------------------------------------------- #
1825 # Class FNBRendererMgr
1826 # A manager that handles all the renderers defined below and calls the
1827 # appropriate one when drawing is needed
1828 # ---------------------------------------------------------------------------- #
1830 class FNBRendererMgr
:
1832 This class represents a manager that handles all the 4 renderers defined
1833 and calls the appropriate one when drawing is needed.
1837 """ Default class constructor. """
1839 # register renderers
1841 self
._renderers
= {}
1842 self
._renderers
.update({-1: FNBRendererDefault()}
)
1843 self
._renderers
.update({FNB_VC71: FNBRendererVC71()}
)
1844 self
._renderers
.update({FNB_FANCY_TABS: FNBRendererFancy()}
)
1845 self
._renderers
.update({FNB_VC8: FNBRendererVC8()}
)
1848 def GetRenderer(self
, style
):
1849 """ Returns the current renderer based on the style selected. """
1851 # since we dont have a style for default tabs, we
1852 # test for all others - FIXME: add style for default tabs
1853 if not style
& FNB_VC71
and not style
& FNB_VC8
and not style
& FNB_FANCY_TABS
:
1854 return self
._renderers
[-1]
1856 if style
& FNB_VC71
:
1857 return self
._renderers
[FNB_VC71
]
1859 if style
& FNB_FANCY_TABS
:
1860 return self
._renderers
[FNB_FANCY_TABS
]
1863 return self
._renderers
[FNB_VC8
]
1865 # the default is to return the default renderer
1866 return self
._renderers
[-1]
1869 #------------------------------------------
1871 #------------------------------------------
1873 class FNBRendererDefault(FNBRenderer
):
1875 This class handles the drawing of tabs using the I{Standard} renderer.
1879 """ Default class constructor. """
1881 FNBRenderer
.__init
__(self
)
1884 def DrawTab(self
, pageContainer
, dc
, posx
, tabIdx
, tabWidth
, tabHeight
, btnStatus
):
1885 """ Draws a tab using the I{Standard} style. """
1888 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
1891 tabPoints
= [wx
.Point() for ii
in xrange(7)]
1892 tabPoints
[0].x
= posx
1893 tabPoints
[0].y
= (pc
.HasFlag(FNB_BOTTOM
) and [2] or [tabHeight
- 2])[0]
1895 tabPoints
[1].x
= int(posx
+(tabHeight
-2)*math
.tan(float(pc
._pagesInfoVec
[tabIdx
].GetTabAngle())/180.0*math
.pi
))
1896 tabPoints
[1].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- (VERTICAL_BORDER_PADDING
+2)] or [(VERTICAL_BORDER_PADDING
+2)])[0]
1898 tabPoints
[2].x
= tabPoints
[1].x
+2
1899 tabPoints
[2].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- VERTICAL_BORDER_PADDING
] or [VERTICAL_BORDER_PADDING
])[0]
1901 tabPoints
[3].x
= int(posx
+tabWidth
-(tabHeight
-2)*math
.tan(float(pc
._pagesInfoVec
[tabIdx
].GetTabAngle())/180.0*math
.pi
))-2
1902 tabPoints
[3].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- VERTICAL_BORDER_PADDING
] or [VERTICAL_BORDER_PADDING
])[0]
1904 tabPoints
[4].x
= tabPoints
[3].x
+2
1905 tabPoints
[4].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- (VERTICAL_BORDER_PADDING
+2)] or [(VERTICAL_BORDER_PADDING
+2)])[0]
1907 tabPoints
[5].x
= int(tabPoints
[4].x
+(tabHeight
-2)*math
.tan(float(pc
._pagesInfoVec
[tabIdx
].GetTabAngle())/180.0*math
.pi
))
1908 tabPoints
[5].y
= (pc
.HasFlag(FNB_BOTTOM
) and [2] or [tabHeight
- 2])[0]
1910 tabPoints
[6].x
= tabPoints
[0].x
1911 tabPoints
[6].y
= tabPoints
[0].y
1913 if tabIdx
== pc
.GetSelection():
1915 # Draw the tab as rounded rectangle
1916 dc
.DrawPolygon(tabPoints
)
1920 if tabIdx
!= pc
.GetSelection() - 1:
1922 # Draw a vertical line to the right of the text
1923 pt1x
= tabPoints
[5].x
1924 pt1y
= (pc
.HasFlag(FNB_BOTTOM
) and [4] or [tabHeight
- 6])[0]
1925 pt2x
= tabPoints
[5].x
1926 pt2y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- 4] or [4])[0]
1927 dc
.DrawLine(pt1x
, pt1y
, pt2x
, pt2y
)
1929 if tabIdx
== pc
.GetSelection():
1931 savePen
= dc
.GetPen()
1932 whitePen
= wx
.Pen(wx
.WHITE
)
1933 whitePen
.SetWidth(1)
1936 secPt
= wx
.Point(tabPoints
[5].x
+ 1, tabPoints
[5].y
)
1937 dc
.DrawLine(tabPoints
[0].x
, tabPoints
[0].y
, secPt
.x
, secPt
.y
)
1942 # -----------------------------------
1943 # Text and image drawing
1944 # -----------------------------------
1946 # Text drawing offset from the left border of the
1949 # The width of the images are 16 pixels
1950 padding
= pc
.GetParent().GetPadding()
1951 shapePoints
= int(tabHeight
*math
.tan(float(pc
._pagesInfoVec
[tabIdx
].GetTabAngle())/180.0*math
.pi
))
1952 hasImage
= pc
._pagesInfoVec
[tabIdx
].GetImageIndex() != -1
1953 imageYCoord
= (pc
.HasFlag(FNB_BOTTOM
) and [6] or [8])[0]
1956 textOffset
= 2*pc
._pParent
._nPadding
+ 16 + shapePoints
/2
1958 textOffset
= pc
._pParent
._nPadding
+ shapePoints
/2
1962 if tabIdx
!= pc
.GetSelection():
1964 # Set the text background to be like the vertical lines
1965 dc
.SetTextForeground(pc
._pParent
.GetNonActiveTabTextColour())
1969 imageXOffset
= textOffset
- 16 - padding
1970 pc
._ImageList
.Draw(pc
._pagesInfoVec
[tabIdx
].GetImageIndex(), dc
,
1971 posx
+ imageXOffset
, imageYCoord
,
1972 wx
.IMAGELIST_DRAW_TRANSPARENT
, True)
1974 dc
.DrawText(pc
.GetPageText(tabIdx
), posx
+ textOffset
, imageYCoord
)
1976 # draw 'x' on tab (if enabled)
1977 if pc
.HasFlag(FNB_X_ON_TAB
) and tabIdx
== pc
.GetSelection():
1979 textWidth
, textHeight
= dc
.GetTextExtent(pc
.GetPageText(tabIdx
))
1980 tabCloseButtonXCoord
= posx
+ textOffset
+ textWidth
+ 1
1982 # take a bitmap from the position of the 'x' button (the x on tab button)
1983 # this bitmap will be used later to delete old buttons
1984 tabCloseButtonYCoord
= imageYCoord
1985 x_rect
= wx
.Rect(tabCloseButtonXCoord
, tabCloseButtonYCoord
, 16, 16)
1986 self
._tabXBgBmp
= self
._GetBitmap
(dc
, x_rect
, self
._tabXBgBmp
)
1989 self
.DrawTabX(pc
, dc
, x_rect
, tabIdx
, btnStatus
)
1992 #------------------------------------------------------------------
1994 #------------------------------------------------------------------
1996 class FNBRendererVC71(FNBRenderer
):
1998 This class handles the drawing of tabs using the I{VC71} renderer.
2002 """ Default class constructor. """
2004 FNBRenderer
.__init
__(self
)
2007 def DrawTab(self
, pageContainer
, dc
, posx
, tabIdx
, tabWidth
, tabHeight
, btnStatus
):
2008 """ Draws a tab using the I{VC71} style. """
2010 # Visual studio 7.1 style
2011 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
2014 dc
.SetPen((tabIdx
== pc
.GetSelection() and [wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
))] or [borderPen
])[0])
2015 dc
.SetBrush((tabIdx
== pc
.GetSelection() and [wx
.Brush(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
))] or [wx
.Brush(wx
.Colour(247, 243, 233))])[0])
2017 if tabIdx
== pc
.GetSelection():
2019 posy
= (pc
.HasFlag(FNB_BOTTOM
) and [0] or [VERTICAL_BORDER_PADDING
])[0]
2020 tabH
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- 5] or [tabHeight
- 3])[0]
2021 dc
.DrawRectangle(posx
, posy
, tabWidth
, tabH
)
2023 # Draw a black line on the left side of the
2025 dc
.SetPen(wx
.BLACK_PEN
)
2027 blackLineY1
= VERTICAL_BORDER_PADDING
2029 dc
.DrawLine(posx
+ tabWidth
, blackLineY1
, posx
+ tabWidth
, blackLineY2
)
2031 # To give the tab more 3D look we do the following
2032 # Incase the tab is on top,
2033 # Draw a thik white line on topof the rectangle
2034 # Otherwise, draw a thin (1 pixel) black line at the bottom
2036 pen
= wx
.Pen((pc
.HasFlag(FNB_BOTTOM
) and [wx
.BLACK
] or [wx
.WHITE
])[0])
2038 whiteLinePosY
= (pc
.HasFlag(FNB_BOTTOM
) and [blackLineY2
] or [VERTICAL_BORDER_PADDING
])[0]
2039 dc
.DrawLine(posx
, whiteLinePosY
, posx
+ tabWidth
+ 1, whiteLinePosY
)
2041 # Draw a white vertical line to the left of the tab
2042 dc
.SetPen(wx
.WHITE_PEN
)
2043 if not pc
.HasFlag(FNB_BOTTOM
):
2046 dc
.DrawLine(posx
, blackLineY1
, posx
, blackLineY2
)
2050 # We dont draw a rectangle for non selected tabs, but only
2051 # vertical line on the left
2053 blackLineY1
= (pc
.HasFlag(FNB_BOTTOM
) and [VERTICAL_BORDER_PADDING
+ 2] or [VERTICAL_BORDER_PADDING
+ 1])[0]
2054 blackLineY2
= pc
.GetSize().y
- 5
2055 dc
.DrawLine(posx
+ tabWidth
, blackLineY1
, posx
+ tabWidth
, blackLineY2
)
2057 # -----------------------------------
2058 # Text and image drawing
2059 # -----------------------------------
2061 # Text drawing offset from the left border of the
2064 # The width of the images are 16 pixels
2065 padding
= pc
.GetParent().GetPadding()
2066 hasImage
= pc
._pagesInfoVec
[tabIdx
].GetImageIndex() != -1
2067 imageYCoord
= (pc
.HasFlag(FNB_BOTTOM
) and [5] or [8])[0]
2070 textOffset
= 2*pc
._pParent
._nPadding
+ 16
2072 textOffset
= pc
._pParent
._nPadding
2074 if tabIdx
!= pc
.GetSelection():
2076 # Set the text background to be like the vertical lines
2077 dc
.SetTextForeground(pc
._pParent
.GetNonActiveTabTextColour())
2081 imageXOffset
= textOffset
- 16 - padding
2082 pc
._ImageList
.Draw(pc
._pagesInfoVec
[tabIdx
].GetImageIndex(), dc
,
2083 posx
+ imageXOffset
, imageYCoord
,
2084 wx
.IMAGELIST_DRAW_TRANSPARENT
, True)
2086 dc
.DrawText(pc
.GetPageText(tabIdx
), posx
+ textOffset
, imageYCoord
)
2088 # draw 'x' on tab (if enabled)
2089 if pc
.HasFlag(FNB_X_ON_TAB
) and tabIdx
== pc
.GetSelection():
2091 textWidth
, textHeight
= dc
.GetTextExtent(pc
.GetPageText(tabIdx
))
2092 tabCloseButtonXCoord
= posx
+ textOffset
+ textWidth
+ 1
2094 # take a bitmap from the position of the 'x' button (the x on tab button)
2095 # this bitmap will be used later to delete old buttons
2096 tabCloseButtonYCoord
= imageYCoord
2097 x_rect
= wx
.Rect(tabCloseButtonXCoord
, tabCloseButtonYCoord
, 16, 16)
2098 self
._tabXBgBmp
= self
._GetBitmap
(dc
, x_rect
, self
._tabXBgBmp
)
2101 self
.DrawTabX(pc
, dc
, x_rect
, tabIdx
, btnStatus
)
2104 #------------------------------------------------------------------
2106 #------------------------------------------------------------------
2108 class FNBRendererFancy(FNBRenderer
):
2110 This class handles the drawing of tabs using the I{Fancy} renderer.
2114 """ Default class constructor. """
2116 FNBRenderer
.__init
__(self
)
2119 def DrawTab(self
, pageContainer
, dc
, posx
, tabIdx
, tabWidth
, tabHeight
, btnStatus
):
2120 """ Draws a tab using the I{Fancy} style, similar to VC71 but with gradients. """
2122 # Fancy tabs - like with VC71 but with the following differences:
2123 # - The Selected tab is colored with gradient color
2124 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
2127 pen
= (tabIdx
== pc
.GetSelection() and [wx
.Pen(pc
._pParent
.GetBorderColour())] or [wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
))])[0]
2129 if tabIdx
== pc
.GetSelection():
2131 posy
= (pc
.HasFlag(FNB_BOTTOM
) and [2] or [VERTICAL_BORDER_PADDING
])[0]
2134 rect
= wx
.Rect(posx
, posy
, tabWidth
, th
)
2136 col2
= (pc
.HasFlag(FNB_BOTTOM
) and [pc
._pParent
.GetGradientColourTo()] or [pc
._pParent
.GetGradientColourFrom()])[0]
2137 col1
= (pc
.HasFlag(FNB_BOTTOM
) and [pc
._pParent
.GetGradientColourFrom()] or [pc
._pParent
.GetGradientColourTo()])[0]
2139 PaintStraightGradientBox(dc
, rect
, col1
, col2
)
2140 dc
.SetBrush(wx
.TRANSPARENT_BRUSH
)
2142 dc
.DrawRectangleRect(rect
)
2144 # erase the bottom/top line of the rectangle
2145 dc
.SetPen(wx
.Pen(pc
._pParent
.GetGradientColourFrom()))
2146 if pc
.HasFlag(FNB_BOTTOM
):
2147 dc
.DrawLine(rect
.x
, 2, rect
.x
+ rect
.width
, 2)
2149 dc
.DrawLine(rect
.x
, rect
.y
+ rect
.height
- 1, rect
.x
+ rect
.width
, rect
.y
+ rect
.height
- 1)
2153 # We dont draw a rectangle for non selected tabs, but only
2154 # vertical line on the left
2155 dc
.SetPen(borderPen
)
2156 dc
.DrawLine(posx
+ tabWidth
, VERTICAL_BORDER_PADDING
+ 3, posx
+ tabWidth
, tabHeight
- 4)
2159 # -----------------------------------
2160 # Text and image drawing
2161 # -----------------------------------
2163 # Text drawing offset from the left border of the
2166 # The width of the images are 16 pixels
2167 padding
= pc
.GetParent().GetPadding()
2168 hasImage
= pc
._pagesInfoVec
[tabIdx
].GetImageIndex() != -1
2169 imageYCoord
= (pc
.HasFlag(FNB_BOTTOM
) and [6] or [8])[0]
2172 textOffset
= 2*pc
._pParent
._nPadding
+ 16
2174 textOffset
= pc
._pParent
._nPadding
2178 if tabIdx
!= pc
.GetSelection():
2180 # Set the text background to be like the vertical lines
2181 dc
.SetTextForeground(pc
._pParent
.GetNonActiveTabTextColour())
2185 imageXOffset
= textOffset
- 16 - padding
2186 pc
._ImageList
.Draw(pc
._pagesInfoVec
[tabIdx
].GetImageIndex(), dc
,
2187 posx
+ imageXOffset
, imageYCoord
,
2188 wx
.IMAGELIST_DRAW_TRANSPARENT
, True)
2190 dc
.DrawText(pc
.GetPageText(tabIdx
), posx
+ textOffset
, imageYCoord
)
2192 # draw 'x' on tab (if enabled)
2193 if pc
.HasFlag(FNB_X_ON_TAB
) and tabIdx
== pc
.GetSelection():
2195 textWidth
, textHeight
= dc
.GetTextExtent(pc
.GetPageText(tabIdx
))
2196 tabCloseButtonXCoord
= posx
+ textOffset
+ textWidth
+ 1
2198 # take a bitmap from the position of the 'x' button (the x on tab button)
2199 # this bitmap will be used later to delete old buttons
2200 tabCloseButtonYCoord
= imageYCoord
2201 x_rect
= wx
.Rect(tabCloseButtonXCoord
, tabCloseButtonYCoord
, 16, 16)
2202 self
._tabXBgBmp
= self
._GetBitmap
(dc
, x_rect
, self
._tabXBgBmp
)
2205 self
.DrawTabX(pc
, dc
, x_rect
, tabIdx
, btnStatus
)
2208 #------------------------------------------------------------------
2209 # Visual studio 2005 (VS8)
2210 #------------------------------------------------------------------
2211 class FNBRendererVC8(FNBRenderer
):
2213 This class handles the drawing of tabs using the I{VC8} renderer.
2217 """ Default class constructor. """
2219 FNBRenderer
.__init
__(self
)
2224 def DrawTabs(self
, pageContainer
, dc
):
2225 """ Draws all the tabs using VC8 style. Overloads The DrawTabs method in parent class. """
2229 if "__WXMAC__" in wx
.PlatformInfo
:
2230 # Works well on MSW & GTK, however this lines should be skipped on MAC
2231 if not pc
._pagesInfoVec
or pc
._nFrom
>= len(pc
._pagesInfoVec
):
2235 # Get the text hight
2236 tabHeight
= self
.CalcTabHeight(pageContainer
)
2238 # Set the font for measuring the tab height
2239 normalFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
2240 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
2241 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
2243 # Calculate the number of rows required for drawing the tabs
2244 rect
= pc
.GetClientRect()
2246 # Set the maximum client size
2247 pc
.SetSizeHints(self
.GetButtonsAreaLength(pc
), tabHeight
)
2248 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
2251 backBrush
= wx
.Brush(pc
._tabAreaColor
)
2252 noselBrush
= wx
.Brush(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNFACE
))
2253 selBrush
= wx
.Brush(pc
._activeTabColor
)
2257 dc
.SetTextBackground(pc
.GetBackgroundColour())
2258 dc
.SetTextForeground(pc
._activeTextColor
)
2260 # If border style is set, set the pen to be border pen
2261 if pc
.HasFlag(FNB_TABS_BORDER_SIMPLE
):
2262 dc
.SetPen(borderPen
)
2264 dc
.SetPen(wx
.TRANSPARENT_PEN
)
2266 lightFactor
= (pc
.HasFlag(FNB_BACKGROUND_GRADIENT
) and [70] or [0])[0]
2268 # For VC8 style, we color the tab area in gradient coloring
2269 lightcolour
= LightColour(pc
._tabAreaColor
, lightFactor
)
2270 PaintStraightGradientBox(dc
, pc
.GetClientRect(), pc
._tabAreaColor
, lightcolour
)
2272 dc
.SetBrush(wx
.TRANSPARENT_BRUSH
)
2273 dc
.DrawRectangle(0, 0, size
.x
, size
.y
)
2275 # Take 3 bitmaps for the background for the buttons
2277 mem_dc
= wx
.MemoryDC()
2278 #---------------------------------------
2280 #---------------------------------------
2281 rect
= wx
.Rect(self
.GetXPos(pc
), 6, 16, 14)
2282 mem_dc
.SelectObject(self
._xBgBmp
)
2283 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
2284 mem_dc
.SelectObject(wx
.NullBitmap
)
2286 #---------------------------------------
2288 #---------------------------------------
2289 rect
= wx
.Rect(self
.GetRightButtonPos(pc
), 6, 16, 14)
2290 mem_dc
.SelectObject(self
._rightBgBmp
)
2291 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
2292 mem_dc
.SelectObject(wx
.NullBitmap
)
2294 #---------------------------------------
2296 #---------------------------------------
2297 rect
= wx
.Rect(self
.GetLeftButtonPos(pc
), 6, 16, 14)
2298 mem_dc
.SelectObject(self
._leftBgBmp
)
2299 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
2300 mem_dc
.SelectObject(wx
.NullBitmap
)
2302 # We always draw the bottom/upper line of the tabs
2303 # regradless the style
2304 dc
.SetPen(borderPen
)
2305 self
.DrawTabsLine(pc
, dc
)
2308 dc
.SetPen(borderPen
)
2311 dc
.SetFont(boldFont
)
2313 # Update all the tabs from 0 to 'pc.self._nFrom' to be non visible
2314 for i
in xrange(pc
._nFrom
):
2316 pc
._pagesInfoVec
[i
].SetPosition(wx
.Point(-1, -1))
2317 pc
._pagesInfoVec
[i
].GetRegion().Clear()
2319 # Draw the visible tabs, in VC8 style, we draw them from right to left
2320 vTabsInfo
= self
.NumberTabsCanFit(pc
)
2326 for cur
in xrange(len(vTabsInfo
)-1, -1, -1):
2328 # 'i' points to the index of the currently drawn tab
2329 # in pc.GetPageInfoVector() vector
2331 dc
.SetPen(borderPen
)
2332 dc
.SetBrush((i
==pc
.GetSelection() and [selBrush
] or [noselBrush
])[0])
2334 # Now set the font to the correct font
2335 dc
.SetFont((i
==pc
.GetSelection() and [boldFont
] or [normalFont
])[0])
2337 # Add the padding to the tab width
2339 # +-----------------------------------------------------------+
2340 # | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING |
2341 # +-----------------------------------------------------------+
2343 tabWidth
= self
.CalcTabWidth(pageContainer
, i
, tabHeight
)
2344 posx
= vTabsInfo
[cur
].x
2346 # By default we clean the tab region
2347 # incase we use the VC8 style which requires
2348 # the region, it will be filled by the function
2350 pc
._pagesInfoVec
[i
].GetRegion().Clear()
2352 # Clean the 'x' buttn on the tab
2353 # 'Clean' rectanlge is a rectangle with width or height
2354 # with values lower than or equal to 0
2355 pc
._pagesInfoVec
[i
].GetXRect().SetSize(wx
.Size(-1, -1))
2358 # Incase we are drawing the active tab
2359 # we need to redraw so it will appear on top
2362 # when using the vc8 style, we keep the position of the active tab so we will draw it again later
2363 if i
== pc
.GetSelection() and pc
.HasFlag(FNB_VC8
):
2365 activeTabPosx
= posx
2366 activeTabWidth
= tabWidth
2367 activeTabHeight
= tabHeight
2371 self
.DrawTab(pc
, dc
, posx
, i
, tabWidth
, tabHeight
, pc
._nTabXButtonStatus
)
2373 # Restore the text forground
2374 dc
.SetTextForeground(pc
._activeTextColor
)
2376 # Update the tab position & size
2377 pc
._pagesInfoVec
[i
].SetPosition(wx
.Point(posx
, VERTICAL_BORDER_PADDING
))
2378 pc
._pagesInfoVec
[i
].SetSize(wx
.Size(tabWidth
, tabHeight
))
2380 # Incase we are in VC8 style, redraw the active tab (incase it is visible)
2381 if pc
.GetSelection() >= pc
._nFrom
and pc
.GetSelection() < pc
._nFrom
+ len(vTabsInfo
):
2383 self
.DrawTab(pc
, dc
, activeTabPosx
, pc
.GetSelection(), activeTabWidth
, activeTabHeight
, pc
._nTabXButtonStatus
)
2385 # Update all tabs that can not fit into the screen as non-visible
2386 for xx
in xrange(pc
._nFrom
+ len(vTabsInfo
), len(pc
._pagesInfoVec
)):
2388 pc
._pagesInfoVec
[xx
].SetPosition(wx
.Point(-1, -1))
2389 pc
._pagesInfoVec
[xx
].GetRegion().Clear()
2391 # Draw the left/right/close buttons
2393 self
.DrawLeftArrow(pc
, dc
)
2394 self
.DrawRightArrow(pc
, dc
)
2396 self
.DrawDropDownArrow(pc
, dc
)
2399 def DrawTab(self
, pageContainer
, dc
, posx
, tabIdx
, tabWidth
, tabHeight
, btnStatus
):
2400 """ Draws a tab using VC8 style. """
2403 borderPen
= wx
.Pen(pc
._pParent
.GetBorderColour())
2404 tabPoints
= [wx
.Point() for ii
in xrange(8)]
2406 # If we draw the first tab or the active tab,
2407 # we draw a full tab, else we draw a truncated tab
2418 tabPoints
[0].x
= (pc
.HasFlag(FNB_BOTTOM
) and [posx
] or [posx
+self
._factor
])[0]
2419 tabPoints
[0].y
= (pc
.HasFlag(FNB_BOTTOM
) and [2] or [tabHeight
- 3])[0]
2421 tabPoints
[1].x
= tabPoints
[0].x
+ tabHeight
- VERTICAL_BORDER_PADDING
- 3 - self
._factor
2422 tabPoints
[1].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- (VERTICAL_BORDER_PADDING
+2)] or [(VERTICAL_BORDER_PADDING
+2)])[0]
2424 tabPoints
[2].x
= tabPoints
[1].x
+ 4
2425 tabPoints
[2].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- VERTICAL_BORDER_PADDING
] or [VERTICAL_BORDER_PADDING
])[0]
2427 tabPoints
[3].x
= tabPoints
[2].x
+ tabWidth
- 2
2428 tabPoints
[3].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- VERTICAL_BORDER_PADDING
] or [VERTICAL_BORDER_PADDING
])[0]
2430 tabPoints
[4].x
= tabPoints
[3].x
+ 1
2431 tabPoints
[4].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabPoints
[3].y
- 1] or [tabPoints
[3].y
+ 1])[0]
2433 tabPoints
[5].x
= tabPoints
[4].x
+ 1
2434 tabPoints
[5].y
= (pc
.HasFlag(FNB_BOTTOM
) and [(tabPoints
[4].y
- 1)] or [tabPoints
[4].y
+ 1])[0]
2436 tabPoints
[6].x
= tabPoints
[2].x
+ tabWidth
2437 tabPoints
[6].y
= tabPoints
[0].y
2439 tabPoints
[7].x
= tabPoints
[0].x
2440 tabPoints
[7].y
= tabPoints
[0].y
2442 pc
._pagesInfoVec
[tabIdx
].SetRegion(tabPoints
)
2446 dc
.SetBrush(wx
.Brush((tabIdx
== pc
.GetSelection() and [pc
._activeTabColor
] or [pc
._colorTo
])[0]))
2447 dc
.SetPen(wx
.Pen((tabIdx
== pc
.GetSelection() and [wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)] or [pc
._colorBorder
])[0]))
2448 dc
.DrawPolygon(tabPoints
)
2452 rect
= pc
.GetClientRect()
2454 if tabIdx
!= pc
.GetSelection() and not pc
.HasFlag(FNB_BOTTOM
):
2457 dc
.SetPen(wx
.Pen(pc
._pParent
.GetBorderColour()))
2459 curPen
= dc
.GetPen()
2462 dc
.DrawLine(posx
, lineY
, posx
+rect
.width
, lineY
)
2464 # Incase we are drawing the selected tab, we draw the border of it as well
2465 # but without the bottom (upper line incase of wxBOTTOM)
2466 if tabIdx
== pc
.GetSelection():
2468 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
2469 dc
.SetPen(borderPen
)
2470 dc
.SetBrush(wx
.TRANSPARENT_BRUSH
)
2471 dc
.DrawPolygon(tabPoints
)
2473 # Delete the bottom line (or the upper one, incase we use wxBOTTOM)
2474 dc
.SetPen(wx
.WHITE_PEN
)
2475 dc
.DrawLine(tabPoints
[0].x
, tabPoints
[0].y
, tabPoints
[6].x
, tabPoints
[6].y
)
2477 self
.FillVC8GradientColour(pc
, dc
, tabPoints
, tabIdx
== pc
.GetSelection(), tabIdx
)
2479 # Draw a thin line to the right of the non-selected tab
2480 if tabIdx
!= pc
.GetSelection():
2482 dc
.SetPen(wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
)))
2483 dc
.DrawLine(tabPoints
[4].x
-1, tabPoints
[4].y
, tabPoints
[5].x
-1, tabPoints
[5].y
)
2484 dc
.DrawLine(tabPoints
[5].x
-1, tabPoints
[5].y
, tabPoints
[6].x
-1, tabPoints
[6].y
)
2486 # Text drawing offset from the left border of the
2489 # The width of the images are 16 pixels
2490 vc8ShapeLen
= tabHeight
- VERTICAL_BORDER_PADDING
- 2
2491 if pc
.TabHasImage(tabIdx
):
2492 textOffset
= 2*pc
._pParent
.GetPadding() + 16 + vc8ShapeLen
2494 textOffset
= pc
._pParent
.GetPadding() + vc8ShapeLen
2496 # Draw the image for the tab if any
2497 imageYCoord
= (pc
.HasFlag(FNB_BOTTOM
) and [6] or [8])[0]
2499 if pc
.TabHasImage(tabIdx
):
2501 imageXOffset
= textOffset
- 16 - pc
._pParent
.GetPadding()
2502 pc
._ImageList
.Draw(pc
._pagesInfoVec
[tabIdx
].GetImageIndex(), dc
,
2503 posx
+ imageXOffset
, imageYCoord
,
2504 wx
.IMAGELIST_DRAW_TRANSPARENT
, True)
2506 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
2508 # if selected tab, draw text in bold
2509 if tabIdx
== pc
.GetSelection():
2510 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
2512 dc
.SetFont(boldFont
)
2513 dc
.DrawText(pc
.GetPageText(tabIdx
), posx
+ textOffset
, imageYCoord
)
2515 # draw 'x' on tab (if enabled)
2516 if pc
.HasFlag(FNB_X_ON_TAB
) and tabIdx
== pc
.GetSelection():
2518 textWidth
, textHeight
= dc
.GetTextExtent(pc
.GetPageText(tabIdx
))
2519 tabCloseButtonXCoord
= posx
+ textOffset
+ textWidth
+ 1
2521 # take a bitmap from the position of the 'x' button (the x on tab button)
2522 # this bitmap will be used later to delete old buttons
2523 tabCloseButtonYCoord
= imageYCoord
2524 x_rect
= wx
.Rect(tabCloseButtonXCoord
, tabCloseButtonYCoord
, 16, 16)
2525 self
._tabXBgBmp
= self
._GetBitmap
(dc
, x_rect
, self
._tabXBgBmp
)
2527 self
.DrawTabX(pc
, dc
, x_rect
, tabIdx
, btnStatus
)
2530 def FillVC8GradientColour(self
, pageContainer
, dc
, tabPoints
, bSelectedTab
, tabIdx
):
2531 """ Fills a tab with a gradient shading. """
2533 # calculate gradient coefficients
2538 pc
._colorTo
= LightColour(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
), 0)
2539 pc
._colorFrom
= LightColour(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
), 60)
2541 col2
= (pc
.HasFlag(FNB_BOTTOM
) and [pc
._pParent
.GetGradientColourTo()] or [pc
._pParent
.GetGradientColourFrom()])[0]
2542 col1
= (pc
.HasFlag(FNB_BOTTOM
) and [pc
._pParent
.GetGradientColourFrom()] or [pc
._pParent
.GetGradientColourTo()])[0]
2544 # If colorful tabs style is set, override the tab color
2545 if pc
.HasFlag(FNB_COLORFUL_TABS
):
2547 if not pc
._pagesInfoVec
[tabIdx
].GetColour():
2549 # First time, generate color, and keep it in the vector
2550 tabColor
= RandomColour()
2551 pc
._pagesInfoVec
[tabIdx
].SetColour(tabColor
)
2553 if pc
.HasFlag(FNB_BOTTOM
):
2555 col2
= LightColour(pc
._pagesInfoVec
[tabIdx
].GetColour(), 50)
2556 col1
= LightColour(pc
._pagesInfoVec
[tabIdx
].GetColour(), 80)
2560 col1
= LightColour(pc
._pagesInfoVec
[tabIdx
].GetColour(), 50)
2561 col2
= LightColour(pc
._pagesInfoVec
[tabIdx
].GetColour(), 80)
2563 size
= abs(tabPoints
[2].y
- tabPoints
[0].y
) - 1
2565 rf
, gf
, bf
= 0, 0, 0
2566 rstep
= float(col2
.Red() - col1
.Red())/float(size
)
2567 gstep
= float(col2
.Green() - col1
.Green())/float(size
)
2568 bstep
= float(col2
.Blue() - col1
.Blue())/float(size
)
2572 # If we are drawing the selected tab, we need also to draw a line
2573 # from 0.tabPoints[0].x and tabPoints[6].x . end, we achieve this
2574 # by drawing the rectangle with transparent brush
2575 # the line under the selected tab will be deleted by the drwaing loop
2577 self
.DrawTabsLine(pc
, dc
)
2581 if pc
.HasFlag(FNB_BOTTOM
):
2583 if y
> tabPoints
[0].y
+ size
:
2588 if y
< tabPoints
[0].y
- size
:
2591 currCol
= wx
.Colour(col1
.Red() + rf
, col1
.Green() + gf
, col1
.Blue() + bf
)
2593 dc
.SetPen((bSelectedTab
and [wx
.Pen(pc
._activeTabColor
)] or [wx
.Pen(currCol
)])[0])
2594 startX
= self
.GetStartX(tabPoints
, y
, pc
.GetParent().GetWindowStyleFlag())
2595 endX
= self
.GetEndX(tabPoints
, y
, pc
.GetParent().GetWindowStyleFlag())
2596 dc
.DrawLine(startX
, y
, endX
, y
)
2598 # Draw the border using the 'edge' point
2599 dc
.SetPen(wx
.Pen((bSelectedTab
and [wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)] or [pc
._colorBorder
])[0]))
2601 dc
.DrawPoint(startX
, y
)
2602 dc
.DrawPoint(endX
, y
)
2604 # Progress the color
2609 if pc
.HasFlag(FNB_BOTTOM
):
2615 def GetStartX(self
, tabPoints
, y
, style
):
2616 """ Returns the x start position of a tab. """
2618 x1
, x2
, y1
, y2
= 0.0, 0.0, 0.0, 0.0
2620 # We check the 3 points to the left
2622 bBottomStyle
= (style
& FNB_BOTTOM
and [True] or [False])[0]
2629 if y
>= tabPoints
[i
].y
and y
< tabPoints
[i
+1].y
:
2632 x2
= tabPoints
[i
+1].x
2634 y2
= tabPoints
[i
+1].y
2642 if y
<= tabPoints
[i
].y
and y
> tabPoints
[i
+1].y
:
2645 x2
= tabPoints
[i
+1].x
2647 y2
= tabPoints
[i
+1].y
2652 return tabPoints
[2].x
2654 # According to the equation y = ax + b => x = (y-b)/a
2655 # We know the first 2 points
2660 a
= (y2
- y1
)/(x2
- x1
)
2662 b
= y1
- ((y2
- y1
)/(x2
- x1
))*x1
2672 def GetEndX(self
, tabPoints
, y
, style
):
2673 """ Returns the x end position of a tab. """
2675 x1
, x2
, y1
, y2
= 0.0, 0.0, 0.0, 0.0
2677 # We check the 3 points to the left
2678 bBottomStyle
= (style
& FNB_BOTTOM
and [True] or [False])[0]
2683 for i
in xrange(7, 3, -1):
2685 if y
>= tabPoints
[i
].y
and y
< tabPoints
[i
-1].y
:
2688 x2
= tabPoints
[i
-1].x
2690 y2
= tabPoints
[i
-1].y
2696 for i
in xrange(7, 3, -1):
2698 if y
<= tabPoints
[i
].y
and y
> tabPoints
[i
-1].y
:
2701 x2
= tabPoints
[i
-1].x
2703 y2
= tabPoints
[i
-1].y
2708 return tabPoints
[3].x
2710 # According to the equation y = ax + b => x = (y-b)/a
2711 # We know the first 2 points
2717 a
= (y2
- y1
)/(x2
- x1
)
2718 b
= y1
- ((y2
- y1
)/(x2
- x1
))*x1
2728 def NumberTabsCanFit(self
, pageContainer
, fr
=-1):
2729 """ Returns the number of tabs that can fit in the visible area. """
2733 rect
= pc
.GetClientRect()
2734 clientWidth
= rect
.width
2738 tabHeight
= self
.CalcTabHeight(pageContainer
)
2740 # The drawing starts from posx
2741 posx
= pc
._pParent
.GetPadding()
2746 for i
in xrange(fr
, len(pc
._pagesInfoVec
)):
2748 vc8glitch
= tabHeight
+ FNB_HEIGHT_SPACER
2749 tabWidth
= self
.CalcTabWidth(pageContainer
, i
, tabHeight
)
2751 if posx
+ tabWidth
+ vc8glitch
+ self
.GetButtonsAreaLength(pc
) >= clientWidth
:
2754 # Add a result to the returned vector
2755 tabRect
= wx
.Rect(posx
, VERTICAL_BORDER_PADDING
, tabWidth
, tabHeight
)
2756 vTabInfo
.append(tabRect
)
2759 posx
+= tabWidth
+ FNB_HEIGHT_SPACER
2764 # ---------------------------------------------------------------------------- #
2765 # Class FlatNotebook
2766 # ---------------------------------------------------------------------------- #
2768 class FlatNotebook(wx
.Panel
):
2770 Display one or more windows in a notebook.
2773 - B{EVT_FLATNOTEBOOK_PAGE_CHANGING}: sent when the active
2774 page in the notebook is changing
2775 - B{EVT_FLATNOTEBOOK_PAGE_CHANGED}: sent when the active
2776 page in the notebook has changed
2777 - B{EVT_FLATNOTEBOOK_PAGE_CLOSING}: sent when a page in the
2779 - B{EVT_FLATNOTEBOOK_PAGE_CLOSED}: sent when a page in the
2780 notebook has been closed
2781 - B{EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU}: sent when the user
2782 clicks a tab in the notebook with the right mouse
2786 def __init__(self
, parent
, id=wx
.ID_ANY
, pos
=wx
.DefaultPosition
, size
=wx
.DefaultSize
,
2787 style
=0, name
="FlatNotebook"):
2789 Default class constructor.
2791 All the parameters are as in wxPython class construction, except the
2792 'style': this can be assigned to whatever combination of FNB_* styles.
2796 self
._bForceSelection
= False
2799 style |
= wx
.TAB_TRAVERSAL
2802 self
._popupWin
= None
2804 wx
.Panel
.__init
__(self
, parent
, id, pos
, size
, style
)
2806 self
._pages
= PageContainer(self
, wx
.ID_ANY
, wx
.DefaultPosition
, wx
.DefaultSize
, style
)
2808 self
.Bind(wx
.EVT_NAVIGATION_KEY
, self
.OnNavigationKey
)
2814 """ Initializes all the class attributes. """
2816 self
._pages
._colorBorder
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)
2818 self
._mainSizer
= wx
.BoxSizer(wx
.VERTICAL
)
2819 self
.SetSizer(self
._mainSizer
)
2821 # The child panels will inherit this bg color, so leave it at the default value
2822 #self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_APPWORKSPACE))
2824 # Set default page height
2825 dc
= wx
.ClientDC(self
)
2827 if "__WXGTK__" in wx
.PlatformInfo
:
2828 # For GTK it seems that we must do this steps in order
2829 # for the tabs will get the proper height on initialization
2830 # on MSW, preforming these steps yields wierd results
2831 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
2832 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
2833 dc
.SetFont(boldFont
)
2835 height
= dc
.GetCharHeight()
2837 tabHeight
= height
+ FNB_HEIGHT_SPACER
# We use 8 pixels as padding
2839 if "__WXGTK__" in wx
.PlatformInfo
:
2842 self
._pages
.SetSizeHints(-1, tabHeight
)
2843 # Add the tab container to the sizer
2844 self
._mainSizer
.Insert(0, self
._pages
, 0, wx
.EXPAND
)
2845 self
._mainSizer
.Layout()
2847 self
._pages
._nFrom
= self
._nFrom
2848 self
._pDropTarget
= FNBDropTarget(self
)
2849 self
.SetDropTarget(self
._pDropTarget
)
2852 def SetActiveTabTextColour(self
, textColour
):
2853 """ Sets the text colour for the active tab. """
2855 self
._pages
._activeTextColor
= textColour
2858 def OnDropTarget(self
, x
, y
, nTabPage
, wnd_oldContainer
):
2859 """ Handles the drop action from a DND operation. """
2861 return self
._pages
.OnDropTarget(x
, y
, nTabPage
, wnd_oldContainer
)
2864 def GetPreviousSelection(self
):
2865 """ Returns the previous selection. """
2867 return self
._pages
._iPreviousActivePage
2870 def AddPage(self
, page
, text
, select
=True, imageId
=-1):
2872 Add a page to the L{FlatNotebook}.
2874 @param page: Specifies the new page.
2875 @param text: Specifies the text for the new page.
2876 @param select: Specifies whether the page should be selected.
2877 @param imageId: Specifies the optional image index for the new page.
2880 True if successful, False otherwise.
2887 # reparent the window to us
2891 bSelected
= select
or len(self
._windows
) == 0
2897 # Check for selection and send events
2898 oldSelection
= self
._pages
._iActivePage
2899 tabIdx
= len(self
._windows
)
2901 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, self
.GetId())
2902 event
.SetSelection(tabIdx
)
2903 event
.SetOldSelection(oldSelection
)
2904 event
.SetEventObject(self
)
2906 if not self
.GetEventHandler().ProcessEvent(event
) or event
.IsAllowed() or len(self
._windows
) == 0:
2909 curSel
= self
._pages
.GetSelection()
2911 if not self
._pages
.IsShown():
2914 self
._pages
.AddPage(text
, bSelected
, imageId
)
2915 self
._windows
.append(page
)
2919 # Check if a new selection was made
2924 # Remove the window from the main sizer
2925 self
._mainSizer
.Detach(self
._windows
[curSel
])
2926 self
._windows
[curSel
].Hide()
2928 if self
.GetWindowStyleFlag() & FNB_BOTTOM
:
2930 self
._mainSizer
.Insert(0, page
, 1, wx
.EXPAND
)
2934 # We leave a space of 1 pixel around the window
2935 self
._mainSizer
.Add(page
, 1, wx
.EXPAND
)
2937 # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
2938 event
.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
)
2939 event
.SetOldSelection(oldSelection
)
2940 self
.GetEventHandler().ProcessEvent(event
)
2948 self
._mainSizer
.Layout()
2954 def SetImageList(self
, imageList
):
2956 Sets the image list for the page control. It does not take ownership
2957 of the image list, you must delete it yourself.
2960 self
._pages
.SetImageList(imageList
)
2963 def GetImageList(self
):
2964 """ Returns the associated image list. """
2966 return self
._pages
.GetImageList()
2969 def InsertPage(self
, indx
, page
, text
, select
=True, imageId
=-1):
2971 Inserts a new page at the specified position.
2973 @param indx: Specifies the position of the new page.
2974 @param page: Specifies the new page.
2975 @param text: Specifies the text for the new page.
2976 @param select: Specifies whether the page should be selected.
2977 @param imageId: Specifies the optional image index for the new page.
2980 True if successful, False otherwise.
2987 # reparent the window to us
2990 if not self
._windows
:
2992 self
.AddPage(page
, text
, select
, imageId
)
2996 bSelected
= select
or not self
._windows
2997 curSel
= self
._pages
.GetSelection()
2999 indx
= max(0, min(indx
, len(self
._windows
)))
3001 if indx
<= len(self
._windows
):
3003 self
._windows
.insert(indx
, page
)
3007 self
._windows
.append(page
)
3013 # Check for selection and send events
3014 oldSelection
= self
._pages
._iActivePage
3016 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, self
.GetId())
3017 event
.SetSelection(indx
)
3018 event
.SetOldSelection(oldSelection
)
3019 event
.SetEventObject(self
)
3021 if not self
.GetEventHandler().ProcessEvent(event
) or event
.IsAllowed() or len(self
._windows
) == 0:
3024 self
._pages
.InsertPage(indx
, text
, bSelected
, imageId
)
3031 # Check if a new selection was made
3036 # Remove the window from the main sizer
3037 self
._mainSizer
.Detach(self
._windows
[curSel
])
3038 self
._windows
[curSel
].Hide()
3040 self
._pages
.SetSelection(indx
)
3042 # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
3043 event
.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
)
3044 event
.SetOldSelection(oldSelection
)
3045 self
.GetEventHandler().ProcessEvent(event
)
3053 self
._mainSizer
.Layout()
3059 def SetSelection(self
, page
):
3061 Sets the selection for the given page.
3062 The call to this function generates the page changing events
3065 if page
>= len(self
._windows
) or not self
._windows
:
3068 # Support for disabed tabs
3069 if not self
._pages
.GetEnabled(page
) and len(self
._windows
) > 1 and not self
._bForceSelection
:
3072 curSel
= self
._pages
.GetSelection()
3074 # program allows the page change
3078 # Remove the window from the main sizer
3079 self
._mainSizer
.Detach(self
._windows
[curSel
])
3080 self
._windows
[curSel
].Hide()
3082 if self
.GetWindowStyleFlag() & FNB_BOTTOM
:
3084 self
._mainSizer
.Insert(0, self
._windows
[page
], 1, wx
.EXPAND
)
3088 # We leave a space of 1 pixel around the window
3089 self
._mainSizer
.Add(self
._windows
[page
], 1, wx
.EXPAND
)
3091 self
._windows
[page
].Show()
3094 self
._mainSizer
.Layout()
3096 if page
!= self
._pages
._iActivePage
:
3097 # there is a real page changing
3098 self
._pages
._iPreviousActivePage
= self
._pages
._iActivePage
3100 self
._pages
._iActivePage
= page
3101 self
._pages
.DoSetSelection(page
)
3104 def DeletePage(self
, page
):
3106 Deletes the specified page, and the associated window.
3107 The call to this function generates the page changing events.
3110 if page
>= len(self
._windows
) or page
< 0:
3113 # Fire a closing event
3114 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING
, self
.GetId())
3115 event
.SetSelection(page
)
3116 event
.SetEventObject(self
)
3117 self
.GetEventHandler().ProcessEvent(event
)
3119 # The event handler allows it?
3120 if not event
.IsAllowed():
3125 # Delete the requested page
3126 pageRemoved
= self
._windows
[page
]
3128 # If the page is the current window, remove it from the sizer
3130 if page
== self
._pages
.GetSelection():
3131 self
._mainSizer
.Detach(pageRemoved
)
3133 # Remove it from the array as well
3134 self
._windows
.pop(page
)
3136 # Now we can destroy it in wxWidgets use Destroy instead of delete
3137 pageRemoved
.Destroy()
3141 self
._pages
.DoDeletePage(page
)
3144 # Fire a closed event
3145 closedEvent
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSED
, self
.GetId())
3146 closedEvent
.SetSelection(page
)
3147 closedEvent
.SetEventObject(self
)
3148 self
.GetEventHandler().ProcessEvent(closedEvent
)
3151 def DeleteAllPages(self
):
3152 """ Deletes all the pages. """
3154 if not self
._windows
:
3159 for page
in self
._windows
:
3165 # Clear the container of the tabs as well
3166 self
._pages
.DeleteAllPages()
3170 def GetCurrentPage(self
):
3171 """ Returns the currently selected notebook page or None. """
3173 sel
= self
._pages
.GetSelection()
3177 return self
._windows
[sel
]
3180 def GetPage(self
, page
):
3181 """ Returns the window at the given page position, or None. """
3183 if page
>= len(self
._windows
):
3186 return self
._windows
[page
]
3189 def GetPageIndex(self
, win
):
3190 """ Returns the index at which the window is found. """
3193 return self
._windows
.index(win
)
3198 def GetSelection(self
):
3199 """ Returns the currently selected page, or -1 if none was selected. """
3201 return self
._pages
.GetSelection()
3204 def AdvanceSelection(self
, forward
=True):
3206 Cycles through the tabs.
3207 The call to this function generates the page changing events.
3210 self
._pages
.AdvanceSelection(forward
)
3213 def GetPageCount(self
):
3214 """ Returns the number of pages in the L{FlatNotebook} control. """
3216 return self
._pages
.GetPageCount()
3219 def OnNavigationKey(self
, event
):
3220 """ Handles the wx.EVT_NAVIGATION_KEY event for L{FlatNotebook}. """
3222 if event
.IsWindowChange():
3223 if len(self
._windows
) == 0:
3226 if self
.HasFlag(FNB_SMART_TABS
):
3227 if not self
._popupWin
:
3228 self
._popupWin
= TabNavigatorWindow(self
)
3229 self
._popupWin
.SetReturnCode(wx
.ID_OK
)
3230 self
._popupWin
.ShowModal()
3231 self
._popupWin
.Destroy()
3232 self
._popupWin
= None
3234 # a dialog is already opened
3235 self
._popupWin
.OnNavigationKey(event
)
3239 self
.AdvanceSelection(event
.GetDirection())
3241 # pass to the parent
3242 if self
.GetParent():
3243 event
.SetCurrentFocus(self
)
3244 self
.GetParent().ProcessEvent(event
)
3247 def GetPageShapeAngle(self
, page_index
):
3248 """ Returns the angle associated to a tab. """
3250 if page_index
< 0 or page_index
>= len(self
._pages
._pagesInfoVec
):
3253 result
= self
._pages
._pagesInfoVec
[page_index
].GetTabAngle()
3257 def SetPageShapeAngle(self
, page_index
, angle
):
3258 """ Sets the angle associated to a tab. """
3260 if page_index
< 0 or page_index
>= len(self
._pages
._pagesInfoVec
):
3266 self
._pages
._pagesInfoVec
[page_index
].SetTabAngle(angle
)
3269 def SetAllPagesShapeAngle(self
, angle
):
3270 """ Sets the angle associated to all the tab. """
3275 for ii
in xrange(len(self
._pages
._pagesInfoVec
)):
3276 self
._pages
._pagesInfoVec
[ii
].SetTabAngle(angle
)
3281 def GetPageBestSize(self
):
3282 """ Return the page best size. """
3284 return self
._pages
.GetClientSize()
3287 def SetPageText(self
, page
, text
):
3288 """ Sets the text for the given page. """
3290 bVal
= self
._pages
.SetPageText(page
, text
)
3291 self
._pages
.Refresh()
3296 def SetPadding(self
, padding
):
3298 Sets the amount of space around each page's icon and label, in pixels.
3299 NB: only the horizontal padding is considered.
3302 self
._nPadding
= padding
.GetWidth()
3305 def GetTabArea(self
):
3306 """ Returns the associated page. """
3311 def GetPadding(self
):
3312 """ Returns the amount of space around each page's icon and label, in pixels. """
3314 return self
._nPadding
3317 def SetWindowStyleFlag(self
, style
):
3318 """ Sets the L{FlatNotebook} window style flags. """
3320 wx
.Panel
.SetWindowStyleFlag(self
, style
)
3321 renderer
= self
._pages
._mgr
.GetRenderer(self
.GetWindowStyleFlag())
3322 renderer
._tabHeight
= None
3326 # For changing the tab position (i.e. placing them top/bottom)
3327 # refreshing the tab container is not enough
3328 self
.SetSelection(self
._pages
._iActivePage
)
3331 def RemovePage(self
, page
):
3332 """ Deletes the specified page, without deleting the associated window. """
3334 if page
>= len(self
._windows
):
3337 # Fire a closing event
3338 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING
, self
.GetId())
3339 event
.SetSelection(page
)
3340 event
.SetEventObject(self
)
3341 self
.GetEventHandler().ProcessEvent(event
)
3343 # The event handler allows it?
3344 if not event
.IsAllowed():
3349 # Remove the requested page
3350 pageRemoved
= self
._windows
[page
]
3352 # If the page is the current window, remove it from the sizer
3354 if page
== self
._pages
.GetSelection():
3355 self
._mainSizer
.Detach(pageRemoved
)
3357 # Remove it from the array as well
3358 self
._windows
.pop(page
)
3361 self
._pages
.DoDeletePage(page
)
3366 def SetRightClickMenu(self
, menu
):
3367 """ Sets the popup menu associated to a right click on a tab. """
3369 self
._pages
._pRightClickMenu
= menu
3372 def GetPageText(self
, nPage
):
3373 """ Returns the tab caption. """
3375 return self
._pages
.GetPageText(nPage
)
3378 def SetGradientColours(self
, fr
, to
, border
):
3379 """ Sets the gradient colours for the tab. """
3381 self
._pages
._colorFrom
= fr
3382 self
._pages
._colorTo
= to
3383 self
._pages
._colorBorder
= border
3386 def SetGradientColourFrom(self
, fr
):
3387 """ Sets the starting colour for the gradient. """
3389 self
._pages
._colorFrom
= fr
3392 def SetGradientColourTo(self
, to
):
3393 """ Sets the ending colour for the gradient. """
3395 self
._pages
._colorTo
= to
3398 def SetGradientColourBorder(self
, border
):
3399 """ Sets the tab border colour. """
3401 self
._pages
._colorBorder
= border
3404 def GetGradientColourFrom(self
):
3405 """ Gets first gradient colour. """
3407 return self
._pages
._colorFrom
3410 def GetGradientColourTo(self
):
3411 """ Gets second gradient colour. """
3413 return self
._pages
._colorTo
3416 def GetGradientColourBorder(self
):
3417 """ Gets the tab border colour. """
3419 return self
._pages
._colorBorder
3422 def GetBorderColour(self
):
3423 """ Returns the border colour. """
3425 return self
._pages
._colorBorder
3428 def GetActiveTabTextColour(self
):
3429 """ Get the active tab text colour. """
3431 return self
._pages
._activeTextColor
3434 def SetPageImage(self
, page
, image
):
3436 Sets the image index for the given page. Image is an index into the
3437 image list which was set with SetImageList.
3440 self
._pages
.SetPageImage(page
, image
)
3443 def GetPageImage(self
, nPage
):
3445 Returns the image index for the given page. Image is an index into the
3446 image list which was set with SetImageList.
3449 return self
._pages
.GetPageImage(nPage
)
3452 def GetEnabled(self
, page
):
3453 """ Returns whether a tab is enabled or not. """
3455 return self
._pages
.GetEnabled(page
)
3458 def Enable(self
, page
, enabled
=True):
3459 """ Enables or disables a tab. """
3461 if page
>= len(self
._windows
):
3464 self
._windows
[page
].Enable(enabled
)
3465 self
._pages
.Enable(page
, enabled
)
3468 def GetNonActiveTabTextColour(self
):
3469 """ Returns the non active tabs text colour. """
3471 return self
._pages
._nonActiveTextColor
3474 def SetNonActiveTabTextColour(self
, color
):
3475 """ Sets the non active tabs text colour. """
3477 self
._pages
._nonActiveTextColor
= color
3480 def SetTabAreaColour(self
, color
):
3481 """ Sets the area behind the tabs colour. """
3483 self
._pages
._tabAreaColor
= color
3486 def GetTabAreaColour(self
):
3487 """ Returns the area behind the tabs colour. """
3489 return self
._pages
._tabAreaColor
3492 def SetActiveTabColour(self
, color
):
3493 """ Sets the active tab colour. """
3495 self
._pages
._activeTabColor
= color
3498 def GetActiveTabColour(self
):
3499 """ Returns the active tab colour. """
3501 return self
._pages
._activeTabColor
3504 # ---------------------------------------------------------------------------- #
3505 # Class PageContainer
3506 # Acts as a container for the pages you add to FlatNotebook
3507 # ---------------------------------------------------------------------------- #
3509 class PageContainer(wx
.Panel
):
3511 This class acts as a container for the pages you add to L{FlatNotebook}.
3514 def __init__(self
, parent
, id=wx
.ID_ANY
, pos
=wx
.DefaultPosition
,
3515 size
=wx
.DefaultSize
, style
=0):
3516 """ Default class constructor. """
3518 self
._ImageList
= None
3519 self
._iActivePage
= -1
3520 self
._pDropTarget
= None
3521 self
._nLeftClickZone
= FNB_NOWHERE
3522 self
._iPreviousActivePage
= -1
3524 self
._pRightClickMenu
= None
3525 self
._nXButtonStatus
= FNB_BTN_NONE
3526 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
3527 self
._pParent
= parent
3528 self
._nRightButtonStatus
= FNB_BTN_NONE
3529 self
._nLeftButtonStatus
= FNB_BTN_NONE
3530 self
._nTabXButtonStatus
= FNB_BTN_NONE
3532 self
._pagesInfoVec
= []
3534 self
._colorTo
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_ACTIVECAPTION
)
3535 self
._colorFrom
= wx
.WHITE
3536 self
._activeTabColor
= wx
.WHITE
3537 self
._activeTextColor
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNTEXT
)
3538 self
._nonActiveTextColor
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)
3539 self
._tabAreaColor
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNFACE
)
3542 self
._isdragging
= False
3544 # Set default page height, this is done according to the system font
3545 memDc
= wx
.MemoryDC()
3546 memDc
.SelectObject(wx
.EmptyBitmap(1,1))
3548 if "__WXGTK__" in wx
.PlatformInfo
:
3549 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
3550 boldFont
.SetWeight(wx
.BOLD
)
3551 memDc
.SetFont(boldFont
)
3553 height
= memDc
.GetCharHeight()
3554 tabHeight
= height
+ FNB_HEIGHT_SPACER
# We use 10 pixels as padding
3556 wx
.Panel
.__init
__(self
, parent
, id, pos
, wx
.Size(size
.x
, tabHeight
),
3557 style|wx
.NO_BORDER|wx
.NO_FULL_REPAINT_ON_RESIZE
)
3559 self
._pDropTarget
= FNBDropTarget(self
)
3560 self
.SetDropTarget(self
._pDropTarget
)
3561 self
._mgr
= FNBRendererMgr()
3563 self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
)
3564 self
.Bind(wx
.EVT_SIZE
, self
.OnSize
)
3565 self
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnLeftDown
)
3566 self
.Bind(wx
.EVT_LEFT_UP
, self
.OnLeftUp
)
3567 self
.Bind(wx
.EVT_RIGHT_DOWN
, self
.OnRightDown
)
3568 self
.Bind(wx
.EVT_MIDDLE_DOWN
, self
.OnMiddleDown
)
3569 self
.Bind(wx
.EVT_MOTION
, self
.OnMouseMove
)
3570 self
.Bind(wx
.EVT_ERASE_BACKGROUND
, self
.OnEraseBackground
)
3571 self
.Bind(wx
.EVT_LEAVE_WINDOW
, self
.OnMouseLeave
)
3572 self
.Bind(wx
.EVT_ENTER_WINDOW
, self
.OnMouseEnterWindow
)
3573 self
.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnLeftDClick
)
3576 def OnEraseBackground(self
, event
):
3577 """ Handles the wx.EVT_ERASE_BACKGROUND event for L{PageContainer} (does nothing)."""
3582 def OnPaint(self
, event
):
3583 """ Handles the wx.EVT_PAINT event for L{PageContainer}."""
3585 dc
= wx
.BufferedPaintDC(self
)
3586 renderer
= self
._mgr
.GetRenderer(self
.GetParent().GetWindowStyleFlag())
3587 renderer
.DrawTabs(self
, dc
)
3590 def AddPage(self
, caption
, selected
=True, imgindex
=-1):
3592 Add a page to the L{FlatNotebook}.
3594 @param window: Specifies the new page.
3595 @param caption: Specifies the text for the new page.
3596 @param selected: Specifies whether the page should be selected.
3597 @param imgindex: Specifies the optional image index for the new page.
3600 True if successful, False otherwise.
3605 self
._iPreviousActivePage
= self
._iActivePage
3606 self
._iActivePage
= len(self
._pagesInfoVec
)
3608 # Create page info and add it to the vector
3609 pageInfo
= PageInfo(caption
, imgindex
)
3610 self
._pagesInfoVec
.append(pageInfo
)
3614 def InsertPage(self
, indx
, text
, selected
=True, imgindex
=-1):
3616 Inserts a new page at the specified position.
3618 @param indx: Specifies the position of the new page.
3619 @param page: Specifies the new page.
3620 @param text: Specifies the text for the new page.
3621 @param select: Specifies whether the page should be selected.
3622 @param imgindex: Specifies the optional image index for the new page.
3625 True if successful, False otherwise.
3630 self
._iPreviousActivePage
= self
._iActivePage
3631 self
._iActivePage
= len(self
._pagesInfoVec
)
3633 self
._pagesInfoVec
.insert(indx
, PageInfo(text
, imgindex
))
3639 def OnSize(self
, event
):
3640 """ Handles the wx.EVT_SIZE events for L{PageContainer}. """
3642 # When resizing the control, try to fit to screen as many tabs as we can
3643 style
= self
.GetParent().GetWindowStyleFlag()
3644 renderer
= self
._mgr
.GetRenderer(style
)
3647 page
= self
.GetSelection()
3649 for fr
in xrange(self
._nFrom
):
3650 vTabInfo
= renderer
.NumberTabsCanFit(self
, fr
)
3651 if page
- fr
>= len(vTabInfo
):
3657 self
.Refresh() # Call on paint
3661 def OnMiddleDown(self
, event
):
3662 """ Handles the wx.EVT_MIDDLE_DOWN events for L{PageContainer}. """
3664 # Test if this style is enabled
3665 style
= self
.GetParent().GetWindowStyleFlag()
3667 if not style
& FNB_MOUSE_MIDDLE_CLOSES_TABS
:
3670 where
, tabIdx
= self
.HitTest(event
.GetPosition())
3672 if where
== FNB_TAB
:
3673 self
.DeletePage(tabIdx
)
3678 def OnRightDown(self
, event
):
3679 """ Handles the wx.EVT_RIGHT_DOWN events for L{PageContainer}. """
3681 where
, tabIdx
= self
.HitTest(event
.GetPosition())
3683 if where
in [FNB_TAB
, FNB_TAB_X
]:
3685 if self
._pagesInfoVec
[tabIdx
].GetEnabled():
3686 # Fire events and eventually (if allowed) change selection
3687 self
.FireEvent(tabIdx
)
3689 # send a message to popup a custom menu
3690 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU
, self
.GetParent().GetId())
3691 event
.SetSelection(tabIdx
)
3692 event
.SetOldSelection(self
._iActivePage
)
3693 event
.SetEventObject(self
.GetParent())
3694 self
.GetParent().GetEventHandler().ProcessEvent(event
)
3696 if self
._pRightClickMenu
:
3697 self
.PopupMenu(self
._pRightClickMenu
)
3702 def OnLeftDown(self
, event
):
3703 """ Handles the wx.EVT_LEFT_DOWN events for L{PageContainer}. """
3705 # Reset buttons status
3706 self
._nXButtonStatus
= FNB_BTN_NONE
3707 self
._nLeftButtonStatus
= FNB_BTN_NONE
3708 self
._nRightButtonStatus
= FNB_BTN_NONE
3709 self
._nTabXButtonStatus
= FNB_BTN_NONE
3710 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
3712 self
._nLeftClickZone
, tabIdx
= self
.HitTest(event
.GetPosition())
3714 if self
._nLeftClickZone
== FNB_DROP_DOWN_ARROW
:
3715 self
._nArrowDownButtonStatus
= FNB_BTN_PRESSED
3717 elif self
._nLeftClickZone
== FNB_LEFT_ARROW
:
3718 self
._nLeftButtonStatus
= FNB_BTN_PRESSED
3720 elif self
._nLeftClickZone
== FNB_RIGHT_ARROW
:
3721 self
._nRightButtonStatus
= FNB_BTN_PRESSED
3723 elif self
._nLeftClickZone
== FNB_X
:
3724 self
._nXButtonStatus
= FNB_BTN_PRESSED
3726 elif self
._nLeftClickZone
== FNB_TAB_X
:
3727 self
._nTabXButtonStatus
= FNB_BTN_PRESSED
3730 elif self
._nLeftClickZone
== FNB_TAB
:
3732 if self
._iActivePage
!= tabIdx
:
3734 # In case the tab is disabled, we dont allow to choose it
3735 if self
._pagesInfoVec
[tabIdx
].GetEnabled():
3736 self
.FireEvent(tabIdx
)
3739 def OnLeftUp(self
, event
):
3740 """ Handles the wx.EVT_LEFT_UP events for L{PageContainer}. """
3742 # forget the zone that was initially clicked
3743 self
._nLeftClickZone
= FNB_NOWHERE
3745 where
, tabIdx
= self
.HitTest(event
.GetPosition())
3747 if where
== FNB_LEFT_ARROW
:
3749 if self
._nFrom
== 0:
3752 # Make sure that the button was pressed before
3753 if self
._nLeftButtonStatus
!= FNB_BTN_PRESSED
:
3756 self
._nLeftButtonStatus
= FNB_BTN_HOVER
3758 # We scroll left with bulks of 5
3759 scrollLeft
= self
.GetNumTabsCanScrollLeft()
3761 self
._nFrom
-= scrollLeft
3767 elif where
== FNB_RIGHT_ARROW
:
3769 if self
._nFrom
>= len(self
._pagesInfoVec
) - 1:
3772 # Make sure that the button was pressed before
3773 if self
._nRightButtonStatus
!= FNB_BTN_PRESSED
:
3776 self
._nRightButtonStatus
= FNB_BTN_HOVER
3778 # Check if the right most tab is visible, if it is
3779 # don't rotate right anymore
3780 if self
._pagesInfoVec
[-1].GetPosition() != wx
.Point(-1, -1):
3783 lastVisibleTab
= self
.GetLastVisibleTab()
3784 if lastVisibleTab
< 0:
3785 # Probably the screen is too small for displaying even a single
3786 # tab, in this case we do nothing
3789 self
._nFrom
+= self
.GetNumOfVisibleTabs()
3792 elif where
== FNB_X
:
3794 # Make sure that the button was pressed before
3795 if self
._nXButtonStatus
!= FNB_BTN_PRESSED
:
3798 self
._nXButtonStatus
= FNB_BTN_HOVER
3800 self
.DeletePage(self
._iActivePage
)
3802 elif where
== FNB_TAB_X
:
3804 # Make sure that the button was pressed before
3805 if self
._nTabXButtonStatus
!= FNB_BTN_PRESSED
:
3808 self
._nTabXButtonStatus
= FNB_BTN_HOVER
3810 self
.DeletePage(self
._iActivePage
)
3812 elif where
== FNB_DROP_DOWN_ARROW
:
3814 # Make sure that the button was pressed before
3815 if self
._nArrowDownButtonStatus
!= FNB_BTN_PRESSED
:
3818 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
3820 # Refresh the button status
3821 renderer
= self
._mgr
.GetRenderer(self
.GetParent().GetWindowStyleFlag())
3822 dc
= wx
.ClientDC(self
)
3823 renderer
.DrawDropDownArrow(self
, dc
)
3825 self
.PopupTabsMenu()
3828 def HitTest(self
, pt
):
3830 HitTest method for L{PageContainer}.
3831 Returns the flag (if any) and the hit page (if any).
3834 style
= self
.GetParent().GetWindowStyleFlag()
3835 render
= self
._mgr
.GetRenderer(style
)
3837 fullrect
= self
.GetClientRect()
3838 btnLeftPos
= render
.GetLeftButtonPos(self
)
3839 btnRightPos
= render
.GetRightButtonPos(self
)
3840 btnXPos
= render
.GetXPos(self
)
3844 if len(self
._pagesInfoVec
) == 0:
3845 return FNB_NOWHERE
, tabIdx
3847 rect
= wx
.Rect(btnXPos
, 8, 16, 16)
3848 if rect
.Contains(pt
):
3849 return (style
& FNB_NO_X_BUTTON
and [FNB_NOWHERE
] or [FNB_X
])[0], tabIdx
3851 rect
= wx
.Rect(btnRightPos
, 8, 16, 16)
3852 if style
& FNB_DROPDOWN_TABS_LIST
:
3853 rect
= wx
.Rect(render
.GetDropArrowButtonPos(self
), 8, 16, 16)
3854 if rect
.Contains(pt
):
3855 return FNB_DROP_DOWN_ARROW
, tabIdx
3857 if rect
.Contains(pt
):
3858 return (style
& FNB_NO_NAV_BUTTONS
and [FNB_NOWHERE
] or [FNB_RIGHT_ARROW
])[0], tabIdx
3860 rect
= wx
.Rect(btnLeftPos
, 8, 16, 16)
3861 if rect
.Contains(pt
):
3862 return (style
& FNB_NO_NAV_BUTTONS
and [FNB_NOWHERE
] or [FNB_LEFT_ARROW
])[0], tabIdx
3864 # Test whether a left click was made on a tab
3867 for cur
in xrange(self
._nFrom
, len(self
._pagesInfoVec
)):
3869 pgInfo
= self
._pagesInfoVec
[cur
]
3871 if pgInfo
.GetPosition() == wx
.Point(-1, -1):
3874 if style
& FNB_X_ON_TAB
and cur
== self
.GetSelection():
3875 # 'x' button exists on a tab
3876 if self
._pagesInfoVec
[cur
].GetXRect().Contains(pt
):
3877 return FNB_TAB_X
, cur
3881 if self
._pagesInfoVec
[cur
].GetRegion().Contains(pt
.x
, pt
.y
):
3882 if bFoundMatch
or cur
== self
.GetSelection():
3890 tabRect
= wx
.Rect(pgInfo
.GetPosition().x
, pgInfo
.GetPosition().y
,
3891 pgInfo
.GetSize().x
, pgInfo
.GetSize().y
)
3893 if tabRect
.Contains(pt
):
3898 return FNB_TAB
, tabIdx
3900 if self
._isdragging
:
3901 # We are doing DND, so check also the region outside the tabs
3902 # try before the first tab
3903 pgInfo
= self
._pagesInfoVec
[0]
3904 tabRect
= wx
.Rect(0, pgInfo
.GetPosition().y
, pgInfo
.GetPosition().x
, self
.GetParent().GetSize().y
)
3905 if tabRect
.Contains(pt
):
3908 # try after the last tab
3909 pgInfo
= self
._pagesInfoVec
[-1]
3910 startpos
= pgInfo
.GetPosition().x
+pgInfo
.GetSize().x
3911 tabRect
= wx
.Rect(startpos
, pgInfo
.GetPosition().y
, fullrect
.width
-startpos
, self
.GetParent().GetSize().y
)
3913 if tabRect
.Contains(pt
):
3914 return FNB_TAB
, len(self
._pagesInfoVec
)
3917 return FNB_NOWHERE
, -1
3920 def SetSelection(self
, page
):
3921 """ Sets the selected page. """
3923 book
= self
.GetParent()
3924 book
.SetSelection(page
)
3925 self
.DoSetSelection(page
)
3928 def DoSetSelection(self
, page
):
3929 """ Does the actual selection of a page. """
3931 if page
< len(self
._pagesInfoVec
):
3933 da_page
= self
._pParent
.GetPage(page
)
3938 if not self
.IsTabVisible(page
):
3939 # Try to remove one tab from start and try again
3941 if not self
.CanFitToScreen(page
):
3943 if self
._nFrom
> page
:
3946 while self
._nFrom
< page
:
3948 if self
.CanFitToScreen(page
):
3954 def DeletePage(self
, page
):
3955 """ Delete the specified page from L{FlatNotebook}. """
3957 book
= self
.GetParent()
3958 book
.DeletePage(page
)
3962 def IsTabVisible(self
, page
):
3963 """ Returns whether a tab is visible or not. """
3965 iLastVisiblePage
= self
.GetLastVisibleTab()
3966 return page
<= iLastVisiblePage
and page
>= self
._nFrom
3969 def DoDeletePage(self
, page
):
3970 """ Does the actual page deletion. """
3972 # Remove the page from the vector
3973 book
= self
.GetParent()
3974 self
._pagesInfoVec
.pop(page
)
3976 # Thanks to Yiaanis AKA Mandrav
3977 if self
._iActivePage
>= page
:
3978 self
._iActivePage
= self
._iActivePage
- 1
3979 self
._iPreviousActivePage
= -1
3981 # The delete page was the last first on the array,
3982 # but the book still has more pages, so we set the
3983 # active page to be the first one (0)
3984 if self
._iActivePage
< 0 and len(self
._pagesInfoVec
) > 0:
3985 self
._iActivePage
= 0
3986 self
._iPreviousActivePage
= -1
3989 if self
._iActivePage
>= 0:
3991 book
._bForceSelection
= True
3993 # Check for selection and send event
3994 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, self
.GetParent().GetId())
3995 event
.SetSelection(self
._iActivePage
)
3996 event
.SetOldSelection(self
._iPreviousActivePage
)
3997 event
.SetEventObject(self
.GetParent())
3999 book
.SetSelection(self
._iActivePage
)
4000 book
._bForceSelection
= False
4002 # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
4003 event
.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
)
4004 event
.SetOldSelection(self
._iPreviousActivePage
)
4005 self
.GetParent().GetEventHandler().ProcessEvent(event
)
4007 if not self
._pagesInfoVec
:
4008 # Erase the page container drawings
4009 dc
= wx
.ClientDC(self
)
4013 def DeleteAllPages(self
):
4014 """ Deletes all the pages. """
4016 self
._iActivePage
= -1
4017 self
._iPreviousActivePage
= -1
4019 self
._pagesInfoVec
= []
4021 # Erase the page container drawings
4022 dc
= wx
.ClientDC(self
)
4026 def OnMouseMove(self
, event
):
4027 """ Handles the wx.EVT_MOTION for L{PageContainer}. """
4029 if self
._pagesInfoVec
and self
.IsShown():
4031 xButtonStatus
= self
._nXButtonStatus
4032 xTabButtonStatus
= self
._nTabXButtonStatus
4033 rightButtonStatus
= self
._nRightButtonStatus
4034 leftButtonStatus
= self
._nLeftButtonStatus
4035 dropDownButtonStatus
= self
._nArrowDownButtonStatus
4037 style
= self
.GetParent().GetWindowStyleFlag()
4039 self
._nXButtonStatus
= FNB_BTN_NONE
4040 self
._nRightButtonStatus
= FNB_BTN_NONE
4041 self
._nLeftButtonStatus
= FNB_BTN_NONE
4042 self
._nTabXButtonStatus
= FNB_BTN_NONE
4043 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
4045 where
, tabIdx
= self
.HitTest(event
.GetPosition())
4048 if event
.LeftIsDown():
4050 self
._nXButtonStatus
= (self
._nLeftClickZone
==FNB_X
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4054 self
._nXButtonStatus
= FNB_BTN_HOVER
4056 elif where
== FNB_DROP_DOWN_ARROW
:
4057 if event
.LeftIsDown():
4059 self
._nArrowDownButtonStatus
= (self
._nLeftClickZone
==FNB_DROP_DOWN_ARROW
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4063 self
._nArrowDownButtonStatus
= FNB_BTN_HOVER
4065 elif where
== FNB_TAB_X
:
4066 if event
.LeftIsDown():
4068 self
._nTabXButtonStatus
= (self
._nLeftClickZone
==FNB_TAB_X
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4072 self
._nTabXButtonStatus
= FNB_BTN_HOVER
4074 elif where
== FNB_RIGHT_ARROW
:
4075 if event
.LeftIsDown():
4077 self
._nRightButtonStatus
= (self
._nLeftClickZone
==FNB_RIGHT_ARROW
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4081 self
._nRightButtonStatus
= FNB_BTN_HOVER
4083 elif where
== FNB_LEFT_ARROW
:
4084 if event
.LeftIsDown():
4086 self
._nLeftButtonStatus
= (self
._nLeftClickZone
==FNB_LEFT_ARROW
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4090 self
._nLeftButtonStatus
= FNB_BTN_HOVER
4092 elif where
== FNB_TAB
:
4093 # Call virtual method for showing tooltip
4094 self
.ShowTabTooltip(tabIdx
)
4096 if not self
.GetEnabled(tabIdx
):
4097 # Set the cursor to be 'No-entry'
4098 wx
.SetCursor(wx
.StockCursor(wx
.CURSOR_NO_ENTRY
))
4100 # Support for drag and drop
4101 if event
.Dragging() and not (style
& FNB_NODRAG
):
4103 self
._isdragging
= True
4104 draginfo
= FNBDragInfo(self
, tabIdx
)
4105 drginfo
= cPickle
.dumps(draginfo
)
4106 dataobject
= wx
.CustomDataObject(wx
.CustomDataFormat("FlatNotebook"))
4107 dataobject
.SetData(drginfo
)
4108 dragSource
= FNBDropSource(self
)
4109 dragSource
.SetData(dataobject
)
4110 dragSource
.DoDragDrop(wx
.Drag_DefaultMove
)
4112 bRedrawX
= self
._nXButtonStatus
!= xButtonStatus
4113 bRedrawRight
= self
._nRightButtonStatus
!= rightButtonStatus
4114 bRedrawLeft
= self
._nLeftButtonStatus
!= leftButtonStatus
4115 bRedrawTabX
= self
._nTabXButtonStatus
!= xTabButtonStatus
4116 bRedrawDropArrow
= self
._nArrowDownButtonStatus
!= dropDownButtonStatus
4118 render
= self
._mgr
.GetRenderer(style
)
4120 if (bRedrawX
or bRedrawRight
or bRedrawLeft
or bRedrawTabX
or bRedrawDropArrow
):
4122 dc
= wx
.ClientDC(self
)
4126 render
.DrawX(self
, dc
)
4130 render
.DrawLeftArrow(self
, dc
)
4134 render
.DrawRightArrow(self
, dc
)
4138 render
.DrawTabX(self
, dc
, self
._pagesInfoVec
[tabIdx
].GetXRect(), tabIdx
, self
._nTabXButtonStatus
)
4140 if bRedrawDropArrow
:
4142 render
.DrawDropDownArrow(self
, dc
)
4147 def GetLastVisibleTab(self
):
4148 """ Returns the last visible tab. """
4155 for ii
in xrange(self
._nFrom
, len(self
._pagesInfoVec
)):
4157 if self
._pagesInfoVec
[ii
].GetPosition() == wx
.Point(-1, -1):
4163 def GetNumTabsCanScrollLeft(self
):
4164 """ Returns the number of tabs than can be scrolled left. """
4166 # Reserved area for the buttons (<>x)
4167 rect
= self
.GetClientRect()
4168 clientWidth
= rect
.width
4169 posx
= self
._pParent
._nPadding
4173 # In case we have error prevent crash
4177 dc
= wx
.ClientDC(self
)
4179 style
= self
.GetParent().GetWindowStyleFlag()
4180 render
= self
._mgr
.GetRenderer(style
)
4182 for ii
in xrange(self
._nFrom
, -1, -1):
4184 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
4185 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
4186 dc
.SetFont(boldFont
)
4188 height
= dc
.GetCharHeight()
4190 tabHeight
= height
+ FNB_HEIGHT_SPACER
# We use 6 pixels as padding
4191 if style
& FNB_VC71
:
4192 tabHeight
= (style
& FNB_BOTTOM
and [tabHeight
- 4] or [tabHeight
])[0]
4193 elif style
& FNB_FANCY_TABS
:
4194 tabHeight
= (style
& FNB_BOTTOM
and [tabHeight
- 3] or [tabHeight
])[0]
4196 width
, pom
= dc
.GetTextExtent(self
.GetPageText(ii
))
4197 if style
!= FNB_VC71
:
4198 shapePoints
= int(tabHeight
*math
.tan(float(self
._pagesInfoVec
[ii
].GetTabAngle())/180.0*math
.pi
))
4202 tabWidth
= 2*self
._pParent
._nPadding
+ width
4204 if not (style
& FNB_VC71
):
4206 tabWidth
+= 2*shapePoints
4208 hasImage
= self
._ImageList
!= None and self
._pagesInfoVec
[ii
].GetImageIndex() != -1
4210 # For VC71 style, we only add the icon size (16 pixels)
4213 if not self
.IsDefaultTabs():
4214 tabWidth
+= 16 + self
._pParent
._nPadding
4217 tabWidth
+= 16 + self
._pParent
._nPadding
+ shapePoints
/2
4219 if posx
+ tabWidth
+ render
.GetButtonsAreaLength(self
) >= clientWidth
:
4222 numTabs
= numTabs
+ 1
4228 def IsDefaultTabs(self
):
4229 """ Returns whether a tab has a default style. """
4231 style
= self
.GetParent().GetWindowStyleFlag()
4232 res
= (style
& FNB_VC71
) or (style
& FNB_FANCY_TABS
) or (style
& FNB_VC8
)
4236 def AdvanceSelection(self
, bForward
=True):
4238 Cycles through the tabs.
4239 The call to this function generates the page changing events.
4242 nSel
= self
.GetSelection()
4247 nMax
= self
.GetPageCount() - 1
4250 newSelection
= (nSel
== nMax
and [0] or [nSel
+ 1])[0]
4252 newSelection
= (nSel
== 0 and [nMax
] or [nSel
- 1])[0]
4254 if not self
._pagesInfoVec
[newSelection
].GetEnabled():
4257 self
.FireEvent(newSelection
)
4260 def OnMouseLeave(self
, event
):
4261 """ Handles the wx.EVT_LEAVE_WINDOW event for L{PageContainer}. """
4263 self
._nLeftButtonStatus
= FNB_BTN_NONE
4264 self
._nXButtonStatus
= FNB_BTN_NONE
4265 self
._nRightButtonStatus
= FNB_BTN_NONE
4266 self
._nTabXButtonStatus
= FNB_BTN_NONE
4267 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
4269 style
= self
.GetParent().GetWindowStyleFlag()
4270 render
= self
._mgr
.GetRenderer(style
)
4272 dc
= wx
.ClientDC(self
)
4274 render
.DrawX(self
, dc
)
4275 render
.DrawLeftArrow(self
, dc
)
4276 render
.DrawRightArrow(self
, dc
)
4278 selection
= self
.GetSelection()
4284 if not self
.IsTabVisible(selection
):
4285 if selection
== len(self
._pagesInfoVec
) - 1:
4286 if not self
.CanFitToScreen(selection
):
4293 render
.DrawTabX(self
, dc
, self
._pagesInfoVec
[selection
].GetXRect(), selection
, self
._nTabXButtonStatus
)
4298 def OnMouseEnterWindow(self
, event
):
4299 """ Handles the wx.EVT_ENTER_WINDOW event for L{PageContainer}. """
4301 self
._nLeftButtonStatus
= FNB_BTN_NONE
4302 self
._nXButtonStatus
= FNB_BTN_NONE
4303 self
._nRightButtonStatus
= FNB_BTN_NONE
4304 self
._nLeftClickZone
= FNB_BTN_NONE
4305 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
4310 def ShowTabTooltip(self
, tabIdx
):
4311 """ Shows a tab tooltip. """
4313 pWindow
= self
._pParent
.GetPage(tabIdx
)
4316 pToolTip
= pWindow
.GetToolTip()
4317 if pToolTip
and pToolTip
.GetWindow() == pWindow
:
4318 self
.SetToolTipString(pToolTip
.GetTip())
4321 def SetPageImage(self
, page
, imgindex
):
4322 """ Sets the image index associated to a page. """
4324 if page
< len(self
._pagesInfoVec
):
4326 self
._pagesInfoVec
[page
].SetImageIndex(imgindex
)
4330 def GetPageImage(self
, page
):
4331 """ Returns the image index associated to a page. """
4333 if page
< len(self
._pagesInfoVec
):
4335 return self
._pagesInfoVec
[page
].GetImageIndex()
4340 def OnDropTarget(self
, x
, y
, nTabPage
, wnd_oldContainer
):
4341 """ Handles the drop action from a DND operation. """
4343 # Disable drag'n'drop for disabled tab
4344 if not wnd_oldContainer
._pagesInfoVec
[nTabPage
].GetEnabled():
4345 return wx
.DragCancel
4347 self
._isdragging
= True
4348 oldContainer
= wnd_oldContainer
4351 where
, nIndex
= self
.HitTest(wx
.Point(x
, y
))
4353 oldNotebook
= oldContainer
.GetParent()
4354 newNotebook
= self
.GetParent()
4356 if oldNotebook
== newNotebook
:
4360 if where
== FNB_TAB
:
4361 self
.MoveTabPage(nTabPage
, nIndex
)
4363 elif self
.GetParent().GetWindowStyleFlag() & FNB_ALLOW_FOREIGN_DND
:
4365 if wx
.Platform
in ["__WXMSW__", "__WXGTK__"]:
4368 window
= oldNotebook
.GetPage(nTabPage
)
4371 where
, nIndex
= newNotebook
._pages
.HitTest(wx
.Point(x
, y
))
4372 caption
= oldContainer
.GetPageText(nTabPage
)
4373 imageindex
= oldContainer
.GetPageImage(nTabPage
)
4374 oldNotebook
.RemovePage(nTabPage
)
4375 window
.Reparent(newNotebook
)
4379 bmp
= oldNotebook
.GetImageList().GetIcon(imageindex
)
4380 newImageList
= newNotebook
.GetImageList()
4382 if not newImageList
:
4383 xbmp
, ybmp
= bmp
.GetWidth(), bmp
.GetHeight()
4384 newImageList
= wx
.ImageList(xbmp
, ybmp
)
4387 imageindex
= newImageList
.GetImageCount()
4389 newImageList
.AddIcon(bmp
)
4390 newNotebook
.SetImageList(newImageList
)
4392 newNotebook
.InsertPage(nIndex
, window
, caption
, True, imageindex
)
4394 self
._isdragging
= False
4399 def MoveTabPage(self
, nMove
, nMoveTo
):
4400 """ Moves a tab inside the same L{FlatNotebook}. """
4402 if nMove
== nMoveTo
:
4405 elif nMoveTo
< len(self
._pParent
._windows
):
4406 nMoveTo
= nMoveTo
+ 1
4408 self
._pParent
.Freeze()
4410 # Remove the window from the main sizer
4411 nCurSel
= self
._pParent
._pages
.GetSelection()
4412 self
._pParent
._mainSizer
.Detach(self
._pParent
._windows
[nCurSel
])
4413 self
._pParent
._windows
[nCurSel
].Hide()
4415 pWindow
= self
._pParent
._windows
[nMove
]
4416 self
._pParent
._windows
.pop(nMove
)
4417 self
._pParent
._windows
.insert(nMoveTo
-1, pWindow
)
4419 pgInfo
= self
._pagesInfoVec
[nMove
]
4421 self
._pagesInfoVec
.pop(nMove
)
4422 self
._pagesInfoVec
.insert(nMoveTo
- 1, pgInfo
)
4424 # Add the page according to the style
4425 pSizer
= self
._pParent
._mainSizer
4426 style
= self
.GetParent().GetWindowStyleFlag()
4428 if style
& FNB_BOTTOM
:
4430 pSizer
.Insert(0, pWindow
, 1, wx
.EXPAND
)
4434 # We leave a space of 1 pixel around the window
4435 pSizer
.Add(pWindow
, 1, wx
.EXPAND
)
4440 self
._iActivePage
= nMoveTo
- 1
4441 self
._iPreviousActivePage
= -1
4442 self
.DoSetSelection(self
._iActivePage
)
4444 self
._pParent
.Thaw()
4447 def CanFitToScreen(self
, page
):
4448 """ Returns wheter a tab can fit in the left space in the screen or not. """
4450 # Incase the from is greater than page,
4451 # we need to reset the self._nFrom, so in order
4452 # to force the caller to do so, we return false
4453 if self
._nFrom
> page
:
4456 style
= self
.GetParent().GetWindowStyleFlag()
4457 render
= self
._mgr
.GetRenderer(style
)
4459 vTabInfo
= render
.NumberTabsCanFit(self
)
4461 if page
- self
._nFrom
>= len(vTabInfo
):
4467 def GetNumOfVisibleTabs(self
):
4468 """ Returns the number of visible tabs. """
4471 for ii
in xrange(self
._nFrom
, len(self
._pagesInfoVec
)):
4472 if self
._pagesInfoVec
[ii
].GetPosition() == wx
.Point(-1, -1):
4479 def GetEnabled(self
, page
):
4480 """ Returns whether a tab is enabled or not. """
4482 if page
>= len(self
._pagesInfoVec
):
4483 return True # Seems strange, but this is the default
4485 return self
._pagesInfoVec
[page
].GetEnabled()
4488 def Enable(self
, page
, enabled
=True):
4489 """ Enables or disables a tab. """
4491 if page
>= len(self
._pagesInfoVec
):
4494 self
._pagesInfoVec
[page
].Enable(enabled
)
4497 def GetSingleLineBorderColour(self
):
4498 """ Returns the colour for the single line border. """
4500 if self
.HasFlag(FNB_FANCY_TABS
):
4501 return self
._colorFrom
4506 def HasFlag(self
, flag
):
4507 """ Returns whether a flag is present in the L{FlatNotebook} style. """
4509 style
= self
.GetParent().GetWindowStyleFlag()
4510 res
= (style
& flag
and [True] or [False])[0]
4514 def ClearFlag(self
, flag
):
4515 """ Deletes a flag from the L{FlatNotebook} style. """
4517 style
= self
.GetParent().GetWindowStyleFlag()
4519 self
.SetWindowStyleFlag(style
)
4522 def TabHasImage(self
, tabIdx
):
4523 """ Returns whether a tab has an associated image index or not. """
4526 return self
._pagesInfoVec
[tabIdx
].GetImageIndex() != -1
4531 def OnLeftDClick(self
, event
):
4532 """ Handles the wx.EVT_LEFT_DCLICK event for L{PageContainer}. """
4534 if self
.HasFlag(FNB_DCLICK_CLOSES_TABS
):
4536 where
, tabIdx
= self
.HitTest(event
.GetPosition())
4538 if where
== FNB_TAB
:
4539 self
.DeletePage(tabIdx
)
4546 def PopupTabsMenu(self
):
4547 """ Pops up the menu activated with the drop down arrow in the navigation area. """
4549 popupMenu
= wx
.Menu()
4551 for i
in xrange(len(self
._pagesInfoVec
)):
4552 pi
= self
._pagesInfoVec
[i
]
4553 item
= wx
.MenuItem(popupMenu
, i
, pi
.GetCaption(), pi
.GetCaption(), wx
.ITEM_NORMAL
)
4554 self
.Bind(wx
.EVT_MENU
, self
.OnTabMenuSelection
, item
)
4556 # This code is commented, since there is an alignment problem with wx2.6.3 & Menus
4557 # if self.TabHasImage(ii):
4558 # item.SetBitmaps( (*m_ImageList)[pi.GetImageIndex()] );
4560 popupMenu
.AppendItem(item
)
4561 item
.Enable(pi
.GetEnabled())
4563 self
.PopupMenu(popupMenu
)
4566 def OnTabMenuSelection(self
, event
):
4567 """ Handles the wx.EVT_MENU event for L{PageContainer}. """
4569 selection
= event
.GetId()
4570 self
.FireEvent(selection
)
4573 def FireEvent(self
, selection
):
4575 Fires the wxEVT_FLATNOTEBOOK_PAGE_CHANGING and wxEVT_FLATNOTEBOOK_PAGE_CHANGED events
4576 called from other methods (from menu selection or Smart Tabbing).
4580 if selection
== self
._iActivePage
:
4581 # No events for the same selection
4584 oldSelection
= self
._iActivePage
4586 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, self
.GetParent().GetId())
4587 event
.SetSelection(selection
)
4588 event
.SetOldSelection(oldSelection
)
4589 event
.SetEventObject(self
.GetParent())
4591 if not self
.GetParent().GetEventHandler().ProcessEvent(event
) or event
.IsAllowed():
4593 self
.SetSelection(selection
)
4595 # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
4596 event
.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
)
4597 event
.SetOldSelection(oldSelection
)
4598 self
.GetParent().GetEventHandler().ProcessEvent(event
)
4601 def SetImageList(self
, imglist
):
4602 """ Sets the image list for the page control. """
4604 self
._ImageList
= imglist
4607 def GetImageList(self
):
4608 """ Returns the image list for the page control. """
4610 return self
._ImageList
4613 def GetSelection(self
):
4614 """ Returns the current selected page. """
4616 return self
._iActivePage
4619 def GetPageCount(self
):
4620 """ Returns the number of tabs in the L{FlatNotebook} control. """
4622 return len(self
._pagesInfoVec
)
4625 def GetPageText(self
, page
):
4626 """ Returns the tab caption of the page. """
4628 return self
._pagesInfoVec
[page
].GetCaption()
4631 def SetPageText(self
, page
, text
):
4632 """ Sets the tab caption of the page. """
4634 self
._pagesInfoVec
[page
].SetCaption(text
)
4638 def DrawDragHint(self
):
4639 """ Draws small arrow at the place that the tab will be placed. """
4641 # get the index of tab that will be replaced with the dragged tab
4642 pt
= wx
.GetMousePosition()
4643 client_pt
= self
.ScreenToClient(pt
)
4644 where
, tabIdx
= self
.HitTest(client_pt
)
4645 self
._mgr
.GetRenderer(self
.GetParent().GetWindowStyleFlag()).DrawDragHint(self
, tabIdx
)