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 FNB_HIDE_ON_SINGLE_TAB
= 65536
150 """Hides the Page Container when there is one or fewer tabs"""
152 VERTICAL_BORDER_PADDING
= 4
154 # Button size is a 16x16 xpm bitmap
156 """Button size is a 16x16 xpm bitmap"""
160 MASK_COLOR
= wx
.Colour(0, 128, 128)
161 """Mask colour for the arrow bitmaps"""
165 """Navigation button is pressed"""
167 """Navigation button is hovered"""
172 FNB_TAB
= 1 # On a tab
173 """Indicates mouse coordinates inside a tab"""
174 FNB_X
= 2 # On the X button
175 """Indicates mouse coordinates inside the I{X} region"""
176 FNB_TAB_X
= 3 # On the 'X' button (tab's X button)
177 """Indicates mouse coordinates inside the I{X} region in a tab"""
178 FNB_LEFT_ARROW
= 4 # On the rotate left arrow button
179 """Indicates mouse coordinates inside the left arrow region"""
180 FNB_RIGHT_ARROW
= 5 # On the rotate right arrow button
181 """Indicates mouse coordinates inside the right arrow region"""
182 FNB_DROP_DOWN_ARROW
= 6 # On the drop down arrow button
183 """Indicates mouse coordinates inside the drop down arrow region"""
184 FNB_NOWHERE
= 0 # Anywhere else
185 """Indicates mouse coordinates not on any tab of the notebook"""
187 FNB_DEFAULT_STYLE
= FNB_MOUSE_MIDDLE_CLOSES_TABS | FNB_HIDE_ON_SINGLE_TAB
188 """L{FlatNotebook} default style"""
190 # FlatNotebook Events:
191 # wxEVT_FLATNOTEBOOK_PAGE_CHANGED: Event Fired When You Switch Page;
192 # wxEVT_FLATNOTEBOOK_PAGE_CHANGING: Event Fired When You Are About To Switch
193 # Pages, But You Can Still "Veto" The Page Changing By Avoiding To Call
194 # event.Skip() In Your Event Handler;
195 # wxEVT_FLATNOTEBOOK_PAGE_CLOSING: Event Fired When A Page Is Closing, But
196 # You Can Still "Veto" The Page Changing By Avoiding To Call event.Skip()
197 # In Your Event Handler;
198 # wxEVT_FLATNOTEBOOK_PAGE_CLOSED: Event Fired When A Page Is Closed.
199 # wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU: Event Fired When A Menu Pops-up In A Tab.
201 wxEVT_FLATNOTEBOOK_PAGE_CHANGED
= wx
.NewEventType()
202 wxEVT_FLATNOTEBOOK_PAGE_CHANGING
= wx
.NewEventType()
203 wxEVT_FLATNOTEBOOK_PAGE_CLOSING
= wx
.NewEventType()
204 wxEVT_FLATNOTEBOOK_PAGE_CLOSED
= wx
.NewEventType()
205 wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU
= wx
.NewEventType()
207 #-----------------------------------#
209 #-----------------------------------#
211 EVT_FLATNOTEBOOK_PAGE_CHANGED
= wx
.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
, 1)
212 """Notify client objects when the active page in L{FlatNotebook}
214 EVT_FLATNOTEBOOK_PAGE_CHANGING
= wx
.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, 1)
215 """Notify client objects when the active page in L{FlatNotebook}
216 is about to change."""
217 EVT_FLATNOTEBOOK_PAGE_CLOSING
= wx
.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CLOSING
, 1)
218 """Notify client objects when a page in L{FlatNotebook} is closing."""
219 EVT_FLATNOTEBOOK_PAGE_CLOSED
= wx
.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CLOSED
, 1)
220 """Notify client objects when a page in L{FlatNotebook} has been closed."""
221 EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU
= wx
.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU
, 1)
222 """Notify client objects when a pop-up menu should appear next to a tab."""
225 # Some icons in XPM format
227 left_arrow_disabled_xpm
= [
255 x_button_pressed_xpm
= [
312 x_button_hilite_xpm
= [
368 left_arrow_pressed_xpm
= [
396 left_arrow_hilite_xpm
= [
424 right_arrow_disabled_xpm
= [
452 right_arrow_hilite_xpm
= [
480 right_arrow_pressed_xpm
= [
537 down_arrow_hilite_xpm
= [
565 down_arrow_pressed_xpm
= [
623 #----------------------------------------------------------------------
624 def GetMondrianData():
626 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\
627 \x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00qID\
628 ATX\x85\xed\xd6;\n\x800\x10E\xd1{\xc5\x8d\xb9r\x97\x16\x0b\xad$\x8a\x82:\x16\
629 o\xda\x84pB2\x1f\x81Fa\x8c\x9c\x08\x04Z{\xcf\xa72\xbcv\xfa\xc5\x08 \x80r\x80\
630 \xfc\xa2\x0e\x1c\xe4\xba\xfaX\x1d\xd0\xde]S\x07\x02\xd8>\xe1wa-`\x9fQ\xe9\
631 \x86\x01\x04\x10\x00\\(Dk\x1b-\x04\xdc\x1d\x07\x14\x98;\x0bS\x7f\x7f\xf9\x13\
632 \x04\x10@\xf9X\xbe\x00\xc9 \x14K\xc1<={\x00\x00\x00\x00IEND\xaeB`\x82'
635 def GetMondrianBitmap():
636 return wx
.BitmapFromImage(GetMondrianImage().Scale(16, 16))
639 def GetMondrianImage():
641 stream
= cStringIO
.StringIO(GetMondrianData())
642 return wx
.ImageFromStream(stream
)
645 def GetMondrianIcon():
646 icon
= wx
.EmptyIcon()
647 icon
.CopyFromBitmap(GetMondrianBitmap())
649 #----------------------------------------------------------------------
652 def LightColour(color
, percent
):
653 """ Brighten input colour by percent. """
657 rd
= end_color
.Red() - color
.Red()
658 gd
= end_color
.Green() - color
.Green()
659 bd
= end_color
.Blue() - color
.Blue()
663 # We take the percent way of the color from color -. white
665 r
= color
.Red() + ((i
*rd
*100)/high
)/100
666 g
= color
.Green() + ((i
*gd
*100)/high
)/100
667 b
= color
.Blue() + ((i
*bd
*100)/high
)/100
668 return wx
.Colour(r
, g
, b
)
672 """ Creates a random colour. """
674 r
= random
.randint(0, 255) # Random value betweem 0-255
675 g
= random
.randint(0, 255) # Random value betweem 0-255
676 b
= random
.randint(0, 255) # Random value betweem 0-255
678 return wx
.Colour(r
, g
, b
)
681 def PaintStraightGradientBox(dc
, rect
, startColor
, endColor
, vertical
=True):
682 """ Draws a gradient colored box from startColor to endColor. """
684 rd
= endColor
.Red() - startColor
.Red()
685 gd
= endColor
.Green() - startColor
.Green()
686 bd
= endColor
.Blue() - startColor
.Blue()
688 # Save the current pen and brush
689 savedPen
= dc
.GetPen()
690 savedBrush
= dc
.GetBrush()
693 high
= rect
.GetHeight()-1
695 high
= rect
.GetWidth()-1
700 for i
in xrange(high
+1):
702 r
= startColor
.Red() + ((i
*rd
*100)/high
)/100
703 g
= startColor
.Green() + ((i
*gd
*100)/high
)/100
704 b
= startColor
.Blue() + ((i
*bd
*100)/high
)/100
706 p
= wx
.Pen(wx
.Colour(r
, g
, b
))
710 dc
.DrawLine(rect
.x
, rect
.y
+i
, rect
.x
+rect
.width
, rect
.y
+i
)
712 dc
.DrawLine(rect
.x
+i
, rect
.y
, rect
.x
+i
, rect
.y
+rect
.height
)
714 # Restore the pen and brush
716 dc
.SetBrush(savedBrush
)
719 # ---------------------------------------------------------------------------- #
720 # Class FNBDropSource
721 # Gives Some Custom UI Feedback during the DnD Operations
722 # ---------------------------------------------------------------------------- #
724 class FNBDropSource(wx
.DropSource
):
726 Give some custom UI feedback during the drag and drop operation in this
727 function. It is called on each mouse move, so your implementation must
731 def __init__(self
, win
):
732 """ Default class constructor. Used internally. """
734 wx
.DropSource
.__init
__(self
, win
)
738 def GiveFeedback(self
, effect
):
739 """ Provides user with a nice feedback when tab is being dragged. """
741 self
._win
.DrawDragHint()
745 # ---------------------------------------------------------------------------- #
747 # Stores All The Information To Allow Drag And Drop Between Different
749 # ---------------------------------------------------------------------------- #
753 _map
= weakref
.WeakValueDictionary()
755 def __init__(self
, container
, pageindex
):
756 """ Default class constructor. """
758 self
._id
= id(container
)
759 FNBDragInfo
._map
[self
._id
] = container
760 self
._pageindex
= pageindex
763 def GetContainer(self
):
764 """ Returns the L{FlatNotebook} page (usually a panel). """
766 return FNBDragInfo
._map
.get(self
._id
, None)
769 def GetPageIndex(self
):
770 """ Returns the page index associated with a page. """
772 return self
._pageindex
775 # ---------------------------------------------------------------------------- #
776 # Class FNBDropTarget
777 # Simply Used To Handle The OnDrop() Method When Dragging And Dropping Between
778 # Different FlatNotebooks.
779 # ---------------------------------------------------------------------------- #
781 class FNBDropTarget(wx
.DropTarget
):
783 def __init__(self
, parent
):
784 """ Default class constructor. """
786 wx
.DropTarget
.__init
__(self
)
788 self
._parent
= parent
789 self
._dataobject
= wx
.CustomDataObject(wx
.CustomDataFormat("FlatNotebook"))
790 self
.SetDataObject(self
._dataobject
)
793 def OnData(self
, x
, y
, dragres
):
794 """ Handles the OnData() method to call the real DnD routine. """
796 if not self
.GetData():
799 draginfo
= self
._dataobject
.GetData()
800 drginfo
= cPickle
.loads(draginfo
)
802 return self
._parent
.OnDropTarget(x
, y
, drginfo
.GetPageIndex(), drginfo
.GetContainer())
805 # ---------------------------------------------------------------------------- #
807 # Contains parameters for every FlatNotebook page
808 # ---------------------------------------------------------------------------- #
812 This class holds all the information (caption, image, etc...) belonging to a
813 single tab in L{FlatNotebook}.
816 def __init__(self
, caption
="", imageindex
=-1, tabangle
=0, enabled
=True):
818 Default Class Constructor.
821 @param caption: the tab caption;
822 @param imageindex: the tab image index based on the assigned (set) wx.ImageList (if any);
823 @param tabangle: the tab angle (only on standard tabs, from 0 to 15 degrees);
824 @param enabled: sets enabled or disabled the tab.
827 self
._strCaption
= caption
828 self
._TabAngle
= tabangle
829 self
._ImageIndex
= imageindex
830 self
._bEnabled
= enabled
831 self
._pos
= wx
.Point(-1, -1)
832 self
._size
= wx
.Size(-1, -1)
833 self
._region
= wx
.Region()
834 self
._xRect
= wx
.Rect()
838 def SetCaption(self
, value
):
839 """ Sets the tab caption. """
841 self
._strCaption
= value
844 def GetCaption(self
):
845 """ Returns the tab caption. """
847 return self
._strCaption
850 def SetPosition(self
, value
):
851 """ Sets the tab position. """
856 def GetPosition(self
):
857 """ Returns the tab position. """
862 def SetSize(self
, value
):
863 """ Sets the tab size. """
869 """ Returns the tab size. """
874 def SetTabAngle(self
, value
):
875 """ Sets the tab header angle (0 <= tab <= 15 degrees). """
877 self
._TabAngle
= min(45, value
)
880 def GetTabAngle(self
):
881 """ Returns the tab angle. """
883 return self
._TabAngle
886 def SetImageIndex(self
, value
):
887 """ Sets the tab image index. """
889 self
._ImageIndex
= value
892 def GetImageIndex(self
):
893 """ Returns the tab umage index. """
895 return self
._ImageIndex
898 def GetEnabled(self
):
899 """ Returns whether the tab is enabled or not. """
901 return self
._bEnabled
904 def Enable(self
, enabled
):
905 """ Sets the tab enabled or disabled. """
907 self
._bEnabled
= enabled
910 def SetRegion(self
, points
=[]):
911 """ Sets the tab region. """
913 self
._region
= wx
.RegionFromPoints(points
)
917 """ Returns the tab region. """
922 def SetXRect(self
, xrect
):
923 """ Sets the button 'X' area rect. """
929 """ Returns the button 'X' area rect. """
935 """ Returns the tab colour. """
940 def SetColour(self
, color
):
941 """ Sets the tab colour. """
946 # ---------------------------------------------------------------------------- #
947 # Class FlatNotebookEvent
948 # ---------------------------------------------------------------------------- #
950 class FlatNotebookEvent(wx
.PyCommandEvent
):
952 This events will be sent when a EVT_FLATNOTEBOOK_PAGE_CHANGED,
953 EVT_FLATNOTEBOOK_PAGE_CHANGING, EVT_FLATNOTEBOOK_PAGE_CLOSING,
954 EVT_FLATNOTEBOOK_PAGE_CLOSED and EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU is
955 mapped in the parent.
958 def __init__(self
, eventType
, id=1, nSel
=-1, nOldSel
=-1):
959 """ Default class constructor. """
961 wx
.PyCommandEvent
.__init
__(self
, eventType
, id)
962 self
._eventType
= eventType
964 self
.notify
= wx
.NotifyEvent(eventType
, id)
967 def GetNotifyEvent(self
):
968 """Returns the actual wx.NotifyEvent."""
974 """Returns whether the event is allowed or not."""
976 return self
.notify
.IsAllowed()
980 """Vetos the event."""
986 """The event is allowed."""
991 def SetSelection(self
, nSel
):
992 """ Sets event selection. """
994 self
._selection
= nSel
997 def SetOldSelection(self
, nOldSel
):
998 """ Sets old event selection. """
1000 self
._oldselection
= nOldSel
1003 def GetSelection(self
):
1004 """ Returns event selection. """
1006 return self
._selection
1009 def GetOldSelection(self
):
1010 """ Returns old event selection """
1012 return self
._oldselection
1015 # ---------------------------------------------------------------------------- #
1016 # Class TabNavigatorWindow
1017 # ---------------------------------------------------------------------------- #
1019 class TabNavigatorWindow(wx
.Dialog
):
1021 This class is used to create a modal dialog that enables "Smart Tabbing",
1022 similar to what you would get by hitting Alt+Tab on Windows.
1025 def __init__(self
, parent
=None):
1026 """ Default class constructor. Used internally."""
1028 wx
.Dialog
.__init
__(self
, parent
, wx
.ID_ANY
, "", style
=0)
1030 self
._selectedItem
= -1
1033 self
._bmp
= GetMondrianBitmap()
1035 sz
= wx
.BoxSizer(wx
.VERTICAL
)
1037 self
._listBox
= wx
.ListBox(self
, wx
.ID_ANY
, wx
.DefaultPosition
, wx
.Size(200, 150), [], wx
.LB_SINGLE | wx
.NO_BORDER
)
1039 mem_dc
= wx
.MemoryDC()
1040 mem_dc
.SelectObject(wx
.EmptyBitmap(1,1))
1041 font
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
1042 font
.SetWeight(wx
.BOLD
)
1043 mem_dc
.SetFont(font
)
1045 panelHeight
= mem_dc
.GetCharHeight()
1046 panelHeight
+= 4 # Place a spacer of 2 pixels
1048 # Out signpost bitmap is 24 pixels
1049 if panelHeight
< 24:
1052 self
._panel
= wx
.Panel(self
, wx
.ID_ANY
, wx
.DefaultPosition
, wx
.Size(200, panelHeight
))
1055 sz
.Add(self
._listBox
, 1, wx
.EXPAND
)
1059 # Connect events to the list box
1060 self
._listBox
.Bind(wx
.EVT_KEY_UP
, self
.OnKeyUp
)
1061 self
._listBox
.Bind(wx
.EVT_NAVIGATION_KEY
, self
.OnNavigationKey
)
1062 self
._listBox
.Bind(wx
.EVT_LISTBOX_DCLICK
, self
.OnItemSelected
)
1064 # Connect paint event to the panel
1065 self
._panel
.Bind(wx
.EVT_PAINT
, self
.OnPanelPaint
)
1066 self
._panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, self
.OnPanelEraseBg
)
1068 self
.SetBackgroundColour(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
))
1069 self
._listBox
.SetBackgroundColour(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
))
1070 self
.PopulateListControl(parent
)
1072 self
.GetSizer().Fit(self
)
1073 self
.GetSizer().SetSizeHints(self
)
1074 self
.GetSizer().Layout()
1078 def OnKeyUp(self
, event
):
1079 """Handles the wx.EVT_KEY_UP for the L{TabNavigatorWindow}."""
1081 if event
.GetKeyCode() == wx
.WXK_CONTROL
:
1085 def OnNavigationKey(self
, event
):
1086 """Handles the wx.EVT_NAVIGATION_KEY for the L{TabNavigatorWindow}. """
1088 selected
= self
._listBox
.GetSelection()
1089 bk
= self
.GetParent()
1090 maxItems
= bk
.GetPageCount()
1092 if event
.GetDirection():
1095 if selected
== maxItems
- 1:
1098 itemToSelect
= selected
+ 1
1104 itemToSelect
= maxItems
- 1
1106 itemToSelect
= selected
- 1
1108 self
._listBox
.SetSelection(itemToSelect
)
1111 def PopulateListControl(self
, book
):
1112 """Populates the L{TabNavigatorWindow} listbox with a list of tabs."""
1114 selection
= book
.GetSelection()
1115 count
= book
.GetPageCount()
1117 self
._listBox
.Append(book
.GetPageText(selection
))
1118 self
._indexMap
.append(selection
)
1120 prevSel
= book
.GetPreviousSelection()
1122 if prevSel
!= wx
.NOT_FOUND
:
1124 # Insert the previous selection as second entry
1125 self
._listBox
.Append(book
.GetPageText(prevSel
))
1126 self
._indexMap
.append(prevSel
)
1128 for c
in xrange(count
):
1130 # Skip selected page
1134 # Skip previous selected page as well
1138 self
._listBox
.Append(book
.GetPageText(c
))
1139 self
._indexMap
.append(c
)
1141 # Select the next entry after the current selection
1142 self
._listBox
.SetSelection(0)
1143 dummy
= wx
.NavigationKeyEvent()
1144 dummy
.SetDirection(True)
1145 self
.OnNavigationKey(dummy
)
1148 def OnItemSelected(self
, event
):
1149 """Handles the wx.EVT_LISTBOX_DCLICK event for the wx.ListBox inside L{TabNavigatorWindow}. """
1154 def CloseDialog(self
):
1155 """Closes the L{TabNavigatorWindow} dialog, setting selection in L{FlatNotebook}."""
1157 bk
= self
.GetParent()
1158 self
._selectedItem
= self
._listBox
.GetSelection()
1159 iter = self
._indexMap
[self
._selectedItem
]
1160 bk
._pages
.FireEvent(iter)
1161 self
.EndModal(wx
.ID_OK
)
1164 def OnPanelPaint(self
, event
):
1165 """Handles the wx.EVT_PAINT event for L{TabNavigatorWindow} top panel. """
1167 dc
= wx
.PaintDC(self
._panel
)
1168 rect
= self
._panel
.GetClientRect()
1170 bmp
= wx
.EmptyBitmap(rect
.width
, rect
.height
)
1172 mem_dc
= wx
.MemoryDC()
1173 mem_dc
.SelectObject(bmp
)
1175 endColour
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)
1176 startColour
= LightColour(endColour
, 50)
1177 PaintStraightGradientBox(mem_dc
, rect
, startColour
, endColour
)
1179 # Draw the caption title and place the bitmap
1180 # get the bitmap optimal position, and draw it
1181 bmpPt
, txtPt
= wx
.Point(), wx
.Point()
1182 bmpPt
.y
= (rect
.height
- self
._bmp
.GetHeight())/2
1184 mem_dc
.DrawBitmap(self
._bmp
, bmpPt
.x
, bmpPt
.y
, True)
1186 # get the text position, and draw it
1187 font
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
1188 font
.SetWeight(wx
.BOLD
)
1189 mem_dc
.SetFont(font
)
1190 fontHeight
= mem_dc
.GetCharHeight()
1192 txtPt
.x
= bmpPt
.x
+ self
._bmp
.GetWidth() + 4
1193 txtPt
.y
= (rect
.height
- fontHeight
)/2
1194 mem_dc
.SetTextForeground(wx
.WHITE
)
1195 mem_dc
.DrawText("Opened tabs:", txtPt
.x
, txtPt
.y
)
1196 mem_dc
.SelectObject(wx
.NullBitmap
)
1198 dc
.DrawBitmap(bmp
, 0, 0)
1201 def OnPanelEraseBg(self
, event
):
1202 """Handles the wx.EVT_ERASE_BACKGROUND event for L{TabNavigatorWindow} top panel. """
1207 # ---------------------------------------------------------------------------- #
1209 # ---------------------------------------------------------------------------- #
1213 Parent class for the 4 renderers defined: I{Standard}, I{VC71}, I{Fancy}
1214 and I{VC8}. This class implements the common methods of all 4 renderers.
1215 @undocumented: _GetBitmap*
1219 """Default class constructor. """
1221 self
._tabXBgBmp
= wx
.EmptyBitmap(16, 16)
1222 self
._xBgBmp
= wx
.EmptyBitmap(16, 14)
1223 self
._leftBgBmp
= wx
.EmptyBitmap(16, 14)
1224 self
._rightBgBmp
= wx
.EmptyBitmap(16, 14)
1225 self
._tabHeight
= None
1228 def GetLeftButtonPos(self
, pageContainer
):
1229 """ Returns the left button position in the navigation area. """
1232 style
= pc
.GetParent().GetWindowStyleFlag()
1233 rect
= pc
.GetClientRect()
1234 clientWidth
= rect
.width
1236 if style
& FNB_NO_X_BUTTON
:
1237 return clientWidth
- 38
1239 return clientWidth
- 54
1243 def GetRightButtonPos(self
, pageContainer
):
1244 """ Returns the right button position in the navigation area. """
1247 style
= pc
.GetParent().GetWindowStyleFlag()
1248 rect
= pc
.GetClientRect()
1249 clientWidth
= rect
.width
1251 if style
& FNB_NO_X_BUTTON
:
1252 return clientWidth
- 22
1254 return clientWidth
- 38
1257 def GetDropArrowButtonPos(self
, pageContainer
):
1258 """ Returns the drop down button position in the navigation area. """
1260 return self
.GetRightButtonPos(pageContainer
)
1263 def GetXPos(self
, pageContainer
):
1264 """ Returns the 'X' button position in the navigation area. """
1267 style
= pc
.GetParent().GetWindowStyleFlag()
1268 rect
= pc
.GetClientRect()
1269 clientWidth
= rect
.width
1271 if style
& FNB_NO_X_BUTTON
:
1274 return clientWidth
- 22
1277 def GetButtonsAreaLength(self
, pageContainer
):
1278 """ Returns the navigation area width. """
1281 style
= pc
.GetParent().GetWindowStyleFlag()
1284 if style
& FNB_NO_NAV_BUTTONS
and style
& FNB_NO_X_BUTTON
and not style
& FNB_DROPDOWN_TABS_LIST
:
1288 elif style
& FNB_NO_NAV_BUTTONS
and not style
& FNB_NO_X_BUTTON
and not style
& FNB_DROPDOWN_TABS_LIST
:
1292 if not style
& FNB_NO_NAV_BUTTONS
and style
& FNB_NO_X_BUTTON
and not style
& FNB_DROPDOWN_TABS_LIST
:
1296 if style
& FNB_DROPDOWN_TABS_LIST
and not style
& FNB_NO_X_BUTTON
:
1300 if style
& FNB_DROPDOWN_TABS_LIST
and style
& FNB_NO_X_BUTTON
:
1307 def DrawLeftArrow(self
, pageContainer
, dc
):
1308 """ Draw the left navigation arrow. """
1312 style
= pc
.GetParent().GetWindowStyleFlag()
1313 if style
& FNB_NO_NAV_BUTTONS
:
1316 # Make sure that there are pages in the container
1317 if not pc
._pagesInfoVec
:
1320 # Set the bitmap according to the button status
1321 if pc
._nLeftButtonStatus
== FNB_BTN_HOVER
:
1322 arrowBmp
= wx
.BitmapFromXPMData(left_arrow_hilite_xpm
)
1323 elif pc
._nLeftButtonStatus
== FNB_BTN_PRESSED
:
1324 arrowBmp
= wx
.BitmapFromXPMData(left_arrow_pressed_xpm
)
1326 arrowBmp
= wx
.BitmapFromXPMData(left_arrow_xpm
)
1329 # Handle disabled arrow
1330 arrowBmp
= wx
.BitmapFromXPMData(left_arrow_disabled_xpm
)
1332 arrowBmp
.SetMask(wx
.Mask(arrowBmp
, MASK_COLOR
))
1335 posx
= self
.GetLeftButtonPos(pc
)
1336 dc
.DrawBitmap(self
._leftBgBmp
, posx
, 6)
1338 # Draw the new bitmap
1339 dc
.DrawBitmap(arrowBmp
, posx
, 6, True)
1342 def DrawRightArrow(self
, pageContainer
, dc
):
1343 """ Draw the right navigation arrow. """
1347 style
= pc
.GetParent().GetWindowStyleFlag()
1348 if style
& FNB_NO_NAV_BUTTONS
:
1351 # Make sure that there are pages in the container
1352 if not pc
._pagesInfoVec
:
1355 # Set the bitmap according to the button status
1356 if pc
._nRightButtonStatus
== FNB_BTN_HOVER
:
1357 arrowBmp
= wx
.BitmapFromXPMData(right_arrow_hilite_xpm
)
1358 elif pc
._nRightButtonStatus
== FNB_BTN_PRESSED
:
1359 arrowBmp
= wx
.BitmapFromXPMData(right_arrow_pressed_xpm
)
1361 arrowBmp
= wx
.BitmapFromXPMData(right_arrow_xpm
)
1363 # Check if the right most tab is visible, if it is
1364 # don't rotate right anymore
1365 if pc
._pagesInfoVec
[-1].GetPosition() != wx
.Point(-1, -1):
1366 arrowBmp
= wx
.BitmapFromXPMData(right_arrow_disabled_xpm
)
1368 arrowBmp
.SetMask(wx
.Mask(arrowBmp
, MASK_COLOR
))
1371 posx
= self
.GetRightButtonPos(pc
)
1372 dc
.DrawBitmap(self
._rightBgBmp
, posx
, 6)
1374 # Draw the new bitmap
1375 dc
.DrawBitmap(arrowBmp
, posx
, 6, True)
1378 def DrawDropDownArrow(self
, pageContainer
, dc
):
1379 """ Draws the drop-down arrow in the navigation area. """
1383 # Check if this style is enabled
1384 style
= pc
.GetParent().GetWindowStyleFlag()
1385 if not style
& FNB_DROPDOWN_TABS_LIST
:
1388 # Make sure that there are pages in the container
1389 if not pc
._pagesInfoVec
:
1392 if pc
._nArrowDownButtonStatus
== FNB_BTN_HOVER
:
1393 downBmp
= wx
.BitmapFromXPMData(down_arrow_hilite_xpm
)
1394 elif pc
._nArrowDownButtonStatus
== FNB_BTN_PRESSED
:
1395 downBmp
= wx
.BitmapFromXPMData(down_arrow_pressed_xpm
)
1397 downBmp
= wx
.BitmapFromXPMData(down_arrow_xpm
)
1399 downBmp
.SetMask(wx
.Mask(downBmp
, MASK_COLOR
))
1402 posx
= self
.GetDropArrowButtonPos(pc
)
1403 dc
.DrawBitmap(self
._xBgBmp
, posx
, 6)
1405 # Draw the new bitmap
1406 dc
.DrawBitmap(downBmp
, posx
, 6, True)
1409 def DrawX(self
, pageContainer
, dc
):
1410 """ Draw the 'X' navigation button in the navigation area. """
1414 # Check if this style is enabled
1415 style
= pc
.GetParent().GetWindowStyleFlag()
1416 if style
& FNB_NO_X_BUTTON
:
1419 # Make sure that there are pages in the container
1420 if not pc
._pagesInfoVec
:
1423 # Set the bitmap according to the button status
1424 if pc
._nXButtonStatus
== FNB_BTN_HOVER
:
1425 xbmp
= wx
.BitmapFromXPMData(x_button_hilite_xpm
)
1426 elif pc
._nXButtonStatus
== FNB_BTN_PRESSED
:
1427 xbmp
= wx
.BitmapFromXPMData(x_button_pressed_xpm
)
1429 xbmp
= wx
.BitmapFromXPMData(x_button_xpm
)
1431 xbmp
.SetMask(wx
.Mask(xbmp
, MASK_COLOR
))
1434 posx
= self
.GetXPos(pc
)
1435 dc
.DrawBitmap(self
._xBgBmp
, posx
, 6)
1437 # Draw the new bitmap
1438 dc
.DrawBitmap(xbmp
, posx
, 6, True)
1441 def DrawTabX(self
, pageContainer
, dc
, rect
, tabIdx
, btnStatus
):
1442 """ Draws the 'X' in the selected tab. """
1445 if not pc
.HasFlag(FNB_X_ON_TAB
):
1448 # We draw the 'x' on the active tab only
1449 if tabIdx
!= pc
.GetSelection() or tabIdx
< 0:
1452 # Set the bitmap according to the button status
1454 if btnStatus
== FNB_BTN_HOVER
:
1455 xBmp
= wx
.BitmapFromXPMData(x_button_hilite_xpm
)
1456 elif btnStatus
== FNB_BTN_PRESSED
:
1457 xBmp
= wx
.BitmapFromXPMData(x_button_pressed_xpm
)
1459 xBmp
= wx
.BitmapFromXPMData(x_button_xpm
)
1462 xBmp
.SetMask(wx
.Mask(xBmp
, MASK_COLOR
))
1465 dc
.DrawBitmap(self
._tabXBgBmp
, rect
.x
, rect
.y
)
1467 # Draw the new bitmap
1468 dc
.DrawBitmap(xBmp
, rect
.x
, rect
.y
, True)
1471 rr
= wx
.Rect(rect
.x
, rect
.y
, 14, 13)
1472 pc
._pagesInfoVec
[tabIdx
].SetXRect(rr
)
1475 def _GetBitmap(self
, dc
, rect
, bmp
):
1477 mem_dc
= wx
.MemoryDC()
1478 mem_dc
.SelectObject(bmp
)
1479 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
1480 mem_dc
.SelectObject(wx
.NullBitmap
)
1484 def DrawTabsLine(self
, pageContainer
, dc
):
1485 """ Draws a line over the tabs. """
1489 clntRect
= pc
.GetClientRect()
1490 clientRect3
= wx
.Rect(0, 0, clntRect
.width
, clntRect
.height
)
1492 if pc
.HasFlag(FNB_BOTTOM
):
1494 clientRect
= wx
.Rect(0, 2, clntRect
.width
, clntRect
.height
- 2)
1495 clientRect2
= wx
.Rect(0, 1, clntRect
.width
, clntRect
.height
- 1)
1499 clientRect
= wx
.Rect(0, 0, clntRect
.width
, clntRect
.height
- 2)
1500 clientRect2
= wx
.Rect(0, 0, clntRect
.width
, clntRect
.height
- 1)
1502 dc
.SetBrush(wx
.TRANSPARENT_BRUSH
)
1503 dc
.SetPen(wx
.Pen(pc
.GetSingleLineBorderColour()))
1504 dc
.DrawRectangleRect(clientRect2
)
1505 dc
.DrawRectangleRect(clientRect3
)
1507 dc
.SetPen(wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)))
1508 dc
.DrawRectangleRect(clientRect
)
1510 if not pc
.HasFlag(FNB_TABS_BORDER_SIMPLE
):
1512 dc
.SetPen(wx
.Pen((pc
.HasFlag(FNB_VC71
) and [wx
.Colour(247, 243, 233)] or [pc
._tabAreaColor
])[0]))
1513 dc
.DrawLine(0, 0, 0, clientRect
.height
+1)
1515 if pc
.HasFlag(FNB_BOTTOM
):
1517 dc
.DrawLine(0, clientRect
.height
+1, clientRect
.width
, clientRect
.height
+1)
1521 dc
.DrawLine(0, 0, clientRect
.width
, 0)
1523 dc
.DrawLine(clientRect
.width
- 1, 0, clientRect
.width
- 1, clientRect
.height
+1)
1526 def CalcTabWidth(self
, pageContainer
, tabIdx
, tabHeight
):
1527 """ Calculates the width of the input tab. """
1531 dc
.SelectObject(wx
.EmptyBitmap(1,1))
1533 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
1534 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
1536 if pc
.IsDefaultTabs():
1537 shapePoints
= int(tabHeight
*math
.tan(float(pc
._pagesInfoVec
[tabIdx
].GetTabAngle())/180.0*math
.pi
))
1539 # Calculate the text length using the bold font, so when selecting a tab
1540 # its width will not change
1541 dc
.SetFont(boldFont
)
1542 width
, pom
= dc
.GetTextExtent(pc
.GetPageText(tabIdx
))
1544 # Set a minimum size to a tab
1548 tabWidth
= 2*pc
._pParent
.GetPadding() + width
1550 # Style to add a small 'x' button on the top right
1552 if pc
.HasFlag(FNB_X_ON_TAB
) and tabIdx
== pc
.GetSelection():
1553 # The xpm image that contains the 'x' button is 9 pixels
1555 if pc
.HasFlag(FNB_VC8
):
1558 tabWidth
+= pc
._pParent
.GetPadding() + spacer
1560 if pc
.IsDefaultTabs():
1562 tabWidth
+= 2*shapePoints
1564 hasImage
= pc
._ImageList
!= None and pc
._pagesInfoVec
[tabIdx
].GetImageIndex() != -1
1566 # For VC71 style, we only add the icon size (16 pixels)
1569 if not pc
.IsDefaultTabs():
1570 tabWidth
+= 16 + pc
._pParent
.GetPadding()
1573 tabWidth
+= 16 + pc
._pParent
.GetPadding() + shapePoints
/2
1578 def CalcTabHeight(self
, pageContainer
):
1579 """ Calculates the height of the input tab. """
1582 return self
._tabHeight
1586 dc
.SelectObject(wx
.EmptyBitmap(1,1))
1588 # For GTK it seems that we must do this steps in order
1589 # for the tabs will get the proper height on initialization
1590 # on MSW, preforming these steps yields wierd results
1591 normalFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
1592 boldFont
= normalFont
1594 if "__WXGTK__" in wx
.PlatformInfo
:
1595 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
1596 dc
.SetFont(boldFont
)
1598 height
= dc
.GetCharHeight()
1600 tabHeight
= height
+ FNB_HEIGHT_SPACER
# We use 8 pixels as padding
1601 if "__WXGTK__" in wx
.PlatformInfo
:
1602 # On GTK the tabs are should be larger
1605 self
._tabHeight
= tabHeight
1610 def DrawTabs(self
, pageContainer
, dc
):
1611 """ Actually draws the tabs in L{FlatNotebook}."""
1614 if "__WXMAC__" in wx
.PlatformInfo
:
1615 # Works well on MSW & GTK, however this lines should be skipped on MAC
1616 if not pc
._pagesInfoVec
or pc
._nFrom
>= len(pc
._pagesInfoVec
):
1620 # Get the text hight
1621 tabHeight
= self
.CalcTabHeight(pageContainer
)
1622 style
= pc
.GetParent().GetWindowStyleFlag()
1624 # Calculate the number of rows required for drawing the tabs
1625 rect
= pc
.GetClientRect()
1626 clientWidth
= rect
.width
1628 # Set the maximum client size
1629 pc
.SetSizeHints(self
.GetButtonsAreaLength(pc
), tabHeight
)
1630 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
1632 if style
& FNB_VC71
:
1633 backBrush
= wx
.Brush(wx
.Colour(247, 243, 233))
1635 backBrush
= wx
.Brush(pc
._tabAreaColor
)
1637 noselBrush
= wx
.Brush(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNFACE
))
1638 selBrush
= wx
.Brush(pc
._activeTabColor
)
1643 dc
.SetTextBackground((style
& FNB_VC71
and [wx
.Colour(247, 243, 233)] or [pc
.GetBackgroundColour()])[0])
1644 dc
.SetTextForeground(pc
._activeTextColor
)
1645 dc
.SetBrush(backBrush
)
1647 # If border style is set, set the pen to be border pen
1648 if pc
.HasFlag(FNB_TABS_BORDER_SIMPLE
):
1649 dc
.SetPen(borderPen
)
1651 colr
= (pc
.HasFlag(FNB_VC71
) and [wx
.Colour(247, 243, 233)] or [pc
.GetBackgroundColour()])[0]
1652 dc
.SetPen(wx
.Pen(colr
))
1654 dc
.DrawRectangle(0, 0, size
.x
, size
.y
)
1656 # Take 3 bitmaps for the background for the buttons
1658 mem_dc
= wx
.MemoryDC()
1659 #---------------------------------------
1661 #---------------------------------------
1662 rect
= wx
.Rect(self
.GetXPos(pc
), 6, 16, 14)
1663 mem_dc
.SelectObject(self
._xBgBmp
)
1664 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
1665 mem_dc
.SelectObject(wx
.NullBitmap
)
1667 #---------------------------------------
1669 #---------------------------------------
1670 rect
= wx
.Rect(self
.GetRightButtonPos(pc
), 6, 16, 14)
1671 mem_dc
.SelectObject(self
._rightBgBmp
)
1672 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
1673 mem_dc
.SelectObject(wx
.NullBitmap
)
1675 #---------------------------------------
1677 #---------------------------------------
1678 rect
= wx
.Rect(self
.GetLeftButtonPos(pc
), 6, 16, 14)
1679 mem_dc
.SelectObject(self
._leftBgBmp
)
1680 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
1681 mem_dc
.SelectObject(wx
.NullBitmap
)
1683 # We always draw the bottom/upper line of the tabs
1684 # regradless the style
1685 dc
.SetPen(borderPen
)
1686 self
.DrawTabsLine(pc
, dc
)
1689 dc
.SetPen(borderPen
)
1691 if pc
.HasFlag(FNB_VC71
):
1693 greyLineYVal
= (pc
.HasFlag(FNB_BOTTOM
) and [0] or [size
.y
- 2])[0]
1694 whiteLineYVal
= (pc
.HasFlag(FNB_BOTTOM
) and [3] or [size
.y
- 3])[0]
1696 pen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
))
1699 # Draw thik grey line between the windows area and
1701 for num
in xrange(3):
1702 dc
.DrawLine(0, greyLineYVal
+ num
, size
.x
, greyLineYVal
+ num
)
1704 wbPen
= (pc
.HasFlag(FNB_BOTTOM
) and [wx
.BLACK_PEN
] or [wx
.WHITE_PEN
])[0]
1706 dc
.DrawLine(1, whiteLineYVal
, size
.x
- 1, whiteLineYVal
)
1709 dc
.SetPen(borderPen
)
1712 normalFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
1713 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
1714 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
1715 dc
.SetFont(boldFont
)
1717 posx
= pc
._pParent
.GetPadding()
1719 # Update all the tabs from 0 to 'pc._nFrom' to be non visible
1720 for i
in xrange(pc
._nFrom
):
1722 pc
._pagesInfoVec
[i
].SetPosition(wx
.Point(-1, -1))
1723 pc
._pagesInfoVec
[i
].GetRegion().Clear()
1727 #----------------------------------------------------------
1728 # Go over and draw the visible tabs
1729 #----------------------------------------------------------
1730 for i
in xrange(pc
._nFrom
, len(pc
._pagesInfoVec
)):
1732 dc
.SetPen(borderPen
)
1733 dc
.SetBrush((i
==pc
.GetSelection() and [selBrush
] or [noselBrush
])[0])
1735 # Now set the font to the correct font
1736 dc
.SetFont((i
==pc
.GetSelection() and [boldFont
] or [normalFont
])[0])
1738 # Add the padding to the tab width
1740 # +-----------------------------------------------------------+
1741 # | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING |
1742 # +-----------------------------------------------------------+
1743 tabWidth
= self
.CalcTabWidth(pageContainer
, i
, tabHeight
)
1745 # Check if we can draw more
1746 if posx
+ tabWidth
+ self
.GetButtonsAreaLength(pc
) >= clientWidth
:
1751 # By default we clean the tab region
1752 pc
._pagesInfoVec
[i
].GetRegion().Clear()
1754 # Clean the 'x' buttn on the tab.
1755 # A 'Clean' rectangle, is a rectangle with width or height
1756 # with values lower than or equal to 0
1757 pc
._pagesInfoVec
[i
].GetXRect().SetSize(wx
.Size(-1, -1))
1759 # Draw the tab (border, text, image & 'x' on tab)
1760 self
.DrawTab(pc
, dc
, posx
, i
, tabWidth
, tabHeight
, pc
._nTabXButtonStatus
)
1762 # Restore the text forground
1763 dc
.SetTextForeground(pc
._activeTextColor
)
1765 # Update the tab position & size
1766 posy
= (pc
.HasFlag(FNB_BOTTOM
) and [0] or [VERTICAL_BORDER_PADDING
])[0]
1768 pc
._pagesInfoVec
[i
].SetPosition(wx
.Point(posx
, posy
))
1769 pc
._pagesInfoVec
[i
].SetSize(wx
.Size(tabWidth
, tabHeight
))
1772 # Update all tabs that can not fit into the screen as non-visible
1773 for i
in xrange(count
, len(pc
._pagesInfoVec
)):
1774 pc
._pagesInfoVec
[i
].SetPosition(wx
.Point(-1, -1))
1775 pc
._pagesInfoVec
[i
].GetRegion().Clear()
1777 # Draw the left/right/close buttons
1779 self
.DrawLeftArrow(pc
, dc
)
1780 self
.DrawRightArrow(pc
, dc
)
1782 self
.DrawDropDownArrow(pc
, dc
)
1785 def DrawDragHint(self
, pc
, tabIdx
):
1787 Draws tab drag hint, the default implementation is to do nothing.
1788 You can override this function to provide a nice feedback to user.
1794 def NumberTabsCanFit(self
, pageContainer
, fr
=-1):
1798 rect
= pc
.GetClientRect()
1799 clientWidth
= rect
.width
1803 tabHeight
= self
.CalcTabHeight(pageContainer
)
1805 # The drawing starts from posx
1806 posx
= pc
._pParent
.GetPadding()
1811 for i
in xrange(fr
, len(pc
._pagesInfoVec
)):
1813 tabWidth
= self
.CalcTabWidth(pageContainer
, i
, tabHeight
)
1814 if posx
+ tabWidth
+ self
.GetButtonsAreaLength(pc
) >= clientWidth
:
1817 # Add a result to the returned vector
1818 tabRect
= wx
.Rect(posx
, VERTICAL_BORDER_PADDING
, tabWidth
, tabHeight
)
1819 vTabInfo
.append(tabRect
)
1822 posx
+= tabWidth
+ FNB_HEIGHT_SPACER
1827 # ---------------------------------------------------------------------------- #
1828 # Class FNBRendererMgr
1829 # A manager that handles all the renderers defined below and calls the
1830 # appropriate one when drawing is needed
1831 # ---------------------------------------------------------------------------- #
1833 class FNBRendererMgr
:
1835 This class represents a manager that handles all the 4 renderers defined
1836 and calls the appropriate one when drawing is needed.
1840 """ Default class constructor. """
1842 # register renderers
1844 self
._renderers
= {}
1845 self
._renderers
.update({-1: FNBRendererDefault()}
)
1846 self
._renderers
.update({FNB_VC71: FNBRendererVC71()}
)
1847 self
._renderers
.update({FNB_FANCY_TABS: FNBRendererFancy()}
)
1848 self
._renderers
.update({FNB_VC8: FNBRendererVC8()}
)
1851 def GetRenderer(self
, style
):
1852 """ Returns the current renderer based on the style selected. """
1854 # since we dont have a style for default tabs, we
1855 # test for all others - FIXME: add style for default tabs
1856 if not style
& FNB_VC71
and not style
& FNB_VC8
and not style
& FNB_FANCY_TABS
:
1857 return self
._renderers
[-1]
1859 if style
& FNB_VC71
:
1860 return self
._renderers
[FNB_VC71
]
1862 if style
& FNB_FANCY_TABS
:
1863 return self
._renderers
[FNB_FANCY_TABS
]
1866 return self
._renderers
[FNB_VC8
]
1868 # the default is to return the default renderer
1869 return self
._renderers
[-1]
1872 #------------------------------------------
1874 #------------------------------------------
1876 class FNBRendererDefault(FNBRenderer
):
1878 This class handles the drawing of tabs using the I{Standard} renderer.
1882 """ Default class constructor. """
1884 FNBRenderer
.__init
__(self
)
1887 def DrawTab(self
, pageContainer
, dc
, posx
, tabIdx
, tabWidth
, tabHeight
, btnStatus
):
1888 """ Draws a tab using the I{Standard} style. """
1891 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
1894 tabPoints
= [wx
.Point() for ii
in xrange(7)]
1895 tabPoints
[0].x
= posx
1896 tabPoints
[0].y
= (pc
.HasFlag(FNB_BOTTOM
) and [2] or [tabHeight
- 2])[0]
1898 tabPoints
[1].x
= int(posx
+(tabHeight
-2)*math
.tan(float(pc
._pagesInfoVec
[tabIdx
].GetTabAngle())/180.0*math
.pi
))
1899 tabPoints
[1].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- (VERTICAL_BORDER_PADDING
+2)] or [(VERTICAL_BORDER_PADDING
+2)])[0]
1901 tabPoints
[2].x
= tabPoints
[1].x
+2
1902 tabPoints
[2].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- VERTICAL_BORDER_PADDING
] or [VERTICAL_BORDER_PADDING
])[0]
1904 tabPoints
[3].x
= int(posx
+tabWidth
-(tabHeight
-2)*math
.tan(float(pc
._pagesInfoVec
[tabIdx
].GetTabAngle())/180.0*math
.pi
))-2
1905 tabPoints
[3].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- VERTICAL_BORDER_PADDING
] or [VERTICAL_BORDER_PADDING
])[0]
1907 tabPoints
[4].x
= tabPoints
[3].x
+2
1908 tabPoints
[4].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- (VERTICAL_BORDER_PADDING
+2)] or [(VERTICAL_BORDER_PADDING
+2)])[0]
1910 tabPoints
[5].x
= int(tabPoints
[4].x
+(tabHeight
-2)*math
.tan(float(pc
._pagesInfoVec
[tabIdx
].GetTabAngle())/180.0*math
.pi
))
1911 tabPoints
[5].y
= (pc
.HasFlag(FNB_BOTTOM
) and [2] or [tabHeight
- 2])[0]
1913 tabPoints
[6].x
= tabPoints
[0].x
1914 tabPoints
[6].y
= tabPoints
[0].y
1916 if tabIdx
== pc
.GetSelection():
1918 # Draw the tab as rounded rectangle
1919 dc
.DrawPolygon(tabPoints
)
1923 if tabIdx
!= pc
.GetSelection() - 1:
1925 # Draw a vertical line to the right of the text
1926 pt1x
= tabPoints
[5].x
1927 pt1y
= (pc
.HasFlag(FNB_BOTTOM
) and [4] or [tabHeight
- 6])[0]
1928 pt2x
= tabPoints
[5].x
1929 pt2y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- 4] or [4])[0]
1930 dc
.DrawLine(pt1x
, pt1y
, pt2x
, pt2y
)
1932 if tabIdx
== pc
.GetSelection():
1934 savePen
= dc
.GetPen()
1935 whitePen
= wx
.Pen(wx
.WHITE
)
1936 whitePen
.SetWidth(1)
1939 secPt
= wx
.Point(tabPoints
[5].x
+ 1, tabPoints
[5].y
)
1940 dc
.DrawLine(tabPoints
[0].x
, tabPoints
[0].y
, secPt
.x
, secPt
.y
)
1945 # -----------------------------------
1946 # Text and image drawing
1947 # -----------------------------------
1949 # Text drawing offset from the left border of the
1952 # The width of the images are 16 pixels
1953 padding
= pc
.GetParent().GetPadding()
1954 shapePoints
= int(tabHeight
*math
.tan(float(pc
._pagesInfoVec
[tabIdx
].GetTabAngle())/180.0*math
.pi
))
1955 hasImage
= pc
._pagesInfoVec
[tabIdx
].GetImageIndex() != -1
1956 imageYCoord
= (pc
.HasFlag(FNB_BOTTOM
) and [6] or [8])[0]
1959 textOffset
= 2*pc
._pParent
._nPadding
+ 16 + shapePoints
/2
1961 textOffset
= pc
._pParent
._nPadding
+ shapePoints
/2
1965 if tabIdx
!= pc
.GetSelection():
1967 # Set the text background to be like the vertical lines
1968 dc
.SetTextForeground(pc
._pParent
.GetNonActiveTabTextColour())
1972 imageXOffset
= textOffset
- 16 - padding
1973 pc
._ImageList
.Draw(pc
._pagesInfoVec
[tabIdx
].GetImageIndex(), dc
,
1974 posx
+ imageXOffset
, imageYCoord
,
1975 wx
.IMAGELIST_DRAW_TRANSPARENT
, True)
1977 dc
.DrawText(pc
.GetPageText(tabIdx
), posx
+ textOffset
, imageYCoord
)
1979 # draw 'x' on tab (if enabled)
1980 if pc
.HasFlag(FNB_X_ON_TAB
) and tabIdx
== pc
.GetSelection():
1982 textWidth
, textHeight
= dc
.GetTextExtent(pc
.GetPageText(tabIdx
))
1983 tabCloseButtonXCoord
= posx
+ textOffset
+ textWidth
+ 1
1985 # take a bitmap from the position of the 'x' button (the x on tab button)
1986 # this bitmap will be used later to delete old buttons
1987 tabCloseButtonYCoord
= imageYCoord
1988 x_rect
= wx
.Rect(tabCloseButtonXCoord
, tabCloseButtonYCoord
, 16, 16)
1989 self
._tabXBgBmp
= self
._GetBitmap
(dc
, x_rect
, self
._tabXBgBmp
)
1992 self
.DrawTabX(pc
, dc
, x_rect
, tabIdx
, btnStatus
)
1995 #------------------------------------------------------------------
1997 #------------------------------------------------------------------
1999 class FNBRendererVC71(FNBRenderer
):
2001 This class handles the drawing of tabs using the I{VC71} renderer.
2005 """ Default class constructor. """
2007 FNBRenderer
.__init
__(self
)
2010 def DrawTab(self
, pageContainer
, dc
, posx
, tabIdx
, tabWidth
, tabHeight
, btnStatus
):
2011 """ Draws a tab using the I{VC71} style. """
2013 # Visual studio 7.1 style
2014 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
2017 dc
.SetPen((tabIdx
== pc
.GetSelection() and [wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
))] or [borderPen
])[0])
2018 dc
.SetBrush((tabIdx
== pc
.GetSelection() and [wx
.Brush(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
))] or [wx
.Brush(wx
.Colour(247, 243, 233))])[0])
2020 if tabIdx
== pc
.GetSelection():
2022 posy
= (pc
.HasFlag(FNB_BOTTOM
) and [0] or [VERTICAL_BORDER_PADDING
])[0]
2023 tabH
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- 5] or [tabHeight
- 3])[0]
2024 dc
.DrawRectangle(posx
, posy
, tabWidth
, tabH
)
2026 # Draw a black line on the left side of the
2028 dc
.SetPen(wx
.BLACK_PEN
)
2030 blackLineY1
= VERTICAL_BORDER_PADDING
2032 dc
.DrawLine(posx
+ tabWidth
, blackLineY1
, posx
+ tabWidth
, blackLineY2
)
2034 # To give the tab more 3D look we do the following
2035 # Incase the tab is on top,
2036 # Draw a thik white line on topof the rectangle
2037 # Otherwise, draw a thin (1 pixel) black line at the bottom
2039 pen
= wx
.Pen((pc
.HasFlag(FNB_BOTTOM
) and [wx
.BLACK
] or [wx
.WHITE
])[0])
2041 whiteLinePosY
= (pc
.HasFlag(FNB_BOTTOM
) and [blackLineY2
] or [VERTICAL_BORDER_PADDING
])[0]
2042 dc
.DrawLine(posx
, whiteLinePosY
, posx
+ tabWidth
+ 1, whiteLinePosY
)
2044 # Draw a white vertical line to the left of the tab
2045 dc
.SetPen(wx
.WHITE_PEN
)
2046 if not pc
.HasFlag(FNB_BOTTOM
):
2049 dc
.DrawLine(posx
, blackLineY1
, posx
, blackLineY2
)
2053 # We dont draw a rectangle for non selected tabs, but only
2054 # vertical line on the left
2056 blackLineY1
= (pc
.HasFlag(FNB_BOTTOM
) and [VERTICAL_BORDER_PADDING
+ 2] or [VERTICAL_BORDER_PADDING
+ 1])[0]
2057 blackLineY2
= pc
.GetSize().y
- 5
2058 dc
.DrawLine(posx
+ tabWidth
, blackLineY1
, posx
+ tabWidth
, blackLineY2
)
2060 # -----------------------------------
2061 # Text and image drawing
2062 # -----------------------------------
2064 # Text drawing offset from the left border of the
2067 # The width of the images are 16 pixels
2068 padding
= pc
.GetParent().GetPadding()
2069 hasImage
= pc
._pagesInfoVec
[tabIdx
].GetImageIndex() != -1
2070 imageYCoord
= (pc
.HasFlag(FNB_BOTTOM
) and [5] or [8])[0]
2073 textOffset
= 2*pc
._pParent
._nPadding
+ 16
2075 textOffset
= pc
._pParent
._nPadding
2077 if tabIdx
!= pc
.GetSelection():
2079 # Set the text background to be like the vertical lines
2080 dc
.SetTextForeground(pc
._pParent
.GetNonActiveTabTextColour())
2084 imageXOffset
= textOffset
- 16 - padding
2085 pc
._ImageList
.Draw(pc
._pagesInfoVec
[tabIdx
].GetImageIndex(), dc
,
2086 posx
+ imageXOffset
, imageYCoord
,
2087 wx
.IMAGELIST_DRAW_TRANSPARENT
, True)
2089 dc
.DrawText(pc
.GetPageText(tabIdx
), posx
+ textOffset
, imageYCoord
)
2091 # draw 'x' on tab (if enabled)
2092 if pc
.HasFlag(FNB_X_ON_TAB
) and tabIdx
== pc
.GetSelection():
2094 textWidth
, textHeight
= dc
.GetTextExtent(pc
.GetPageText(tabIdx
))
2095 tabCloseButtonXCoord
= posx
+ textOffset
+ textWidth
+ 1
2097 # take a bitmap from the position of the 'x' button (the x on tab button)
2098 # this bitmap will be used later to delete old buttons
2099 tabCloseButtonYCoord
= imageYCoord
2100 x_rect
= wx
.Rect(tabCloseButtonXCoord
, tabCloseButtonYCoord
, 16, 16)
2101 self
._tabXBgBmp
= self
._GetBitmap
(dc
, x_rect
, self
._tabXBgBmp
)
2104 self
.DrawTabX(pc
, dc
, x_rect
, tabIdx
, btnStatus
)
2107 #------------------------------------------------------------------
2109 #------------------------------------------------------------------
2111 class FNBRendererFancy(FNBRenderer
):
2113 This class handles the drawing of tabs using the I{Fancy} renderer.
2117 """ Default class constructor. """
2119 FNBRenderer
.__init
__(self
)
2122 def DrawTab(self
, pageContainer
, dc
, posx
, tabIdx
, tabWidth
, tabHeight
, btnStatus
):
2123 """ Draws a tab using the I{Fancy} style, similar to VC71 but with gradients. """
2125 # Fancy tabs - like with VC71 but with the following differences:
2126 # - The Selected tab is colored with gradient color
2127 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
2130 pen
= (tabIdx
== pc
.GetSelection() and [wx
.Pen(pc
._pParent
.GetBorderColour())] or [wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
))])[0]
2132 if tabIdx
== pc
.GetSelection():
2134 posy
= (pc
.HasFlag(FNB_BOTTOM
) and [2] or [VERTICAL_BORDER_PADDING
])[0]
2137 rect
= wx
.Rect(posx
, posy
, tabWidth
, th
)
2139 col2
= (pc
.HasFlag(FNB_BOTTOM
) and [pc
._pParent
.GetGradientColourTo()] or [pc
._pParent
.GetGradientColourFrom()])[0]
2140 col1
= (pc
.HasFlag(FNB_BOTTOM
) and [pc
._pParent
.GetGradientColourFrom()] or [pc
._pParent
.GetGradientColourTo()])[0]
2142 PaintStraightGradientBox(dc
, rect
, col1
, col2
)
2143 dc
.SetBrush(wx
.TRANSPARENT_BRUSH
)
2145 dc
.DrawRectangleRect(rect
)
2147 # erase the bottom/top line of the rectangle
2148 dc
.SetPen(wx
.Pen(pc
._pParent
.GetGradientColourFrom()))
2149 if pc
.HasFlag(FNB_BOTTOM
):
2150 dc
.DrawLine(rect
.x
, 2, rect
.x
+ rect
.width
, 2)
2152 dc
.DrawLine(rect
.x
, rect
.y
+ rect
.height
- 1, rect
.x
+ rect
.width
, rect
.y
+ rect
.height
- 1)
2156 # We dont draw a rectangle for non selected tabs, but only
2157 # vertical line on the left
2158 dc
.SetPen(borderPen
)
2159 dc
.DrawLine(posx
+ tabWidth
, VERTICAL_BORDER_PADDING
+ 3, posx
+ tabWidth
, tabHeight
- 4)
2162 # -----------------------------------
2163 # Text and image drawing
2164 # -----------------------------------
2166 # Text drawing offset from the left border of the
2169 # The width of the images are 16 pixels
2170 padding
= pc
.GetParent().GetPadding()
2171 hasImage
= pc
._pagesInfoVec
[tabIdx
].GetImageIndex() != -1
2172 imageYCoord
= (pc
.HasFlag(FNB_BOTTOM
) and [6] or [8])[0]
2175 textOffset
= 2*pc
._pParent
._nPadding
+ 16
2177 textOffset
= pc
._pParent
._nPadding
2181 if tabIdx
!= pc
.GetSelection():
2183 # Set the text background to be like the vertical lines
2184 dc
.SetTextForeground(pc
._pParent
.GetNonActiveTabTextColour())
2188 imageXOffset
= textOffset
- 16 - padding
2189 pc
._ImageList
.Draw(pc
._pagesInfoVec
[tabIdx
].GetImageIndex(), dc
,
2190 posx
+ imageXOffset
, imageYCoord
,
2191 wx
.IMAGELIST_DRAW_TRANSPARENT
, True)
2193 dc
.DrawText(pc
.GetPageText(tabIdx
), posx
+ textOffset
, imageYCoord
)
2195 # draw 'x' on tab (if enabled)
2196 if pc
.HasFlag(FNB_X_ON_TAB
) and tabIdx
== pc
.GetSelection():
2198 textWidth
, textHeight
= dc
.GetTextExtent(pc
.GetPageText(tabIdx
))
2199 tabCloseButtonXCoord
= posx
+ textOffset
+ textWidth
+ 1
2201 # take a bitmap from the position of the 'x' button (the x on tab button)
2202 # this bitmap will be used later to delete old buttons
2203 tabCloseButtonYCoord
= imageYCoord
2204 x_rect
= wx
.Rect(tabCloseButtonXCoord
, tabCloseButtonYCoord
, 16, 16)
2205 self
._tabXBgBmp
= self
._GetBitmap
(dc
, x_rect
, self
._tabXBgBmp
)
2208 self
.DrawTabX(pc
, dc
, x_rect
, tabIdx
, btnStatus
)
2211 #------------------------------------------------------------------
2212 # Visual studio 2005 (VS8)
2213 #------------------------------------------------------------------
2214 class FNBRendererVC8(FNBRenderer
):
2216 This class handles the drawing of tabs using the I{VC8} renderer.
2220 """ Default class constructor. """
2222 FNBRenderer
.__init
__(self
)
2227 def DrawTabs(self
, pageContainer
, dc
):
2228 """ Draws all the tabs using VC8 style. Overloads The DrawTabs method in parent class. """
2232 if "__WXMAC__" in wx
.PlatformInfo
:
2233 # Works well on MSW & GTK, however this lines should be skipped on MAC
2234 if not pc
._pagesInfoVec
or pc
._nFrom
>= len(pc
._pagesInfoVec
):
2238 # Get the text hight
2239 tabHeight
= self
.CalcTabHeight(pageContainer
)
2241 # Set the font for measuring the tab height
2242 normalFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
2243 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
2244 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
2246 # Calculate the number of rows required for drawing the tabs
2247 rect
= pc
.GetClientRect()
2249 # Set the maximum client size
2250 pc
.SetSizeHints(self
.GetButtonsAreaLength(pc
), tabHeight
)
2251 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
2254 backBrush
= wx
.Brush(pc
._tabAreaColor
)
2255 noselBrush
= wx
.Brush(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNFACE
))
2256 selBrush
= wx
.Brush(pc
._activeTabColor
)
2260 dc
.SetTextBackground(pc
.GetBackgroundColour())
2261 dc
.SetTextForeground(pc
._activeTextColor
)
2263 # If border style is set, set the pen to be border pen
2264 if pc
.HasFlag(FNB_TABS_BORDER_SIMPLE
):
2265 dc
.SetPen(borderPen
)
2267 dc
.SetPen(wx
.TRANSPARENT_PEN
)
2269 lightFactor
= (pc
.HasFlag(FNB_BACKGROUND_GRADIENT
) and [70] or [0])[0]
2271 # For VC8 style, we color the tab area in gradient coloring
2272 lightcolour
= LightColour(pc
._tabAreaColor
, lightFactor
)
2273 PaintStraightGradientBox(dc
, pc
.GetClientRect(), pc
._tabAreaColor
, lightcolour
)
2275 dc
.SetBrush(wx
.TRANSPARENT_BRUSH
)
2276 dc
.DrawRectangle(0, 0, size
.x
, size
.y
)
2278 # Take 3 bitmaps for the background for the buttons
2280 mem_dc
= wx
.MemoryDC()
2281 #---------------------------------------
2283 #---------------------------------------
2284 rect
= wx
.Rect(self
.GetXPos(pc
), 6, 16, 14)
2285 mem_dc
.SelectObject(self
._xBgBmp
)
2286 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
2287 mem_dc
.SelectObject(wx
.NullBitmap
)
2289 #---------------------------------------
2291 #---------------------------------------
2292 rect
= wx
.Rect(self
.GetRightButtonPos(pc
), 6, 16, 14)
2293 mem_dc
.SelectObject(self
._rightBgBmp
)
2294 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
2295 mem_dc
.SelectObject(wx
.NullBitmap
)
2297 #---------------------------------------
2299 #---------------------------------------
2300 rect
= wx
.Rect(self
.GetLeftButtonPos(pc
), 6, 16, 14)
2301 mem_dc
.SelectObject(self
._leftBgBmp
)
2302 mem_dc
.Blit(0, 0, rect
.width
, rect
.height
, dc
, rect
.x
, rect
.y
)
2303 mem_dc
.SelectObject(wx
.NullBitmap
)
2305 # We always draw the bottom/upper line of the tabs
2306 # regradless the style
2307 dc
.SetPen(borderPen
)
2308 self
.DrawTabsLine(pc
, dc
)
2311 dc
.SetPen(borderPen
)
2314 dc
.SetFont(boldFont
)
2316 # Update all the tabs from 0 to 'pc.self._nFrom' to be non visible
2317 for i
in xrange(pc
._nFrom
):
2319 pc
._pagesInfoVec
[i
].SetPosition(wx
.Point(-1, -1))
2320 pc
._pagesInfoVec
[i
].GetRegion().Clear()
2322 # Draw the visible tabs, in VC8 style, we draw them from right to left
2323 vTabsInfo
= self
.NumberTabsCanFit(pc
)
2329 for cur
in xrange(len(vTabsInfo
)-1, -1, -1):
2331 # 'i' points to the index of the currently drawn tab
2332 # in pc.GetPageInfoVector() vector
2334 dc
.SetPen(borderPen
)
2335 dc
.SetBrush((i
==pc
.GetSelection() and [selBrush
] or [noselBrush
])[0])
2337 # Now set the font to the correct font
2338 dc
.SetFont((i
==pc
.GetSelection() and [boldFont
] or [normalFont
])[0])
2340 # Add the padding to the tab width
2342 # +-----------------------------------------------------------+
2343 # | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING |
2344 # +-----------------------------------------------------------+
2346 tabWidth
= self
.CalcTabWidth(pageContainer
, i
, tabHeight
)
2347 posx
= vTabsInfo
[cur
].x
2349 # By default we clean the tab region
2350 # incase we use the VC8 style which requires
2351 # the region, it will be filled by the function
2353 pc
._pagesInfoVec
[i
].GetRegion().Clear()
2355 # Clean the 'x' buttn on the tab
2356 # 'Clean' rectanlge is a rectangle with width or height
2357 # with values lower than or equal to 0
2358 pc
._pagesInfoVec
[i
].GetXRect().SetSize(wx
.Size(-1, -1))
2361 # Incase we are drawing the active tab
2362 # we need to redraw so it will appear on top
2365 # when using the vc8 style, we keep the position of the active tab so we will draw it again later
2366 if i
== pc
.GetSelection() and pc
.HasFlag(FNB_VC8
):
2368 activeTabPosx
= posx
2369 activeTabWidth
= tabWidth
2370 activeTabHeight
= tabHeight
2374 self
.DrawTab(pc
, dc
, posx
, i
, tabWidth
, tabHeight
, pc
._nTabXButtonStatus
)
2376 # Restore the text forground
2377 dc
.SetTextForeground(pc
._activeTextColor
)
2379 # Update the tab position & size
2380 pc
._pagesInfoVec
[i
].SetPosition(wx
.Point(posx
, VERTICAL_BORDER_PADDING
))
2381 pc
._pagesInfoVec
[i
].SetSize(wx
.Size(tabWidth
, tabHeight
))
2383 # Incase we are in VC8 style, redraw the active tab (incase it is visible)
2384 if pc
.GetSelection() >= pc
._nFrom
and pc
.GetSelection() < pc
._nFrom
+ len(vTabsInfo
):
2386 self
.DrawTab(pc
, dc
, activeTabPosx
, pc
.GetSelection(), activeTabWidth
, activeTabHeight
, pc
._nTabXButtonStatus
)
2388 # Update all tabs that can not fit into the screen as non-visible
2389 for xx
in xrange(pc
._nFrom
+ len(vTabsInfo
), len(pc
._pagesInfoVec
)):
2391 pc
._pagesInfoVec
[xx
].SetPosition(wx
.Point(-1, -1))
2392 pc
._pagesInfoVec
[xx
].GetRegion().Clear()
2394 # Draw the left/right/close buttons
2396 self
.DrawLeftArrow(pc
, dc
)
2397 self
.DrawRightArrow(pc
, dc
)
2399 self
.DrawDropDownArrow(pc
, dc
)
2402 def DrawTab(self
, pageContainer
, dc
, posx
, tabIdx
, tabWidth
, tabHeight
, btnStatus
):
2403 """ Draws a tab using VC8 style. """
2406 borderPen
= wx
.Pen(pc
._pParent
.GetBorderColour())
2407 tabPoints
= [wx
.Point() for ii
in xrange(8)]
2409 # If we draw the first tab or the active tab,
2410 # we draw a full tab, else we draw a truncated tab
2421 tabPoints
[0].x
= (pc
.HasFlag(FNB_BOTTOM
) and [posx
] or [posx
+self
._factor
])[0]
2422 tabPoints
[0].y
= (pc
.HasFlag(FNB_BOTTOM
) and [2] or [tabHeight
- 3])[0]
2424 tabPoints
[1].x
= tabPoints
[0].x
+ tabHeight
- VERTICAL_BORDER_PADDING
- 3 - self
._factor
2425 tabPoints
[1].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- (VERTICAL_BORDER_PADDING
+2)] or [(VERTICAL_BORDER_PADDING
+2)])[0]
2427 tabPoints
[2].x
= tabPoints
[1].x
+ 4
2428 tabPoints
[2].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- VERTICAL_BORDER_PADDING
] or [VERTICAL_BORDER_PADDING
])[0]
2430 tabPoints
[3].x
= tabPoints
[2].x
+ tabWidth
- 2
2431 tabPoints
[3].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabHeight
- VERTICAL_BORDER_PADDING
] or [VERTICAL_BORDER_PADDING
])[0]
2433 tabPoints
[4].x
= tabPoints
[3].x
+ 1
2434 tabPoints
[4].y
= (pc
.HasFlag(FNB_BOTTOM
) and [tabPoints
[3].y
- 1] or [tabPoints
[3].y
+ 1])[0]
2436 tabPoints
[5].x
= tabPoints
[4].x
+ 1
2437 tabPoints
[5].y
= (pc
.HasFlag(FNB_BOTTOM
) and [(tabPoints
[4].y
- 1)] or [tabPoints
[4].y
+ 1])[0]
2439 tabPoints
[6].x
= tabPoints
[2].x
+ tabWidth
2440 tabPoints
[6].y
= tabPoints
[0].y
2442 tabPoints
[7].x
= tabPoints
[0].x
2443 tabPoints
[7].y
= tabPoints
[0].y
2445 pc
._pagesInfoVec
[tabIdx
].SetRegion(tabPoints
)
2449 dc
.SetBrush(wx
.Brush((tabIdx
== pc
.GetSelection() and [pc
._activeTabColor
] or [pc
._colorTo
])[0]))
2450 dc
.SetPen(wx
.Pen((tabIdx
== pc
.GetSelection() and [wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)] or [pc
._colorBorder
])[0]))
2451 dc
.DrawPolygon(tabPoints
)
2455 rect
= pc
.GetClientRect()
2457 if tabIdx
!= pc
.GetSelection() and not pc
.HasFlag(FNB_BOTTOM
):
2460 dc
.SetPen(wx
.Pen(pc
._pParent
.GetBorderColour()))
2462 curPen
= dc
.GetPen()
2465 dc
.DrawLine(posx
, lineY
, posx
+rect
.width
, lineY
)
2467 # Incase we are drawing the selected tab, we draw the border of it as well
2468 # but without the bottom (upper line incase of wxBOTTOM)
2469 if tabIdx
== pc
.GetSelection():
2471 borderPen
= wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
))
2472 dc
.SetPen(borderPen
)
2473 dc
.SetBrush(wx
.TRANSPARENT_BRUSH
)
2474 dc
.DrawPolygon(tabPoints
)
2476 # Delete the bottom line (or the upper one, incase we use wxBOTTOM)
2477 dc
.SetPen(wx
.WHITE_PEN
)
2478 dc
.DrawLine(tabPoints
[0].x
, tabPoints
[0].y
, tabPoints
[6].x
, tabPoints
[6].y
)
2480 self
.FillVC8GradientColour(pc
, dc
, tabPoints
, tabIdx
== pc
.GetSelection(), tabIdx
)
2482 # Draw a thin line to the right of the non-selected tab
2483 if tabIdx
!= pc
.GetSelection():
2485 dc
.SetPen(wx
.Pen(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
)))
2486 dc
.DrawLine(tabPoints
[4].x
-1, tabPoints
[4].y
, tabPoints
[5].x
-1, tabPoints
[5].y
)
2487 dc
.DrawLine(tabPoints
[5].x
-1, tabPoints
[5].y
, tabPoints
[6].x
-1, tabPoints
[6].y
)
2489 # Text drawing offset from the left border of the
2492 # The width of the images are 16 pixels
2493 vc8ShapeLen
= tabHeight
- VERTICAL_BORDER_PADDING
- 2
2494 if pc
.TabHasImage(tabIdx
):
2495 textOffset
= 2*pc
._pParent
.GetPadding() + 16 + vc8ShapeLen
2497 textOffset
= pc
._pParent
.GetPadding() + vc8ShapeLen
2499 # Draw the image for the tab if any
2500 imageYCoord
= (pc
.HasFlag(FNB_BOTTOM
) and [6] or [8])[0]
2502 if pc
.TabHasImage(tabIdx
):
2504 imageXOffset
= textOffset
- 16 - pc
._pParent
.GetPadding()
2505 pc
._ImageList
.Draw(pc
._pagesInfoVec
[tabIdx
].GetImageIndex(), dc
,
2506 posx
+ imageXOffset
, imageYCoord
,
2507 wx
.IMAGELIST_DRAW_TRANSPARENT
, True)
2509 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
2511 # if selected tab, draw text in bold
2512 if tabIdx
== pc
.GetSelection():
2513 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
2515 dc
.SetFont(boldFont
)
2516 dc
.DrawText(pc
.GetPageText(tabIdx
), posx
+ textOffset
, imageYCoord
)
2518 # draw 'x' on tab (if enabled)
2519 if pc
.HasFlag(FNB_X_ON_TAB
) and tabIdx
== pc
.GetSelection():
2521 textWidth
, textHeight
= dc
.GetTextExtent(pc
.GetPageText(tabIdx
))
2522 tabCloseButtonXCoord
= posx
+ textOffset
+ textWidth
+ 1
2524 # take a bitmap from the position of the 'x' button (the x on tab button)
2525 # this bitmap will be used later to delete old buttons
2526 tabCloseButtonYCoord
= imageYCoord
2527 x_rect
= wx
.Rect(tabCloseButtonXCoord
, tabCloseButtonYCoord
, 16, 16)
2528 self
._tabXBgBmp
= self
._GetBitmap
(dc
, x_rect
, self
._tabXBgBmp
)
2530 self
.DrawTabX(pc
, dc
, x_rect
, tabIdx
, btnStatus
)
2533 def FillVC8GradientColour(self
, pageContainer
, dc
, tabPoints
, bSelectedTab
, tabIdx
):
2534 """ Fills a tab with a gradient shading. """
2536 # calculate gradient coefficients
2541 pc
._colorTo
= LightColour(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
), 0)
2542 pc
._colorFrom
= LightColour(wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
), 60)
2544 col2
= pc
._pParent
.GetGradientColourTo()
2545 col1
= pc
._pParent
.GetGradientColourFrom()
2547 # If colorful tabs style is set, override the tab color
2548 if pc
.HasFlag(FNB_COLORFUL_TABS
):
2550 if not pc
._pagesInfoVec
[tabIdx
].GetColour():
2552 # First time, generate color, and keep it in the vector
2553 tabColor
= RandomColour()
2554 pc
._pagesInfoVec
[tabIdx
].SetColour(tabColor
)
2556 if pc
.HasFlag(FNB_BOTTOM
):
2558 col2
= LightColour(pc
._pagesInfoVec
[tabIdx
].GetColour(), 50)
2559 col1
= LightColour(pc
._pagesInfoVec
[tabIdx
].GetColour(), 80)
2563 col1
= LightColour(pc
._pagesInfoVec
[tabIdx
].GetColour(), 50)
2564 col2
= LightColour(pc
._pagesInfoVec
[tabIdx
].GetColour(), 80)
2566 size
= abs(tabPoints
[2].y
- tabPoints
[0].y
) - 1
2568 rf
, gf
, bf
= 0, 0, 0
2569 rstep
= float(col2
.Red() - col1
.Red())/float(size
)
2570 gstep
= float(col2
.Green() - col1
.Green())/float(size
)
2571 bstep
= float(col2
.Blue() - col1
.Blue())/float(size
)
2575 # If we are drawing the selected tab, we need also to draw a line
2576 # from 0.tabPoints[0].x and tabPoints[6].x . end, we achieve this
2577 # by drawing the rectangle with transparent brush
2578 # the line under the selected tab will be deleted by the drwaing loop
2580 self
.DrawTabsLine(pc
, dc
)
2584 if pc
.HasFlag(FNB_BOTTOM
):
2586 if y
> tabPoints
[0].y
+ size
:
2591 if y
< tabPoints
[0].y
- size
:
2594 currCol
= wx
.Colour(col1
.Red() + rf
, col1
.Green() + gf
, col1
.Blue() + bf
)
2596 dc
.SetPen((bSelectedTab
and [wx
.Pen(pc
._activeTabColor
)] or [wx
.Pen(currCol
)])[0])
2597 startX
= self
.GetStartX(tabPoints
, y
, pc
.GetParent().GetWindowStyleFlag())
2598 endX
= self
.GetEndX(tabPoints
, y
, pc
.GetParent().GetWindowStyleFlag())
2599 dc
.DrawLine(startX
, y
, endX
, y
)
2601 # Draw the border using the 'edge' point
2602 dc
.SetPen(wx
.Pen((bSelectedTab
and [wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)] or [pc
._colorBorder
])[0]))
2604 dc
.DrawPoint(startX
, y
)
2605 dc
.DrawPoint(endX
, y
)
2607 # Progress the color
2612 if pc
.HasFlag(FNB_BOTTOM
):
2618 def GetStartX(self
, tabPoints
, y
, style
):
2619 """ Returns the x start position of a tab. """
2621 x1
, x2
, y1
, y2
= 0.0, 0.0, 0.0, 0.0
2623 # We check the 3 points to the left
2625 bBottomStyle
= (style
& FNB_BOTTOM
and [True] or [False])[0]
2632 if y
>= tabPoints
[i
].y
and y
< tabPoints
[i
+1].y
:
2635 x2
= tabPoints
[i
+1].x
2637 y2
= tabPoints
[i
+1].y
2645 if y
<= tabPoints
[i
].y
and y
> tabPoints
[i
+1].y
:
2648 x2
= tabPoints
[i
+1].x
2650 y2
= tabPoints
[i
+1].y
2655 return tabPoints
[2].x
2657 # According to the equation y = ax + b => x = (y-b)/a
2658 # We know the first 2 points
2663 a
= (y2
- y1
)/(x2
- x1
)
2665 b
= y1
- ((y2
- y1
)/(x2
- x1
))*x1
2675 def GetEndX(self
, tabPoints
, y
, style
):
2676 """ Returns the x end position of a tab. """
2678 x1
, x2
, y1
, y2
= 0.0, 0.0, 0.0, 0.0
2680 # We check the 3 points to the left
2681 bBottomStyle
= (style
& FNB_BOTTOM
and [True] or [False])[0]
2686 for i
in xrange(7, 3, -1):
2688 if y
>= tabPoints
[i
].y
and y
< tabPoints
[i
-1].y
:
2691 x2
= tabPoints
[i
-1].x
2693 y2
= tabPoints
[i
-1].y
2699 for i
in xrange(7, 3, -1):
2701 if y
<= tabPoints
[i
].y
and y
> tabPoints
[i
-1].y
:
2704 x2
= tabPoints
[i
-1].x
2706 y2
= tabPoints
[i
-1].y
2711 return tabPoints
[3].x
2713 # According to the equation y = ax + b => x = (y-b)/a
2714 # We know the first 2 points
2720 a
= (y2
- y1
)/(x2
- x1
)
2721 b
= y1
- ((y2
- y1
)/(x2
- x1
))*x1
2731 def NumberTabsCanFit(self
, pageContainer
, fr
=-1):
2732 """ Returns the number of tabs that can fit in the visible area. """
2736 rect
= pc
.GetClientRect()
2737 clientWidth
= rect
.width
2741 tabHeight
= self
.CalcTabHeight(pageContainer
)
2743 # The drawing starts from posx
2744 posx
= pc
._pParent
.GetPadding()
2749 for i
in xrange(fr
, len(pc
._pagesInfoVec
)):
2751 vc8glitch
= tabHeight
+ FNB_HEIGHT_SPACER
2752 tabWidth
= self
.CalcTabWidth(pageContainer
, i
, tabHeight
)
2754 if posx
+ tabWidth
+ vc8glitch
+ self
.GetButtonsAreaLength(pc
) >= clientWidth
:
2757 # Add a result to the returned vector
2758 tabRect
= wx
.Rect(posx
, VERTICAL_BORDER_PADDING
, tabWidth
, tabHeight
)
2759 vTabInfo
.append(tabRect
)
2762 posx
+= tabWidth
+ FNB_HEIGHT_SPACER
2767 # ---------------------------------------------------------------------------- #
2768 # Class FlatNotebook
2769 # ---------------------------------------------------------------------------- #
2771 class FlatNotebook(wx
.Panel
):
2773 Display one or more windows in a notebook.
2776 - B{EVT_FLATNOTEBOOK_PAGE_CHANGING}: sent when the active
2777 page in the notebook is changing
2778 - B{EVT_FLATNOTEBOOK_PAGE_CHANGED}: sent when the active
2779 page in the notebook has changed
2780 - B{EVT_FLATNOTEBOOK_PAGE_CLOSING}: sent when a page in the
2782 - B{EVT_FLATNOTEBOOK_PAGE_CLOSED}: sent when a page in the
2783 notebook has been closed
2784 - B{EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU}: sent when the user
2785 clicks a tab in the notebook with the right mouse
2789 def __init__(self
, parent
, id=wx
.ID_ANY
, pos
=wx
.DefaultPosition
, size
=wx
.DefaultSize
,
2790 style
=0, name
="FlatNotebook"):
2792 Default class constructor.
2794 All the parameters are as in wxPython class construction, except the
2795 'style': this can be assigned to whatever combination of FNB_* styles.
2799 self
._bForceSelection
= False
2802 style |
= wx
.TAB_TRAVERSAL
2805 self
._popupWin
= None
2807 wx
.Panel
.__init
__(self
, parent
, id, pos
, size
, style
)
2809 self
._pages
= PageContainer(self
, wx
.ID_ANY
, wx
.DefaultPosition
, wx
.DefaultSize
, style
)
2811 self
.Bind(wx
.EVT_NAVIGATION_KEY
, self
.OnNavigationKey
)
2817 """ Initializes all the class attributes. """
2819 self
._pages
._colorBorder
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)
2821 self
._mainSizer
= wx
.BoxSizer(wx
.VERTICAL
)
2822 self
.SetSizer(self
._mainSizer
)
2824 # The child panels will inherit this bg color, so leave it at the default value
2825 #self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_APPWORKSPACE))
2827 # Set default page height
2828 dc
= wx
.ClientDC(self
)
2830 if "__WXGTK__" in wx
.PlatformInfo
:
2831 # For GTK it seems that we must do this steps in order
2832 # for the tabs will get the proper height on initialization
2833 # on MSW, preforming these steps yields wierd results
2834 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
2835 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
2836 dc
.SetFont(boldFont
)
2838 height
= dc
.GetCharHeight()
2840 tabHeight
= height
+ FNB_HEIGHT_SPACER
# We use 8 pixels as padding
2842 if "__WXGTK__" in wx
.PlatformInfo
:
2845 self
._pages
.SetSizeHints(-1, tabHeight
)
2846 # Add the tab container to the sizer
2847 self
._mainSizer
.Insert(0, self
._pages
, 0, wx
.EXPAND
)
2848 self
._mainSizer
.Layout()
2850 self
._pages
._nFrom
= self
._nFrom
2851 self
._pDropTarget
= FNBDropTarget(self
)
2852 self
.SetDropTarget(self
._pDropTarget
)
2855 def SetActiveTabTextColour(self
, textColour
):
2856 """ Sets the text colour for the active tab. """
2858 self
._pages
._activeTextColor
= textColour
2861 def OnDropTarget(self
, x
, y
, nTabPage
, wnd_oldContainer
):
2862 """ Handles the drop action from a DND operation. """
2864 return self
._pages
.OnDropTarget(x
, y
, nTabPage
, wnd_oldContainer
)
2867 def GetPreviousSelection(self
):
2868 """ Returns the previous selection. """
2870 return self
._pages
._iPreviousActivePage
2873 def AddPage(self
, page
, text
, select
=True, imageId
=-1):
2875 Add a page to the L{FlatNotebook}.
2877 @param page: Specifies the new page.
2878 @param text: Specifies the text for the new page.
2879 @param select: Specifies whether the page should be selected.
2880 @param imageId: Specifies the optional image index for the new page.
2883 True if successful, False otherwise.
2890 # reparent the window to us
2894 bSelected
= select
or len(self
._windows
) == 0
2900 # Check for selection and send events
2901 oldSelection
= self
._pages
._iActivePage
2902 tabIdx
= len(self
._windows
)
2904 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, self
.GetId())
2905 event
.SetSelection(tabIdx
)
2906 event
.SetOldSelection(oldSelection
)
2907 event
.SetEventObject(self
)
2909 if not self
.GetEventHandler().ProcessEvent(event
) or event
.IsAllowed() or len(self
._windows
) == 0:
2912 curSel
= self
._pages
.GetSelection()
2914 if not self
._pages
.IsShown():
2917 self
._pages
.AddPage(text
, bSelected
, imageId
)
2918 self
._windows
.append(page
)
2922 # Check if a new selection was made
2927 # Remove the window from the main sizer
2928 self
._mainSizer
.Detach(self
._windows
[curSel
])
2929 self
._windows
[curSel
].Hide()
2931 if self
.GetWindowStyleFlag() & FNB_BOTTOM
:
2933 self
._mainSizer
.Insert(0, page
, 1, wx
.EXPAND
)
2937 # We leave a space of 1 pixel around the window
2938 self
._mainSizer
.Add(page
, 1, wx
.EXPAND
)
2940 # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
2941 event
.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
)
2942 event
.SetOldSelection(oldSelection
)
2943 self
.GetEventHandler().ProcessEvent(event
)
2951 self
._mainSizer
.Layout()
2957 def SetImageList(self
, imageList
):
2959 Sets the image list for the page control. It does not take ownership
2960 of the image list, you must delete it yourself.
2963 self
._pages
.SetImageList(imageList
)
2966 def GetImageList(self
):
2967 """ Returns the associated image list. """
2969 return self
._pages
.GetImageList()
2972 def InsertPage(self
, indx
, page
, text
, select
=True, imageId
=-1):
2974 Inserts a new page at the specified position.
2976 @param indx: Specifies the position of the new page.
2977 @param page: Specifies the new page.
2978 @param text: Specifies the text for the new page.
2979 @param select: Specifies whether the page should be selected.
2980 @param imageId: Specifies the optional image index for the new page.
2983 True if successful, False otherwise.
2990 # reparent the window to us
2993 if not self
._windows
:
2995 self
.AddPage(page
, text
, select
, imageId
)
2999 bSelected
= select
or not self
._windows
3000 curSel
= self
._pages
.GetSelection()
3002 indx
= max(0, min(indx
, len(self
._windows
)))
3004 if indx
<= len(self
._windows
):
3006 self
._windows
.insert(indx
, page
)
3010 self
._windows
.append(page
)
3016 # Check for selection and send events
3017 oldSelection
= self
._pages
._iActivePage
3019 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, self
.GetId())
3020 event
.SetSelection(indx
)
3021 event
.SetOldSelection(oldSelection
)
3022 event
.SetEventObject(self
)
3024 if not self
.GetEventHandler().ProcessEvent(event
) or event
.IsAllowed() or len(self
._windows
) == 0:
3027 self
._pages
.InsertPage(indx
, text
, bSelected
, imageId
)
3034 # Check if a new selection was made
3039 # Remove the window from the main sizer
3040 self
._mainSizer
.Detach(self
._windows
[curSel
])
3041 self
._windows
[curSel
].Hide()
3043 self
._pages
.SetSelection(indx
)
3045 # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
3046 event
.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
)
3047 event
.SetOldSelection(oldSelection
)
3048 self
.GetEventHandler().ProcessEvent(event
)
3056 self
._mainSizer
.Layout()
3062 def SetSelection(self
, page
):
3064 Sets the selection for the given page.
3065 The call to this function generates the page changing events
3068 if page
>= len(self
._windows
) or not self
._windows
:
3071 # Support for disabed tabs
3072 if not self
._pages
.GetEnabled(page
) and len(self
._windows
) > 1 and not self
._bForceSelection
:
3075 curSel
= self
._pages
.GetSelection()
3077 # program allows the page change
3081 # Remove the window from the main sizer
3082 self
._mainSizer
.Detach(self
._windows
[curSel
])
3083 self
._windows
[curSel
].Hide()
3085 if self
.GetWindowStyleFlag() & FNB_BOTTOM
:
3087 self
._mainSizer
.Insert(0, self
._windows
[page
], 1, wx
.EXPAND
)
3091 # We leave a space of 1 pixel around the window
3092 self
._mainSizer
.Add(self
._windows
[page
], 1, wx
.EXPAND
)
3094 self
._windows
[page
].Show()
3097 self
._mainSizer
.Layout()
3099 if page
!= self
._pages
._iActivePage
:
3100 # there is a real page changing
3101 self
._pages
._iPreviousActivePage
= self
._pages
._iActivePage
3103 self
._pages
._iActivePage
= page
3104 self
._pages
.DoSetSelection(page
)
3107 def DeletePage(self
, page
):
3109 Deletes the specified page, and the associated window.
3110 The call to this function generates the page changing events.
3113 if page
>= len(self
._windows
) or page
< 0:
3116 # Fire a closing event
3117 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING
, self
.GetId())
3118 event
.SetSelection(page
)
3119 event
.SetEventObject(self
)
3120 self
.GetEventHandler().ProcessEvent(event
)
3122 # The event handler allows it?
3123 if not event
.IsAllowed():
3128 # Delete the requested page
3129 pageRemoved
= self
._windows
[page
]
3131 # If the page is the current window, remove it from the sizer
3133 if page
== self
._pages
.GetSelection():
3134 self
._mainSizer
.Detach(pageRemoved
)
3136 # Remove it from the array as well
3137 self
._windows
.pop(page
)
3139 # Now we can destroy it in wxWidgets use Destroy instead of delete
3140 pageRemoved
.Destroy()
3144 self
._pages
.DoDeletePage(page
)
3147 # Fire a closed event
3148 closedEvent
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSED
, self
.GetId())
3149 closedEvent
.SetSelection(page
)
3150 closedEvent
.SetEventObject(self
)
3151 self
.GetEventHandler().ProcessEvent(closedEvent
)
3154 def DeleteAllPages(self
):
3155 """ Deletes all the pages. """
3157 if not self
._windows
:
3162 for page
in self
._windows
:
3168 # Clear the container of the tabs as well
3169 self
._pages
.DeleteAllPages()
3173 def GetCurrentPage(self
):
3174 """ Returns the currently selected notebook page or None. """
3176 sel
= self
._pages
.GetSelection()
3180 return self
._windows
[sel
]
3183 def GetPage(self
, page
):
3184 """ Returns the window at the given page position, or None. """
3186 if page
>= len(self
._windows
):
3189 return self
._windows
[page
]
3192 def GetPageIndex(self
, win
):
3193 """ Returns the index at which the window is found. """
3196 return self
._windows
.index(win
)
3201 def GetSelection(self
):
3202 """ Returns the currently selected page, or -1 if none was selected. """
3204 return self
._pages
.GetSelection()
3207 def AdvanceSelection(self
, forward
=True):
3209 Cycles through the tabs.
3210 The call to this function generates the page changing events.
3213 self
._pages
.AdvanceSelection(forward
)
3216 def GetPageCount(self
):
3217 """ Returns the number of pages in the L{FlatNotebook} control. """
3219 return self
._pages
.GetPageCount()
3222 def OnNavigationKey(self
, event
):
3223 """ Handles the wx.EVT_NAVIGATION_KEY event for L{FlatNotebook}. """
3225 if event
.IsWindowChange():
3226 if len(self
._windows
) == 0:
3229 if self
.HasFlag(FNB_SMART_TABS
):
3230 if not self
._popupWin
:
3231 self
._popupWin
= TabNavigatorWindow(self
)
3232 self
._popupWin
.SetReturnCode(wx
.ID_OK
)
3233 self
._popupWin
.ShowModal()
3234 self
._popupWin
.Destroy()
3235 self
._popupWin
= None
3237 # a dialog is already opened
3238 self
._popupWin
.OnNavigationKey(event
)
3242 self
.AdvanceSelection(event
.GetDirection())
3244 # pass to the parent
3245 if self
.GetParent():
3246 event
.SetCurrentFocus(self
)
3247 self
.GetParent().ProcessEvent(event
)
3250 def GetPageShapeAngle(self
, page_index
):
3251 """ Returns the angle associated to a tab. """
3253 if page_index
< 0 or page_index
>= len(self
._pages
._pagesInfoVec
):
3256 result
= self
._pages
._pagesInfoVec
[page_index
].GetTabAngle()
3260 def SetPageShapeAngle(self
, page_index
, angle
):
3261 """ Sets the angle associated to a tab. """
3263 if page_index
< 0 or page_index
>= len(self
._pages
._pagesInfoVec
):
3269 self
._pages
._pagesInfoVec
[page_index
].SetTabAngle(angle
)
3272 def SetAllPagesShapeAngle(self
, angle
):
3273 """ Sets the angle associated to all the tab. """
3278 for ii
in xrange(len(self
._pages
._pagesInfoVec
)):
3279 self
._pages
._pagesInfoVec
[ii
].SetTabAngle(angle
)
3284 def GetPageBestSize(self
):
3285 """ Return the page best size. """
3287 return self
._pages
.GetClientSize()
3290 def SetPageText(self
, page
, text
):
3291 """ Sets the text for the given page. """
3293 bVal
= self
._pages
.SetPageText(page
, text
)
3294 self
._pages
.Refresh()
3299 def SetPadding(self
, padding
):
3301 Sets the amount of space around each page's icon and label, in pixels.
3302 NB: only the horizontal padding is considered.
3305 self
._nPadding
= padding
.GetWidth()
3308 def GetTabArea(self
):
3309 """ Returns the associated page. """
3314 def GetPadding(self
):
3315 """ Returns the amount of space around each page's icon and label, in pixels. """
3317 return self
._nPadding
3320 def SetWindowStyleFlag(self
, style
):
3321 """ Sets the L{FlatNotebook} window style flags. """
3323 wx
.Panel
.SetWindowStyleFlag(self
, style
)
3324 renderer
= self
._pages
._mgr
.GetRenderer(self
.GetWindowStyleFlag())
3325 renderer
._tabHeight
= None
3329 # For changing the tab position (i.e. placing them top/bottom)
3330 # refreshing the tab container is not enough
3331 self
.SetSelection(self
._pages
._iActivePage
)
3333 if not self
._pages
.HasFlag(FNB_HIDE_ON_SINGLE_TAB
):
3334 #For Redrawing the Tabs once you remove the Hide tyle
3335 self
._pages
._ReShow
()
3338 def RemovePage(self
, page
):
3339 """ Deletes the specified page, without deleting the associated window. """
3341 if page
>= len(self
._windows
):
3344 # Fire a closing event
3345 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING
, self
.GetId())
3346 event
.SetSelection(page
)
3347 event
.SetEventObject(self
)
3348 self
.GetEventHandler().ProcessEvent(event
)
3350 # The event handler allows it?
3351 if not event
.IsAllowed():
3356 # Remove the requested page
3357 pageRemoved
= self
._windows
[page
]
3359 # If the page is the current window, remove it from the sizer
3361 if page
== self
._pages
.GetSelection():
3362 self
._mainSizer
.Detach(pageRemoved
)
3364 # Remove it from the array as well
3365 self
._windows
.pop(page
)
3368 self
._pages
.DoDeletePage(page
)
3373 def SetRightClickMenu(self
, menu
):
3374 """ Sets the popup menu associated to a right click on a tab. """
3376 self
._pages
._pRightClickMenu
= menu
3379 def GetPageText(self
, nPage
):
3380 """ Returns the tab caption. """
3382 return self
._pages
.GetPageText(nPage
)
3385 def SetGradientColours(self
, fr
, to
, border
):
3386 """ Sets the gradient colours for the tab. """
3388 self
._pages
._colorFrom
= fr
3389 self
._pages
._colorTo
= to
3390 self
._pages
._colorBorder
= border
3393 def SetGradientColourFrom(self
, fr
):
3394 """ Sets the starting colour for the gradient. """
3396 self
._pages
._colorFrom
= fr
3399 def SetGradientColourTo(self
, to
):
3400 """ Sets the ending colour for the gradient. """
3402 self
._pages
._colorTo
= to
3405 def SetGradientColourBorder(self
, border
):
3406 """ Sets the tab border colour. """
3408 self
._pages
._colorBorder
= border
3411 def GetGradientColourFrom(self
):
3412 """ Gets first gradient colour. """
3414 return self
._pages
._colorFrom
3417 def GetGradientColourTo(self
):
3418 """ Gets second gradient colour. """
3420 return self
._pages
._colorTo
3423 def GetGradientColourBorder(self
):
3424 """ Gets the tab border colour. """
3426 return self
._pages
._colorBorder
3429 def GetBorderColour(self
):
3430 """ Returns the border colour. """
3432 return self
._pages
._colorBorder
3435 def GetActiveTabTextColour(self
):
3436 """ Get the active tab text colour. """
3438 return self
._pages
._activeTextColor
3441 def SetPageImage(self
, page
, image
):
3443 Sets the image index for the given page. Image is an index into the
3444 image list which was set with SetImageList.
3447 self
._pages
.SetPageImage(page
, image
)
3450 def GetPageImage(self
, nPage
):
3452 Returns the image index for the given page. Image is an index into the
3453 image list which was set with SetImageList.
3456 return self
._pages
.GetPageImage(nPage
)
3459 def GetEnabled(self
, page
):
3460 """ Returns whether a tab is enabled or not. """
3462 return self
._pages
.GetEnabled(page
)
3465 def Enable(self
, page
, enabled
=True):
3466 """ Enables or disables a tab. """
3468 if page
>= len(self
._windows
):
3471 self
._windows
[page
].Enable(enabled
)
3472 self
._pages
.Enable(page
, enabled
)
3475 def GetNonActiveTabTextColour(self
):
3476 """ Returns the non active tabs text colour. """
3478 return self
._pages
._nonActiveTextColor
3481 def SetNonActiveTabTextColour(self
, color
):
3482 """ Sets the non active tabs text colour. """
3484 self
._pages
._nonActiveTextColor
= color
3487 def SetTabAreaColour(self
, color
):
3488 """ Sets the area behind the tabs colour. """
3490 self
._pages
._tabAreaColor
= color
3493 def GetTabAreaColour(self
):
3494 """ Returns the area behind the tabs colour. """
3496 return self
._pages
._tabAreaColor
3499 def SetActiveTabColour(self
, color
):
3500 """ Sets the active tab colour. """
3502 self
._pages
._activeTabColor
= color
3505 def GetActiveTabColour(self
):
3506 """ Returns the active tab colour. """
3508 return self
._pages
._activeTabColor
3511 # ---------------------------------------------------------------------------- #
3512 # Class PageContainer
3513 # Acts as a container for the pages you add to FlatNotebook
3514 # ---------------------------------------------------------------------------- #
3516 class PageContainer(wx
.Panel
):
3518 This class acts as a container for the pages you add to L{FlatNotebook}.
3521 def __init__(self
, parent
, id=wx
.ID_ANY
, pos
=wx
.DefaultPosition
,
3522 size
=wx
.DefaultSize
, style
=0):
3523 """ Default class constructor. """
3525 self
._ImageList
= None
3526 self
._iActivePage
= -1
3527 self
._pDropTarget
= None
3528 self
._nLeftClickZone
= FNB_NOWHERE
3529 self
._iPreviousActivePage
= -1
3531 self
._pRightClickMenu
= None
3532 self
._nXButtonStatus
= FNB_BTN_NONE
3533 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
3534 self
._pParent
= parent
3535 self
._nRightButtonStatus
= FNB_BTN_NONE
3536 self
._nLeftButtonStatus
= FNB_BTN_NONE
3537 self
._nTabXButtonStatus
= FNB_BTN_NONE
3539 self
._pagesInfoVec
= []
3541 self
._colorTo
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_ACTIVECAPTION
)
3542 self
._colorFrom
= wx
.WHITE
3543 self
._activeTabColor
= wx
.WHITE
3544 self
._activeTextColor
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNTEXT
)
3545 self
._nonActiveTextColor
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)
3546 self
._tabAreaColor
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNFACE
)
3549 self
._isdragging
= False
3551 # Set default page height, this is done according to the system font
3552 memDc
= wx
.MemoryDC()
3553 memDc
.SelectObject(wx
.EmptyBitmap(1,1))
3555 if "__WXGTK__" in wx
.PlatformInfo
:
3556 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
3557 boldFont
.SetWeight(wx
.BOLD
)
3558 memDc
.SetFont(boldFont
)
3560 height
= memDc
.GetCharHeight()
3561 tabHeight
= height
+ FNB_HEIGHT_SPACER
# We use 10 pixels as padding
3563 wx
.Panel
.__init
__(self
, parent
, id, pos
, wx
.Size(size
.x
, tabHeight
),
3564 style|wx
.NO_BORDER|wx
.NO_FULL_REPAINT_ON_RESIZE
)
3566 self
._pDropTarget
= FNBDropTarget(self
)
3567 self
.SetDropTarget(self
._pDropTarget
)
3568 self
._mgr
= FNBRendererMgr()
3570 self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
)
3571 self
.Bind(wx
.EVT_SIZE
, self
.OnSize
)
3572 self
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnLeftDown
)
3573 self
.Bind(wx
.EVT_LEFT_UP
, self
.OnLeftUp
)
3574 self
.Bind(wx
.EVT_RIGHT_DOWN
, self
.OnRightDown
)
3575 self
.Bind(wx
.EVT_MIDDLE_DOWN
, self
.OnMiddleDown
)
3576 self
.Bind(wx
.EVT_MOTION
, self
.OnMouseMove
)
3577 self
.Bind(wx
.EVT_ERASE_BACKGROUND
, self
.OnEraseBackground
)
3578 self
.Bind(wx
.EVT_LEAVE_WINDOW
, self
.OnMouseLeave
)
3579 self
.Bind(wx
.EVT_ENTER_WINDOW
, self
.OnMouseEnterWindow
)
3580 self
.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnLeftDClick
)
3583 def OnEraseBackground(self
, event
):
3584 """ Handles the wx.EVT_ERASE_BACKGROUND event for L{PageContainer} (does nothing)."""
3590 """ Handles the Redraw of the tabs when the FNB_HIDE_ON_SINGLE_TAB has been removed """
3592 self
.GetParent()._mainSizer
.Layout()
3596 def OnPaint(self
, event
):
3597 """ Handles the wx.EVT_PAINT event for L{PageContainer}."""
3599 dc
= wx
.BufferedPaintDC(self
)
3600 renderer
= self
._mgr
.GetRenderer(self
.GetParent().GetWindowStyleFlag())
3601 renderer
.DrawTabs(self
, dc
)
3603 if self
.HasFlag(FNB_HIDE_ON_SINGLE_TAB
) and len(self
._pagesInfoVec
) <= 1:
3605 self
.GetParent()._mainSizer
.Layout()
3609 def AddPage(self
, caption
, selected
=True, imgindex
=-1):
3611 Add a page to the L{FlatNotebook}.
3613 @param window: Specifies the new page.
3614 @param caption: Specifies the text for the new page.
3615 @param selected: Specifies whether the page should be selected.
3616 @param imgindex: Specifies the optional image index for the new page.
3619 True if successful, False otherwise.
3624 self
._iPreviousActivePage
= self
._iActivePage
3625 self
._iActivePage
= len(self
._pagesInfoVec
)
3627 # Create page info and add it to the vector
3628 pageInfo
= PageInfo(caption
, imgindex
)
3629 self
._pagesInfoVec
.append(pageInfo
)
3633 def InsertPage(self
, indx
, text
, selected
=True, imgindex
=-1):
3635 Inserts a new page at the specified position.
3637 @param indx: Specifies the position of the new page.
3638 @param page: Specifies the new page.
3639 @param text: Specifies the text for the new page.
3640 @param select: Specifies whether the page should be selected.
3641 @param imgindex: Specifies the optional image index for the new page.
3644 True if successful, False otherwise.
3649 self
._iPreviousActivePage
= self
._iActivePage
3650 self
._iActivePage
= len(self
._pagesInfoVec
)
3652 self
._pagesInfoVec
.insert(indx
, PageInfo(text
, imgindex
))
3658 def OnSize(self
, event
):
3659 """ Handles the wx.EVT_SIZE events for L{PageContainer}. """
3661 # When resizing the control, try to fit to screen as many tabs as we can
3662 style
= self
.GetParent().GetWindowStyleFlag()
3663 renderer
= self
._mgr
.GetRenderer(style
)
3666 page
= self
.GetSelection()
3668 for fr
in xrange(self
._nFrom
):
3669 vTabInfo
= renderer
.NumberTabsCanFit(self
, fr
)
3670 if page
- fr
>= len(vTabInfo
):
3676 self
.Refresh() # Call on paint
3680 def OnMiddleDown(self
, event
):
3681 """ Handles the wx.EVT_MIDDLE_DOWN events for L{PageContainer}. """
3683 # Test if this style is enabled
3684 style
= self
.GetParent().GetWindowStyleFlag()
3686 if not style
& FNB_MOUSE_MIDDLE_CLOSES_TABS
:
3689 where
, tabIdx
= self
.HitTest(event
.GetPosition())
3691 if where
== FNB_TAB
:
3692 self
.DeletePage(tabIdx
)
3697 def OnRightDown(self
, event
):
3698 """ Handles the wx.EVT_RIGHT_DOWN events for L{PageContainer}. """
3700 where
, tabIdx
= self
.HitTest(event
.GetPosition())
3702 if where
in [FNB_TAB
, FNB_TAB_X
]:
3704 if self
._pagesInfoVec
[tabIdx
].GetEnabled():
3705 # Fire events and eventually (if allowed) change selection
3706 self
.FireEvent(tabIdx
)
3708 # send a message to popup a custom menu
3709 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU
, self
.GetParent().GetId())
3710 event
.SetSelection(tabIdx
)
3711 event
.SetOldSelection(self
._iActivePage
)
3712 event
.SetEventObject(self
.GetParent())
3713 self
.GetParent().GetEventHandler().ProcessEvent(event
)
3715 if self
._pRightClickMenu
:
3716 self
.PopupMenu(self
._pRightClickMenu
)
3721 def OnLeftDown(self
, event
):
3722 """ Handles the wx.EVT_LEFT_DOWN events for L{PageContainer}. """
3724 # Reset buttons status
3725 self
._nXButtonStatus
= FNB_BTN_NONE
3726 self
._nLeftButtonStatus
= FNB_BTN_NONE
3727 self
._nRightButtonStatus
= FNB_BTN_NONE
3728 self
._nTabXButtonStatus
= FNB_BTN_NONE
3729 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
3731 self
._nLeftClickZone
, tabIdx
= self
.HitTest(event
.GetPosition())
3733 if self
._nLeftClickZone
== FNB_DROP_DOWN_ARROW
:
3734 self
._nArrowDownButtonStatus
= FNB_BTN_PRESSED
3736 elif self
._nLeftClickZone
== FNB_LEFT_ARROW
:
3737 self
._nLeftButtonStatus
= FNB_BTN_PRESSED
3739 elif self
._nLeftClickZone
== FNB_RIGHT_ARROW
:
3740 self
._nRightButtonStatus
= FNB_BTN_PRESSED
3742 elif self
._nLeftClickZone
== FNB_X
:
3743 self
._nXButtonStatus
= FNB_BTN_PRESSED
3745 elif self
._nLeftClickZone
== FNB_TAB_X
:
3746 self
._nTabXButtonStatus
= FNB_BTN_PRESSED
3749 elif self
._nLeftClickZone
== FNB_TAB
:
3751 if self
._iActivePage
!= tabIdx
:
3753 # In case the tab is disabled, we dont allow to choose it
3754 if self
._pagesInfoVec
[tabIdx
].GetEnabled():
3755 self
.FireEvent(tabIdx
)
3758 def OnLeftUp(self
, event
):
3759 """ Handles the wx.EVT_LEFT_UP events for L{PageContainer}. """
3761 # forget the zone that was initially clicked
3762 self
._nLeftClickZone
= FNB_NOWHERE
3764 where
, tabIdx
= self
.HitTest(event
.GetPosition())
3766 if where
== FNB_LEFT_ARROW
:
3768 if self
._nFrom
== 0:
3771 # Make sure that the button was pressed before
3772 if self
._nLeftButtonStatus
!= FNB_BTN_PRESSED
:
3775 self
._nLeftButtonStatus
= FNB_BTN_HOVER
3777 # We scroll left with bulks of 5
3778 scrollLeft
= self
.GetNumTabsCanScrollLeft()
3780 self
._nFrom
-= scrollLeft
3786 elif where
== FNB_RIGHT_ARROW
:
3788 if self
._nFrom
>= len(self
._pagesInfoVec
) - 1:
3791 # Make sure that the button was pressed before
3792 if self
._nRightButtonStatus
!= FNB_BTN_PRESSED
:
3795 self
._nRightButtonStatus
= FNB_BTN_HOVER
3797 # Check if the right most tab is visible, if it is
3798 # don't rotate right anymore
3799 if self
._pagesInfoVec
[-1].GetPosition() != wx
.Point(-1, -1):
3802 lastVisibleTab
= self
.GetLastVisibleTab()
3803 if lastVisibleTab
< 0:
3804 # Probably the screen is too small for displaying even a single
3805 # tab, in this case we do nothing
3808 self
._nFrom
+= self
.GetNumOfVisibleTabs()
3811 elif where
== FNB_X
:
3813 # Make sure that the button was pressed before
3814 if self
._nXButtonStatus
!= FNB_BTN_PRESSED
:
3817 self
._nXButtonStatus
= FNB_BTN_HOVER
3819 self
.DeletePage(self
._iActivePage
)
3821 elif where
== FNB_TAB_X
:
3823 # Make sure that the button was pressed before
3824 if self
._nTabXButtonStatus
!= FNB_BTN_PRESSED
:
3827 self
._nTabXButtonStatus
= FNB_BTN_HOVER
3829 self
.DeletePage(self
._iActivePage
)
3831 elif where
== FNB_DROP_DOWN_ARROW
:
3833 # Make sure that the button was pressed before
3834 if self
._nArrowDownButtonStatus
!= FNB_BTN_PRESSED
:
3837 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
3839 # Refresh the button status
3840 renderer
= self
._mgr
.GetRenderer(self
.GetParent().GetWindowStyleFlag())
3841 dc
= wx
.ClientDC(self
)
3842 renderer
.DrawDropDownArrow(self
, dc
)
3844 self
.PopupTabsMenu()
3847 def HitTest(self
, pt
):
3849 HitTest method for L{PageContainer}.
3850 Returns the flag (if any) and the hit page (if any).
3853 style
= self
.GetParent().GetWindowStyleFlag()
3854 render
= self
._mgr
.GetRenderer(style
)
3856 fullrect
= self
.GetClientRect()
3857 btnLeftPos
= render
.GetLeftButtonPos(self
)
3858 btnRightPos
= render
.GetRightButtonPos(self
)
3859 btnXPos
= render
.GetXPos(self
)
3863 if len(self
._pagesInfoVec
) == 0:
3864 return FNB_NOWHERE
, tabIdx
3866 rect
= wx
.Rect(btnXPos
, 8, 16, 16)
3867 if rect
.Contains(pt
):
3868 return (style
& FNB_NO_X_BUTTON
and [FNB_NOWHERE
] or [FNB_X
])[0], tabIdx
3870 rect
= wx
.Rect(btnRightPos
, 8, 16, 16)
3871 if style
& FNB_DROPDOWN_TABS_LIST
:
3872 rect
= wx
.Rect(render
.GetDropArrowButtonPos(self
), 8, 16, 16)
3873 if rect
.Contains(pt
):
3874 return FNB_DROP_DOWN_ARROW
, tabIdx
3876 if rect
.Contains(pt
):
3877 return (style
& FNB_NO_NAV_BUTTONS
and [FNB_NOWHERE
] or [FNB_RIGHT_ARROW
])[0], tabIdx
3879 rect
= wx
.Rect(btnLeftPos
, 8, 16, 16)
3880 if rect
.Contains(pt
):
3881 return (style
& FNB_NO_NAV_BUTTONS
and [FNB_NOWHERE
] or [FNB_LEFT_ARROW
])[0], tabIdx
3883 # Test whether a left click was made on a tab
3886 for cur
in xrange(self
._nFrom
, len(self
._pagesInfoVec
)):
3888 pgInfo
= self
._pagesInfoVec
[cur
]
3890 if pgInfo
.GetPosition() == wx
.Point(-1, -1):
3893 if style
& FNB_X_ON_TAB
and cur
== self
.GetSelection():
3894 # 'x' button exists on a tab
3895 if self
._pagesInfoVec
[cur
].GetXRect().Contains(pt
):
3896 return FNB_TAB_X
, cur
3900 if self
._pagesInfoVec
[cur
].GetRegion().Contains(pt
.x
, pt
.y
):
3901 if bFoundMatch
or cur
== self
.GetSelection():
3909 tabRect
= wx
.Rect(pgInfo
.GetPosition().x
, pgInfo
.GetPosition().y
,
3910 pgInfo
.GetSize().x
, pgInfo
.GetSize().y
)
3912 if tabRect
.Contains(pt
):
3917 return FNB_TAB
, tabIdx
3919 if self
._isdragging
:
3920 # We are doing DND, so check also the region outside the tabs
3921 # try before the first tab
3922 pgInfo
= self
._pagesInfoVec
[0]
3923 tabRect
= wx
.Rect(0, pgInfo
.GetPosition().y
, pgInfo
.GetPosition().x
, self
.GetParent().GetSize().y
)
3924 if tabRect
.Contains(pt
):
3927 # try after the last tab
3928 pgInfo
= self
._pagesInfoVec
[-1]
3929 startpos
= pgInfo
.GetPosition().x
+pgInfo
.GetSize().x
3930 tabRect
= wx
.Rect(startpos
, pgInfo
.GetPosition().y
, fullrect
.width
-startpos
, self
.GetParent().GetSize().y
)
3932 if tabRect
.Contains(pt
):
3933 return FNB_TAB
, len(self
._pagesInfoVec
)
3936 return FNB_NOWHERE
, -1
3939 def SetSelection(self
, page
):
3940 """ Sets the selected page. """
3942 book
= self
.GetParent()
3943 book
.SetSelection(page
)
3944 self
.DoSetSelection(page
)
3947 def DoSetSelection(self
, page
):
3948 """ Does the actual selection of a page. """
3950 if page
< len(self
._pagesInfoVec
):
3952 da_page
= self
._pParent
.GetPage(page
)
3957 if not self
.IsTabVisible(page
):
3958 # Try to remove one tab from start and try again
3960 if not self
.CanFitToScreen(page
):
3962 if self
._nFrom
> page
:
3965 while self
._nFrom
< page
:
3967 if self
.CanFitToScreen(page
):
3973 def DeletePage(self
, page
):
3974 """ Delete the specified page from L{FlatNotebook}. """
3976 book
= self
.GetParent()
3977 book
.DeletePage(page
)
3981 def IsTabVisible(self
, page
):
3982 """ Returns whether a tab is visible or not. """
3984 iLastVisiblePage
= self
.GetLastVisibleTab()
3985 return page
<= iLastVisiblePage
and page
>= self
._nFrom
3988 def DoDeletePage(self
, page
):
3989 """ Does the actual page deletion. """
3991 # Remove the page from the vector
3992 book
= self
.GetParent()
3993 self
._pagesInfoVec
.pop(page
)
3995 # Thanks to Yiaanis AKA Mandrav
3996 if self
._iActivePage
>= page
:
3997 self
._iActivePage
= self
._iActivePage
- 1
3998 self
._iPreviousActivePage
= -1
4000 # The delete page was the last first on the array,
4001 # but the book still has more pages, so we set the
4002 # active page to be the first one (0)
4003 if self
._iActivePage
< 0 and len(self
._pagesInfoVec
) > 0:
4004 self
._iActivePage
= 0
4005 self
._iPreviousActivePage
= -1
4008 if self
._iActivePage
>= 0:
4010 book
._bForceSelection
= True
4012 # Check for selection and send event
4013 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, self
.GetParent().GetId())
4014 event
.SetSelection(self
._iActivePage
)
4015 event
.SetOldSelection(self
._iPreviousActivePage
)
4016 event
.SetEventObject(self
.GetParent())
4018 book
.SetSelection(self
._iActivePage
)
4019 book
._bForceSelection
= False
4021 # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
4022 event
.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
)
4023 event
.SetOldSelection(self
._iPreviousActivePage
)
4024 self
.GetParent().GetEventHandler().ProcessEvent(event
)
4026 if not self
._pagesInfoVec
:
4027 # Erase the page container drawings
4028 dc
= wx
.ClientDC(self
)
4032 def DeleteAllPages(self
):
4033 """ Deletes all the pages. """
4035 self
._iActivePage
= -1
4036 self
._iPreviousActivePage
= -1
4038 self
._pagesInfoVec
= []
4040 # Erase the page container drawings
4041 dc
= wx
.ClientDC(self
)
4045 def OnMouseMove(self
, event
):
4046 """ Handles the wx.EVT_MOTION for L{PageContainer}. """
4048 if self
._pagesInfoVec
and self
.IsShown():
4050 xButtonStatus
= self
._nXButtonStatus
4051 xTabButtonStatus
= self
._nTabXButtonStatus
4052 rightButtonStatus
= self
._nRightButtonStatus
4053 leftButtonStatus
= self
._nLeftButtonStatus
4054 dropDownButtonStatus
= self
._nArrowDownButtonStatus
4056 style
= self
.GetParent().GetWindowStyleFlag()
4058 self
._nXButtonStatus
= FNB_BTN_NONE
4059 self
._nRightButtonStatus
= FNB_BTN_NONE
4060 self
._nLeftButtonStatus
= FNB_BTN_NONE
4061 self
._nTabXButtonStatus
= FNB_BTN_NONE
4062 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
4064 where
, tabIdx
= self
.HitTest(event
.GetPosition())
4067 if event
.LeftIsDown():
4069 self
._nXButtonStatus
= (self
._nLeftClickZone
==FNB_X
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4073 self
._nXButtonStatus
= FNB_BTN_HOVER
4075 elif where
== FNB_DROP_DOWN_ARROW
:
4076 if event
.LeftIsDown():
4078 self
._nArrowDownButtonStatus
= (self
._nLeftClickZone
==FNB_DROP_DOWN_ARROW
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4082 self
._nArrowDownButtonStatus
= FNB_BTN_HOVER
4084 elif where
== FNB_TAB_X
:
4085 if event
.LeftIsDown():
4087 self
._nTabXButtonStatus
= (self
._nLeftClickZone
==FNB_TAB_X
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4091 self
._nTabXButtonStatus
= FNB_BTN_HOVER
4093 elif where
== FNB_RIGHT_ARROW
:
4094 if event
.LeftIsDown():
4096 self
._nRightButtonStatus
= (self
._nLeftClickZone
==FNB_RIGHT_ARROW
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4100 self
._nRightButtonStatus
= FNB_BTN_HOVER
4102 elif where
== FNB_LEFT_ARROW
:
4103 if event
.LeftIsDown():
4105 self
._nLeftButtonStatus
= (self
._nLeftClickZone
==FNB_LEFT_ARROW
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4109 self
._nLeftButtonStatus
= FNB_BTN_HOVER
4111 elif where
== FNB_TAB
:
4112 # Call virtual method for showing tooltip
4113 self
.ShowTabTooltip(tabIdx
)
4115 if not self
.GetEnabled(tabIdx
):
4116 # Set the cursor to be 'No-entry'
4117 wx
.SetCursor(wx
.StockCursor(wx
.CURSOR_NO_ENTRY
))
4119 # Support for drag and drop
4120 if event
.Dragging() and not (style
& FNB_NODRAG
):
4122 self
._isdragging
= True
4123 draginfo
= FNBDragInfo(self
, tabIdx
)
4124 drginfo
= cPickle
.dumps(draginfo
)
4125 dataobject
= wx
.CustomDataObject(wx
.CustomDataFormat("FlatNotebook"))
4126 dataobject
.SetData(drginfo
)
4127 dragSource
= FNBDropSource(self
)
4128 dragSource
.SetData(dataobject
)
4129 dragSource
.DoDragDrop(wx
.Drag_DefaultMove
)
4131 bRedrawX
= self
._nXButtonStatus
!= xButtonStatus
4132 bRedrawRight
= self
._nRightButtonStatus
!= rightButtonStatus
4133 bRedrawLeft
= self
._nLeftButtonStatus
!= leftButtonStatus
4134 bRedrawTabX
= self
._nTabXButtonStatus
!= xTabButtonStatus
4135 bRedrawDropArrow
= self
._nArrowDownButtonStatus
!= dropDownButtonStatus
4137 render
= self
._mgr
.GetRenderer(style
)
4139 if (bRedrawX
or bRedrawRight
or bRedrawLeft
or bRedrawTabX
or bRedrawDropArrow
):
4141 dc
= wx
.ClientDC(self
)
4145 render
.DrawX(self
, dc
)
4149 render
.DrawLeftArrow(self
, dc
)
4153 render
.DrawRightArrow(self
, dc
)
4157 render
.DrawTabX(self
, dc
, self
._pagesInfoVec
[tabIdx
].GetXRect(), tabIdx
, self
._nTabXButtonStatus
)
4159 if bRedrawDropArrow
:
4161 render
.DrawDropDownArrow(self
, dc
)
4166 def GetLastVisibleTab(self
):
4167 """ Returns the last visible tab. """
4174 for ii
in xrange(self
._nFrom
, len(self
._pagesInfoVec
)):
4176 if self
._pagesInfoVec
[ii
].GetPosition() == wx
.Point(-1, -1):
4182 def GetNumTabsCanScrollLeft(self
):
4183 """ Returns the number of tabs than can be scrolled left. """
4185 # Reserved area for the buttons (<>x)
4186 rect
= self
.GetClientRect()
4187 clientWidth
= rect
.width
4188 posx
= self
._pParent
._nPadding
4192 # In case we have error prevent crash
4196 dc
= wx
.ClientDC(self
)
4198 style
= self
.GetParent().GetWindowStyleFlag()
4199 render
= self
._mgr
.GetRenderer(style
)
4201 for ii
in xrange(self
._nFrom
, -1, -1):
4203 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
4204 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
4205 dc
.SetFont(boldFont
)
4207 height
= dc
.GetCharHeight()
4209 tabHeight
= height
+ FNB_HEIGHT_SPACER
# We use 6 pixels as padding
4210 if style
& FNB_VC71
:
4211 tabHeight
= (style
& FNB_BOTTOM
and [tabHeight
- 4] or [tabHeight
])[0]
4212 elif style
& FNB_FANCY_TABS
:
4213 tabHeight
= (style
& FNB_BOTTOM
and [tabHeight
- 3] or [tabHeight
])[0]
4215 width
, pom
= dc
.GetTextExtent(self
.GetPageText(ii
))
4216 if style
!= FNB_VC71
:
4217 shapePoints
= int(tabHeight
*math
.tan(float(self
._pagesInfoVec
[ii
].GetTabAngle())/180.0*math
.pi
))
4221 tabWidth
= 2*self
._pParent
._nPadding
+ width
4223 if not (style
& FNB_VC71
):
4225 tabWidth
+= 2*shapePoints
4227 hasImage
= self
._ImageList
!= None and self
._pagesInfoVec
[ii
].GetImageIndex() != -1
4229 # For VC71 style, we only add the icon size (16 pixels)
4232 if not self
.IsDefaultTabs():
4233 tabWidth
+= 16 + self
._pParent
._nPadding
4236 tabWidth
+= 16 + self
._pParent
._nPadding
+ shapePoints
/2
4238 if posx
+ tabWidth
+ render
.GetButtonsAreaLength(self
) >= clientWidth
:
4241 numTabs
= numTabs
+ 1
4247 def IsDefaultTabs(self
):
4248 """ Returns whether a tab has a default style. """
4250 style
= self
.GetParent().GetWindowStyleFlag()
4251 res
= (style
& FNB_VC71
) or (style
& FNB_FANCY_TABS
) or (style
& FNB_VC8
)
4255 def AdvanceSelection(self
, bForward
=True):
4257 Cycles through the tabs.
4258 The call to this function generates the page changing events.
4261 nSel
= self
.GetSelection()
4266 nMax
= self
.GetPageCount() - 1
4269 newSelection
= (nSel
== nMax
and [0] or [nSel
+ 1])[0]
4271 newSelection
= (nSel
== 0 and [nMax
] or [nSel
- 1])[0]
4273 if not self
._pagesInfoVec
[newSelection
].GetEnabled():
4276 self
.FireEvent(newSelection
)
4279 def OnMouseLeave(self
, event
):
4280 """ Handles the wx.EVT_LEAVE_WINDOW event for L{PageContainer}. """
4282 self
._nLeftButtonStatus
= FNB_BTN_NONE
4283 self
._nXButtonStatus
= FNB_BTN_NONE
4284 self
._nRightButtonStatus
= FNB_BTN_NONE
4285 self
._nTabXButtonStatus
= FNB_BTN_NONE
4286 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
4288 style
= self
.GetParent().GetWindowStyleFlag()
4289 render
= self
._mgr
.GetRenderer(style
)
4291 dc
= wx
.ClientDC(self
)
4293 render
.DrawX(self
, dc
)
4294 render
.DrawLeftArrow(self
, dc
)
4295 render
.DrawRightArrow(self
, dc
)
4297 selection
= self
.GetSelection()
4303 if not self
.IsTabVisible(selection
):
4304 if selection
== len(self
._pagesInfoVec
) - 1:
4305 if not self
.CanFitToScreen(selection
):
4312 render
.DrawTabX(self
, dc
, self
._pagesInfoVec
[selection
].GetXRect(), selection
, self
._nTabXButtonStatus
)
4317 def OnMouseEnterWindow(self
, event
):
4318 """ Handles the wx.EVT_ENTER_WINDOW event for L{PageContainer}. """
4320 self
._nLeftButtonStatus
= FNB_BTN_NONE
4321 self
._nXButtonStatus
= FNB_BTN_NONE
4322 self
._nRightButtonStatus
= FNB_BTN_NONE
4323 self
._nLeftClickZone
= FNB_BTN_NONE
4324 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
4329 def ShowTabTooltip(self
, tabIdx
):
4330 """ Shows a tab tooltip. """
4332 pWindow
= self
._pParent
.GetPage(tabIdx
)
4335 pToolTip
= pWindow
.GetToolTip()
4336 if pToolTip
and pToolTip
.GetWindow() == pWindow
:
4337 self
.SetToolTipString(pToolTip
.GetTip())
4340 def SetPageImage(self
, page
, imgindex
):
4341 """ Sets the image index associated to a page. """
4343 if page
< len(self
._pagesInfoVec
):
4345 self
._pagesInfoVec
[page
].SetImageIndex(imgindex
)
4349 def GetPageImage(self
, page
):
4350 """ Returns the image index associated to a page. """
4352 if page
< len(self
._pagesInfoVec
):
4354 return self
._pagesInfoVec
[page
].GetImageIndex()
4359 def OnDropTarget(self
, x
, y
, nTabPage
, wnd_oldContainer
):
4360 """ Handles the drop action from a DND operation. """
4362 # Disable drag'n'drop for disabled tab
4363 if not wnd_oldContainer
._pagesInfoVec
[nTabPage
].GetEnabled():
4364 return wx
.DragCancel
4366 self
._isdragging
= True
4367 oldContainer
= wnd_oldContainer
4370 where
, nIndex
= self
.HitTest(wx
.Point(x
, y
))
4372 oldNotebook
= oldContainer
.GetParent()
4373 newNotebook
= self
.GetParent()
4375 if oldNotebook
== newNotebook
:
4379 if where
== FNB_TAB
:
4380 self
.MoveTabPage(nTabPage
, nIndex
)
4382 elif self
.GetParent().GetWindowStyleFlag() & FNB_ALLOW_FOREIGN_DND
:
4384 if wx
.Platform
in ["__WXMSW__", "__WXGTK__"]:
4387 window
= oldNotebook
.GetPage(nTabPage
)
4390 where
, nIndex
= newNotebook
._pages
.HitTest(wx
.Point(x
, y
))
4391 caption
= oldContainer
.GetPageText(nTabPage
)
4392 imageindex
= oldContainer
.GetPageImage(nTabPage
)
4393 oldNotebook
.RemovePage(nTabPage
)
4394 window
.Reparent(newNotebook
)
4398 bmp
= oldNotebook
.GetImageList().GetIcon(imageindex
)
4399 newImageList
= newNotebook
.GetImageList()
4401 if not newImageList
:
4402 xbmp
, ybmp
= bmp
.GetWidth(), bmp
.GetHeight()
4403 newImageList
= wx
.ImageList(xbmp
, ybmp
)
4406 imageindex
= newImageList
.GetImageCount()
4408 newImageList
.AddIcon(bmp
)
4409 newNotebook
.SetImageList(newImageList
)
4411 newNotebook
.InsertPage(nIndex
, window
, caption
, True, imageindex
)
4413 self
._isdragging
= False
4418 def MoveTabPage(self
, nMove
, nMoveTo
):
4419 """ Moves a tab inside the same L{FlatNotebook}. """
4421 if nMove
== nMoveTo
:
4424 elif nMoveTo
< len(self
._pParent
._windows
):
4425 nMoveTo
= nMoveTo
+ 1
4427 self
._pParent
.Freeze()
4429 # Remove the window from the main sizer
4430 nCurSel
= self
._pParent
._pages
.GetSelection()
4431 self
._pParent
._mainSizer
.Detach(self
._pParent
._windows
[nCurSel
])
4432 self
._pParent
._windows
[nCurSel
].Hide()
4434 pWindow
= self
._pParent
._windows
[nMove
]
4435 self
._pParent
._windows
.pop(nMove
)
4436 self
._pParent
._windows
.insert(nMoveTo
-1, pWindow
)
4438 pgInfo
= self
._pagesInfoVec
[nMove
]
4440 self
._pagesInfoVec
.pop(nMove
)
4441 self
._pagesInfoVec
.insert(nMoveTo
- 1, pgInfo
)
4443 # Add the page according to the style
4444 pSizer
= self
._pParent
._mainSizer
4445 style
= self
.GetParent().GetWindowStyleFlag()
4447 if style
& FNB_BOTTOM
:
4449 pSizer
.Insert(0, pWindow
, 1, wx
.EXPAND
)
4453 # We leave a space of 1 pixel around the window
4454 pSizer
.Add(pWindow
, 1, wx
.EXPAND
)
4459 self
._iActivePage
= nMoveTo
- 1
4460 self
._iPreviousActivePage
= -1
4461 self
.DoSetSelection(self
._iActivePage
)
4463 self
._pParent
.Thaw()
4466 def CanFitToScreen(self
, page
):
4467 """ Returns wheter a tab can fit in the left space in the screen or not. """
4469 # Incase the from is greater than page,
4470 # we need to reset the self._nFrom, so in order
4471 # to force the caller to do so, we return false
4472 if self
._nFrom
> page
:
4475 style
= self
.GetParent().GetWindowStyleFlag()
4476 render
= self
._mgr
.GetRenderer(style
)
4478 vTabInfo
= render
.NumberTabsCanFit(self
)
4480 if page
- self
._nFrom
>= len(vTabInfo
):
4486 def GetNumOfVisibleTabs(self
):
4487 """ Returns the number of visible tabs. """
4490 for ii
in xrange(self
._nFrom
, len(self
._pagesInfoVec
)):
4491 if self
._pagesInfoVec
[ii
].GetPosition() == wx
.Point(-1, -1):
4498 def GetEnabled(self
, page
):
4499 """ Returns whether a tab is enabled or not. """
4501 if page
>= len(self
._pagesInfoVec
):
4502 return True # Seems strange, but this is the default
4504 return self
._pagesInfoVec
[page
].GetEnabled()
4507 def Enable(self
, page
, enabled
=True):
4508 """ Enables or disables a tab. """
4510 if page
>= len(self
._pagesInfoVec
):
4513 self
._pagesInfoVec
[page
].Enable(enabled
)
4516 def GetSingleLineBorderColour(self
):
4517 """ Returns the colour for the single line border. """
4519 if self
.HasFlag(FNB_FANCY_TABS
):
4520 return self
._colorFrom
4525 def HasFlag(self
, flag
):
4526 """ Returns whether a flag is present in the L{FlatNotebook} style. """
4528 style
= self
.GetParent().GetWindowStyleFlag()
4529 res
= (style
& flag
and [True] or [False])[0]
4533 def ClearFlag(self
, flag
):
4534 """ Deletes a flag from the L{FlatNotebook} style. """
4536 style
= self
.GetParent().GetWindowStyleFlag()
4538 self
.SetWindowStyleFlag(style
)
4541 def TabHasImage(self
, tabIdx
):
4542 """ Returns whether a tab has an associated image index or not. """
4545 return self
._pagesInfoVec
[tabIdx
].GetImageIndex() != -1
4550 def OnLeftDClick(self
, event
):
4551 """ Handles the wx.EVT_LEFT_DCLICK event for L{PageContainer}. """
4553 if self
.HasFlag(FNB_DCLICK_CLOSES_TABS
):
4555 where
, tabIdx
= self
.HitTest(event
.GetPosition())
4557 if where
== FNB_TAB
:
4558 self
.DeletePage(tabIdx
)
4565 def PopupTabsMenu(self
):
4566 """ Pops up the menu activated with the drop down arrow in the navigation area. """
4568 popupMenu
= wx
.Menu()
4570 for i
in xrange(len(self
._pagesInfoVec
)):
4571 pi
= self
._pagesInfoVec
[i
]
4572 item
= wx
.MenuItem(popupMenu
, i
, pi
.GetCaption(), pi
.GetCaption(), wx
.ITEM_NORMAL
)
4573 self
.Bind(wx
.EVT_MENU
, self
.OnTabMenuSelection
, item
)
4575 # This code is commented, since there is an alignment problem with wx2.6.3 & Menus
4576 # if self.TabHasImage(ii):
4577 # item.SetBitmaps( (*m_ImageList)[pi.GetImageIndex()] );
4579 popupMenu
.AppendItem(item
)
4580 item
.Enable(pi
.GetEnabled())
4582 self
.PopupMenu(popupMenu
)
4585 def OnTabMenuSelection(self
, event
):
4586 """ Handles the wx.EVT_MENU event for L{PageContainer}. """
4588 selection
= event
.GetId()
4589 self
.FireEvent(selection
)
4592 def FireEvent(self
, selection
):
4594 Fires the wxEVT_FLATNOTEBOOK_PAGE_CHANGING and wxEVT_FLATNOTEBOOK_PAGE_CHANGED events
4595 called from other methods (from menu selection or Smart Tabbing).
4599 if selection
== self
._iActivePage
:
4600 # No events for the same selection
4603 oldSelection
= self
._iActivePage
4605 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, self
.GetParent().GetId())
4606 event
.SetSelection(selection
)
4607 event
.SetOldSelection(oldSelection
)
4608 event
.SetEventObject(self
.GetParent())
4610 if not self
.GetParent().GetEventHandler().ProcessEvent(event
) or event
.IsAllowed():
4612 self
.SetSelection(selection
)
4614 # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
4615 event
.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
)
4616 event
.SetOldSelection(oldSelection
)
4617 self
.GetParent().GetEventHandler().ProcessEvent(event
)
4620 def SetImageList(self
, imglist
):
4621 """ Sets the image list for the page control. """
4623 self
._ImageList
= imglist
4626 def GetImageList(self
):
4627 """ Returns the image list for the page control. """
4629 return self
._ImageList
4632 def GetSelection(self
):
4633 """ Returns the current selected page. """
4635 return self
._iActivePage
4638 def GetPageCount(self
):
4639 """ Returns the number of tabs in the L{FlatNotebook} control. """
4641 return len(self
._pagesInfoVec
)
4644 def GetPageText(self
, page
):
4645 """ Returns the tab caption of the page. """
4647 return self
._pagesInfoVec
[page
].GetCaption()
4650 def SetPageText(self
, page
, text
):
4651 """ Sets the tab caption of the page. """
4653 self
._pagesInfoVec
[page
].SetCaption(text
)
4657 def DrawDragHint(self
):
4658 """ Draws small arrow at the place that the tab will be placed. """
4660 # get the index of tab that will be replaced with the dragged tab
4661 pt
= wx
.GetMousePosition()
4662 client_pt
= self
.ScreenToClient(pt
)
4663 where
, tabIdx
= self
.HitTest(client_pt
)
4664 self
._mgr
.GetRenderer(self
.GetParent().GetWindowStyleFlag()).DrawDragHint(self
, tabIdx
)