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
.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
202 wxEVT_FLATNOTEBOOK_PAGE_CHANGING
= wx
.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING
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
.EVT_NOTEBOOK_PAGE_CHANGED
212 """Notify client objects when the active page in L{FlatNotebook}
214 EVT_FLATNOTEBOOK_PAGE_CHANGING
= wx
.EVT_NOTEBOOK_PAGE_CHANGING
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
):
2958 """ Sets the image list for the page control. """
2960 self
._pages
.SetImageList(imageList
)
2963 def AssignImageList(self
, imageList
):
2964 """ Assigns the image list for the page control. """
2966 self
._pages
.AssignImageList(imageList
)
2969 def GetImageList(self
):
2970 """ Returns the associated image list. """
2972 return self
._pages
.GetImageList()
2975 def InsertPage(self
, indx
, page
, text
, select
=True, imageId
=-1):
2977 Inserts a new page at the specified position.
2979 @param indx: Specifies the position of the new page.
2980 @param page: Specifies the new page.
2981 @param text: Specifies the text for the new page.
2982 @param select: Specifies whether the page should be selected.
2983 @param imageId: Specifies the optional image index for the new page.
2986 True if successful, False otherwise.
2993 # reparent the window to us
2996 if not self
._windows
:
2998 self
.AddPage(page
, text
, select
, imageId
)
3002 bSelected
= select
or not self
._windows
3003 curSel
= self
._pages
.GetSelection()
3005 indx
= max(0, min(indx
, len(self
._windows
)))
3007 if indx
<= len(self
._windows
):
3009 self
._windows
.insert(indx
, page
)
3013 self
._windows
.append(page
)
3019 # Check for selection and send events
3020 oldSelection
= self
._pages
._iActivePage
3022 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, self
.GetId())
3023 event
.SetSelection(indx
)
3024 event
.SetOldSelection(oldSelection
)
3025 event
.SetEventObject(self
)
3027 if not self
.GetEventHandler().ProcessEvent(event
) or event
.IsAllowed() or len(self
._windows
) == 0:
3030 self
._pages
.InsertPage(indx
, text
, bSelected
, imageId
)
3037 # Check if a new selection was made
3042 # Remove the window from the main sizer
3043 self
._mainSizer
.Detach(self
._windows
[curSel
])
3044 self
._windows
[curSel
].Hide()
3046 self
._pages
.SetSelection(indx
)
3048 # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
3049 event
.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
)
3050 event
.SetOldSelection(oldSelection
)
3051 self
.GetEventHandler().ProcessEvent(event
)
3059 self
._mainSizer
.Layout()
3065 def SetSelection(self
, page
):
3067 Sets the selection for the given page.
3068 The call to this function generates the page changing events
3071 if page
>= len(self
._windows
) or not self
._windows
:
3074 # Support for disabed tabs
3075 if not self
._pages
.GetEnabled(page
) and len(self
._windows
) > 1 and not self
._bForceSelection
:
3078 curSel
= self
._pages
.GetSelection()
3080 # program allows the page change
3084 # Remove the window from the main sizer
3085 self
._mainSizer
.Detach(self
._windows
[curSel
])
3086 self
._windows
[curSel
].Hide()
3088 if self
.GetWindowStyleFlag() & FNB_BOTTOM
:
3090 self
._mainSizer
.Insert(0, self
._windows
[page
], 1, wx
.EXPAND
)
3094 # We leave a space of 1 pixel around the window
3095 self
._mainSizer
.Add(self
._windows
[page
], 1, wx
.EXPAND
)
3097 self
._windows
[page
].Show()
3100 self
._mainSizer
.Layout()
3102 if page
!= self
._pages
._iActivePage
:
3103 # there is a real page changing
3104 self
._pages
._iPreviousActivePage
= self
._pages
._iActivePage
3106 self
._pages
._iActivePage
= page
3107 self
._pages
.DoSetSelection(page
)
3110 def DeletePage(self
, page
):
3112 Deletes the specified page, and the associated window.
3113 The call to this function generates the page changing events.
3116 if page
>= len(self
._windows
) or page
< 0:
3119 # Fire a closing event
3120 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING
, self
.GetId())
3121 event
.SetSelection(page
)
3122 event
.SetEventObject(self
)
3123 self
.GetEventHandler().ProcessEvent(event
)
3125 # The event handler allows it?
3126 if not event
.IsAllowed():
3131 # Delete the requested page
3132 pageRemoved
= self
._windows
[page
]
3134 # If the page is the current window, remove it from the sizer
3136 if page
== self
._pages
.GetSelection():
3137 self
._mainSizer
.Detach(pageRemoved
)
3139 # Remove it from the array as well
3140 self
._windows
.pop(page
)
3142 # Now we can destroy it in wxWidgets use Destroy instead of delete
3143 pageRemoved
.Destroy()
3147 self
._pages
.DoDeletePage(page
)
3150 # Fire a closed event
3151 closedEvent
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSED
, self
.GetId())
3152 closedEvent
.SetSelection(page
)
3153 closedEvent
.SetEventObject(self
)
3154 self
.GetEventHandler().ProcessEvent(closedEvent
)
3157 def DeleteAllPages(self
):
3158 """ Deletes all the pages. """
3160 if not self
._windows
:
3165 for page
in self
._windows
:
3171 # Clear the container of the tabs as well
3172 self
._pages
.DeleteAllPages()
3176 def GetCurrentPage(self
):
3177 """ Returns the currently selected notebook page or None. """
3179 sel
= self
._pages
.GetSelection()
3183 return self
._windows
[sel
]
3186 def GetPage(self
, page
):
3187 """ Returns the window at the given page position, or None. """
3189 if page
>= len(self
._windows
):
3192 return self
._windows
[page
]
3195 def GetPageIndex(self
, win
):
3196 """ Returns the index at which the window is found. """
3199 return self
._windows
.index(win
)
3204 def GetSelection(self
):
3205 """ Returns the currently selected page, or -1 if none was selected. """
3207 return self
._pages
.GetSelection()
3210 def AdvanceSelection(self
, forward
=True):
3212 Cycles through the tabs.
3213 The call to this function generates the page changing events.
3216 self
._pages
.AdvanceSelection(forward
)
3219 def GetPageCount(self
):
3220 """ Returns the number of pages in the L{FlatNotebook} control. """
3222 return self
._pages
.GetPageCount()
3225 def OnNavigationKey(self
, event
):
3226 """ Handles the wx.EVT_NAVIGATION_KEY event for L{FlatNotebook}. """
3228 if event
.IsWindowChange():
3229 if len(self
._windows
) == 0:
3232 if self
.HasFlag(FNB_SMART_TABS
):
3233 if not self
._popupWin
:
3234 self
._popupWin
= TabNavigatorWindow(self
)
3235 self
._popupWin
.SetReturnCode(wx
.ID_OK
)
3236 self
._popupWin
.ShowModal()
3237 self
._popupWin
.Destroy()
3238 self
._popupWin
= None
3240 # a dialog is already opened
3241 self
._popupWin
.OnNavigationKey(event
)
3245 self
.AdvanceSelection(event
.GetDirection())
3247 # pass to the parent
3248 if self
.GetParent():
3249 event
.SetCurrentFocus(self
)
3250 self
.GetParent().ProcessEvent(event
)
3253 def GetPageShapeAngle(self
, page_index
):
3254 """ Returns the angle associated to a tab. """
3256 if page_index
< 0 or page_index
>= len(self
._pages
._pagesInfoVec
):
3259 result
= self
._pages
._pagesInfoVec
[page_index
].GetTabAngle()
3263 def SetPageShapeAngle(self
, page_index
, angle
):
3264 """ Sets the angle associated to a tab. """
3266 if page_index
< 0 or page_index
>= len(self
._pages
._pagesInfoVec
):
3272 self
._pages
._pagesInfoVec
[page_index
].SetTabAngle(angle
)
3275 def SetAllPagesShapeAngle(self
, angle
):
3276 """ Sets the angle associated to all the tab. """
3281 for ii
in xrange(len(self
._pages
._pagesInfoVec
)):
3282 self
._pages
._pagesInfoVec
[ii
].SetTabAngle(angle
)
3287 def GetPageBestSize(self
):
3288 """ Return the page best size. """
3290 return self
._pages
.GetClientSize()
3293 def SetPageText(self
, page
, text
):
3294 """ Sets the text for the given page. """
3296 bVal
= self
._pages
.SetPageText(page
, text
)
3297 self
._pages
.Refresh()
3302 def SetPadding(self
, padding
):
3304 Sets the amount of space around each page's icon and label, in pixels.
3305 NB: only the horizontal padding is considered.
3308 self
._nPadding
= padding
.GetWidth()
3311 def GetTabArea(self
):
3312 """ Returns the associated page. """
3317 def GetPadding(self
):
3318 """ Returns the amount of space around each page's icon and label, in pixels. """
3320 return self
._nPadding
3323 def SetWindowStyleFlag(self
, style
):
3324 """ Sets the L{FlatNotebook} window style flags. """
3326 wx
.Panel
.SetWindowStyleFlag(self
, style
)
3327 renderer
= self
._pages
._mgr
.GetRenderer(self
.GetWindowStyleFlag())
3328 renderer
._tabHeight
= None
3332 # For changing the tab position (i.e. placing them top/bottom)
3333 # refreshing the tab container is not enough
3334 self
.SetSelection(self
._pages
._iActivePage
)
3336 if not self
._pages
.HasFlag(FNB_HIDE_ON_SINGLE_TAB
):
3337 #For Redrawing the Tabs once you remove the Hide tyle
3338 self
._pages
._ReShow
()
3341 def RemovePage(self
, page
):
3342 """ Deletes the specified page, without deleting the associated window. """
3344 if page
>= len(self
._windows
):
3347 # Fire a closing event
3348 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING
, self
.GetId())
3349 event
.SetSelection(page
)
3350 event
.SetEventObject(self
)
3351 self
.GetEventHandler().ProcessEvent(event
)
3353 # The event handler allows it?
3354 if not event
.IsAllowed():
3359 # Remove the requested page
3360 pageRemoved
= self
._windows
[page
]
3362 # If the page is the current window, remove it from the sizer
3364 if page
== self
._pages
.GetSelection():
3365 self
._mainSizer
.Detach(pageRemoved
)
3367 # Remove it from the array as well
3368 self
._windows
.pop(page
)
3371 self
._pages
.DoDeletePage(page
)
3376 def SetRightClickMenu(self
, menu
):
3377 """ Sets the popup menu associated to a right click on a tab. """
3379 self
._pages
._pRightClickMenu
= menu
3382 def GetPageText(self
, nPage
):
3383 """ Returns the tab caption. """
3385 return self
._pages
.GetPageText(nPage
)
3388 def SetGradientColours(self
, fr
, to
, border
):
3389 """ Sets the gradient colours for the tab. """
3391 self
._pages
._colorFrom
= fr
3392 self
._pages
._colorTo
= to
3393 self
._pages
._colorBorder
= border
3396 def SetGradientColourFrom(self
, fr
):
3397 """ Sets the starting colour for the gradient. """
3399 self
._pages
._colorFrom
= fr
3402 def SetGradientColourTo(self
, to
):
3403 """ Sets the ending colour for the gradient. """
3405 self
._pages
._colorTo
= to
3408 def SetGradientColourBorder(self
, border
):
3409 """ Sets the tab border colour. """
3411 self
._pages
._colorBorder
= border
3414 def GetGradientColourFrom(self
):
3415 """ Gets first gradient colour. """
3417 return self
._pages
._colorFrom
3420 def GetGradientColourTo(self
):
3421 """ Gets second gradient colour. """
3423 return self
._pages
._colorTo
3426 def GetGradientColourBorder(self
):
3427 """ Gets the tab border colour. """
3429 return self
._pages
._colorBorder
3432 def GetBorderColour(self
):
3433 """ Returns the border colour. """
3435 return self
._pages
._colorBorder
3438 def GetActiveTabTextColour(self
):
3439 """ Get the active tab text colour. """
3441 return self
._pages
._activeTextColor
3444 def SetPageImage(self
, page
, image
):
3446 Sets the image index for the given page. Image is an index into the
3447 image list which was set with SetImageList.
3450 self
._pages
.SetPageImage(page
, image
)
3453 def GetPageImage(self
, nPage
):
3455 Returns the image index for the given page. Image is an index into the
3456 image list which was set with SetImageList.
3459 return self
._pages
.GetPageImage(nPage
)
3462 def GetEnabled(self
, page
):
3463 """ Returns whether a tab is enabled or not. """
3465 return self
._pages
.GetEnabled(page
)
3468 def Enable(self
, page
, enabled
=True):
3469 """ Enables or disables a tab. """
3471 if page
>= len(self
._windows
):
3474 self
._windows
[page
].Enable(enabled
)
3475 self
._pages
.Enable(page
, enabled
)
3478 def GetNonActiveTabTextColour(self
):
3479 """ Returns the non active tabs text colour. """
3481 return self
._pages
._nonActiveTextColor
3484 def SetNonActiveTabTextColour(self
, color
):
3485 """ Sets the non active tabs text colour. """
3487 self
._pages
._nonActiveTextColor
= color
3490 def SetTabAreaColour(self
, color
):
3491 """ Sets the area behind the tabs colour. """
3493 self
._pages
._tabAreaColor
= color
3496 def GetTabAreaColour(self
):
3497 """ Returns the area behind the tabs colour. """
3499 return self
._pages
._tabAreaColor
3502 def SetActiveTabColour(self
, color
):
3503 """ Sets the active tab colour. """
3505 self
._pages
._activeTabColor
= color
3508 def GetActiveTabColour(self
):
3509 """ Returns the active tab colour. """
3511 return self
._pages
._activeTabColor
3514 # ---------------------------------------------------------------------------- #
3515 # Class PageContainer
3516 # Acts as a container for the pages you add to FlatNotebook
3517 # ---------------------------------------------------------------------------- #
3519 class PageContainer(wx
.Panel
):
3521 This class acts as a container for the pages you add to L{FlatNotebook}.
3524 def __init__(self
, parent
, id=wx
.ID_ANY
, pos
=wx
.DefaultPosition
,
3525 size
=wx
.DefaultSize
, style
=0):
3526 """ Default class constructor. """
3528 self
._ImageList
= None
3529 self
._iActivePage
= -1
3530 self
._pDropTarget
= None
3531 self
._nLeftClickZone
= FNB_NOWHERE
3532 self
._iPreviousActivePage
= -1
3534 self
._pRightClickMenu
= None
3535 self
._nXButtonStatus
= FNB_BTN_NONE
3536 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
3537 self
._pParent
= parent
3538 self
._nRightButtonStatus
= FNB_BTN_NONE
3539 self
._nLeftButtonStatus
= FNB_BTN_NONE
3540 self
._nTabXButtonStatus
= FNB_BTN_NONE
3542 self
._pagesInfoVec
= []
3544 self
._colorTo
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_ACTIVECAPTION
)
3545 self
._colorFrom
= wx
.WHITE
3546 self
._activeTabColor
= wx
.WHITE
3547 self
._activeTextColor
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNTEXT
)
3548 self
._nonActiveTextColor
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)
3549 self
._tabAreaColor
= wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNFACE
)
3552 self
._isdragging
= False
3554 # Set default page height, this is done according to the system font
3555 memDc
= wx
.MemoryDC()
3556 memDc
.SelectObject(wx
.EmptyBitmap(1,1))
3558 if "__WXGTK__" in wx
.PlatformInfo
:
3559 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
3560 boldFont
.SetWeight(wx
.BOLD
)
3561 memDc
.SetFont(boldFont
)
3563 height
= memDc
.GetCharHeight()
3564 tabHeight
= height
+ FNB_HEIGHT_SPACER
# We use 10 pixels as padding
3566 wx
.Panel
.__init
__(self
, parent
, id, pos
, wx
.Size(size
.x
, tabHeight
),
3567 style|wx
.NO_BORDER|wx
.NO_FULL_REPAINT_ON_RESIZE
)
3569 self
._pDropTarget
= FNBDropTarget(self
)
3570 self
.SetDropTarget(self
._pDropTarget
)
3571 self
._mgr
= FNBRendererMgr()
3573 self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
)
3574 self
.Bind(wx
.EVT_SIZE
, self
.OnSize
)
3575 self
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnLeftDown
)
3576 self
.Bind(wx
.EVT_LEFT_UP
, self
.OnLeftUp
)
3577 self
.Bind(wx
.EVT_RIGHT_DOWN
, self
.OnRightDown
)
3578 self
.Bind(wx
.EVT_MIDDLE_DOWN
, self
.OnMiddleDown
)
3579 self
.Bind(wx
.EVT_MOTION
, self
.OnMouseMove
)
3580 self
.Bind(wx
.EVT_ERASE_BACKGROUND
, self
.OnEraseBackground
)
3581 self
.Bind(wx
.EVT_LEAVE_WINDOW
, self
.OnMouseLeave
)
3582 self
.Bind(wx
.EVT_ENTER_WINDOW
, self
.OnMouseEnterWindow
)
3583 self
.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnLeftDClick
)
3586 def OnEraseBackground(self
, event
):
3587 """ Handles the wx.EVT_ERASE_BACKGROUND event for L{PageContainer} (does nothing)."""
3593 """ Handles the Redraw of the tabs when the FNB_HIDE_ON_SINGLE_TAB has been removed """
3595 self
.GetParent()._mainSizer
.Layout()
3599 def OnPaint(self
, event
):
3600 """ Handles the wx.EVT_PAINT event for L{PageContainer}."""
3602 dc
= wx
.BufferedPaintDC(self
)
3603 renderer
= self
._mgr
.GetRenderer(self
.GetParent().GetWindowStyleFlag())
3604 renderer
.DrawTabs(self
, dc
)
3606 if self
.HasFlag(FNB_HIDE_ON_SINGLE_TAB
) and len(self
._pagesInfoVec
) <= 1:
3608 self
.GetParent()._mainSizer
.Layout()
3612 def AddPage(self
, caption
, selected
=True, imgindex
=-1):
3614 Add a page to the L{FlatNotebook}.
3616 @param window: Specifies the new page.
3617 @param caption: Specifies the text for the new page.
3618 @param selected: Specifies whether the page should be selected.
3619 @param imgindex: Specifies the optional image index for the new page.
3622 True if successful, False otherwise.
3627 self
._iPreviousActivePage
= self
._iActivePage
3628 self
._iActivePage
= len(self
._pagesInfoVec
)
3630 # Create page info and add it to the vector
3631 pageInfo
= PageInfo(caption
, imgindex
)
3632 self
._pagesInfoVec
.append(pageInfo
)
3636 def InsertPage(self
, indx
, text
, selected
=True, imgindex
=-1):
3638 Inserts a new page at the specified position.
3640 @param indx: Specifies the position of the new page.
3641 @param page: Specifies the new page.
3642 @param text: Specifies the text for the new page.
3643 @param select: Specifies whether the page should be selected.
3644 @param imgindex: Specifies the optional image index for the new page.
3647 True if successful, False otherwise.
3652 self
._iPreviousActivePage
= self
._iActivePage
3653 self
._iActivePage
= len(self
._pagesInfoVec
)
3655 self
._pagesInfoVec
.insert(indx
, PageInfo(text
, imgindex
))
3661 def OnSize(self
, event
):
3662 """ Handles the wx.EVT_SIZE events for L{PageContainer}. """
3664 # When resizing the control, try to fit to screen as many tabs as we can
3665 style
= self
.GetParent().GetWindowStyleFlag()
3666 renderer
= self
._mgr
.GetRenderer(style
)
3669 page
= self
.GetSelection()
3671 for fr
in xrange(self
._nFrom
):
3672 vTabInfo
= renderer
.NumberTabsCanFit(self
, fr
)
3673 if page
- fr
>= len(vTabInfo
):
3679 self
.Refresh() # Call on paint
3683 def OnMiddleDown(self
, event
):
3684 """ Handles the wx.EVT_MIDDLE_DOWN events for L{PageContainer}. """
3686 # Test if this style is enabled
3687 style
= self
.GetParent().GetWindowStyleFlag()
3689 if not style
& FNB_MOUSE_MIDDLE_CLOSES_TABS
:
3692 where
, tabIdx
= self
.HitTest(event
.GetPosition())
3694 if where
== FNB_TAB
:
3695 self
.DeletePage(tabIdx
)
3700 def OnRightDown(self
, event
):
3701 """ Handles the wx.EVT_RIGHT_DOWN events for L{PageContainer}. """
3703 where
, tabIdx
= self
.HitTest(event
.GetPosition())
3705 if where
in [FNB_TAB
, FNB_TAB_X
]:
3707 if self
._pagesInfoVec
[tabIdx
].GetEnabled():
3708 # Fire events and eventually (if allowed) change selection
3709 self
.FireEvent(tabIdx
)
3711 # send a message to popup a custom menu
3712 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU
, self
.GetParent().GetId())
3713 event
.SetSelection(tabIdx
)
3714 event
.SetOldSelection(self
._iActivePage
)
3715 event
.SetEventObject(self
.GetParent())
3716 self
.GetParent().GetEventHandler().ProcessEvent(event
)
3718 if self
._pRightClickMenu
:
3719 self
.PopupMenu(self
._pRightClickMenu
)
3724 def OnLeftDown(self
, event
):
3725 """ Handles the wx.EVT_LEFT_DOWN events for L{PageContainer}. """
3727 # Reset buttons status
3728 self
._nXButtonStatus
= FNB_BTN_NONE
3729 self
._nLeftButtonStatus
= FNB_BTN_NONE
3730 self
._nRightButtonStatus
= FNB_BTN_NONE
3731 self
._nTabXButtonStatus
= FNB_BTN_NONE
3732 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
3734 self
._nLeftClickZone
, tabIdx
= self
.HitTest(event
.GetPosition())
3736 if self
._nLeftClickZone
== FNB_DROP_DOWN_ARROW
:
3737 self
._nArrowDownButtonStatus
= FNB_BTN_PRESSED
3739 elif self
._nLeftClickZone
== FNB_LEFT_ARROW
:
3740 self
._nLeftButtonStatus
= FNB_BTN_PRESSED
3742 elif self
._nLeftClickZone
== FNB_RIGHT_ARROW
:
3743 self
._nRightButtonStatus
= FNB_BTN_PRESSED
3745 elif self
._nLeftClickZone
== FNB_X
:
3746 self
._nXButtonStatus
= FNB_BTN_PRESSED
3748 elif self
._nLeftClickZone
== FNB_TAB_X
:
3749 self
._nTabXButtonStatus
= FNB_BTN_PRESSED
3752 elif self
._nLeftClickZone
== FNB_TAB
:
3754 if self
._iActivePage
!= tabIdx
:
3756 # In case the tab is disabled, we dont allow to choose it
3757 if self
._pagesInfoVec
[tabIdx
].GetEnabled():
3758 self
.FireEvent(tabIdx
)
3761 def OnLeftUp(self
, event
):
3762 """ Handles the wx.EVT_LEFT_UP events for L{PageContainer}. """
3764 # forget the zone that was initially clicked
3765 self
._nLeftClickZone
= FNB_NOWHERE
3767 where
, tabIdx
= self
.HitTest(event
.GetPosition())
3769 if where
== FNB_LEFT_ARROW
:
3771 if self
._nFrom
== 0:
3774 # Make sure that the button was pressed before
3775 if self
._nLeftButtonStatus
!= FNB_BTN_PRESSED
:
3778 self
._nLeftButtonStatus
= FNB_BTN_HOVER
3780 # We scroll left with bulks of 5
3781 scrollLeft
= self
.GetNumTabsCanScrollLeft()
3783 self
._nFrom
-= scrollLeft
3789 elif where
== FNB_RIGHT_ARROW
:
3791 if self
._nFrom
>= len(self
._pagesInfoVec
) - 1:
3794 # Make sure that the button was pressed before
3795 if self
._nRightButtonStatus
!= FNB_BTN_PRESSED
:
3798 self
._nRightButtonStatus
= FNB_BTN_HOVER
3800 # Check if the right most tab is visible, if it is
3801 # don't rotate right anymore
3802 if self
._pagesInfoVec
[-1].GetPosition() != wx
.Point(-1, -1):
3805 lastVisibleTab
= self
.GetLastVisibleTab()
3806 if lastVisibleTab
< 0:
3807 # Probably the screen is too small for displaying even a single
3808 # tab, in this case we do nothing
3811 self
._nFrom
+= self
.GetNumOfVisibleTabs()
3814 elif where
== FNB_X
:
3816 # Make sure that the button was pressed before
3817 if self
._nXButtonStatus
!= FNB_BTN_PRESSED
:
3820 self
._nXButtonStatus
= FNB_BTN_HOVER
3822 self
.DeletePage(self
._iActivePage
)
3824 elif where
== FNB_TAB_X
:
3826 # Make sure that the button was pressed before
3827 if self
._nTabXButtonStatus
!= FNB_BTN_PRESSED
:
3830 self
._nTabXButtonStatus
= FNB_BTN_HOVER
3832 self
.DeletePage(self
._iActivePage
)
3834 elif where
== FNB_DROP_DOWN_ARROW
:
3836 # Make sure that the button was pressed before
3837 if self
._nArrowDownButtonStatus
!= FNB_BTN_PRESSED
:
3840 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
3842 # Refresh the button status
3843 renderer
= self
._mgr
.GetRenderer(self
.GetParent().GetWindowStyleFlag())
3844 dc
= wx
.ClientDC(self
)
3845 renderer
.DrawDropDownArrow(self
, dc
)
3847 self
.PopupTabsMenu()
3850 def HitTest(self
, pt
):
3852 HitTest method for L{PageContainer}.
3853 Returns the flag (if any) and the hit page (if any).
3856 style
= self
.GetParent().GetWindowStyleFlag()
3857 render
= self
._mgr
.GetRenderer(style
)
3859 fullrect
= self
.GetClientRect()
3860 btnLeftPos
= render
.GetLeftButtonPos(self
)
3861 btnRightPos
= render
.GetRightButtonPos(self
)
3862 btnXPos
= render
.GetXPos(self
)
3866 if len(self
._pagesInfoVec
) == 0:
3867 return FNB_NOWHERE
, tabIdx
3869 rect
= wx
.Rect(btnXPos
, 8, 16, 16)
3870 if rect
.Contains(pt
):
3871 return (style
& FNB_NO_X_BUTTON
and [FNB_NOWHERE
] or [FNB_X
])[0], tabIdx
3873 rect
= wx
.Rect(btnRightPos
, 8, 16, 16)
3874 if style
& FNB_DROPDOWN_TABS_LIST
:
3875 rect
= wx
.Rect(render
.GetDropArrowButtonPos(self
), 8, 16, 16)
3876 if rect
.Contains(pt
):
3877 return FNB_DROP_DOWN_ARROW
, tabIdx
3879 if rect
.Contains(pt
):
3880 return (style
& FNB_NO_NAV_BUTTONS
and [FNB_NOWHERE
] or [FNB_RIGHT_ARROW
])[0], tabIdx
3882 rect
= wx
.Rect(btnLeftPos
, 8, 16, 16)
3883 if rect
.Contains(pt
):
3884 return (style
& FNB_NO_NAV_BUTTONS
and [FNB_NOWHERE
] or [FNB_LEFT_ARROW
])[0], tabIdx
3886 # Test whether a left click was made on a tab
3889 for cur
in xrange(self
._nFrom
, len(self
._pagesInfoVec
)):
3891 pgInfo
= self
._pagesInfoVec
[cur
]
3893 if pgInfo
.GetPosition() == wx
.Point(-1, -1):
3896 if style
& FNB_X_ON_TAB
and cur
== self
.GetSelection():
3897 # 'x' button exists on a tab
3898 if self
._pagesInfoVec
[cur
].GetXRect().Contains(pt
):
3899 return FNB_TAB_X
, cur
3903 if self
._pagesInfoVec
[cur
].GetRegion().Contains(pt
.x
, pt
.y
):
3904 if bFoundMatch
or cur
== self
.GetSelection():
3912 tabRect
= wx
.Rect(pgInfo
.GetPosition().x
, pgInfo
.GetPosition().y
,
3913 pgInfo
.GetSize().x
, pgInfo
.GetSize().y
)
3915 if tabRect
.Contains(pt
):
3920 return FNB_TAB
, tabIdx
3922 if self
._isdragging
:
3923 # We are doing DND, so check also the region outside the tabs
3924 # try before the first tab
3925 pgInfo
= self
._pagesInfoVec
[0]
3926 tabRect
= wx
.Rect(0, pgInfo
.GetPosition().y
, pgInfo
.GetPosition().x
, self
.GetParent().GetSize().y
)
3927 if tabRect
.Contains(pt
):
3930 # try after the last tab
3931 pgInfo
= self
._pagesInfoVec
[-1]
3932 startpos
= pgInfo
.GetPosition().x
+pgInfo
.GetSize().x
3933 tabRect
= wx
.Rect(startpos
, pgInfo
.GetPosition().y
, fullrect
.width
-startpos
, self
.GetParent().GetSize().y
)
3935 if tabRect
.Contains(pt
):
3936 return FNB_TAB
, len(self
._pagesInfoVec
)
3939 return FNB_NOWHERE
, -1
3942 def SetSelection(self
, page
):
3943 """ Sets the selected page. """
3945 book
= self
.GetParent()
3946 book
.SetSelection(page
)
3947 self
.DoSetSelection(page
)
3950 def DoSetSelection(self
, page
):
3951 """ Does the actual selection of a page. """
3953 if page
< len(self
._pagesInfoVec
):
3955 da_page
= self
._pParent
.GetPage(page
)
3960 if not self
.IsTabVisible(page
):
3961 # Try to remove one tab from start and try again
3963 if not self
.CanFitToScreen(page
):
3965 if self
._nFrom
> page
:
3968 while self
._nFrom
< page
:
3970 if self
.CanFitToScreen(page
):
3976 def DeletePage(self
, page
):
3977 """ Delete the specified page from L{FlatNotebook}. """
3979 book
= self
.GetParent()
3980 book
.DeletePage(page
)
3984 def IsTabVisible(self
, page
):
3985 """ Returns whether a tab is visible or not. """
3987 iLastVisiblePage
= self
.GetLastVisibleTab()
3988 return page
<= iLastVisiblePage
and page
>= self
._nFrom
3991 def DoDeletePage(self
, page
):
3992 """ Does the actual page deletion. """
3994 # Remove the page from the vector
3995 book
= self
.GetParent()
3996 self
._pagesInfoVec
.pop(page
)
3998 # Thanks to Yiaanis AKA Mandrav
3999 if self
._iActivePage
>= page
:
4000 self
._iActivePage
= self
._iActivePage
- 1
4001 self
._iPreviousActivePage
= -1
4003 # The delete page was the last first on the array,
4004 # but the book still has more pages, so we set the
4005 # active page to be the first one (0)
4006 if self
._iActivePage
< 0 and len(self
._pagesInfoVec
) > 0:
4007 self
._iActivePage
= 0
4008 self
._iPreviousActivePage
= -1
4011 if self
._iActivePage
>= 0:
4013 book
._bForceSelection
= True
4015 # Check for selection and send event
4016 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, self
.GetParent().GetId())
4017 event
.SetSelection(self
._iActivePage
)
4018 event
.SetOldSelection(self
._iPreviousActivePage
)
4019 event
.SetEventObject(self
.GetParent())
4021 book
.SetSelection(self
._iActivePage
)
4022 book
._bForceSelection
= False
4024 # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
4025 event
.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
)
4026 event
.SetOldSelection(self
._iPreviousActivePage
)
4027 self
.GetParent().GetEventHandler().ProcessEvent(event
)
4029 if not self
._pagesInfoVec
:
4030 # Erase the page container drawings
4031 dc
= wx
.ClientDC(self
)
4035 def DeleteAllPages(self
):
4036 """ Deletes all the pages. """
4038 self
._iActivePage
= -1
4039 self
._iPreviousActivePage
= -1
4041 self
._pagesInfoVec
= []
4043 # Erase the page container drawings
4044 dc
= wx
.ClientDC(self
)
4048 def OnMouseMove(self
, event
):
4049 """ Handles the wx.EVT_MOTION for L{PageContainer}. """
4051 if self
._pagesInfoVec
and self
.IsShown():
4053 xButtonStatus
= self
._nXButtonStatus
4054 xTabButtonStatus
= self
._nTabXButtonStatus
4055 rightButtonStatus
= self
._nRightButtonStatus
4056 leftButtonStatus
= self
._nLeftButtonStatus
4057 dropDownButtonStatus
= self
._nArrowDownButtonStatus
4059 style
= self
.GetParent().GetWindowStyleFlag()
4061 self
._nXButtonStatus
= FNB_BTN_NONE
4062 self
._nRightButtonStatus
= FNB_BTN_NONE
4063 self
._nLeftButtonStatus
= FNB_BTN_NONE
4064 self
._nTabXButtonStatus
= FNB_BTN_NONE
4065 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
4067 where
, tabIdx
= self
.HitTest(event
.GetPosition())
4070 if event
.LeftIsDown():
4072 self
._nXButtonStatus
= (self
._nLeftClickZone
==FNB_X
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4076 self
._nXButtonStatus
= FNB_BTN_HOVER
4078 elif where
== FNB_DROP_DOWN_ARROW
:
4079 if event
.LeftIsDown():
4081 self
._nArrowDownButtonStatus
= (self
._nLeftClickZone
==FNB_DROP_DOWN_ARROW
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4085 self
._nArrowDownButtonStatus
= FNB_BTN_HOVER
4087 elif where
== FNB_TAB_X
:
4088 if event
.LeftIsDown():
4090 self
._nTabXButtonStatus
= (self
._nLeftClickZone
==FNB_TAB_X
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4094 self
._nTabXButtonStatus
= FNB_BTN_HOVER
4096 elif where
== FNB_RIGHT_ARROW
:
4097 if event
.LeftIsDown():
4099 self
._nRightButtonStatus
= (self
._nLeftClickZone
==FNB_RIGHT_ARROW
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4103 self
._nRightButtonStatus
= FNB_BTN_HOVER
4105 elif where
== FNB_LEFT_ARROW
:
4106 if event
.LeftIsDown():
4108 self
._nLeftButtonStatus
= (self
._nLeftClickZone
==FNB_LEFT_ARROW
and [FNB_BTN_PRESSED
] or [FNB_BTN_NONE
])[0]
4112 self
._nLeftButtonStatus
= FNB_BTN_HOVER
4114 elif where
== FNB_TAB
:
4115 # Call virtual method for showing tooltip
4116 self
.ShowTabTooltip(tabIdx
)
4118 if not self
.GetEnabled(tabIdx
):
4119 # Set the cursor to be 'No-entry'
4120 wx
.SetCursor(wx
.StockCursor(wx
.CURSOR_NO_ENTRY
))
4122 # Support for drag and drop
4123 if event
.Dragging() and not (style
& FNB_NODRAG
):
4125 self
._isdragging
= True
4126 draginfo
= FNBDragInfo(self
, tabIdx
)
4127 drginfo
= cPickle
.dumps(draginfo
)
4128 dataobject
= wx
.CustomDataObject(wx
.CustomDataFormat("FlatNotebook"))
4129 dataobject
.SetData(drginfo
)
4130 dragSource
= FNBDropSource(self
)
4131 dragSource
.SetData(dataobject
)
4132 dragSource
.DoDragDrop(wx
.Drag_DefaultMove
)
4134 bRedrawX
= self
._nXButtonStatus
!= xButtonStatus
4135 bRedrawRight
= self
._nRightButtonStatus
!= rightButtonStatus
4136 bRedrawLeft
= self
._nLeftButtonStatus
!= leftButtonStatus
4137 bRedrawTabX
= self
._nTabXButtonStatus
!= xTabButtonStatus
4138 bRedrawDropArrow
= self
._nArrowDownButtonStatus
!= dropDownButtonStatus
4140 render
= self
._mgr
.GetRenderer(style
)
4142 if (bRedrawX
or bRedrawRight
or bRedrawLeft
or bRedrawTabX
or bRedrawDropArrow
):
4144 dc
= wx
.ClientDC(self
)
4148 render
.DrawX(self
, dc
)
4152 render
.DrawLeftArrow(self
, dc
)
4156 render
.DrawRightArrow(self
, dc
)
4160 render
.DrawTabX(self
, dc
, self
._pagesInfoVec
[tabIdx
].GetXRect(), tabIdx
, self
._nTabXButtonStatus
)
4162 if bRedrawDropArrow
:
4164 render
.DrawDropDownArrow(self
, dc
)
4169 def GetLastVisibleTab(self
):
4170 """ Returns the last visible tab. """
4177 for ii
in xrange(self
._nFrom
, len(self
._pagesInfoVec
)):
4179 if self
._pagesInfoVec
[ii
].GetPosition() == wx
.Point(-1, -1):
4185 def GetNumTabsCanScrollLeft(self
):
4186 """ Returns the number of tabs than can be scrolled left. """
4188 # Reserved area for the buttons (<>x)
4189 rect
= self
.GetClientRect()
4190 clientWidth
= rect
.width
4191 posx
= self
._pParent
._nPadding
4195 # In case we have error prevent crash
4199 dc
= wx
.ClientDC(self
)
4201 style
= self
.GetParent().GetWindowStyleFlag()
4202 render
= self
._mgr
.GetRenderer(style
)
4204 for ii
in xrange(self
._nFrom
, -1, -1):
4206 boldFont
= wx
.SystemSettings_GetFont(wx
.SYS_DEFAULT_GUI_FONT
)
4207 boldFont
.SetWeight(wx
.FONTWEIGHT_BOLD
)
4208 dc
.SetFont(boldFont
)
4210 height
= dc
.GetCharHeight()
4212 tabHeight
= height
+ FNB_HEIGHT_SPACER
# We use 6 pixels as padding
4213 if style
& FNB_VC71
:
4214 tabHeight
= (style
& FNB_BOTTOM
and [tabHeight
- 4] or [tabHeight
])[0]
4215 elif style
& FNB_FANCY_TABS
:
4216 tabHeight
= (style
& FNB_BOTTOM
and [tabHeight
- 3] or [tabHeight
])[0]
4218 width
, pom
= dc
.GetTextExtent(self
.GetPageText(ii
))
4219 if style
!= FNB_VC71
:
4220 shapePoints
= int(tabHeight
*math
.tan(float(self
._pagesInfoVec
[ii
].GetTabAngle())/180.0*math
.pi
))
4224 tabWidth
= 2*self
._pParent
._nPadding
+ width
4226 if not (style
& FNB_VC71
):
4228 tabWidth
+= 2*shapePoints
4230 hasImage
= self
._ImageList
!= None and self
._pagesInfoVec
[ii
].GetImageIndex() != -1
4232 # For VC71 style, we only add the icon size (16 pixels)
4235 if not self
.IsDefaultTabs():
4236 tabWidth
+= 16 + self
._pParent
._nPadding
4239 tabWidth
+= 16 + self
._pParent
._nPadding
+ shapePoints
/2
4241 if posx
+ tabWidth
+ render
.GetButtonsAreaLength(self
) >= clientWidth
:
4244 numTabs
= numTabs
+ 1
4250 def IsDefaultTabs(self
):
4251 """ Returns whether a tab has a default style. """
4253 style
= self
.GetParent().GetWindowStyleFlag()
4254 res
= (style
& FNB_VC71
) or (style
& FNB_FANCY_TABS
) or (style
& FNB_VC8
)
4258 def AdvanceSelection(self
, bForward
=True):
4260 Cycles through the tabs.
4261 The call to this function generates the page changing events.
4264 nSel
= self
.GetSelection()
4269 nMax
= self
.GetPageCount() - 1
4272 newSelection
= (nSel
== nMax
and [0] or [nSel
+ 1])[0]
4274 newSelection
= (nSel
== 0 and [nMax
] or [nSel
- 1])[0]
4276 if not self
._pagesInfoVec
[newSelection
].GetEnabled():
4279 self
.FireEvent(newSelection
)
4282 def OnMouseLeave(self
, event
):
4283 """ Handles the wx.EVT_LEAVE_WINDOW event for L{PageContainer}. """
4285 self
._nLeftButtonStatus
= FNB_BTN_NONE
4286 self
._nXButtonStatus
= FNB_BTN_NONE
4287 self
._nRightButtonStatus
= FNB_BTN_NONE
4288 self
._nTabXButtonStatus
= FNB_BTN_NONE
4289 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
4291 style
= self
.GetParent().GetWindowStyleFlag()
4292 render
= self
._mgr
.GetRenderer(style
)
4294 dc
= wx
.ClientDC(self
)
4296 render
.DrawX(self
, dc
)
4297 render
.DrawLeftArrow(self
, dc
)
4298 render
.DrawRightArrow(self
, dc
)
4300 selection
= self
.GetSelection()
4306 if not self
.IsTabVisible(selection
):
4307 if selection
== len(self
._pagesInfoVec
) - 1:
4308 if not self
.CanFitToScreen(selection
):
4315 render
.DrawTabX(self
, dc
, self
._pagesInfoVec
[selection
].GetXRect(), selection
, self
._nTabXButtonStatus
)
4320 def OnMouseEnterWindow(self
, event
):
4321 """ Handles the wx.EVT_ENTER_WINDOW event for L{PageContainer}. """
4323 self
._nLeftButtonStatus
= FNB_BTN_NONE
4324 self
._nXButtonStatus
= FNB_BTN_NONE
4325 self
._nRightButtonStatus
= FNB_BTN_NONE
4326 self
._nLeftClickZone
= FNB_BTN_NONE
4327 self
._nArrowDownButtonStatus
= FNB_BTN_NONE
4332 def ShowTabTooltip(self
, tabIdx
):
4333 """ Shows a tab tooltip. """
4335 pWindow
= self
._pParent
.GetPage(tabIdx
)
4338 pToolTip
= pWindow
.GetToolTip()
4339 if pToolTip
and pToolTip
.GetWindow() == pWindow
:
4340 self
.SetToolTipString(pToolTip
.GetTip())
4343 def SetPageImage(self
, page
, imgindex
):
4344 """ Sets the image index associated to a page. """
4346 if page
< len(self
._pagesInfoVec
):
4348 self
._pagesInfoVec
[page
].SetImageIndex(imgindex
)
4352 def GetPageImage(self
, page
):
4353 """ Returns the image index associated to a page. """
4355 if page
< len(self
._pagesInfoVec
):
4357 return self
._pagesInfoVec
[page
].GetImageIndex()
4362 def OnDropTarget(self
, x
, y
, nTabPage
, wnd_oldContainer
):
4363 """ Handles the drop action from a DND operation. """
4365 # Disable drag'n'drop for disabled tab
4366 if not wnd_oldContainer
._pagesInfoVec
[nTabPage
].GetEnabled():
4367 return wx
.DragCancel
4369 self
._isdragging
= True
4370 oldContainer
= wnd_oldContainer
4373 where
, nIndex
= self
.HitTest(wx
.Point(x
, y
))
4375 oldNotebook
= oldContainer
.GetParent()
4376 newNotebook
= self
.GetParent()
4378 if oldNotebook
== newNotebook
:
4382 if where
== FNB_TAB
:
4383 self
.MoveTabPage(nTabPage
, nIndex
)
4385 elif self
.GetParent().GetWindowStyleFlag() & FNB_ALLOW_FOREIGN_DND
:
4387 if wx
.Platform
in ["__WXMSW__", "__WXGTK__", "__WXMAC__"]:
4390 window
= oldNotebook
.GetPage(nTabPage
)
4393 where
, nIndex
= newNotebook
._pages
.HitTest(wx
.Point(x
, y
))
4394 caption
= oldContainer
.GetPageText(nTabPage
)
4395 imageindex
= oldContainer
.GetPageImage(nTabPage
)
4396 oldNotebook
.RemovePage(nTabPage
)
4397 window
.Reparent(newNotebook
)
4401 bmp
= oldNotebook
.GetImageList().GetIcon(imageindex
)
4402 newImageList
= newNotebook
.GetImageList()
4404 if not newImageList
:
4405 xbmp
, ybmp
= bmp
.GetWidth(), bmp
.GetHeight()
4406 newImageList
= wx
.ImageList(xbmp
, ybmp
)
4409 imageindex
= newImageList
.GetImageCount()
4411 newImageList
.AddIcon(bmp
)
4412 newNotebook
.SetImageList(newImageList
)
4414 newNotebook
.InsertPage(nIndex
, window
, caption
, True, imageindex
)
4416 self
._isdragging
= False
4421 def MoveTabPage(self
, nMove
, nMoveTo
):
4422 """ Moves a tab inside the same L{FlatNotebook}. """
4424 if nMove
== nMoveTo
:
4427 elif nMoveTo
< len(self
._pParent
._windows
):
4428 nMoveTo
= nMoveTo
+ 1
4430 self
._pParent
.Freeze()
4432 # Remove the window from the main sizer
4433 nCurSel
= self
._pParent
._pages
.GetSelection()
4434 self
._pParent
._mainSizer
.Detach(self
._pParent
._windows
[nCurSel
])
4435 self
._pParent
._windows
[nCurSel
].Hide()
4437 pWindow
= self
._pParent
._windows
[nMove
]
4438 self
._pParent
._windows
.pop(nMove
)
4439 self
._pParent
._windows
.insert(nMoveTo
-1, pWindow
)
4441 pgInfo
= self
._pagesInfoVec
[nMove
]
4443 self
._pagesInfoVec
.pop(nMove
)
4444 self
._pagesInfoVec
.insert(nMoveTo
- 1, pgInfo
)
4446 # Add the page according to the style
4447 pSizer
= self
._pParent
._mainSizer
4448 style
= self
.GetParent().GetWindowStyleFlag()
4450 if style
& FNB_BOTTOM
:
4452 pSizer
.Insert(0, pWindow
, 1, wx
.EXPAND
)
4456 # We leave a space of 1 pixel around the window
4457 pSizer
.Add(pWindow
, 1, wx
.EXPAND
)
4462 self
._iActivePage
= nMoveTo
- 1
4463 self
._iPreviousActivePage
= -1
4464 self
.DoSetSelection(self
._iActivePage
)
4466 self
._pParent
.Thaw()
4469 def CanFitToScreen(self
, page
):
4470 """ Returns wheter a tab can fit in the left space in the screen or not. """
4472 # Incase the from is greater than page,
4473 # we need to reset the self._nFrom, so in order
4474 # to force the caller to do so, we return false
4475 if self
._nFrom
> page
:
4478 style
= self
.GetParent().GetWindowStyleFlag()
4479 render
= self
._mgr
.GetRenderer(style
)
4481 vTabInfo
= render
.NumberTabsCanFit(self
)
4483 if page
- self
._nFrom
>= len(vTabInfo
):
4489 def GetNumOfVisibleTabs(self
):
4490 """ Returns the number of visible tabs. """
4493 for ii
in xrange(self
._nFrom
, len(self
._pagesInfoVec
)):
4494 if self
._pagesInfoVec
[ii
].GetPosition() == wx
.Point(-1, -1):
4501 def GetEnabled(self
, page
):
4502 """ Returns whether a tab is enabled or not. """
4504 if page
>= len(self
._pagesInfoVec
):
4505 return True # Seems strange, but this is the default
4507 return self
._pagesInfoVec
[page
].GetEnabled()
4510 def Enable(self
, page
, enabled
=True):
4511 """ Enables or disables a tab. """
4513 if page
>= len(self
._pagesInfoVec
):
4516 self
._pagesInfoVec
[page
].Enable(enabled
)
4519 def GetSingleLineBorderColour(self
):
4520 """ Returns the colour for the single line border. """
4522 if self
.HasFlag(FNB_FANCY_TABS
):
4523 return self
._colorFrom
4528 def HasFlag(self
, flag
):
4529 """ Returns whether a flag is present in the L{FlatNotebook} style. """
4531 style
= self
.GetParent().GetWindowStyleFlag()
4532 res
= (style
& flag
and [True] or [False])[0]
4536 def ClearFlag(self
, flag
):
4537 """ Deletes a flag from the L{FlatNotebook} style. """
4539 style
= self
.GetParent().GetWindowStyleFlag()
4541 self
.SetWindowStyleFlag(style
)
4544 def TabHasImage(self
, tabIdx
):
4545 """ Returns whether a tab has an associated image index or not. """
4548 return self
._pagesInfoVec
[tabIdx
].GetImageIndex() != -1
4553 def OnLeftDClick(self
, event
):
4554 """ Handles the wx.EVT_LEFT_DCLICK event for L{PageContainer}. """
4556 if self
.HasFlag(FNB_DCLICK_CLOSES_TABS
):
4558 where
, tabIdx
= self
.HitTest(event
.GetPosition())
4560 if where
== FNB_TAB
:
4561 self
.DeletePage(tabIdx
)
4568 def PopupTabsMenu(self
):
4569 """ Pops up the menu activated with the drop down arrow in the navigation area. """
4571 popupMenu
= wx
.Menu()
4573 for i
in xrange(len(self
._pagesInfoVec
)):
4574 pi
= self
._pagesInfoVec
[i
]
4575 item
= wx
.MenuItem(popupMenu
, i
, pi
.GetCaption(), pi
.GetCaption(), wx
.ITEM_NORMAL
)
4576 self
.Bind(wx
.EVT_MENU
, self
.OnTabMenuSelection
, item
)
4578 # This code is commented, since there is an alignment problem with wx2.6.3 & Menus
4579 # if self.TabHasImage(ii):
4580 # item.SetBitmaps( (*m_ImageList)[pi.GetImageIndex()] );
4582 popupMenu
.AppendItem(item
)
4583 item
.Enable(pi
.GetEnabled())
4585 self
.PopupMenu(popupMenu
)
4588 def OnTabMenuSelection(self
, event
):
4589 """ Handles the wx.EVT_MENU event for L{PageContainer}. """
4591 selection
= event
.GetId()
4592 self
.FireEvent(selection
)
4595 def FireEvent(self
, selection
):
4597 Fires the wxEVT_FLATNOTEBOOK_PAGE_CHANGING and wxEVT_FLATNOTEBOOK_PAGE_CHANGED events
4598 called from other methods (from menu selection or Smart Tabbing).
4602 if selection
== self
._iActivePage
:
4603 # No events for the same selection
4606 oldSelection
= self
._iActivePage
4608 event
= FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING
, self
.GetParent().GetId())
4609 event
.SetSelection(selection
)
4610 event
.SetOldSelection(oldSelection
)
4611 event
.SetEventObject(self
.GetParent())
4613 if not self
.GetParent().GetEventHandler().ProcessEvent(event
) or event
.IsAllowed():
4615 self
.SetSelection(selection
)
4617 # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
4618 event
.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED
)
4619 event
.SetOldSelection(oldSelection
)
4620 self
.GetParent().GetEventHandler().ProcessEvent(event
)
4623 def SetImageList(self
, imglist
):
4624 """ Sets the image list for the page control. """
4626 self
._ImageList
= imglist
4629 def AssignImageList(self
, imglist
):
4630 """ Assigns the image list for the page control. """
4632 self
._ImageList
= imglist
4635 def GetImageList(self
):
4636 """ Returns the image list for the page control. """
4638 return self
._ImageList
4641 def GetSelection(self
):
4642 """ Returns the current selected page. """
4644 return self
._iActivePage
4647 def GetPageCount(self
):
4648 """ Returns the number of tabs in the L{FlatNotebook} control. """
4650 return len(self
._pagesInfoVec
)
4653 def GetPageText(self
, page
):
4654 """ Returns the tab caption of the page. """
4656 return self
._pagesInfoVec
[page
].GetCaption()
4659 def SetPageText(self
, page
, text
):
4660 """ Sets the tab caption of the page. """
4662 self
._pagesInfoVec
[page
].SetCaption(text
)
4666 def DrawDragHint(self
):
4667 """ Draws small arrow at the place that the tab will be placed. """
4669 # get the index of tab that will be replaced with the dragged tab
4670 pt
= wx
.GetMousePosition()
4671 client_pt
= self
.ScreenToClient(pt
)
4672 where
, tabIdx
= self
.HitTest(client_pt
)
4673 self
._mgr
.GetRenderer(self
.GetParent().GetWindowStyleFlag()).DrawDragHint(self
, tabIdx
)