comparison orpg/tools/NotebookCtrl.py @ 0:4385a7d0efd1 grumpy-goblin

Deleted and repushed it with the 'grumpy-goblin' branch. I forgot a y
author sirebral
date Tue, 14 Jul 2009 16:41:58 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4385a7d0efd1
1 # --------------------------------------------------------------------------- #
2 # NOTEBOOKCTRL Control wxPython IMPLEMENTATION
3 # Python Code By:
4 #
5 # Andrea Gavana, @ 11 Nov 2005
6 # Latest Revision: 06 Oct 2006, 18.10 GMT
7 #
8 #
9 # AKNOWLEDGEMENTS
10 #
11 # A big load of thanks goes to Julianne Sharer that has implemented the new
12 # features of left/right tabs, rotated or horizontal, with the ability to
13 # switch between the two views by a single mouse click. Moreover, all the
14 # work done to refactor NotebookCtrl in a more readable way has been done
15 # by Julianne Sharer. Thanks Julianne.
16 #
17 #
18 # TODO List/Caveats
19 #
20 # 1. Ay Idea?
21 #
22 # For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
23 # Write To Me At:
24 #
25 # andrea.gavana@gmail.com
26 # gavana@kpo.kz
27 #
28 # Or, Obviously, To The wxPython Mailing List!!!
29 #
30 #
31 # End Of Comments
32 # --------------------------------------------------------------------------- #
33
34
35 """
36 A full-featured notebook control, worked out by Andrea Gavana And Julianne Sharer.
37
38 Description:
39
40 NotebookCtrl Mimics The Behavior Of wx.Notebook, And Most Of Its Functionalities
41 Are Implemented In NotebookCtrl. However, NotebookCtrl Has A Lot Of Options That
42 wx.Notebook Does Not Have, And It Is Therefore Quite Customizable.
43 wx.Notebook Styles Not Implemented in NotebookCtrl Are:
44
45 - wx.NB_MULTILINE (But NotebookCtrl Has A SpinButton To Navigate
46 Through Tabs).
47
48 Supported Customizations For NotebookCtrl Include:
49
50 - Setting Individual Tab Font And Text Colour;
51 - Images On Tabs (Line wx.Notebook);
52 - Setting Individual Tab Colours;
53 - Disabling/Enabling Individual Tabs (Also Visually Effective);
54 Now Supports Grayed Out Icons When A Page Is Disabled;
55 - Drawing Of A Small Closing "X" At The Right Of Every Tab, That Enable The User
56 To Close A Tab With A Mouse Click (Like eMule Tab Style);
57 - Enabling Highlighted Tabs On Selection;
58 - Drawing Focus Indicator In Each Tab (Like wx.Notebook);
59 - Ctrl-Tab Keyboard Navigation Between Pages;
60 - Tab With Animated Icons (Animation On Tabs);
61 - Drag And Drop Tabs In NotebookCtrl (Plus A Visual Arrow Effect
62 To Indicate Dropping Position);
63 - Drag And Drop Event;
64 - ToolTips On Individual Tabs, With Customizable ToolTip Time
65 Popup And ToolTip Window Size For Individual Tabs;
66 - Possibility To Hide The TabCtrl There Is Only One Tab (Thus
67 Maximizing The Corresponding Window);
68 - Possibility To Convert The Tab Image Into A Close Button While
69 Mouse Is Hovering On The Tab Image;
70 - Popup Menus On Tabs (Popup Menus Specific To Each Tab);
71 - Showing Pages In "Column/Row Mode", Which Means That All Pages
72 Will Be Shown In NotebookCtrl While The Tabs Are Hidden. They
73 Can Be Shown In Columns (Default) Or In Rows;
74 - Possibility To Hide Tabs On User Request, Thus Showing Only The
75 Current Panel;
76 - Multiple Tabs Selection (Hold Ctrl Key Down And Left Mouse
77 Click), Useful When You Use The Show All The Panels In
78 Columns/Rows. In This Case, Only The Selected Tabs Are Shown In
79 Columns/Rows;
80 - Events For Mouse Events (Left Double Click, Middle Click, Right Click);
81 - Possibility To Reparent A NotebookCtrl Page To A Freshly Created
82 Frame As A Simple Panel Or To A New NotebookCtrl Created Inside
83 That New Frame.
84 - Possibility To Add A Custom Panel To Show A Logo Or HTML
85 Information Or Whatever You Like When There Are No Tabs In
86 NotebookCtrl;
87 - Possibility To Change The ToolTip Window Background Colour;
88 - Possibility To Draw Vertical Or Horizontal Gradient Coloured Tabs
89 (2 Colours);
90 - Themes On Tabs: Built-In Themes Are KDE (Unix/Linux), Metal,
91 Aqua Light And Aqua Dark (MacOS), Windows Silver (Windows) Or
92 Generic Gradient Coloured Tabs. It's Also Possible To Define A
93 Separate Theme For Selected Tabs And Control Background (The
94 Last Two Are Work In Progress);
95 - Contour Line Colour Around Tabs Is Customizable;
96 - Highlight Colour Of Selected Tab Is Customizable;
97 - Each Tab Can Have Its Own Gradient Colouring (2 Colours For Every Tab);
98 - Custom Images May Be Drawn As A "X" Close Buttons On Tabs;
99 - Possibility To Hide A Particular Tab Using A wx.PopupMenu That
100 Is Shown If You Call EnableHiding(True). Look At The Top Right
101 Of NotebookCtrl;
102 - Allows Drag And Drop Of Tabs/Pages Between Different
103 NotebookCtrls In The Same Application.
104 - Draw tabs on the left or right side, rotated or horizontal
105 - Allow user to switch between rotated and horizontal displays of
106 tabs on the left or right side.
107
108
109 Usage:
110
111 NotebookCtrl Construction Is Quite Similar To wx.Notebook::
112
113 NotebookCtrl.__init__(self, parent, id, pos=wx.DefaultPosition,
114 size=wx.DefaultSize, style=style, sizer=nbsizer)
115
116 See L{NotebookCtrl.__init__} Method For The Definition Of Non Standard (Non
117 wxPython) Parameters.
118
119 NotebookCtrl Control Is Freeware And Distributed Under The wxPython License.
120
121 Latest Revision: Andrea Gavana @ 06 Oct 2006, 18.10 GMT
122
123 @undocumented: NC_MAC*, topaqua*, botaqua*, distaqua*, disbaqua*,
124 kdetheme, silvertheme*, wxEVT*, attrs, GetMenuButton*, NCDragInfo,
125 NCDropTarget, TabbedPage, TabCtrl, TransientTipWindow,
126 macPopupWindow, macTransientTipWindow, NCFrame, DEFAULT_SIZE,
127 NotebookSpinButton, NotebookMenuButton
128 """
129
130 __docformat__ = "epytext"
131
132
133 #----------------------------------------------------------------------
134 # Beginning Of NOTEBOOKCTRL wxPython Code
135 #----------------------------------------------------------------------
136
137 from orpg.orpg_wx import *
138 from wx.lib.buttons import GenBitmapButton as BitmapButton
139 import wx.xrc as xrc
140
141 import cStringIO, zlib
142 import cPickle
143 import weakref
144
145 # HitTest Results
146 NC_HITTEST_NOWHERE = 0 # Not On Tab
147 """Indicates mouse coordinates not on any tab of the notebook"""
148 NC_HITTEST_ONICON = 1 # On Icon
149 """Indicates mouse coordinates on an icon in a tab of the notebook"""
150 NC_HITTEST_ONLABEL = 2 # On Label
151 """Indicates mouse coordinates on a label in a tab of the notebook"""
152 NC_HITTEST_ONITEM = 4 # Generic, On Item
153 """Indicates mouse coordinates on a tab of the notebook"""
154 NC_HITTEST_ONX = 8 # On Small Square On Every Page
155 """Indicates mouse coordinates on the closing I{X} in a tab of the notebook"""
156
157 # NotebookCtrl Styles
158 # NotebookCtrl Placed On Top (Default)
159 NC_TOP = 1
160 """Specify tabs at the top of the notebook control."""
161 # NotebookCtrl Placed At The Bottom
162 NC_BOTTOM = 2
163 """Specify tabs at the bottom of the notebook control."""
164 # NotebookCtrl With Fixed Width Tabs
165 NC_FIXED_WIDTH = 4
166 """Specify tabs of a fixed width in the notebook control."""
167 # NotebookCtrl Placed At The Left
168 NC_LEFT = 8
169 """Specify tabs on the left side of the notebook control."""
170 # NotebookCtrl Placed At The Right
171 NC_RIGHT = 16
172 """Specify tabs on the right side of the notebook control."""
173 # NotebookCtrl tab rotated
174 NC_ROTATE = 32
175 """Specify rotated tabs (with vertical text) in the notebook control."""
176 # NotebookCtrl switchable between compact and expanded sizes
177 NC_EXPANDABLE = 64
178 """Specify that the notebook control includes a toggle button to
179 switch between compact tabs (rotated on the left or right side)
180 expanded tabs (horizontal on the left or right side)."""
181
182 NC_DEFAULT_STYLE = NC_TOP | wx.NO_BORDER
183 """The default style for the notebook control (tabs on top with no border)"""
184 # Also wx.STATIC_BORDER Is Supported
185
186 # NotebookCtrl theme styles
187 NC_GRADIENT_VERTICAL = 1
188 """Specify tabs rendered with a vertical gradient background."""
189 NC_GRADIENT_HORIZONTAL = 2
190 """Specify tabs rendered with a horizontal gradient background."""
191 NC_GRADIENT_SELECTION = 4
192 NC_AQUA_LIGHT = 8
193 """Specify tabs rendered with a Mac I{Light Aqua}-like background."""
194 NC_AQUA_DARK = 16
195 """Specify tabs rendered with a Mac I{Dark Aqua}-like background."""
196 NC_AQUA = NC_AQUA_LIGHT
197 """Specify tabs rendered with a Mac I{Light Aqua}-like background."""
198 NC_METAL = 32
199 """Specify tabs rendered with a Mac I{Metal}-like background."""
200 NC_SILVER = 64
201 """Specify tabs rendered with a Windows I{Silver}-like background."""
202 NC_KDE = 128
203 """Specify tabs rendered with a KDE-style background."""
204
205 # Patch To Make NotebookCtrl Working Also On MacOS: Thanks To Stani ;-)
206 if wx.Platform == '__WXMAC__':
207 DEFAULT_SIZE = wx.Size(26, 26)
208 else:
209 DEFAULT_SIZE = wx.DefaultSize
210
211 # Themes On Mac... This May Slow Down The Paint Event If You Turn It On!
212 NC_MAC_LIGHT = (240, 236)
213 NC_MAC_DARK = (232, 228)
214
215 topaqua1 = [wx.Colour(106, 152, 231), wx.Colour(124, 173, 236)]
216 botaqua1 = [wx.Colour(54, 128, 213), wx.Colour(130, 225, 249)]
217
218 topaqua2 = [wx.Colour(176, 222, 251), wx.Colour(166, 211, 245)]
219 botaqua2 = [wx.Colour(120, 182, 244), wx.Colour(162, 230, 245)]
220
221 distaqua = [wx.Colour(248, 248, 248), wx.Colour(243, 243, 243)]
222 disbaqua = [wx.Colour(219, 219, 219), wx.Colour(248, 248, 248)]
223
224 # Themes On KDE... This May Slow Down The Paint Event If You Turn It On!
225 kdetheme = [wx.Colour(0xf3,0xf7,0xf9), wx.Colour(0xf3,0xf7,0xf9),
226 wx.Colour(0xee,0xf3,0xf7), wx.Colour(0xee,0xf3,0xf7),
227 wx.Colour(0xea,0xf0,0xf4), wx.Colour(0xea,0xf0,0xf4),
228 wx.Colour(0xe6,0xec,0xf1), wx.Colour(0xe6,0xec,0xf1),
229 wx.Colour(0xe2,0xe9,0xef), wx.Colour(0xe2,0xe9,0xef),
230 wx.Colour(0xdd,0xe5,0xec), wx.Colour(0xdd,0xe5,0xec),
231 wx.Colour(0xd9,0xe2,0xea), wx.Colour(0xd9,0xe2,0xea)]
232
233 # Themes On Windows... This May Slow Down The Paint Event If You Turn It On!
234 silvertheme2 = [wx.Colour(255, 255, 255), wx.Colour(190, 190, 216),
235 wx.Colour(180, 180, 200)]
236 silvertheme1 = [wx.Colour(252, 252, 254), wx.Colour(252, 252, 254)]
237
238 # NotebookCtrl Events:
239 # wxEVT_NOTEBOOKCTRL_PAGE_CHANGED: Event Fired When You Switch Page;
240 # wxEVT_NOTEBOOKCTRL_PAGE_CHANGING: Event Fired When You Are About To Switch
241 # Pages, But You Can Still "Veto" The Page Changing By Avoiding To Call
242 # event.Skip() In Your Event Handler;
243 # wxEVT_NOTEBOOKCTRL_PAGE_CLOSING: Event Fired When A Page Is Closing, But
244 # You Can Still "Veto" The Page Changing By Avoiding To Call event.Skip()
245 # In Your Event Handler;
246 # wxEVT_NOTEBOOKCTRL_PAGE_DND: Event Fired When A Drag And Drop Action On
247 # Tabs Ends.
248 wxEVT_NOTEBOOKCTRL_PAGE_CHANGED = wx.NewEventType()
249 wxEVT_NOTEBOOKCTRL_PAGE_CHANGING = wx.NewEventType()
250 wxEVT_NOTEBOOKCTRL_PAGE_CLOSING = wx.NewEventType()
251 wxEVT_NOTEBOOKCTRL_PAGE_DND = wx.NewEventType()
252 wxEVT_NOTEBOOKCTRL_PAGE_DCLICK = wx.NewEventType()
253 wxEVT_NOTEBOOKCTRL_PAGE_RIGHT = wx.NewEventType()
254 wxEVT_NOTEBOOKCTRL_PAGE_MIDDLE = wx.NewEventType()
255
256 #-----------------------------------#
257 # NotebookCtrlEvent
258 #-----------------------------------#
259
260 EVT_NOTEBOOKCTRL_PAGE_CHANGED = wx.PyEventBinder(wxEVT_NOTEBOOKCTRL_PAGE_CHANGED, 1)
261 """Notify client objects when the active page in the notebook control
262 has changed."""
263
264 EVT_NOTEBOOKCTRL_PAGE_CHANGING = wx.PyEventBinder(wxEVT_NOTEBOOKCTRL_PAGE_CHANGING, 1)
265 """Notify client objects when the active page in the notebook control
266 is changing."""
267
268 EVT_NOTEBOOKCTRL_PAGE_CLOSING = wx.PyEventBinder(wxEVT_NOTEBOOKCTRL_PAGE_CLOSING, 1)
269 """Notify client objects when a page in the notebook control is closing."""
270
271 EVT_NOTEBOOKCTRL_PAGE_DND = wx.PyEventBinder(wxEVT_NOTEBOOKCTRL_PAGE_DND, 1)
272 """Enable client objects to override the behavior of the notebook control
273 when a dragged tab is dropped onto it."""
274
275 EVT_NOTEBOOKCTRL_PAGE_DCLICK = wx.PyEventBinder(wxEVT_NOTEBOOKCTRL_PAGE_DCLICK, 1)
276 """Notify client objects when the user double-clicks a tab
277 in the notebook control."""
278
279 EVT_NOTEBOOKCTRL_PAGE_RIGHT = wx.PyEventBinder(wxEVT_NOTEBOOKCTRL_PAGE_RIGHT, 1)
280 """Notify client objects when the user right-clicks a tab
281 in the notebook control."""
282
283 EVT_NOTEBOOKCTRL_PAGE_MIDDLE = wx.PyEventBinder(wxEVT_NOTEBOOKCTRL_PAGE_MIDDLE, 1)
284 """Notify client objects when the user clicks with the
285 middle mouse button on a tab in the notebook control."""
286
287 attrs = ["_backstyle", "_backtooltip", "_borderpen", "_convertimage", "_drawx",
288 "_drawxstyle", "_enabledragging", "_focusindpen", "_hideonsingletab",
289 "_highlight", "_padding", "_selectioncolour", "_selstyle", "_tabstyle",
290 "_upperhigh", "_usefocus", "_usegradients"]
291
292
293 # Check for the new method in 2.7 (not present in 2.6.3.3)
294 if wx.VERSION_STRING < "2.7":
295 wx.Rect.Contains = lambda self, point: wx.Rect.Inside(self, point)
296
297
298 # ---------------------------------------------------------------------------- #
299 def GetMenuButtonData():
300
301 return zlib.decompress(
302 "x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\x9c \xcc\xc1\
303 \x06$\x1fLd\x13\x00R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4[x\xba8\x86HL\xed\
304 \xbd`\xc8\xc7\xa0\xc0\xe1|q\xdb\x9d\xff'\xba\xb4\x1d\x05v\xff}\xe2\xab\x9a:c\
305 \x99\xc4\xbe\xe9\xfd+\x9a\xc5W%t\x1a\xe5\x08\xa6\xd6,\xe2\xf0\x9a\xc2\xc8\
306 \xf0\xe1\xf9r\xe6\xa3\xc9\x02b\xd9\x0c35\x80f0x\xba\xfa\xb9\xacsJh\x02\x00\
307 \xcd-%1")
308
309
310 def GetMenuButtonBitmap():
311
312 return wx.BitmapFromImage(GetMenuButtonImage())
313
314
315 def GetMenuButtonImage():
316
317 stream = cStringIO.StringIO(GetMenuButtonData())
318 return wx.ImageFromStream(stream)
319
320 # ---------------------------------------------------------------------------- #
321
322 def GrayOut(anImage):
323 """
324 Convert The Given Image (In Place) To A Grayed-Out Version,
325 Appropriate For A 'Disabled' Appearance.
326 """
327
328 factor = 0.7 # 0 < f < 1. Higher Is Grayer
329
330 if anImage.HasMask():
331 maskColor = (anImage.GetMaskRed(), anImage.GetMaskGreen(), anImage.GetMaskBlue())
332 else:
333 maskColor = None
334
335 data = map(ord, list(anImage.GetData()))
336
337 for i in range(0, len(data), 3):
338
339 pixel = (data[i], data[i+1], data[i+2])
340 pixel = MakeGray(pixel, factor, maskColor)
341
342 for x in range(3):
343 data[i+x] = pixel[x]
344
345 anImage.SetData(''.join(map(chr, data)))
346
347 return anImage
348
349
350 def MakeGray((r,g,b), factor, maskColor):
351 """
352 Make A Pixel Grayed-Out. If The Pixel Matches The MaskColor, It Won't Be
353 Changed.
354 """
355
356 if (r,g,b) != maskColor:
357 return map(lambda x: int((230 - x) * factor) + x, (r,g,b))
358 else:
359 return (r,g,b)
360
361 def GetDefaultTabStyle():
362 tabstyle = ThemeStyle()
363
364 # Draw Mac Themes On Tabs?
365 if wx.Platform == "__WXMAC__" or wx.Platform == "__WXCOCOA__":
366 tabstyle.EnableAquaTheme(True, 2)
367 # Draw Windows Silver Theme On Tabs?
368 elif wx.Platform == "__WXMSW__":
369 tabstyle.EnableSilverTheme(True)
370 else:
371 tabstyle.EnableKDETheme(True)
372
373 return tabstyle
374
375 # ---------------------------------------------------------------------------- #
376 # Class NotebookCtrlEvent
377 # ---------------------------------------------------------------------------- #
378
379 class NotebookCtrlEvent(wx.PyCommandEvent):
380 """
381 Represent details of the events that the L{NotebookCtrl} object sends.
382 """
383
384 def __init__(self, eventType, id=1, nSel=-1, nOldSel=-1):
385 """ Default Class Constructor. """
386
387 wx.PyCommandEvent.__init__(self, eventType, id)
388 self._eventType = eventType
389
390
391 def SetSelection(self, nSel):
392 """ Sets Event Selection. """
393
394 self._selection = nSel
395
396
397 def SetOldSelection(self, nOldSel):
398 """ Sets Old Event Selection. """
399
400 self._oldselection = nOldSel
401
402
403 def GetSelection(self):
404 """ Returns Event Selection. """
405
406 return self._selection
407
408
409 def GetOldSelection(self):
410 """ Returns Old Event Selection """
411
412 return self._oldselection
413
414
415 def SetOldPosition(self, pos):
416 """ Sets Old Event Position. """
417
418 self._oldposition = pos
419
420
421 def SetNewPosition(self, pos):
422 """ Sets New Event Position. """
423
424 self._newposition = pos
425
426
427 def GetOldPosition(self):
428 """ Returns Old Event Position. """
429
430 return self._oldposition
431
432
433 def GetNewPosition(self):
434 """ Returns New Event Position. """
435
436 return self._newposition
437
438
439 # ---------------------------------------------------------------------------- #
440 # Class NCDragInfo
441 # Stores All The Information To Allow Drag And Drop Between Different
442 # NotebookCtrls In The Same Application.
443 # ---------------------------------------------------------------------------- #
444
445 class NCDragInfo:
446
447 _map = weakref.WeakValueDictionary()
448
449 def __init__(self, container, pageindex):
450 """ Default Class Constructor. """
451
452 self._id = id(container)
453 NCDragInfo._map[self._id] = container
454 self._pageindex = pageindex
455
456
457 def GetContainer(self):
458 """ Returns The NotebookCtrl Page (Usually A Panel). """
459
460 return NCDragInfo._map.get(self._id, None)
461
462
463 def GetPageIndex(self):
464 """ Returns The Page Index Associated With A Page. """
465
466 return self._pageindex
467
468
469 # ---------------------------------------------------------------------------- #
470 # Class NCDropTarget
471 # Simply Used To Handle The OnDrop() Method When Dragging And Dropping Between
472 # Different NotebookCtrls.
473 # ---------------------------------------------------------------------------- #
474
475 class NCDropTarget(wx.DropTarget):
476
477 def __init__(self, parent):
478 """ Default Class Constructor. """
479
480 wx.DropTarget.__init__(self)
481
482 self._parent = parent
483 self._dataobject = wx.CustomDataObject(wx.CustomDataFormat("NotebookCtrl"))
484 self.SetDataObject(self._dataobject)
485
486
487 def OnData(self, x, y, dragres):
488 """ Handles The OnData() Method TO Call The Real DnD Routine. """
489
490 if not self.GetData():
491 return wx.DragNone
492
493 draginfo = self._dataobject.GetData()
494 drginfo = cPickle.loads(draginfo)
495
496 return self._parent.OnDropTarget(x, y, drginfo.GetPageIndex(), drginfo.GetContainer())
497
498
499 # ---------------------------------------------------------------------------- #
500 # Class ThemeStyle. Used To Define A Custom Style For Tabs And Control
501 # Background Colour.
502 # ---------------------------------------------------------------------------- #
503
504 class ThemeStyle:
505 """
506 Represent the style for rendering a notebook tab.
507 """
508
509 GRADIENT_VERTICAL = 1
510 GRADIENT_HORIZONTAL = 2
511 DIFFERENT_GRADIENT_FOR_SELECTED = 4
512
513 def __init__(self):
514 """ Default Constructor For This Class."""
515
516 self.ResetDefaults()
517
518
519 def ResetDefaults(self):
520 """ Resets Default Theme. """
521
522 self._normal = True
523 self._aqua = False
524 self._metal = False
525 self._macstyle = False
526 self._kdetheme = False
527 self._silver = False
528 self._gradient = False
529 self._firstcolour = wx.WHITE
530 self._secondcolour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)
531 self._firstcolourselected = wx.WHITE
532 self._secondcolourselected = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)
533
534
535 def EnableMacTheme(self, enable=True, style=1):
536 """
537 Enables/Disables Mac Themes. style=1 Is The Light Style, While style=2
538 Is The Dark Style. Mainly Used For Control Background Colour, Not For Tabs.
539 """
540
541 if enable:
542 self._normal = False
543 self._macstyle = style
544 self._kdetheme = False
545 self._metal = False
546 self._aqua = False
547 self._silver = False
548 self._gradient = False
549 else:
550 self._macstyle = 0
551
552
553 def EnableKDETheme(self, enable=True):
554 """ Globally Enables/Disables Unix-Like KDE Theme For Tabs. """
555
556 self._kdetheme = enable
557
558 if enable:
559 self._normal = False
560 self._macstyle = False
561 self._metal = False
562 self._aqua = False
563 self._silver = False
564 self._gradient = False
565
566
567 def EnableMetalTheme(self, enable=True):
568 """ Globally Enables/Disables Mac-Like Metal Theme For Tabs. """
569
570 self._metal = enable
571
572 if enable:
573 self._normal = False
574 self._macstyle = False
575 self._kdetheme = False
576 self._aqua = False
577 self._silver = False
578 self._gradient = False
579
580
581 def EnableAquaTheme(self, enable=True, style=1):
582 """ Globally Enables/Disables Mac-Like Aqua Theme For Tabs. """
583
584 if enable:
585 self._aqua = style
586 self._normal = False
587 self._macstyle = False
588 self._kdetheme = False
589 self._metal = False
590 self._silver = False
591 self._gradient = False
592 else:
593 self._aqua = 0
594
595
596 def EnableSilverTheme(self, enable=True):
597 """ Globally Enables/Disables Windows Silver Theme For Tabs. """
598
599 self._silver = enable
600
601 if enable:
602 self._normal = False
603 self._macstyle = False
604 self._kdetheme = False
605 self._metal = False
606 self._aqua = False
607 self._gradient = False
608
609
610 def EnableGradientStyle(self, enable=True, style=1):
611 """
612 Enables/Disables Gradient Drawing On Tabs. style=1 Is The Vertical Gradient,
613 While style=2 Is The Horizontal Gradient.
614 If style flag 4 is set, the style has a separate set of colors for the
615 selected tab.
616 """
617
618 if enable:
619 self._normal = False
620 if style & self.GRADIENT_VERTICAL == 0 and style & self.GRADIENT_HORIZONTAL == 0:
621 style |= self.GRADIENT_VERTICAL
622 self._gradient = style
623 self._macstyle = False
624 self._kdetheme = False
625 self._metal = False
626 self._aqua = False
627 self._silver = False
628 else:
629 self._gradient = 0
630
631
632 def SetFirstGradientColour(self, colour=None):
633 """ Sets The First Gradient Colour. """
634
635 if colour is None:
636 colour = wx.WHITE
637
638 self._firstcolour = colour
639
640 def SetFirstGradientColourSelected(self, colour=None):
641 """Sets The First Gradient Colour For The Selected Tab."""
642 if colour is None:
643 colour = wx.WHITE
644
645 self._firstcolourselected = colour
646
647 def SetSecondGradientColour(self, colour=None):
648 """ Sets The Second Gradient Colour. """
649
650 if colour is None:
651 color = self.GetBackgroundColour()
652 r, g, b = int(color.Red()), int(color.Green()), int(color.Blue())
653 color = ((r >> 1) + 20, (g >> 1) + 20, (b >> 1) + 20)
654 colour = wx.Colour(color[0], color[1], color[2])
655
656 self._secondcolour = colour
657
658 def SetSecondGradientColourSelected(self, colour=None):
659 """ Sets The Second Gradient Colour For The Selected Tab. """
660
661 if colour is None:
662 color = self.GetBackgroundColour()
663 r, g, b = int(color.Red()), int(color.Green()), int(color.Blue())
664 color = ((r >> 1) + 20, (g >> 1) + 20, (b >> 1) + 20)
665 colour = wx.Colour(color[0], color[1], color[2])
666
667 self._secondcolourselected = colour
668
669 def GetFirstGradientColour(self, selected=False):
670 """ Returns The First Gradient Colour. """
671
672 if selected and self._gradient & self.DIFFERENT_GRADIENT_FOR_SELECTED:
673 return self._firstcolourselected
674 else:
675 return self._firstcolour
676
677 def GetSecondGradientColour(self, selected=False):
678 """ Returns The Second Gradient Colour. """
679
680 if selected and self._gradient & self.DIFFERENT_GRADIENT_FOR_SELECTED:
681 return self._secondcolourselected
682 else:
683 return self._secondcolour
684
685
686 # ---------------------------------------------------------------------------- #
687 # Class TabbedPage
688 # This Is Just A Container Class That Initialize All The Default Settings For
689 # Every Tab.
690 # ---------------------------------------------------------------------------- #
691
692 class TabbedPage:
693
694 def __init__(self, text="", image=-1, hidden=False):
695 """ Default Class Constructor. """
696
697 self._text = text
698 self._image = image
699 self._font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
700 self._secondaryfont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
701 self._pagetextcolour = wx.BLACK
702 self._pagecolour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)
703 self._enable = True
704 self._animationimages = []
705 self._tooltip = ""
706 self._tooltiptime = 500
707 self._winsize = 400
708 self._menu = None
709 self._ishidden = hidden
710 self._firstcolour = color = wx.WHITE
711 r, g, b = int(color.Red()), int(color.Green()), int(color.Blue())
712 color = ((r >> 1) + 20, (g >> 1) + 20, (b >> 1) + 20)
713 colour = wx.Colour(color[0], color[1], color[2])
714 self._secondcolour = colour
715
716
717 # ---------------------------------------------------------------------------- #
718 # Class NotebookSpinButton
719 # This SpinButton Is Created/Shown Only When The Total Tabs Size Exceed The
720 # Client Size, Allowing The User To Navigate Between Tabs By Clicking On The
721 # SpinButton. It Is Very Similar To The wx.Notebook SpinButton
722 # ---------------------------------------------------------------------------- #
723
724 class NotebookSpinButton(wx.SpinButton):
725
726 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
727 size=wx.DefaultSize, style=wx.SP_HORIZONTAL):
728 """ Default Class Constructor. """
729
730 wx.SpinButton.__init__(self, parent, id, pos, size, style)
731 self._nb = parent
732 self._oldvalue = 0
733 self._style = style
734 self.Bind(wx.EVT_SPIN, self.OnSpin)
735
736 def GetValue(self):
737 result = super(NotebookSpinButton, self).GetValue()
738 if self._style & wx.SP_VERTICAL:
739 result = -result
740 return result
741
742 def OnSpin(self, event):
743 """ Handles The User's Clicks On The SpinButton. """
744
745 if type(event) != type(1):
746 pos = event.GetPosition()
747 else:
748 pos = event
749
750 if pos < self.GetMin():
751 self.SetValue(self.GetMin())
752 return
753
754 if type(event) != type(1):
755 if self._nb._enablehiding:
756 if pos < self._oldvalue:
757 incr = -1
758 else:
759 incr = 1
760 while self._nb._pages[pos]._ishidden:
761 pos = pos + incr
762
763 self.SetValue(pos)
764
765 if self._nb.IsLastVisible():
766 if (self._style & wx.SP_HORIZONTAL and self._oldvalue < pos) or \
767 (self._style & wx.SP_VERTICAL and self._oldvalue > pos):
768 self.SetValue(self._oldvalue)
769 return
770
771 self._oldvalue = pos
772
773 self._nb.Refresh()
774
775
776 # ---------------------------------------------------------------------------- #
777 # Class NotebookMenuButton
778 # This MenuButton Is Created/Shown Only When You Activate The Option EnableHiding
779 # Of NotebookCtrl. This Small Button Will Be Shown Right Above The Spin Button
780 # (If Present), Or In The Position Of The Spin Button.
781 # ---------------------------------------------------------------------------- #
782
783 class NotebookMenuButton(BitmapButton):
784
785 def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=(15, 11),
786 style=0):
787 """ Default Class Constructor. """
788
789 bmp = GetMenuButtonBitmap()
790
791 BitmapButton.__init__(self, parent, id, bmp, pos, size, style)
792
793 self.SetUseFocusIndicator(False)
794 self.SetBezelWidth(1)
795
796 self._originalcolour = self.GetBackgroundColour()
797 self._nb = parent
798
799 self.Bind(wx.EVT_BUTTON, self.OnButton)
800 self.Bind(wx.EVT_ENTER_WINDOW, self.OnEnterWindow)
801 self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
802 self.Bind(wx.EVT_MENU, self.OnMenu)
803
804
805 def OnButton(self, event):
806 """ Handles The wx.EVT_BUTTON For NotebookMenuButton (Opens The wx.PopupMenu) """
807
808 count = self._nb.GetPageCount()
809
810 if count <= 0:
811 return
812
813 menu = wx.Menu()
814 id = wx.NewId()
815 myids = []
816
817 for ii in xrange(count):
818
819 id = id + 1
820 myids.append(id)
821 name = self._nb.GetPageText(ii)
822
823 if self._nb._pages[ii]._ishidden:
824 msg = "Page Hidden"
825 check = False
826 else:
827 msg = "Page Shown"
828 check = True
829
830 item = wx.MenuItem(menu, id, name, msg, wx.ITEM_CHECK)
831 menu.AppendItem(item)
832
833 if not self._nb._pages[ii]._ishidden:
834 item.Check()
835
836 menu.SetHelpString(id, msg)
837
838 self._myids = myids
839
840 self.PopupMenu(menu)
841
842 event.Skip()
843
844
845 def OnMenu(self, event):
846 """ Handles The wx.EVT_MENU For NotebookMenuButton. Calls HideTab(). """
847
848 indx = self._myids.index(event.GetId())
849 checked = not event.GetEventObject().IsChecked(event.GetId())
850
851 self._nb.HideTab(indx, not checked)
852
853 event.Skip()
854
855
856 def OnEnterWindow(self, event):
857 """
858 Changes The NotebookMenuButton Background Colour When The Mouse
859 Enters The Button Region.
860 """
861
862 entercolour = self.GetBackgroundColour()
863 firstcolour = entercolour.Red()
864 secondcolour = entercolour.Green()
865 thirdcolour = entercolour.Blue()
866
867 if entercolour.Red() > 235:
868 firstcolour = entercolour.Red() - 40
869 if entercolour.Green() > 235:
870 secondcolour = entercolour.Green() - 40
871 if entercolour.Blue() > 235:
872 thirdcolour = entercolour.Blue() - 40
873
874 entercolour = wx.Colour(firstcolour+20, secondcolour+20, thirdcolour+20)
875
876 self.SetBackgroundColour(entercolour)
877 self.Refresh()
878
879 event.Skip()
880
881
882 def OnLeaveWindow(self, event):
883 """
884 Restore The NotebookMenuButton Background Colour When The Mouse
885 Leaves The Button Region.
886 """
887
888 self.SetBackgroundColour(self._originalcolour)
889 self.Refresh()
890
891 event.Skip()
892
893 class _TabCtrlPaintTools(object):
894 # Structure-like object for passing data among
895 # private rendering methods
896 def __init__(self, backBrush, backPen, borderPen, highlightPen,
897 shadowPen, upperHighlightPen, selectionPen, selectionEdgePen,
898 xPen, focusPen):
899 self.BackBrush = backBrush
900 self.BackPen = backPen
901 self.BorderPen = borderPen
902 self.HighlightPen = highlightPen
903 self.ShadowPen = shadowPen
904 self.UpperHighlightPen = upperHighlightPen
905 self.SelectionPen = selectionPen
906 self.SelectionEdgePen = selectionEdgePen
907 self.XPen = xPen
908 self.FocusPen = focusPen
909
910
911 # ---------------------------------------------------------------------------- #
912 # Class TabCtrl
913 # This Class Handles The Drawing Of Every Tab In The NotebookCtrl, And Also
914 # All Settings/Methods For Every Tab.
915 # ---------------------------------------------------------------------------- #
916
917 class TabCtrl(wx.PyControl):
918
919 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
920 size=DEFAULT_SIZE, style=NC_DEFAULT_STYLE,
921 validator=wx.DefaultValidator, name="TabCtrl"):
922 """
923 Default Class Constructor.
924 Used Internally. Do Not Call It Explicitely!
925 """
926
927 wx.PyControl.__init__(self, parent, id, pos, size, wx.NO_BORDER | wx.WANTS_CHARS,
928 validator, name)
929
930 # Set All The Default Parameters For TabCtrl
931 self._selection = -1
932 self._imglist = 0
933 self._style = style
934 self._expanded = False
935 self._pages = []
936 self._enabledpages = []
937
938 self._padding = wx.Point(8, 4)
939 self._spacetabs = 2
940 self._xrect = []
941 self._xrefreshed = False
942 self._imageconverted = False
943 self._convertimage = False
944 self._disabledcolour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_GRAYTEXT)
945
946 self._hover = False
947 self._parent = parent
948 self._firsttime = True
949 self._somethingchanged = True
950 self._isdragging = False
951 self._tabID = -1
952 self._enabledragging = False
953 self._olddragpos = -1
954 self._fromdnd = False
955 self._isleaving = False
956 self._highlight = False
957 self._usefocus = True
958 self._hideonsingletab = False
959 self._selectioncolour = wx.Colour(255, 200, 60)
960 self._selectionedgecolour = wx.Colour(230, 139, 44)
961
962 self._tabstyle = ThemeStyle()
963 self._backstyle = ThemeStyle()
964 self._selstyle = ThemeStyle()
965 self._usegradients = False
966
967 self._insidetab = -1
968 self._showtooltip = False
969 self._istooltipshown = False
970 self._tipwindow = None
971 self._tiptimer = wx.PyTimer(self.OnShowToolTip)
972 self._backtooltip = wx.Colour(255, 255, 230)
973 self._xvideo = wx.SystemSettings_GetMetric(wx.SYS_SCREEN_X)
974 self._yvideo = wx.SystemSettings_GetMetric(wx.SYS_SCREEN_Y)
975
976 self._selectedtabs = []
977
978 self._timers = []
979
980 self._dragcursor = wx.StockCursor(wx.CURSOR_HAND)
981 self._dragstartpos = wx.Point()
982
983 self._drawx = False
984 self._drawxstyle = 1
985
986 self._pmenu = None
987
988 self._enablehiding = False
989 if (style & NC_LEFT or style & NC_RIGHT) and style & NC_EXPANDABLE:
990 self._InitExpandableStyles(style)
991 self._InitExpandableTabStyles(self._style, self._expanded, self._tabstyle)
992 self._CreateSizeToggleButton()
993 else:
994 self._sizeToggleButton = None
995
996 self.SetDefaultPage()
997
998 if style & NC_TOP or style & NC_BOTTOM:
999 self.SetBestSize((-1, 28))
1000 self._firsttabpos = wx.Point(3, 0)
1001 else:
1002 self.SetBestSize((28, -1))
1003 self._firsttabpos = wx.Point(0, 3 + self._CalcSizeToggleBestSize()[1])
1004
1005 self._borderpen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
1006 self._highlightpen2 = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
1007 self._highlightpen = wx.Pen((145, 167, 180))
1008 self._upperhigh = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
1009 self._shadowpen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DDKSHADOW), 2)
1010 self._shadowpen.SetCap(wx.CAP_BUTT)
1011 self._highlightpen.SetCap(wx.CAP_BUTT)
1012 self._highlightpen2.SetCap(wx.CAP_BUTT)
1013
1014 if wx.Platform == "__WXMAC__":
1015 self._focusindpen = wx.Pen(wx.BLACK, 1, wx.SOLID)
1016 else:
1017 self._focusindpen = wx.Pen(wx.BLACK, 1, wx.USER_DASH)
1018 self._focusindpen.SetDashes([1,1])
1019 self._focusindpen.SetCap(wx.CAP_BUTT)
1020
1021 self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
1022 self.Bind(wx.EVT_LEFT_DCLICK, self.OnMouseLeftDClick)
1023 self.Bind(wx.EVT_MOTION, self.OnMouseMotion)
1024 self.Bind(wx.EVT_LEFT_UP, self.OnMouseLeftUp)
1025 self.Bind(wx.EVT_RIGHT_UP, self.OnMouseRightUp)
1026 self.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseRightDown)
1027 self.Bind(wx.EVT_MIDDLE_DOWN, self.OnMouseMiddleDown)
1028 self.Bind(wx.EVT_SIZE, self.OnSize)
1029
1030 self.Bind(wx.EVT_PAINT, self.OnPaint)
1031 self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
1032
1033 self.Bind(wx.EVT_TIMER, self.AnimateTab)
1034 self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
1035 self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
1036
1037 self._droptarget = NCDropTarget(self)
1038 self.SetDropTarget(self._droptarget)
1039
1040 def Contract(self):
1041 if self._style & NC_EXPANDABLE and self._expanded:
1042 self._ToggleSize()
1043
1044 def Expand(self):
1045 if self._style & NC_EXPANDABLE and not self._expanded:
1046 self._ToggleSize()
1047
1048 def _ToggleSize(self, event=None):
1049 if self._style & NC_EXPANDABLE and not self._expanded:
1050 # contract
1051 self._style = self._expandedstyle
1052 self._tabstyle = self._expandedtabstyle
1053 self._expanded = True
1054 self._sizeToggleButton.SetLabel("<<")
1055 elif self._style & NC_EXPANDABLE and self._expanded:
1056 # expand
1057 self._style = self._contractedstyle
1058 self._tabstyle = self._contractedtabstyle
1059 self._expanded = False
1060 self._sizeToggleButton.SetLabel(">>")
1061 self._OnStyleChange()
1062
1063
1064 def OnDropTarget(self, x, y, nPage, oldcont):
1065 """ Handles The OnDrop Action For Drag And Drop Between Different NotebookCtrl. """
1066
1067 where = self.HitTest(wx.Point(x, y))
1068
1069 oldNotebook = oldcont.GetParent()
1070 newNotebook = self.GetParent()
1071
1072 if oldNotebook == newNotebook:
1073 if where >= 0 and where != self._tabID:
1074
1075 self._isdragging = False
1076 self._olddragpos = -1
1077 eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_DND, self.GetId())
1078 eventOut.SetOldPosition(self._tabID)
1079 eventOut.SetNewPosition(where)
1080 eventOut.SetEventObject(self)
1081
1082 if self.GetEventHandler().ProcessEvent(eventOut):
1083 self._tabID = -1
1084 self._olddragpos = -1
1085 self.SetCursor(wx.STANDARD_CURSOR)
1086 self.Refresh()
1087 return
1088
1089 self._parent.Freeze()
1090
1091 try:
1092 text = self.GetPageText(self._tabID)
1093 image = self.GetPageImage(self._tabID)
1094 font1 = self.GetPageTextFont(self._tabID)
1095 font2 = self.GetPageTextSecondaryFont(self._tabID)
1096 fontcolour = self.GetPageTextColour(self._tabID)
1097 pagecolour = self.GetPageColour(self._tabID)
1098 enabled = self.IsPageEnabled(self._tabID)
1099 tooltip, ontime, winsize = self.GetPageToolTip(self._tabID)
1100 menu = self.GetPagePopupMenu(self._tabID)
1101 firstcol = self.GetPageFirstGradientColour(self._tabID)
1102 secondcol = self.GetPageSecondGradientColour(self._tabID)
1103 ishidden = self._pages[self._tabID]._ishidden
1104 except:
1105 self._parent.Thaw()
1106 self._tabID = -1
1107 self.SetCursor(wx.STANDARD_CURSOR)
1108 return
1109
1110 isanimated = 0
1111 if self._timers[self._tabID].IsRunning():
1112 isanimated = 1
1113 timer = self._timers[self._tabID].GetInterval()
1114
1115 self.StopAnimation(self._tabID)
1116 animatedimages = self.GetAnimationImages(self._tabID)
1117
1118 pagerange = range(self.GetPageCount())
1119
1120 newrange = pagerange[:]
1121 newrange.remove(self._tabID)
1122 newrange.insert(where, self._tabID)
1123
1124 newpages = []
1125 counter = self.GetPageCount() - 1
1126
1127 for ii in xrange(self.GetPageCount()):
1128 newpages.append(self._parent.GetPage(ii))
1129 self._parent.bsizer.Detach(counter-ii)
1130
1131 cc = 0
1132
1133 self._parent._notebookpages = []
1134
1135 for jj in newrange:
1136 self._parent.bsizer.Add(newpages[jj], 1, wx.EXPAND | wx.ALL, 2)
1137 self._parent.bsizer.Show(cc, False)
1138 self._parent._notebookpages.append(newpages[jj])
1139 cc = cc + 1
1140
1141 self.DeletePage(self._tabID)
1142
1143 if enabled:
1144 if id == self.GetPageCount():
1145 self.AddPage(text, True, image)
1146 else:
1147 self.InsertPage(where, text, True, image)
1148 else:
1149 if id == self.GetPageCount():
1150 self.AddPage(text, False, image)
1151 else:
1152 self.InsertPage(where, text, False, image)
1153
1154 self.SetPageImage(where, image)
1155 self.SetPageText(where, text)
1156 self.SetPageTextFont(where, font1)
1157 self.SetPageTextSecondaryFont(where, font2)
1158 self.SetPageTextColour(where, fontcolour)
1159 self.SetPageColour(where, pagecolour)
1160 self.EnablePage(where, enabled)
1161 self.SetPageToolTip(where, tooltip, ontime, winsize)
1162 self.SetPagePopupMenu(where, menu)
1163 self.SetPageFirstGradientColour(where, firstcol)
1164 self.SetPageSecondGradientColour(where, secondcol)
1165 self._pages[where]._ishidden = ishidden
1166
1167 if isanimated and len(animatedimages) > 1:
1168 self.SetAnimationImages(where, animatedimages)
1169 self.StartAnimation(where, timer)
1170
1171 if enabled:
1172 self._parent.bsizer.Show(where, True)
1173 else:
1174 sel = self.GetSelection()
1175
1176 if sel == -1:
1177 sel = 0
1178 self._parent.bsizer.Show(where, False)
1179 self._parent.SetSelection(sel)
1180 self._parent.bsizer.Show(sel, True)
1181
1182 self._parent.bsizer.Layout()
1183
1184 self._parent.Thaw()
1185
1186 self._isdragging = False
1187 self._olddragpos = -1
1188 self._fromdnd = True
1189 self.Refresh()
1190 self._tabID = -1
1191 self.SetCursor(wx.STANDARD_CURSOR)
1192
1193 return
1194
1195 if nPage >= 0 and where >= 0:
1196 panel = oldNotebook.GetPage(nPage)
1197
1198 if panel:
1199 eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_DND, oldNotebook.GetId())
1200 eventOut.SetOldPosition(nPage)
1201 eventOut.SetNewPosition(where)
1202 eventOut.SetEventObject(oldNotebook)
1203
1204 if oldNotebook.GetEventHandler().ProcessEvent(eventOut):
1205 oldNotebook.nb._tabID = -1
1206 oldNotebook.nb._olddragpos = -1
1207 oldNotebook.SetCursor(wx.STANDARD_CURSOR)
1208 oldNotebook.Refresh()
1209 return
1210
1211 oldNotebook.Freeze()
1212 infos = oldNotebook.GetPageInfo(nPage)
1213
1214 text = infos["text"]
1215 image = infos["image"]
1216 hidden = infos["ishidden"]
1217
1218 panel.Reparent(newNotebook)
1219 newNotebook.InsertPage(where, panel, text, True, image, hidden)
1220 newNotebook.SetPageInfo(where, infos)
1221
1222 oldNotebook.nb.DeletePage(nPage)
1223
1224 oldNotebook.bsizer.Detach(nPage)
1225 oldNotebook.bsizer.Layout()
1226 oldNotebook.sizer.Layout()
1227
1228 oldNotebook._notebookpages.pop(nPage)
1229
1230 oldNotebook.AdvanceSelection()
1231
1232 if oldNotebook.GetPageCount() == 0:
1233 if oldNotebook._style & NC_TOP:
1234 oldNotebook.sizer.Show(0, False)
1235 oldNotebook.sizer.Show(1, False)
1236 else:
1237 oldNotebook.sizer.Show(1, False)
1238 oldNotebook.sizer.Show(2, False)
1239
1240 oldNotebook.sizer.Layout()
1241
1242 oldNotebook.Thaw()
1243 newNotebook.Refresh()
1244
1245 return wx.DragMove
1246
1247 def OnLeaveWindow(self, event):
1248 """ Handles The wx.EVT_LEAVE_WINDOW Events For TabCtrl. """
1249
1250 if self._enabledragging:
1251 if self._isdragging:
1252
1253 page = self._parent.GetPage(self._tabID)
1254 draginfo = NCDragInfo(page, self._tabID)
1255 drginfo = cPickle.dumps(draginfo)
1256 dataobject = wx.CustomDataObject(wx.CustomDataFormat("NotebookCtrl"))
1257 dataobject.SetData(drginfo)
1258 dragSource = wx.DropSource(self)
1259 dragSource.SetData(dataobject)
1260 dragSource.DoDragDrop(wx.Drag_DefaultMove)
1261
1262 self._isleaving = True
1263 self.Refresh()
1264
1265 if self._istooltipshown:
1266 self._tipwindow.Destroy()
1267 self._istooltipshown = False
1268 self.Refresh()
1269
1270 event.Skip()
1271
1272
1273 def OnKeyDown(self, event):
1274 """
1275 Handles The wx.EVT_KEY_DOWN Event For TabCtrl. This Is Only Processed If
1276 The User Navigate Through Tabs With Ctrl-Tab Keyboard Navigation.
1277 """
1278
1279 if event.GetKeyCode == wx.WXK_TAB:
1280 if event.ControlDown():
1281 sel = self.GetSelection()
1282 if sel == self.GetPageCount() - 1:
1283 sel = 0
1284 else:
1285 sel = sel + 1
1286
1287 while not self.IsPageEnabled(sel):
1288 sel = sel + 1
1289 if sel == self.GetPageCount() - 1:
1290 sel = 0
1291
1292 self._parent.SetSelection(sel)
1293
1294 event.Skip()
1295
1296
1297 def AddPage(self, text, select=False, img=-1, hidden=False):
1298 """
1299 Add A Page To The Notebook.
1300
1301 @param text: The Tab Text;
1302 @param select: Whether The Page Should Be Selected Or Not;
1303 @param img: Specifies The Optional Image Index For The New Page.
1304 """
1305
1306 self._pages.append(TabbedPage(text, img, hidden))
1307 self._somethingchanged = True
1308
1309 self._firsttime = True
1310 self._timers.append(wx.Timer(self))
1311
1312 # JS: The following two lines caused this control not to fire
1313 # the EVT_NOTEBOOKCTRL_PAGE_CHANGING/CHANGED events for the
1314 # first page. The NotebookCtrl sets the selection later anyway,
1315 # and without these two lines, the events fire.
1316 ## if select or self.GetSelection() == -1:
1317 ## self._selection = self.GetPageCount() - 1
1318
1319 if self._style & NC_LEFT or self._style & NC_RIGHT:
1320 self.SetBestSize((self._CalcBestWidth(wx.ClientDC(self)), -1))
1321
1322 self.Refresh()
1323
1324
1325 def InsertPage(self, nPage, text, select=False, img=-1, hidden=False):
1326 """
1327 Insert A Page Into The Notebook.
1328
1329 @param nPage: Specifies The Position For The New Page;
1330 @param text: The Tab Text;
1331 @param select: Whether The Page Should Be Selected Or Not;
1332 @param img: Specifies The Optional Image Index For The New Page.
1333 """
1334
1335 if nPage < 0 or (self.GetSelection() >= 0 and nPage >= self.GetPageCount()):
1336 raise "\nERROR: Invalid Notebook Page In InsertPage: (" + str(nPage) + ")"
1337
1338 oldselection = self.GetSelection()
1339
1340 self._pages.insert(nPage, TabbedPage(text, img, hidden))
1341 self._timers.insert(nPage, wx.Timer(self))
1342
1343 self._somethingchanged = True
1344 self._firsttime = True
1345
1346 if select or self.GetSelection() == -1:
1347 self._selection = nPage
1348 self.SetSelection(nPage)
1349 else:
1350 if nPage <= oldselection:
1351 self._selection = self._selection + 1
1352
1353 if self._style & NC_LEFT or self._style & NC_RIGHT:
1354 self.SetBestSize((self._CalcBestWidth(wx.ClientDC(self)), -1))
1355
1356 self.Refresh()
1357
1358
1359 def DeleteAllPages(self):
1360 """ Deletes All NotebookCtrl Pages. """
1361
1362 for tims in self._timers:
1363 if tims.IsRunning():
1364 tims.Stop()
1365
1366 tims.Destroy()
1367
1368 self._timers = []
1369 self._pages = []
1370 self._selection = -1
1371 self._somethingchanged = True
1372 self._firsttime = True
1373 self.Refresh()
1374
1375
1376 def DeletePage(self, nPage, oncontinue=True):
1377 """ Deletes The Page nPage, And The Associated Window. """
1378
1379 if nPage < 0 or nPage >= self.GetPageCount():
1380 raise "\nERROR: Invalid Notebook Page In DeletePage: (" + str(nPage) + ")"
1381
1382 oldselection = self.GetSelection()
1383
1384 self._pages.pop(nPage)
1385
1386 if self._timers[nPage].IsRunning():
1387 self._timers[nPage].Stop()
1388
1389 self._timers[nPage].Destroy()
1390
1391 if self._istooltipshown:
1392 self._tipwindow.Destroy()
1393 self._istooltipshown = False
1394
1395 if not oncontinue:
1396 self._somethingchanged = True
1397 self._firsttime = True
1398 self.Refresh()
1399 return
1400
1401 if nPage < self._selection:
1402 self._selection = self._selection - 1
1403 elif self._selection == nPage and self._selection == self.GetPageCount():
1404 self._selection = self._selection - 1
1405 else:
1406 self._selection = oldselection
1407
1408 self._somethingchanged = True
1409 self._firsttime = True
1410 self.Refresh()
1411
1412
1413 def SetSelection(self, nPage):
1414 """
1415 Sets The Current Tab Selection To The Given nPage. This Call Generates The
1416 EVT_NOTEBOOKCTRL_PAGE_CHANGING Event.
1417 """
1418
1419 if nPage < 0 or nPage >= self.GetPageCount():
1420 raise "\nERROR: Invalid Notebook Page In SetSelection: (" + str(nPage) + ")"
1421
1422 oldselection = self._selection
1423
1424 if nPage != self._selection:
1425
1426 if not self.IsPageEnabled(nPage):
1427 return
1428
1429 eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_CHANGING, self.GetId())
1430 eventOut.SetSelection(nPage)
1431 eventOut.SetOldSelection(self._selection)
1432 eventOut.SetEventObject(self)
1433
1434 if not self.GetEventHandler().ProcessEvent(eventOut):
1435
1436 # Prevent full paint unless never fully painted
1437 if hasattr(self, "_initrect"):
1438 self._firsttime = False
1439 # Program Allows The Page Change
1440 self._selection = nPage
1441 eventOut.SetEventType(wxEVT_NOTEBOOKCTRL_PAGE_CHANGED)
1442 eventOut.SetOldSelection(self._selection)
1443 self.GetEventHandler().ProcessEvent(eventOut)
1444
1445 if oldselection != -1:
1446 self._parent.bsizer.Show(oldselection, False)
1447
1448 self.EnsureVisible(self._selection)
1449 self._parent.bsizer.Show(self._selection, True)
1450 self._parent.bsizer.Layout()
1451
1452 self.Refresh()
1453
1454 self._shown = nPage
1455
1456
1457 def EnsureVisible(self, selection):
1458
1459 if self.GetPageCount() < 2:
1460 return
1461
1462 if not self.HasSpinButton():
1463 return
1464
1465 fullrect = self.GetClientSize()
1466 count = self._tabvisible[0:selection].count(0)
1467 currect = self._tabrect[selection-self._firstvisible-count]
1468
1469 spinval = self._spinbutton.GetValue()
1470 firstrect = self._initrect[spinval]
1471 if self._style & NC_LEFT or self._style & NC_RIGHT:
1472 pos = currect.y
1473 size = currect.height
1474 posIndex = 1
1475 else:
1476 pos = currect.x
1477 size = currect.width
1478 posIndex = 0
1479 torefresh = 0
1480
1481 while pos + size > fullrect[posIndex] - self._spinbutton.GetSize()[posIndex]:
1482
1483 if self._style & NC_LEFT or self._style & NC_RIGHT:
1484 pos -= firstrect.height
1485 else:
1486 pos -= firstrect.width
1487
1488 if not self._enablehiding:
1489 spinval = spinval + 1
1490 else:
1491 oldspinval = spinval
1492 spinval = spinval + self._tabvisible[0:selection].count(0)
1493 if spinval == oldspinval:
1494 spinval = spinval + 1
1495
1496 if spinval >= len(self._initrect):
1497 spinval = spinval - 1
1498
1499 firstrect = self._initrect[spinval]
1500
1501 if self._style & NC_LEFT or self._style & NC_RIGHT:
1502 self._spinbutton.OnSpin(-spinval)
1503 self._spinbutton.SetValue(-spinval)
1504 else:
1505 self._spinbutton.OnSpin(spinval)
1506 self._spinbutton.SetValue(spinval)
1507
1508 torefresh = 1
1509
1510 if torefresh:
1511 self.Refresh()
1512
1513
1514 def GetPageCount(self):
1515 """ Returns The Number Of Pages In NotebookCtrl. """
1516
1517 return len(self._pages)
1518
1519
1520 def GetSelection(self):
1521 """ Returns The Current Selection. """
1522
1523 return self._selection
1524
1525
1526 def GetImageList(self):
1527 """ Returns The Image List Associated With The NotebookCtrl. """
1528
1529 return self._imglist
1530
1531
1532 def SetImageList(self, imagelist):
1533 """ Associate An Image List To NotebookCtrl. """
1534
1535 self._imglist = imagelist
1536 self._grayedlist = wx.ImageList(16, 16, True, 0)
1537
1538 for ii in xrange(imagelist.GetImageCount()):
1539
1540 bmp = imagelist.GetBitmap(ii)
1541 image = wx.ImageFromBitmap(bmp)
1542 image = GrayOut(image)
1543 newbmp = wx.BitmapFromImage(image)
1544 self._grayedlist.Add(newbmp)
1545
1546
1547 def AssignImageList(self, imagelist):
1548 """ Associate An Image List To NotebookCtrl. """
1549
1550 self._imglist = imagelist
1551 self._grayedlist = wx.ImageList(16, 16, True, 0)
1552
1553 for ii in xrange(imagelist.GetImageCount()):
1554
1555 bmp = imagelist.GetBitmap(ii)
1556 image = wx.ImageFromBitmap(bmp)
1557 image = GrayOut(image)
1558 newbmp = wx.BitmapFromImage(image)
1559 self._grayedlist.Add(newbmp)
1560
1561
1562 def GetPadding(self):
1563 """ Returns The (Horizontal, Vertical) Padding Of The Text Inside Tabs. """
1564
1565 return self._padding
1566
1567
1568 def SetPadding(self, padding):
1569 """ Sets The (Horizontal, Vertical) Padding Of The Text Inside Tabs. """
1570
1571 self._padding = padding
1572 self._somethingchanged = True
1573 self._firsttime = True
1574 self.Refresh()
1575
1576
1577 def GetPageText(self, nPage):
1578 """ Returns The String For The Given Page nPage. """
1579
1580 if nPage < 0 or nPage >= self.GetPageCount():
1581 raise "\nERROR: Invalid Notebook Page In GetPageText: (" + str(nPage) + ")"
1582
1583 return self._pages[nPage]._text
1584
1585
1586 def SetPageText(self, nPage, text):
1587 """ Sets The String For The Given Page nPage. """
1588
1589 if nPage < 0 or nPage >= self.GetPageCount():
1590 raise "\nERROR: Invalid Notebook Page In SetPageText: (" + str(nPage) + ")"
1591
1592 if self._pages[nPage]._text != text:
1593 self._pages[nPage]._text = text
1594 self._somethingchanged = True
1595 self._firsttime = True
1596 self.Refresh()
1597
1598
1599 def GetPageImage(self, nPage):
1600 """ Returns The Image Index For The Given Page nPage. """
1601
1602 if nPage < 0 or nPage >= self.GetPageCount():
1603 raise "\nERROR: Invalid Notebook Page In GetPageImage: (" + str(nPage) + ")"
1604
1605 return self._pages[nPage]._image
1606
1607
1608 def SetPageImage(self, nPage, img):
1609 """ Sets The Image Index For The Given Page nPage. """
1610
1611 if nPage < 0 or nPage >= self.GetPageCount():
1612 raise "\nERROR: Invalid Notebook Page In SetPageImage: (" + str(nPage) + ")"
1613
1614 if self._pages[nPage]._image != img:
1615 self._pages[nPage]._image = img
1616 self._somethingchanged = True
1617 self._firsttime = True
1618
1619 if self._style & NC_LEFT or self._style & NC_RIGHT:
1620 self.SetBestSize((self._CalcBestWidth(wx.ClientDC(self)), -1))
1621 self._parent.GetSizer().Layout()
1622
1623 self.Refresh()
1624
1625
1626 def SetPageTextFont(self, nPage, font=None):
1627 """ Sets The Primary Font For The Given Page nPage. """
1628
1629 if nPage < 0 or nPage >= self.GetPageCount():
1630 raise "\nERROR: Invalid Notebook Page In SetPageTextFont: (" + str(nPage) + ")"
1631
1632 if font is None:
1633 font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
1634
1635 normalfont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
1636
1637 self._pages[nPage]._font = font
1638
1639 if font == normalfont:
1640 self._parent.GetSizer().Layout()
1641 self._somethingchanged = True
1642 self._firsttime = True
1643 self.Refresh()
1644 return
1645
1646 dc = wx.ClientDC(self)
1647 dc.SetFont(font)
1648 w1, h1 = dc.GetTextExtent("Aq")
1649 dc.SetFont(normalfont)
1650 wn, hn = dc.GetTextExtent("Aq")
1651 w2, h2 = (0, 0)
1652
1653 if hasattr(self._pages[nPage], "_secondaryfont"):
1654 dc.SetFont(self._pages[nPage]._secondaryfont)
1655 w2, h2 = dc.GetTextExtent("Aq")
1656
1657 h = max(h1, h2)
1658
1659 if h < hn:
1660 self._somethingchanged = True
1661 self._firsttime = True
1662 self.Refresh()
1663 return
1664
1665 if h + 2*self._padding.y < 24:
1666 newheight = 24
1667 else:
1668 newheight = h + 2*self._padding.y
1669
1670 oldsize = self.GetSize()
1671
1672 if newheight < oldsize[1]:
1673 newheight = oldsize[1]
1674
1675 if self._style & NC_TOP or self._style & NC_BOTTOM:
1676 self.SetBestSize((-1, newheight))
1677 else:
1678 self.SetBestSize((self._CalcBestWidth(dc), -1))
1679 self._parent.GetSizer().Layout()
1680 self._somethingchanged = True
1681 self._firsttime = True
1682 self.Refresh()
1683
1684 def SetTabHeight(self, height=28):
1685 """ Sets The Tabs Height. """
1686
1687 if self._style & NC_TOP or self._style & NC_BOTTOM:
1688 self.SetBestSize((-1, height))
1689 self._bestsize = height
1690
1691
1692 def SetControlBackgroundColour(self, colour=None):
1693 """ Sets The TabCtrl Background Colour (Behind The Tabs). """
1694
1695 if colour is None:
1696 colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
1697
1698 self.SetBackgroundColour(colour)
1699 self.Refresh()
1700
1701
1702 def GetPageTextFont(self, nPage):
1703 """ Returns The Primary Font For The Given Page nPage. """
1704
1705 if nPage < 0 or nPage >= self.GetPageCount():
1706 raise "\nERROR: Invalid Notebook Page In GetPageTextFont: (" + str(nPage) + ")"
1707
1708 return self._pages[nPage]._font
1709
1710
1711 def SetPageTextSecondaryFont(self, nPage, font=None):
1712 """ Sets The Secondary Font For The Given Page nPage. """
1713
1714 if nPage < 0 or nPage >= self.GetPageCount():
1715 raise "\nERROR: Invalid Notebook Page In SetPageTextSecondaryFont: (" + str(nPage) + ")"
1716
1717 if font is None:
1718 font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
1719
1720 normalfont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
1721
1722 self._pages[nPage]._secondaryfont = font
1723
1724 if font == normalfont:
1725 self._somethingchanged = True
1726 self._firsttime = True
1727 self.Refresh()
1728 return
1729
1730 dc = wx.ClientDC(self)
1731 dc.SetFont(font)
1732 w1, h1 = dc.GetTextExtent("Aq")
1733 dc.SetFont(normalfont)
1734 wn, hn = dc.GetTextExtent("Aq")
1735 w2, h2 = (0, 0)
1736
1737 if hasattr(self._pages[nPage], "_font"):
1738 dc.SetFont(self._pages[nPage]._font)
1739 w2, h2 = dc.GetTextExtent("Aq")
1740
1741 h = max(h1, h2)
1742
1743 if h < hn:
1744 self._somethingchanged = True
1745 self._firsttime = True
1746 self.Refresh()
1747 return
1748
1749 if h + 2*self._padding.y < 24:
1750 newheight = 24
1751 else:
1752 newheight = h + 2*self._padding.y
1753
1754 oldsize = self.GetSize()
1755
1756 if newheight < oldsize[-1]:
1757 newheight = oldsize[-1]
1758
1759 if self._style & NC_TOP or self._style & NC_BOTTOM:
1760 self.SetBestSize((-1, newheight))
1761 else:
1762 self.SetBestSize((self._CalcBestWidth(dc), -1))
1763 self._parent.GetSizer().Layout()
1764
1765 self._somethingchanged = True
1766 self._firsttime = True
1767 self.Refresh()
1768
1769
1770 def GetPageTextSecondaryFont(self, nPage):
1771 """ Returns The Secondary Font For The Given Page nPage. """
1772
1773 if nPage < 0 or nPage >= self.GetPageCount():
1774 raise "\nERROR: Invalid Notebook Page In GetPageTextSecondaryFont: (" + str(nPage) + ")"
1775
1776 return self._pages[nPage]._secondaryfont
1777
1778
1779 def SetPageTextColour(self, nPage, colour=None):
1780 """ Sets The Text Colour For The Given Page nPage. """
1781
1782 if nPage < 0 or nPage >= self.GetPageCount():
1783 raise "\nERROR: Invalid Notebook Page In SetPageTextColour: (" + str(nPage) + ")"
1784
1785 if colour is None:
1786 colour = wx.BLACK
1787
1788 self._pages[nPage]._pagetextcolour = colour
1789 self._somethingchanged = True
1790 self.Refresh()
1791
1792
1793 def GetPageTextColour(self, nPage):
1794 """ Returns The Text Colour For The Given Page nPage. """
1795
1796 if nPage < 0 or nPage >= self.GetPageCount():
1797 raise "\nERROR: Invalid Notebook Page In GetPageTextColour: (" + str(nPage) + ")"
1798
1799 return self._pages[nPage]._pagetextcolour
1800
1801
1802 def SetPageColour(self, nPage, colour=None):
1803 """ Sets The Tab Background Colour For The Given Page nPage. """
1804
1805 if nPage < 0 or nPage >= self.GetPageCount():
1806 raise "\nERROR: Invalid Notebook Page In SetPageColour: (" + str(nPage) + ")"
1807
1808 if colour is None:
1809 colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)
1810
1811 self._pages[nPage]._pagecolour = colour
1812 self._somethingchanged = True
1813 self.Refresh()
1814
1815
1816 def GetPageColour(self, nPage):
1817 """ Returns The Tab Background Colour For The Given Page nPage. """
1818
1819 if nPage < 0 or nPage >= self.GetPageCount():
1820 raise "\nERROR: Invalid Notebook Page In GetPageColour: (" + str(nPage) + ")"
1821
1822 if not self._tabstyle._normal or self._usegradients:
1823 if self._usegradients:
1824 return self._tabstyle._firstcolour
1825 else:
1826 return self._GetThemePageColour(nPage)
1827 else:
1828 return self._pages[nPage]._pagecolour
1829
1830
1831 def EnablePage(self, nPage, enable=True):
1832 """ Enable/Disable The Given Page nPage. """
1833
1834 if nPage < 0 or nPage >= self.GetPageCount():
1835 raise "\nERROR: Invalid Notebook Page In EnablePage: (" + str(nPage) + ")"
1836
1837 self._pages[nPage]._enable = enable
1838
1839 if not enable and self.GetSelection() == nPage:
1840 defpage = self.GetDefaultPage()
1841 if defpage < 0:
1842 self.AdvanceSelection()
1843 else:
1844 if defpage >= self.GetPageCount():
1845 self.AdvanceSelection()
1846 else:
1847 if defpage == nPage:
1848 self.AdvanceSelection()
1849 else:
1850 self.SetSelection(defpage)
1851
1852 self.Refresh()
1853
1854
1855 def IsPageEnabled(self, nPage):
1856 """ Returns Whether A Page Is Enabled Or Not. """
1857
1858 if nPage < 0 or nPage >= self.GetPageCount():
1859 raise "\nERROR: Invalid Notebook Page In IsPageEnabled: (" + str(nPage) + ")"
1860
1861 return self._pages[nPage]._enable
1862
1863
1864 def SetHighlightSelection(self, highlight=True):
1865 """ Globally Enables/Disables Tab Highlighting On Tab Selection. """
1866
1867 self._highlight = highlight
1868 self.Refresh()
1869
1870
1871 def GetHighlightSelection(self):
1872 """ Returns Globally Enable/Disable State For Tab Highlighting On Tab Selection. """
1873
1874 return self._highlight
1875
1876
1877 def SetUseFocusIndicator(self, focus=True):
1878 """ Globally Enables/Disables Tab Focus Indicator. """
1879
1880 self._usefocus = focus
1881 self.Refresh()
1882
1883
1884 def GetUseFocusIndicator(self):
1885 """ Returns Globally Enable/Disable State For Tab Focus Indicator. """
1886
1887 return self._usefocus
1888
1889
1890 def SetPageToolTip(self, nPage, tooltip="", timer=500, winsize=400):
1891 """
1892 Sets A ToolTip For The Given Page nPage.
1893
1894 @param nPage: The Given Page;
1895 @param tooltip: The ToolTip String;
1896 @param timer: The Timer After Which The Tip Window Is Popped Up;
1897 @param winsize: The Maximum Width Of The Tip Window.
1898 """
1899
1900 if nPage < 0 or nPage >= self.GetPageCount():
1901 raise "\nERROR: Invalid Notebook Page In SetPageToolTip: (" + str(nPage) + ")"
1902
1903 self._pages[nPage]._tooltip = tooltip
1904 self._pages[nPage]._tooltiptime = timer
1905 self._pages[nPage]._winsize = winsize
1906
1907
1908 def GetPageToolTip(self, nPage):
1909 """ Returns A Tuple With All Page ToolTip Parameters. """
1910
1911 if nPage < 0 or nPage >= self.GetPageCount():
1912 raise "\nERROR: Invalid Notebook Page In GetPageToolTip: (" + str(nPage) + ")"
1913
1914 return self._pages[nPage]._tooltip, self._pages[nPage]._tooltiptime, \
1915 self._pages[nPage]._winsize
1916
1917
1918 def EnableToolTip(self, show=True):
1919 """ Globally Enables/Disables Tab ToolTips. """
1920
1921 self._showtooltip = show
1922
1923 if show:
1924 try:
1925 wx.PopupWindow(self)
1926 self.TransientTipWindow = TransientTipWindow
1927
1928 except NotImplementedError:
1929
1930 self.TransientTipWindow = macTransientTipWindow
1931
1932 else:
1933 if self._istooltipshown:
1934 self._tipwindow.Destroy()
1935 self._istooltipshown = False
1936 self.Refresh()
1937
1938 if self._tiptimer.IsRunning():
1939 self._tiptimer.Stop()
1940
1941
1942 def GetToolTipBackgroundColour(self):
1943 """ Returns The ToolTip Window Background Colour. """
1944
1945 return self._backtooltip
1946
1947
1948 def SetToolTipBackgroundColour(self, colour=None):
1949 """ Sets The ToolTip Window Background Colour. """
1950
1951 if colour is None:
1952 colour = wx.Colour(255, 255, 230)
1953
1954 self._backtooltip = colour
1955
1956
1957 def EnableTabGradients(self, enable=True):
1958 """ Globally Enables/Disables Drawing Of Gradient Coloured Tabs For Each Tab. """
1959
1960 self._usegradients = enable
1961
1962 if enable:
1963 self._tabstyle.ResetDefaults()
1964 self._selstyle.ResetDefaults()
1965
1966 self.Refresh()
1967
1968
1969 def SetPageFirstGradientColour(self, nPage, colour=None):
1970 """ Sets The Single Tab First Gradient Colour. """
1971
1972 if nPage < 0 or nPage >= self.GetPageCount():
1973 raise "\nERROR: Invalid Notebook Page In SetPageFirstGradientColour: (" + str(nPage) + ")"
1974
1975 if colour is None:
1976 colour = wx.WHITE
1977
1978 self._pages[nPage]._firstcolour = colour
1979 self.Refresh()
1980
1981
1982 def SetPageSecondGradientColour(self, nPage, colour=None):
1983 """ Sets The Single Tab Second Gradient Colour. """
1984
1985 if nPage < 0 or nPage >= self.GetPageCount():
1986 raise "\nERROR: Invalid Notebook Page In SetPageSecondGradientColour: (" + str(nPage) + ")"
1987
1988 if colour is None:
1989 color = self._pages[nPage]._firstcolour
1990 r, g, b = int(color.Red()), int(color.Green()), int(color.Blue())
1991 color = ((r >> 1) + 20, (g >> 1) + 20, (b >> 1) + 20)
1992 colour = wx.Colour(color[0], color[1], color[2])
1993
1994 self._pages[nPage]._secondcolour = colour
1995 self.Refresh()
1996
1997
1998 def GetPageFirstGradientColour(self, nPage):
1999 """ Returns The Single Tab First Gradient Colour. """
2000
2001 if nPage < 0 or nPage >= self.GetPageCount():
2002 raise "\nERROR: Invalid Notebook Page In GetPageFirstGradientColour: (" + str(nPage) + ")"
2003
2004 return self._pages[nPage]._firstcolour
2005
2006
2007 def GetPageSecondGradientColour(self, nPage):
2008 """ Returns The Single Tab Second Gradient Colour. """
2009
2010 if nPage < 0 or nPage >= self.GetPageCount():
2011 raise "\nERROR: Invalid Notebook Page In GetPageSecondGradientColour: (" + str(nPage) + ")"
2012
2013 return self._pages[nPage]._secondcolour
2014
2015
2016 def CancelTip(self):
2017 """ Destroys The Tip Window (Probably You Won't Need This One). """
2018
2019 if self._istooltipshown:
2020 self._istooltipshown = False
2021 self._tipwindow.Destroy()
2022 self.Refresh()
2023
2024
2025 def AdvanceSelection(self, forward=True):
2026 """
2027 Cycles Through The Tabs. The Call To This Function Generates The
2028 EVT_NOTEBOOKCTRL_PAGE_CHANGING Event.
2029 """
2030
2031 if self.GetPageCount() <= 1:
2032 return
2033
2034 sel = self.GetSelection()
2035 count = 0
2036
2037 if forward:
2038 if sel == self.GetPageCount() - 1:
2039 sel = 0
2040 else:
2041 sel = sel + 1
2042
2043 while not self.IsPageEnabled(sel) or \
2044 (self._enablehiding and self._pages[sel]._ishidden):
2045
2046 count = count + 1
2047 sel = sel + 1
2048
2049 if self._enablehiding and self._pages[sel]._ishidden:
2050 count = count + 1
2051 sel = sel + 1
2052
2053 if sel == self.GetPageCount() - 1:
2054 sel = 0
2055
2056 if count > self.GetPageCount() + 1:
2057 return None
2058
2059 else:
2060 if sel == 0:
2061 sel = self.GetPageCount() - 1
2062 else:
2063 sel = sel - 1
2064
2065 while not self.IsPageEnabled(sel):
2066 count = count + 1
2067 sel = sel - 1
2068 if sel == 0:
2069 sel = self.GetPageCount() - 1
2070
2071 if count > self.GetPageCount() + 1:
2072 return None
2073
2074 self._parent.SetSelection(sel)
2075
2076
2077 def SetDefaultPage(self, defaultpage=-1):
2078 """
2079 Sets The Default Page That Will Be Selected When An Active And Selected
2080 Tab Is Made Inactive.
2081 """
2082
2083 if defaultpage >= self.GetPageCount():
2084 raise "\nERROR: Invalid Notebook Page In SetDefaultPage: (" + str(defaultpage) + ")"
2085
2086 self._defaultpage = defaultpage
2087
2088
2089 def GetDefaultPage(self):
2090 """ Returns The Default Page. """
2091
2092 return self._defaultpage
2093
2094
2095 def UpdateSpinButton(self):
2096 """ Update The NotebookSpinButton. Used Internally. """
2097
2098 count = self.GetPageCount()
2099
2100 if count == 0:
2101 return
2102
2103 nbsize = []
2104 nbsize.append(self._initrect[-1][0] + self._initrect[-1][2])
2105 nbsize.append(self._initrect[-1][1] + self._initrect[-1][3])
2106 clsize = self.GetClientSize()
2107
2108 if self._style & NC_TOP or self._style & NC_BOTTOM:
2109 spinstyle = wx.SP_HORIZONTAL
2110 showspin = nbsize[0] > clsize[0]
2111 else:
2112 spinstyle = wx.SP_VERTICAL
2113 showspin = nbsize[1] > clsize[1]
2114
2115 if showspin:
2116 if not hasattr(self, "_spinbutton"):
2117 self._spinbutton = NotebookSpinButton(self, pos=(10000,10000),
2118 style=spinstyle)
2119 self._spinbutton.SetValue(0)
2120 self._originalspinsize = self._spinbutton.GetSize()
2121
2122 sbsize = self._spinbutton.GetSize()
2123 if self._style & NC_LEFT or self._style & NC_RIGHT:
2124 ypos = clsize[1] - sbsize[1]
2125 if self._style & NC_LEFT:
2126 xpos = nbsize[0] - (2 + sbsize[0])
2127 else:
2128 xpos = 2
2129 else:
2130 xpos = clsize[0] - sbsize[0]
2131 if self._style & NC_BOTTOM:
2132 ypos = 2
2133 else:
2134 ypos = clsize[1] - sbsize[1]
2135
2136 if self.HasMenuButton():
2137 self._spinbutton.SetSize((-1, 16))
2138 else:
2139 self._spinbutton.SetSize(self._originalspinsize)
2140
2141 self._spinbutton.Move((xpos, ypos))
2142 self._spinbutton.Show()
2143 if self._style & NC_LEFT or self._style & NC_RIGHT:
2144 self._spinbutton.SetRange(-(count-1), 0)
2145 else:
2146 self._spinbutton.SetRange(0, count-1)
2147
2148 else:
2149
2150 if hasattr(self, "_spinbutton") and self._spinbutton.IsShown():
2151 self._spinbutton.Hide()
2152 self._spinbutton.SetValue(0)
2153
2154
2155 def HasSpinButton(self):
2156 """ Returns Wheter The NotebookSpinButton Exists And Is Shown. """
2157
2158 return hasattr(self, "_spinbutton") and self._spinbutton.IsShown()
2159
2160
2161 def IsLastVisible(self):
2162 """ Returns Whether The Last Tab Is Visible Or Not. """
2163
2164 if self.HasSpinButton():
2165 if self._style & NC_LEFT or self._style & NC_RIGHT:
2166 pos, size = (1, 3)
2167 else:
2168 pos, size = (0, 2)
2169 lastpos = self._tabrect[-1][pos] + self._tabrect[-1][size]
2170 if lastpos < self._spinbutton.GetPosition()[pos]:
2171 return True
2172
2173 return False
2174
2175
2176 def UpdateMenuButton(self, show):
2177 """ Updates The Notebook Menu Button To Show/Hide Tabs. Used Internally. """
2178
2179 count = self.GetPageCount()
2180
2181 if count == 0:
2182 return
2183
2184 if not hasattr(self, "_initrect"):
2185 return
2186
2187 if not show and not hasattr(self, "_menubutton"):
2188 return
2189
2190 if not hasattr(self, "_menubutton"):
2191 self._menubutton = NotebookMenuButton(self, pos=(10000,10000))
2192
2193 sbsize = self._menubutton.GetSize()
2194 nbsize = []
2195 nbsize.append(self._initrect[-1][0] + self._initrect[-1][2])
2196 nbsize.append(self._initrect[-1][1] + self._initrect[-1][3])
2197 clsize = self.GetClientSize()
2198
2199 xpos = clsize[0] - sbsize[0]
2200 ypos = clsize[1] - sbsize[1]
2201
2202 if self.HasSpinButton():
2203 self._menubutton.Move((xpos-1, ypos-16))
2204 else:
2205 self._menubutton.Move((xpos-1, ypos-1))
2206
2207 self._menubutton.Show(show)
2208
2209
2210 def HasMenuButton(self):
2211 """ Returns Wheter The NotebookMenuButton Exists And Is Shown. """
2212
2213 return hasattr(self, "_menubutton") and self._menubutton.IsShown()
2214
2215
2216 def HideTab(self, nPage, hide=True):
2217 """ Hides A Tab In The NotebookCtrl. """
2218
2219 if hide:
2220 self._pages[nPage]._ishidden = True
2221 else:
2222 self._pages[nPage]._ishidden = False
2223
2224 if nPage == self.GetSelection():
2225 self.AdvanceSelection()
2226
2227 self._firsttime = True
2228 self.Refresh()
2229
2230
2231 def HitTest(self, point, flags=0):
2232 """
2233 Standard NotebookCtrl HitTest() Method. If Called With 2 Outputs, It
2234 Returns The Page Clicked (If Any) And One Of These Flags:
2235
2236 NC_HITTEST_NOWHERE = 0 ==> Hit Not On Tab
2237 NC_HITTEST_ONICON = 1 ==> Hit On Icon
2238 NC_HITTEST_ONLABEL = 2 ==> Hit On Label
2239 NC_HITTEST_ONITEM = 4 ==> Hit Generic, On Item
2240 NC_HITTEST_ONX = 8 ==> Hit On Closing "X" On Every Page
2241 """
2242
2243 mirror = self._style & NC_BOTTOM
2244 size = self.GetSize()
2245 dc = wx.ClientDC(self)
2246
2247 height = self._tabrect[0].height
2248
2249 if flags:
2250 flags = wx.NB_HITTEST_NOWHERE
2251
2252 if point.x <= 0 or point.x >= size.x:
2253 if flags:
2254 return wx.NOT_FOUND, flags
2255 else:
2256 return wx.NOT_FOUND
2257
2258 if not point.y >= self._tabrect[0].y and point.y < self._tabrect[0].y + height:
2259 if flags:
2260 return wx.NOT_FOUND, flags
2261 else:
2262 return wx.NOT_FOUND
2263
2264 posx = self._firsttabpos.x
2265 posy = self._firsttabpos.y
2266 maxwidth = max(self._maxtabwidths)
2267
2268 for ii in xrange(self._firstvisible, self.GetPageCount()):
2269
2270 if not self._enablehiding or not self._pages[ii]._ishidden:
2271
2272 width = self._CalcTabTextWidth(dc, ii)
2273
2274 bmpWidth, bmpHeight = self._CalcTabBitmapSize(ii)
2275
2276 tabrect = self._CalcTabRect(ii, posx, posy, width, bmpWidth, bmpHeight)
2277
2278 if tabrect.Contains(point):
2279
2280 if flags:
2281 flags = NC_HITTEST_ONITEM
2282
2283 #onx attempt
2284 if self.GetDrawX()[0]:
2285 count = self._tabvisible[0:ii].count(0)
2286 if flags and self._xrect[ii-self._firstvisible-count].Contains(point):
2287 flags = NC_HITTEST_ONX
2288
2289 #onicon attempt
2290 if flags and bmpWidth > 0 and \
2291 wx.RectPS(wx.Point(*self._CalcTabBitmapPosition(ii,
2292 bmpWidth, bmpHeight, tabrect)),
2293 wx.Size(bmpWidth, bmpHeight)).Contains(point):
2294 flags = NC_HITTEST_ONICON
2295
2296 #onlabel attempt
2297 elif flags and wx.RectPS(wx.Point(*self._CalcTabTextPosition(ii,
2298 tabrect, self._CalcTabBitmapSpace(bmpWidth, bmpHeight))),
2299 wx.Size(width, height)).Contains(point):
2300 flags = NC_HITTEST_ONLABEL
2301
2302 if flags:
2303 return ii, flags
2304 else:
2305 return ii
2306
2307 if self._style & NC_TOP or self._style & NC_BOTTOM:
2308 posx += tabrect.width
2309 else:
2310 posy += tabrect.height
2311
2312 if flags:
2313 return wx.NOT_FOUND, flags
2314 else:
2315 return wx.NOT_FOUND
2316
2317
2318 def EnableDragAndDrop(self, enable=True):
2319 """ Globall Enables/Disables Tabs Drag And Drop. """
2320
2321 self._enabledragging = enable
2322
2323
2324 def EnableHiding(self, enable=True):
2325 """ Globally Enables/Disables Hiding On Tabs In Runtime. """
2326
2327 self._enablehiding = enable
2328 self.UpdateMenuButton(enable)
2329
2330 wx.FutureCall(1000, self.UpdateMenuButton, enable)
2331
2332
2333 def SetAnimationImages(self, nPage, imgarray):
2334 """
2335 Sets An Animation List Associated To The Given Page nPage.
2336
2337 @param nPage: The Given Page
2338 @param imgarray: A List Of Image Indexes Of Images Inside The
2339 ImageList Associated To NotebookCtrl.
2340 """
2341
2342 if nPage < 0 or nPage >= self.GetPageCount():
2343 raise "\nERROR: Invalid Notebook Page In SetAnimationImages: (" + str(nPage) + ")"
2344
2345 if not imgarray:
2346 raise "\nERROR: Invalid Image Array In SetAnimationImages: (" + repr(imgarray) + ")"
2347
2348 if min(imgarray) < 0:
2349 raise "\nERROR: Invalid Image Array In SetAnimationImages: (Min(ImgArray) = " + \
2350 str(min(imgarray)) + " < 0)"
2351
2352 if max(imgarray) > self.GetImageList().GetImageCount() - 1:
2353 raise "\nERROR: Invalid Image Array In SetAnimationImages: (Max(ImgArray) = " + \
2354 str(max(imgarray)) + " > " + str(self.GetImageList().GetImageCount()-1) + ")"
2355
2356 self._pages[nPage]._animationimages = imgarray
2357
2358
2359 def GetAnimationImages(self, nPage):
2360 """ Returns The Animation Images List Associated To The Given Page nPage. """
2361
2362 if nPage < 0 or nPage >= self.GetPageCount():
2363 raise "\nERROR: Invalid Notebook Page In GetAnimationImages: (" + str(nPage) + ")"
2364
2365 return self._pages[nPage]._animationimages
2366
2367
2368 def AnimateTab(self, event):
2369 """ Called When The Refreshing Animation Timer Expires. Used Internally"""
2370
2371 obj = event.GetEventObject()
2372 nPage = self._timers.index(obj)
2373
2374 if not self.IsPageEnabled(nPage):
2375 return
2376
2377 indx = self.GetPageImage(nPage)
2378 images = self.GetAnimationImages(nPage)
2379 myindx = images.index(indx)
2380
2381 if indx == images[-1]:
2382 myindx = -1
2383
2384 myindx = myindx + 1
2385
2386 self.SetPageImage(nPage, images[myindx])
2387
2388
2389 def StartAnimation(self, nPage, timer=500):
2390 """ Starts The Animation On The Given Page, With Refreshing Time Rate "timer". """
2391
2392 if nPage < 0 or nPage >= self.GetPageCount():
2393 raise "\nERROR: Invalid Notebook Page In StartAnimation: (" + str(nPage) + ")"
2394
2395 images = self.GetAnimationImages(nPage)
2396
2397 if not images:
2398 raise "\nERROR: No Images Array Defined For Page: (" + str(nPage) + ")"
2399
2400 if len(images) == 1:
2401 raise "\nERROR: Impossible To Animate Tab: " + str(nPage) + " With Only One Image"
2402
2403 self._timers[nPage].Start(timer)
2404
2405
2406 def StopAnimation(self, nPage):
2407 """ Stops The Animation On The Given Page nPage. """
2408
2409 if nPage < 0 or nPage >= self.GetPageCount():
2410 raise "\nERROR: Invalid Notebook Page In StopAnimation: (" + str(nPage) + ")"
2411
2412 if self._timers[nPage].IsRunning():
2413 self._timers[nPage].Stop()
2414
2415
2416 def SetDrawX(self, drawx=True, style=1, image1=None, image2=None):
2417 """
2418 Globally Enables/Disables The Drawing Of A Closing "X" In The Tab.
2419
2420 @param drawx: C{True} to enable drawing a closing "X"; C{False} to
2421 disable it
2422 @param style: the style of the X to draw when C{drawx} is C{True};
2423 possible values are:
2424 - C{1}: Small "X" At The Top-Right Of The Tab;
2425 - C{2}: Bigger "X" In The Middle Vertical Of The Tab (Like Opera Notebook);
2426 - C{3}: Custom "X" Image Is Drawn On Tabs.
2427 @param image1: if C{style} is C{3}, the image to use when drawing
2428 the X on an unhighlighted tab
2429 @param image2: if C{style} is C{3}, the image to use when drawing
2430 the X on a highlighted tab
2431 """
2432
2433 self._drawx = drawx
2434 self._drawxstyle = style
2435
2436 if style == 3:
2437 self._imglist2 = wx.ImageList(16, 16, True, 0)
2438 self._imglist2.Add(image1)
2439 self._imglist2.Add(image2)
2440
2441 if self._style & NC_LEFT or self._style & NC_RIGHT:
2442 self.SetBestSize((self._CalcBestWidth(wx.ClientDC(self)), -1))
2443 self._parent.GetSizer().Layout()
2444
2445 self.Refresh()
2446
2447
2448 def GetDrawX(self):
2449 """
2450 Returns The Enable/Disable State Of Drawing Of A Small "X" At The Top-Right Of
2451 Every Page.
2452 """
2453
2454 return self._drawx, self._drawxstyle
2455
2456
2457 def GetInsideTab(self, pt):
2458 """ Returns The Tab On Which The Mouse Is Hovering On. """
2459
2460 count = 0
2461
2462 for tabs in self._tabrect:
2463 if tabs.Contains(pt):
2464 return count
2465
2466 count = count + 1
2467
2468 return -1
2469
2470
2471 def GetInsideX(self, pt):
2472 """ Returns The Tab On Which The Mouse Is Hovering On The "X" Button. """
2473
2474 count = 0
2475
2476 for rects in self._xrect:
2477 if rects.Contains(pt):
2478 return count
2479
2480 count = count + 1
2481
2482 return -1
2483
2484
2485 def SetImageToCloseButton(self, convert=True):
2486 """ Set Whether The Tab Icon Should Be Converted To The Close Button Or Not. """
2487
2488 self._convertimage = convert
2489
2490
2491 def GetImageToCloseButton(self):
2492 """ Get Whether The Tab Icon Should Be Converted To The Close Button Or Not. """
2493
2494 return self._convertimage
2495
2496
2497 def ConvertImageToCloseButton(self, page):
2498 """ Globally Converts The Page Image To The "Opera" Style Close Button. """
2499
2500 bmpindex = self.GetPageImage(page)
2501 if bmpindex < 0:
2502 return
2503
2504 tabrect = self._tabrect[page]
2505 size = self.GetSize()
2506
2507 maxfont = self._maxfont
2508
2509 dc = wx.ClientDC(self)
2510
2511 dc.SetFont(maxfont)
2512 pom, height = dc.GetTextExtent("Aq")
2513
2514 bmp = self._imglist.GetBitmap(bmpindex)
2515
2516 bmpposx = tabrect.x + self._padding.x
2517 bmpposy = size.y - (height + 2*self._padding.y + bmp.GetHeight())/2 - 1
2518
2519 ypos = size.y - height - self._padding.y*2
2520 ysize = height + self._padding.y*2 + 3
2521
2522 if page == self.GetSelection():
2523 bmpposx = bmpposx + 1
2524 bmpposy = bmpposy - 1
2525 ypos = ypos - 3
2526 ysize = ysize + 2
2527
2528 colour = self.GetPageColour(page)
2529 bmprect = wx.Rect(bmpposx, bmpposy, bmp.GetWidth()+self._padding.x, bmp.GetHeight())
2530
2531 dc.SetBrush(wx.Brush(colour))
2532 dc.SetPen(wx.TRANSPARENT_PEN)
2533 dc.DrawRectangleRect(bmprect)
2534
2535 colour = self.GetPageTextColour(page)
2536
2537 r = colour.Red()
2538 g = colour.Green()
2539 b = colour.Blue()
2540
2541 hr, hg, hb = min(255,r+64), min(255,g+64), min(255,b+64)
2542
2543 colour = wx.Colour(hr, hg, hb)
2544 back_colour = wx.WHITE
2545
2546 yypos = ypos+(ysize-height-self._padding.y/2)/2
2547
2548 xrect = wx.Rect(bmprect.x+(bmprect.width - self._padding.x - height)/2,
2549 yypos, height, height)
2550
2551 # Opera Style
2552 dc.SetPen(wx.Pen(colour, 1))
2553 dc.SetBrush(wx.Brush(colour))
2554 dc.DrawRoundedRectangleRect(xrect, 2)
2555 dc.SetPen(wx.Pen(back_colour, 2))
2556 dc.DrawLine(xrect[0]+2, xrect[1]+2, xrect[0]+xrect[2]-3, xrect[1]+xrect[3]-3)
2557 dc.DrawLine(xrect[0]+2, xrect[1]+xrect[3]-3, xrect[0]+xrect[2]-3, xrect[1]+2)
2558
2559
2560 def RedrawClosingX(self, pt, insidex, drawx, highlight=False):
2561 """ Redraw The Closing "X" Accordingly To The Mouse "Hovering" Position. """
2562
2563 colour = self.GetPageTextColour(insidex)
2564 back_colour = self.GetBackgroundColour()
2565 imagelist = 0
2566
2567 if highlight:
2568 r = colour.Red()
2569 g = colour.Green()
2570 b = colour.Blue()
2571
2572 hr, hg, hb = min(255,r+64), min(255,g+64), min(255,b+64)
2573
2574 colour = wx.Colour(hr, hg, hb)
2575 back_colour = wx.WHITE
2576 imagelist = 1
2577
2578 dc = wx.ClientDC(self)
2579 xrect = self._xrect[insidex]
2580
2581 if drawx == 1:
2582 # Emule Style
2583 dc.SetPen(wx.Pen(colour, 1))
2584 dc.SetBrush(wx.TRANSPARENT_BRUSH)
2585 dc.DrawRectangleRect(xrect)
2586 elif drawx == 2:
2587 # Opera Style
2588 dc.SetPen(wx.Pen(colour, 1))
2589 dc.SetBrush(wx.Brush(colour))
2590 dc.DrawRoundedRectangleRect(xrect, 2)
2591 dc.SetPen(wx.Pen(back_colour, 2))
2592 dc.DrawLine(xrect[0]+2, xrect[1]+2, xrect[0]+xrect[2]-3, xrect[1]+xrect[3]-3)
2593 dc.DrawLine(xrect[0]+2, xrect[1]+xrect[3]-3, xrect[0]+xrect[2]-3, xrect[1]+2)
2594 else:
2595 self._imglist2.Draw(imagelist, dc, xrect[0], xrect[1],
2596 wx.IMAGELIST_DRAW_TRANSPARENT, True)
2597
2598
2599 def HideOnSingleTab(self, hide=True):
2600 """ Hides The TabCtrl When There Is Only One Tab In NotebookCtrl. """
2601
2602 self._hideonsingletab = hide
2603
2604
2605 def SetPagePopupMenu(self, nPage, menu):
2606 """ Sets A Popup Menu Specific To A Single Tab. """
2607
2608 if nPage < 0 or nPage >= self.GetPageCount():
2609 raise "\nERROR: Invalid Notebook Page In SetPagePopupMenu: (" + str(nPage) + ")"
2610
2611 self._pages[nPage]._menu = menu
2612
2613
2614 def GetPagePopupMenu(self, nPage):
2615 """ Returns The Popup Menu Associated To A Single Tab. """
2616
2617 if nPage < 0 or nPage >= self.GetPageCount():
2618 raise "\nERROR: Invalid Notebook Page In GetPagePopupMenu: (" + str(nPage) + ")"
2619
2620 return self._pages[nPage]._menu
2621
2622
2623 def DrawInsertionMark(self, dc, nPage):
2624 """
2625 Draw An Insertion Arrow To Let The User Understand Where A Dragged Tab Will
2626 Be Dropped (Between Which Tabs).
2627 """
2628
2629 if not self._enablehiding:
2630 if nPage < 0 or nPage >= len(self._tabrect):
2631 return
2632 else:
2633 if nPage < 0 or nPage >= len(self._tabrect) + self._tabvisible.count(0):
2634 return
2635
2636 colour = wx.BLACK
2637 somehidden = False
2638
2639 if self._enablehiding:
2640 for ii in xrange(nPage):
2641 if self._pages[ii]._ishidden:
2642 nPage = nPage - 1
2643 somehidden = True
2644
2645 rect = self._tabrect[nPage]
2646
2647 x1 = rect.x - 4
2648 y1 = rect.y - 1
2649 x2 = rect.x
2650 y2 = y1 + 5
2651 x3 = rect.x + 3
2652 y3 = y1
2653
2654 mybrush = wx.Brush(self.GetPageTextColour(nPage))
2655
2656 if not self._enablehiding:
2657 if nPage > self._tabID:
2658 x1 = x1 + rect.width
2659 x2 = x2 + rect.width
2660 x3 = x3 + rect.width
2661 else:
2662 mybrush = wx.Brush(self.GetPageTextColour(nPage))
2663 if nPage >= self._tabID:
2664 x1 = x1 + rect.width
2665 x2 = x2 + rect.width
2666 x3 = x3 + rect.width
2667
2668 dc.SetPen(wx.Pen(wx.BLACK, 1))
2669 dc.SetBrush(mybrush)
2670 dc.DrawPolygon([(x1, y1), (x2, y2), (x3, y3)])
2671
2672
2673 def OnMouseMotion(self, event):
2674 """ Handles The wx.EVT_MOTION Event For TabCtrl. """
2675
2676 pt = event.GetPosition()
2677
2678 if self._enabledragging:
2679
2680 if event.Dragging() and not event.RightIsDown() and not event.MiddleIsDown():
2681
2682 tolerance = 2
2683
2684 dx = abs(pt.x - self._dragstartpos.x)
2685 dy = abs(pt.y - self._dragstartpos.y)
2686
2687 if dx <= tolerance and dy <= tolerance:
2688 self.SetCursor(wx.STANDARD_CURSOR)
2689 return
2690
2691 self.SetCursor(self._dragcursor)
2692 self._isdragging = True
2693 self._isleaving = False
2694 newpos = self.HitTest(pt)
2695
2696 if newpos >= 0 and newpos != self._olddragpos:
2697 self._olddragpos = newpos
2698 self.Refresh()
2699
2700 else:
2701
2702 self._isdragging = False
2703 self.SetCursor(wx.STANDARD_CURSOR)
2704
2705 if not event.Dragging():
2706 drawx = self.GetDrawX()
2707
2708 if drawx[0]:
2709 insidex = self.GetInsideX(pt)
2710 if insidex >= 0:
2711 if self.IsPageEnabled(insidex):
2712 self.RedrawClosingX(pt, insidex, drawx[1], True)
2713 self._xrefreshed = False
2714 else:
2715 if not self._xrefreshed:
2716 insidetab = self.GetInsideTab(pt)
2717 if insidetab >= 0:
2718 if self.IsPageEnabled(insidetab):
2719 self.RedrawClosingX(pt, insidetab, drawx[1])
2720 self._xrefreshed = True
2721 else:
2722 if self.GetImageToCloseButton():
2723 page, flags = self.HitTest(pt, 1)
2724 if page >= 0:
2725 if self.IsPageEnabled(page):
2726 if flags == NC_HITTEST_ONICON:
2727 if not self._imageconverted:
2728 self.ConvertImageToCloseButton(page)
2729 self._imageconverted = True
2730 else:
2731 if self._imageconverted:
2732 self.Refresh()
2733 self._imageconverted = False
2734
2735 if self._showtooltip:
2736 if not event.Dragging():
2737 if not event.LeftDown():
2738
2739 oldinside = self._insidetab
2740 self._insidetab = self.GetInsideTab(pt)
2741
2742 if self._insidetab >= 0:
2743 if oldinside != self._insidetab:
2744
2745 if self._istooltipshown:
2746 self._tipwindow.Destroy()
2747 self._istooltipshown = False
2748 self.Refresh()
2749
2750 if self._tiptimer.IsRunning():
2751 self._tiptimer.Stop()
2752
2753 tip, ontime, winsize= self.GetPageToolTip(self._insidetab)
2754
2755 if tip.strip() != "":
2756 self._currenttip = tip
2757 self._currentwinsize = winsize
2758 self._tiptimer.Start(ontime, wx.TIMER_ONE_SHOT)
2759
2760 else:
2761 if self._istooltipshown:
2762 self._tipwindow.Destroy()
2763 self._istooltipshown = False
2764 self.Refresh()
2765
2766 self._mousepos = pt
2767
2768 event.Skip()
2769
2770
2771 def OnShowToolTip(self):
2772 """ Called When The Timer For The ToolTip Expires. Used Internally. """
2773
2774 pt = self.ScreenToClient(wx.GetMousePosition())
2775
2776 oldinside = self._insidetab
2777 self._insidetab = self.GetInsideTab(pt)
2778
2779 if self._insidetab != oldinside or self._insidetab < 0:
2780 return
2781
2782 self._istooltipshown = True
2783 self._tipwindow = self.TransientTipWindow(self, self._currenttip,
2784 self._currentwinsize)
2785
2786 xsize, ysize = self._tipwindow.GetSize()
2787 xpos, ypos = self.ClientToScreen(self._mousepos)
2788
2789 if xpos + xsize > self._xvideo - 10:
2790 if ypos + ysize > self._yvideo - 10: # SW Tip Positioning
2791 posx = xpos - xsize
2792 posy = ypos - ysize
2793 else: # NE Tip Positioning
2794 posx = xpos - xsize
2795 posy = ypos
2796 else:
2797 if ypos + ysize > self._yvideo - 10: # SE Tip Positioning
2798 posx = xpos + 10
2799 posy = ypos - ysize
2800 else: # NW Tip Positioning
2801 posx = xpos + 10
2802 posy = ypos
2803
2804 if posy < 0:
2805 posy = ypos
2806
2807 if posx < 0:
2808 posx = xpos
2809
2810 self._tipwindow.SetPosition((posx, posy))
2811 self._tipwindow.Show()
2812
2813
2814 def OnMouseLeftDown(self, event):
2815 """ Handles The wx.EVT_LEFT_DOWN Event For TabCtrl. """
2816
2817 pos = event.GetPosition()
2818 page, flags = self.HitTest(pos, 1)
2819 self._dragstartpos = pos
2820
2821 if page != wx.NOT_FOUND:
2822
2823 if self.IsPageEnabled(page):
2824
2825 if event.m_controlDown:
2826 if page in self._selectedtabs:
2827 self._selectedtabs.remove(page)
2828 else:
2829 self._selectedtabs.append(page)
2830 self.Refresh()
2831 else:
2832 self._selectedtabs = []
2833 if flags == NC_HITTEST_ONX or (flags == NC_HITTEST_ONICON and self.GetImageToCloseButton()):
2834 eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_CLOSING, self.GetId())
2835 eventOut.SetOldSelection(self._selection)
2836 eventOut.SetSelection(page)
2837 eventOut.SetEventObject(self)
2838
2839 if not self.GetEventHandler().ProcessEvent(eventOut):
2840 self._parent.DeletePage(page)
2841 self._parent.bsizer.Layout()
2842
2843 else:
2844 self.SetSelection(page)
2845 self._tabID = page
2846
2847 event.Skip()
2848
2849
2850 def OnMouseLeftDClick(self, event):
2851 """ Handles The wx.EVT_LEFT_DCLICK Event For TabCtrl. """
2852
2853 pos = event.GetPosition()
2854 page = self.HitTest(pos)
2855 self._selectedtabs = []
2856
2857 if page == wx.NOT_FOUND:
2858 return
2859
2860 if not self.IsPageEnabled(page):
2861 return
2862
2863 eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_DCLICK, self.GetId())
2864 eventOut.SetOldSelection(self._selection)
2865 eventOut.SetSelection(page)
2866 eventOut.SetEventObject(self)
2867
2868 if not self.GetEventHandler().ProcessEvent(eventOut):
2869 return
2870
2871 event.Skip()
2872
2873
2874 def OnMouseLeftUp(self, event):
2875 """ Handles The wx.EVT_LEFT_UP Event For TabCtrl. """
2876
2877 if not self._enabledragging:
2878 event.Skip()
2879 return
2880
2881 if not self._isdragging:
2882 self.SetCursor(wx.STANDARD_CURSOR)
2883 event.Skip()
2884 return
2885
2886 id = self.HitTest(wx.Point(event.GetX(), event.GetY()))
2887
2888 if id >= 0 and id != self._tabID:
2889
2890 self._isdragging = False
2891 self._olddragpos = -1
2892 eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_DND, self.GetId())
2893 eventOut.SetOldPosition(self._tabID)
2894 eventOut.SetNewPosition(id)
2895 eventOut.SetEventObject(self)
2896
2897 if self.GetEventHandler().ProcessEvent(eventOut):
2898 self._tabID = -1
2899 self._olddragpos = -1
2900 self.SetCursor(wx.STANDARD_CURSOR)
2901 self.Refresh()
2902 return
2903
2904 self._parent.Freeze()
2905
2906 try:
2907 text = self.GetPageText(self._tabID)
2908 image = self.GetPageImage(self._tabID)
2909 font1 = self.GetPageTextFont(self._tabID)
2910 font2 = self.GetPageTextSecondaryFont(self._tabID)
2911 fontcolour = self.GetPageTextColour(self._tabID)
2912 pagecolour = self.GetPageColour(self._tabID)
2913 enabled = self.IsPageEnabled(self._tabID)
2914 tooltip, ontime, winsize = self.GetPageToolTip(self._tabID)
2915 menu = self.GetPagePopupMenu(self._tabID)
2916 firstcol = self.GetPageFirstGradientColour(self._tabID)
2917 secondcol = self.GetPageSecondGradientColour(self._tabID)
2918 ishidden = self._pages[self._tabID]._ishidden
2919 except:
2920 self._parent.Thaw()
2921 self._tabID = -1
2922 self.SetCursor(wx.STANDARD_CURSOR)
2923 return
2924
2925 isanimated = 0
2926 if self._timers[self._tabID].IsRunning():
2927 isanimated = 1
2928 timer = self._timers[self._tabID].GetInterval()
2929
2930 self.StopAnimation(self._tabID)
2931 animatedimages = self.GetAnimationImages(self._tabID)
2932
2933 pagerange = range(self.GetPageCount())
2934
2935 newrange = pagerange[:]
2936 newrange.remove(self._tabID)
2937 newrange.insert(id, self._tabID)
2938
2939 newpages = []
2940 counter = self.GetPageCount() - 1
2941
2942 for ii in xrange(self.GetPageCount()):
2943 newpages.append(self._parent.GetPage(ii))
2944 self._parent.bsizer.Detach(counter-ii)
2945
2946 cc = 0
2947
2948 self._parent._notebookpages = []
2949
2950 for jj in newrange:
2951 self._parent.bsizer.Add(newpages[jj], 1, wx.EXPAND | wx.ALL, 2)
2952 self._parent.bsizer.Show(cc, False)
2953 self._parent._notebookpages.append(newpages[jj])
2954 cc = cc + 1
2955
2956 self.DeletePage(self._tabID)
2957
2958 if enabled:
2959 if id == self.GetPageCount():
2960 self.AddPage(text, True, image)
2961 else:
2962 self.InsertPage(id, text, True, image)
2963 else:
2964 if id == self.GetPageCount():
2965 self.AddPage(text, False, image)
2966 else:
2967 self.InsertPage(id, text, False, image)
2968
2969 self.SetPageImage(id, image)
2970 self.SetPageText(id, text)
2971 self.SetPageTextFont(id, font1)
2972 self.SetPageTextSecondaryFont(id, font2)
2973 self.SetPageTextColour(id, fontcolour)
2974 self.SetPageColour(id, pagecolour)
2975 self.EnablePage(id, enabled)
2976 self.SetPageToolTip(id, tooltip, ontime, winsize)
2977 self.SetPagePopupMenu(id, menu)
2978 self.SetPageFirstGradientColour(id, firstcol)
2979 self.SetPageSecondGradientColour(id, secondcol)
2980 self._pages[id]._ishidden = ishidden
2981
2982 if isanimated and len(animatedimages) > 1:
2983 self.SetAnimationImages(id, animatedimages)
2984 self.StartAnimation(id, timer)
2985
2986 if enabled:
2987 self._parent.bsizer.Show(id, True)
2988 else:
2989 sel = self.GetSelection()
2990
2991 if sel == -1:
2992 sel = 0
2993 self._parent.bsizer.Show(id, False)
2994 self._parent.SetSelection(sel)
2995 self._parent.bsizer.Show(sel, True)
2996
2997 self._parent.bsizer.Layout()
2998
2999 self._parent.Thaw()
3000
3001 self._isdragging = False
3002 self._olddragpos = -1
3003 self._fromdnd = True
3004 self.Refresh()
3005 self._tabID = -1
3006 self.SetCursor(wx.STANDARD_CURSOR)
3007
3008 event.Skip()
3009
3010
3011 def OnSize(self, event=None):
3012 """ Handles The wx.EVT_SIZE Event For TabCtrl. """
3013
3014 if self._sizeToggleButton:
3015 width = self.GetSize()[0]
3016 height = self._CalcSizeToggleBestSize()[1]
3017 self._sizeToggleButton.SetSize(wx.Size(width, height))
3018 self.Refresh()
3019
3020 if event is not None:
3021 event.Skip()
3022
3023
3024 def OnMouseRightUp(self, event):
3025 """ Handles The wx.EVT_RIGHT_UP Event For TabCtrl. """
3026
3027 pt = event.GetPosition()
3028 id = self.HitTest(pt)
3029
3030 self._selectedtabs = []
3031
3032 if id >= 0:
3033 if self.IsPageEnabled(id):
3034 menu = self.GetPagePopupMenu(id)
3035 if menu:
3036 self.PopupMenu(menu)
3037
3038 event.Skip()
3039
3040
3041 def OnMouseRightDown(self, event):
3042 """ Handles The wx.EVT_RIGHT_DOWN Event For TabCtrl. """
3043
3044 pos = event.GetPosition()
3045 page = self.HitTest(pos)
3046
3047 self._selectedtabs = []
3048
3049 if page == wx.NOT_FOUND:
3050 return
3051
3052 if not self.IsPageEnabled(page):
3053 return
3054
3055 eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_RIGHT, self.GetId())
3056 eventOut.SetOldSelection(self._selection)
3057 eventOut.SetSelection(page)
3058 eventOut.SetEventObject(self)
3059
3060 if not self.GetEventHandler().ProcessEvent(eventOut):
3061 return
3062
3063 event.Skip()
3064
3065
3066 def OnMouseMiddleDown(self, event):
3067 """ Handles The wx.EVT_MIDDLE_DOWN Event For TabCtrl. """
3068
3069 pos = event.GetPosition()
3070 page = self.HitTest(pos)
3071
3072 self._selectedtabs = []
3073
3074 if page == wx.NOT_FOUND:
3075 return
3076
3077 if not self.IsPageEnabled(page):
3078 return
3079
3080 eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_MIDDLE, self.GetId())
3081 eventOut.SetOldSelection(self._selection)
3082 eventOut.SetSelection(page)
3083 eventOut.SetEventObject(self)
3084
3085 if not self.GetEventHandler().ProcessEvent(eventOut):
3086 return
3087
3088 event.Skip()
3089
3090
3091 def SetSelectionColour(self, colour=None):
3092 """ Sets The Tab Selection Colour (Thin Line Above The Selected Tab). """
3093
3094 if colour is None:
3095 colour = wx.Colour(255, 180, 0)
3096
3097 self._selectioncolour = colour
3098
3099
3100 def SetContourLineColour(self, colour=None):
3101 """ Sets The Contour Line Colour (Controur Line Around Tabs). """
3102
3103 if colour is None:
3104 if not self._tabstyle._normal or self._usegradients:
3105 colour = wx.Colour(145, 167, 180)
3106 else:
3107 colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)
3108
3109 if not self._tabstyle._normal or self._usegradients:
3110 self._highlightpen = wx.Pen(colour)
3111 self._highlightpen.SetCap(wx.CAP_BUTT)
3112 else:
3113 self._highlightpen2 = wx.Pen(colour)
3114 self._highlightpen2.SetCap(wx.CAP_BUTT)
3115
3116 self.Refresh()
3117
3118
3119 def ApplyTabTheme(self, theme=None):
3120 """ Applies A Particular Theme To Be Drawn On Tabs. """
3121
3122 if theme is None:
3123 theme = ThemeStyle()
3124
3125 self._tabstyle = theme
3126 if self._style & NC_EXPANDABLE:
3127 self._InitExpandableTabStyles(self._style, self._expanded, theme)
3128 self.Refresh()
3129
3130 def DrawMacTheme(self, dc, tabrect, theme):
3131 """ Draws The Mac Theme On Tabs, If It Is Enabled. """
3132
3133 if theme == 1:
3134 col1, col2 = NC_MAC_LIGHT
3135 else:
3136 col1, col2 = NC_MAC_DARK
3137
3138 colour1 = wx.Colour(col1, col1, col1)
3139 colour2 = wx.Colour(col2, col2, col2)
3140
3141 x, y, w, h = tabrect
3142 endrange = self._style & NC_ROTATE and w or h
3143
3144 index = 0
3145
3146 for ii in xrange(0, endrange, 2):
3147 if index%2 == 0:
3148 colour = colour1
3149 else:
3150 colour = colour2
3151
3152 dc.SetBrush(wx.Brush(colour))
3153 dc.SetPen(wx.Pen(colour))
3154 if self._style & NC_ROTATE:
3155 if ii > 3:
3156 dc.DrawRectangle(x+ii, y, 2, w)
3157 else:
3158 dc.DrawRoundedRectangle(x+ii, y, 3, 3)
3159 else:
3160 if ii > 3:
3161 dc.DrawRectangle(x, y+ii, w, 2)
3162 else:
3163 dc.DrawRoundedRectangle(x, y+ii, w, 3, 3)
3164
3165 index = index + 1
3166
3167 self._lastcolour = colour
3168
3169
3170 def DrawKDETheme(self, dc, rect):
3171 """ Draws Unix-Style KDE Theme On Tabs. """
3172
3173 x, y, w, h = rect
3174
3175 if self._style & NC_ROTATE and self._style & NC_RIGHT:
3176 bandrange = xrange(13, -1, -1)
3177 self._lastcolour = kdetheme[13]
3178 brush = wx.Brush(kdetheme[0], wx.SOLID)
3179 else:
3180 bandrange = xrange(14)
3181 self._lastcolour = kdetheme[0]
3182 brush = wx.Brush(kdetheme[13], wx.SOLID)
3183
3184 dc.SetBackground(brush)
3185 for band in bandrange:
3186 pen = wx.Pen(kdetheme[band])
3187 dc.SetPen(pen)
3188 if self._style & NC_ROTATE:
3189 if self._style & NC_RIGHT:
3190 dc.DrawLine(x+1+band, y+1, x+1+band, y+h-1)
3191 dc.DrawLine(x+w-(1+band), y+1, x+w-(1+band), y+h-2)
3192 else:
3193 dc.DrawLine(x+1+band, y+1, x+1+band, y+h-1)
3194 dc.DrawLine(x+w-(2+band), y+1, x+w-(2+band), y+h-2)
3195 else:
3196 dc.DrawLine(x+1, y+band, x+w-1, y+band)
3197 dc.DrawLine(x+1, y+h-1-band, x+w-2, y+h-1-band)
3198
3199
3200 def DrawSilverTheme(self, dc, rect, selected):
3201 """ Draws Windows XP Silver-Like Theme. """
3202
3203 x, y, w, h = rect
3204
3205 if selected:
3206 r1 = silvertheme1[0].Red()
3207 g1 = silvertheme1[0].Green()
3208 b1 = silvertheme1[0].Blue()
3209 r2 = silvertheme1[1].Red()
3210 g2 = silvertheme1[1].Green()
3211 b2 = silvertheme1[1].Blue()
3212 else:
3213 r1 = silvertheme2[0].Red()
3214 g1 = silvertheme2[0].Green()
3215 b1 = silvertheme2[0].Blue()
3216 r2 = silvertheme2[1].Red()
3217 g2 = silvertheme2[1].Green()
3218 b2 = silvertheme2[1].Blue()
3219 rend = silvertheme2[2].Red()
3220 gend = silvertheme2[2].Green()
3221 bend = silvertheme2[2].Blue()
3222
3223 if self._style & NC_ROTATE:
3224 flrect = float(w-2)
3225 else:
3226 flrect = float(h-2)
3227
3228 rstep = float((r2 - r1)) / flrect
3229 gstep = float((g2 - g1)) / flrect
3230 bstep = float((b2 - b1)) / flrect
3231
3232 rf, gf, bf = 0, 0, 0
3233
3234 counter = 0
3235
3236 if self._style & NC_ROTATE:
3237 if self._style & NC_RIGHT:
3238 bandrange = xrange(x+w-2, x, -1)
3239 else:
3240 bandrange = xrange(x+1, x+w-1)
3241 else:
3242 bandrange = xrange(y+1, y+h)
3243
3244 for band in bandrange:
3245 currCol = (int(round(r1 + rf)), int(round(g1 + gf)), int(round(b1 + bf)))
3246 dc.SetBrush(wx.Brush(currCol, wx.SOLID))
3247 dc.SetPen(wx.Pen(currCol))
3248 if self._style & NC_ROTATE:
3249 if counter == 0:
3250 ypos = y + 2
3251 yend = h - 4
3252 elif counter == 1:
3253 ypos = y + 1
3254 yend = h - 2
3255 else:
3256 ypos = y + 1
3257 yend = h - 2
3258
3259 dc.DrawRectangle(band, ypos, 1, yend)
3260
3261 else:
3262 if counter == 0:
3263 xpos = x + 2
3264 xend = w - 4
3265 elif counter == 1:
3266 xpos = x + 1
3267 xend = w - 2
3268 else:
3269 xpos = x + 1
3270 xend = w - 2
3271
3272 dc.DrawRectangle(xpos, band, xend, 1)
3273
3274 counter = counter + 1
3275 rf = rf + rstep
3276 gf = gf + gstep
3277 bf = bf + bstep
3278 self._lastcolour = currCol
3279
3280 if not selected and self._style & NC_TOP:
3281 dc.SetBrush(wx.Brush((rend, gend, bend)))
3282 dc.SetPen(wx.Pen((rend, gend, bend)))
3283 if self._style & NC_ROTATE:
3284 if self._style & NC_LEFT:
3285 xpos = x + w - 4
3286 else:
3287 xpos = x
3288
3289 dc.DrawRectangle(xpos, ypos, 3, yend)
3290 else:
3291 dc.DrawRectangle(xpos, y+h-3, xend, 3)
3292 self._lastcolour = wx.Colour(rend, gend, bend)
3293
3294
3295 def DrawAquaTheme(self, dc, rect, style, selected):
3296 """ Draws Mac-Style Aqua Theme On Tabs. """
3297
3298 x, y, w, h = rect
3299
3300 if selected:
3301 if style == 1: # Dark Aqua
3302 r1 = topaqua1[0].Red()
3303 g1 = topaqua1[0].Green()
3304 b1 = topaqua1[0].Blue()
3305
3306 r2 = topaqua1[1].Red()
3307 g2 = topaqua1[1].Green()
3308 b2 = topaqua1[1].Blue()
3309 else:
3310 r1 = topaqua2[0].Red()
3311 g1 = topaqua2[0].Green()
3312 b1 = topaqua2[0].Blue()
3313
3314 r2 = topaqua2[1].Red()
3315 g2 = topaqua2[1].Green()
3316 b2 = topaqua2[1].Blue()
3317
3318 else:
3319 r1 = distaqua[0].Red()
3320 g1 = distaqua[0].Green()
3321 b1 = distaqua[0].Blue()
3322
3323 r2 = distaqua[1].Red()
3324 g2 = distaqua[1].Green()
3325 b2 = distaqua[1].Blue()
3326
3327 flrect = float((h-2)/2)
3328
3329 rstep = float((r2 - r1)) / flrect
3330 gstep = float((g2 - g1)) / flrect
3331 bstep = float((b2 - b1)) / flrect
3332
3333 rf, gf, bf = 0, 0, 0
3334
3335 counter = 0
3336 dc.SetPen(wx.TRANSPARENT_PEN)
3337
3338 if self._style & NC_ROTATE:
3339 startrange, endrange = (x, w)
3340 else:
3341 startrange, endrange = (y, h)
3342 if self._style & NC_ROTATE and self._style & NC_RIGHT:
3343 bandrange = xrange(startrange+endrange, startrange+endrange/2, -1)
3344 else:
3345 bandrange = xrange(startrange+1, startrange+endrange/2)
3346
3347 for band in bandrange:
3348 currCol = (int(round(r1 + rf)), int(round(g1 + gf)), int(round(b1 + bf)))
3349 dc.SetBrush(wx.Brush(currCol, wx.SOLID))
3350 if self._style & NC_ROTATE:
3351 if counter == 0:
3352 ypos = y + 2
3353 yend = h - 4
3354 elif counter == 1:
3355 ypos = y + 1
3356 yend = h - 2
3357 else:
3358 ypos = y + 1
3359 yend = h - 2
3360
3361 dc.DrawRectangle(band, ypos, 1, yend)
3362 else:
3363 if counter == 0:
3364 xpos = x + 2
3365 xend = w - 4
3366 elif counter == 1:
3367 xpos = x + 1
3368 xend = w - 2
3369 else:
3370 xpos = x + 1
3371 xend = w - 2
3372
3373 dc.DrawRectangle(xpos, band, xend, 1)
3374
3375 counter = counter + 1
3376
3377 rf = rf + rstep
3378 gf = gf + gstep
3379 bf = bf + bstep
3380
3381 if selected:
3382 if style == 1: # Dark Aqua
3383 r1 = botaqua1[0].Red()
3384 g1 = botaqua1[0].Green()
3385 b1 = botaqua1[0].Blue()
3386
3387 r2 = botaqua1[1].Red()
3388 g2 = botaqua1[1].Green()
3389 b2 = botaqua1[1].Blue()
3390 else:
3391 r1 = botaqua2[0].Red()
3392 g1 = botaqua2[0].Green()
3393 b1 = botaqua2[0].Blue()
3394
3395 r2 = botaqua2[1].Red()
3396 g2 = botaqua2[1].Green()
3397 b2 = botaqua2[1].Blue()
3398 else:
3399 r1 = disbaqua[0].Red()
3400 g1 = disbaqua[0].Green()
3401 b1 = disbaqua[0].Blue()
3402
3403 r2 = disbaqua[1].Red()
3404 g2 = disbaqua[1].Green()
3405 b2 = disbaqua[1].Blue()
3406
3407 flrect = float((h-2)/2)
3408
3409 rstep = float((r2 - r1)) / flrect
3410 gstep = float((g2 - g1)) / flrect
3411 bstep = float((b2 - b1)) / flrect
3412
3413 rf, gf, bf = 0, 0, 0
3414
3415 counter = 0
3416
3417 if self._style & NC_ROTATE and self._style & NC_RIGHT:
3418 bandrange = xrange(startrange+endrange/2, startrange+1, -1)
3419 else:
3420 bandrange = xrange(startrange+endrange/2, startrange+endrange)
3421 for band in bandrange:
3422 currCol = (int(round(r1 + rf)), int(round(g1 + gf)), int(round(b1 + bf)))
3423 dc.SetBrush(wx.Brush(currCol, wx.SOLID))
3424 if self._style & NC_ROTATE:
3425 dc.DrawRectangle(band, y + 1, 1, h-2)
3426 else:
3427 dc.DrawRectangle(x+1, band, w-2, 1)
3428 rf = rf + rstep
3429 gf = gf + gstep
3430 bf = bf + bstep
3431
3432 self._lastcolour = currCol
3433
3434
3435 def DrawMetalTheme(self, dc, rect):
3436 """ Draws Mac-Style Metal Gradient On Tabs. """
3437
3438 x, y, w, h = rect
3439
3440 dc.SetPen(wx.TRANSPARENT_PEN)
3441 counter = 0
3442
3443 if self._style & NC_ROTATE:
3444 bandrange = xrange(x+1, x+w)
3445 else:
3446 bandrange = xrange(y+1, h+y)
3447 for band in bandrange:
3448 if self._style & NC_ROTATE:
3449 intens = (230 + 80 * (x-band)/w)
3450 else:
3451 intens = (230 + 80 * (y-band)/h)
3452
3453 colour = wx.Colour(intens, intens, intens)
3454 dc.SetBrush(wx.Brush(colour))
3455
3456 if self._style & NC_ROTATE:
3457 if counter == 0:
3458 ypos = y + 2
3459 yend = h - 4
3460 elif counter == 1:
3461 ypos = y + 1
3462 yend = h - 2
3463 else:
3464 ypos = y + 1
3465 yend = h - 2
3466 if self._style & NC_RIGHT:
3467 dc.DrawRectangle(x+w-band, ypos, 1, yend)
3468 else:
3469 dc.DrawRectangle(x+band, ypos, 1, yend)
3470
3471 else:
3472 if counter == 0:
3473 xpos = x + 2
3474 xend = w - 4
3475 elif counter == 1:
3476 xpos = x + 1
3477 xend = w - 2
3478 else:
3479 xpos = x + 1
3480 xend = w - 2
3481 dc.DrawRectangle(xpos, band, xend, 1)
3482
3483 counter = counter + 1
3484
3485 self._lastcolour = colour
3486
3487
3488 def DrawVerticalGradient(self, dc, rect, index):
3489 """ Gradient Fill From Colour 1 To Colour 2 From Top To Bottom. """
3490
3491 dc.SetPen(wx.TRANSPARENT_PEN)
3492
3493 # calculate gradient coefficients
3494 col2 = self._tabstyle.GetSecondGradientColour(index == self.GetSelection())
3495 col1 = self._tabstyle.GetFirstGradientColour(index == self.GetSelection())
3496
3497 r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
3498 r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
3499
3500 flrect = float(rect.height)
3501
3502 rstep = float((r2 - r1)) / flrect
3503 gstep = float((g2 - g1)) / flrect
3504 bstep = float((b2 - b1)) / flrect
3505
3506 rf, gf, bf = 0, 0, 0
3507
3508 counter = 0
3509
3510 bandrange = xrange(rect.y+1, rect.y + rect.height-1)
3511 lenc = len(bandrange)
3512
3513 for y in bandrange:
3514 currCol = (r1 + rf, g1 + gf, b1 + bf)
3515
3516 dc.SetBrush(wx.Brush(currCol, wx.SOLID))
3517
3518 # adjust along x-axis to preserve the curved tab edge
3519 def GetXAdjust(counter):
3520 if counter >=2 or counter <=lenc-2:
3521 return 1
3522 if self._style & NC_LEFT or self._style & NC_RIGHT and not self._style & NC_ROTATE:
3523 if counter == 0 and self._style & NC_RIGHT or \
3524 counter == lenc - 1 and self._style & NC_LEFT:
3525 return 3
3526 elif counter == 1 and self._style & NC_RIGHT or \
3527 counter == lend - 2 and self._style & NC_LEFT:
3528 return 2
3529 else:
3530 return 1
3531 else:
3532 if counter == lenc - 2:
3533 return 2
3534 elif counter == lenc - 1:
3535 return 3
3536 else:
3537 return 1
3538
3539 xadjust = GetXAdjust(counter)
3540 xpos = rect.x + xadjust
3541 xend = rect.width - xadjust
3542
3543
3544 counter = counter + 1
3545
3546 dc.DrawRectangle(xpos, y, xend, 1)
3547 rf = rf + rstep
3548 gf = gf + gstep
3549 bf = bf + bstep
3550
3551 self._lastcolour = currCol
3552
3553
3554 def DrawHorizontalGradient(self, dc, rect, index):
3555 """ Gradient Fill From Colour 1 To Colour 2 From Left To Right. """
3556
3557 dc.SetPen(wx.TRANSPARENT_PEN)
3558
3559 # calculate gradient coefficients
3560 col2 = self._tabstyle.GetSecondGradientColour(index == self.GetSelection())
3561 col1 = self._tabstyle.GetFirstGradientColour(index == self.GetSelection())
3562
3563 r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
3564 r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
3565
3566 flrect = float(rect.width)
3567
3568 rstep = float((r2 - r1)) / flrect
3569 gstep = float((g2 - g1)) / flrect
3570 bstep = float((b2 - b1)) / flrect
3571
3572 rf, gf, bf = 0, 0, 0
3573 counter = 0
3574
3575 bandrange = xrange(rect.x + 1, rect.x + rect.width - 1)
3576 lenc = len(bandrange)
3577
3578 for x in bandrange:
3579 currCol = (r1 + rf, g1 + gf, b1 + bf)
3580
3581 dc.SetBrush(wx.Brush(currCol, wx.SOLID))
3582 # adjust along y-axis to preserve the curved tab edge
3583 def GetYAdjust(counter):
3584 if counter >=2 or counter <=lenc-2:
3585 return 1
3586 if self._style & NC_TOP or self._style & NC_BOTTOM or \
3587 (self._style & NC_LEFT and self._style & NC_ROTATE):
3588 if counter == 0 or counter == lenc - 1 and not self._style & NC_LEFT:
3589 return 3
3590 elif counter == 1 or counter == lenc - 2 and not self._style & NC_LEFT:
3591 return 2
3592 else:
3593 return 1
3594 else:
3595 if counter == lenc - 2:
3596 return 2
3597 elif counter == lenc - 1:
3598 return 3
3599 else:
3600 return 1
3601
3602 yadjust = GetYAdjust(counter)
3603 ypos = rect.y + yadjust
3604 yend = rect.height - yadjust
3605
3606 counter = counter + 1
3607
3608 dc.DrawRectangle(x, ypos, 1, yend)
3609 rf = rf + rstep
3610 gf = gf + gstep
3611 bf = bf + bstep
3612
3613 self._lastcolour = currCol
3614
3615
3616 def GetAllTextExtents(self, dc):
3617 """ Returns All Tabs Text Extents. Used Internally. """
3618
3619 self._mintabwidths = []
3620 self._maxtabwidths = []
3621 self._mintabheights = []
3622 self._maxtabheights = []
3623 self._incrtext = []
3624 minheight = 0
3625
3626 for ii in xrange(self.GetPageCount()):
3627
3628 txts = self.GetPageText(ii)
3629 font1 = self.GetPageTextFont(ii)
3630 dc.SetFont(font1)
3631 w1, h1 = dc.GetTextExtent(txts)
3632 minheight = max(minheight, h1)
3633 self._mintabwidths.append(w1)
3634 self._mintabheights.append(h1)
3635 font2 = self.GetPageTextSecondaryFont(ii)
3636 dc.SetFont(font2)
3637 w2, h2 = dc.GetTextExtent(txts)
3638 minheight = max(minheight, h2)
3639
3640 self._maxtabwidths.append(w2)
3641 self._maxtabheights.append(h2)
3642 self._incrtext.append(abs(self._mintabwidths[ii] - self._maxtabwidths[ii]))
3643
3644 mh1 = max(self._mintabheights)
3645 font1 = self.GetPageTextFont(self._mintabheights.index(mh1))
3646 mh2 = max(self._maxtabheights)
3647 font2 = self.GetPageTextSecondaryFont(self._maxtabheights.index(mh2))
3648
3649 mhend = max(mh1, mh2)
3650
3651 if mhend == mh1:
3652 maxfont = font1
3653 else:
3654 maxfont = font2
3655
3656 minheight = self.GetSize()[1]
3657
3658 return minheight, maxfont
3659
3660
3661 def DrawBuiltinStyle(self, dc, style, rect, index, selection):
3662 """ Methods That Holds All The Theme Styles. """
3663
3664 if style._aqua:
3665 if self._selstyle._normal:
3666 self.DrawAquaTheme(dc, rect, style._aqua, index==selection)
3667 else:
3668 oldselstyle = self._selstyle[:]
3669 self._selstyle._normal = True
3670 self.DrawBuiltinStyle(dc, self._selstyle, rect, index, selection)
3671 self._selstyle = oldselstyle
3672
3673 elif style._metal:
3674 if self._selstyle._normal:
3675 self.DrawMetalTheme(dc, rect)
3676 else:
3677 oldselstyle = self._selstyle[:]
3678 self._selstyle._normal = True
3679 self.DrawBuiltinStyle(dc, self._selstyle, rect, index, selection)
3680 self._selstyle = oldselstyle
3681
3682 elif style._kdetheme:
3683 if self._selstyle._normal:
3684 self.DrawKDETheme(dc, rect)
3685 else:
3686 oldselstyle = self._selstyle[:]
3687 self._selstyle._normal = True
3688 self.DrawBuiltinStyle(dc, self._selstyle, rect, index, selection)
3689 self._selstyle = oldselstyle
3690
3691 elif style._macstyle:
3692 if self._selstyle._normal:
3693 self.DrawMacTheme(dc, rect, style._macstyle)
3694 else:
3695 oldselstyle = self._selstyle[:]
3696 self._selstyle._normal = True
3697 self.DrawBuiltinStyle(dc, self._selstyle, rect, index, selection)
3698 self._selstyle = oldselstyle
3699
3700 elif style._gradient:
3701 if self._selstyle._normal:
3702 if style._gradient & ThemeStyle.GRADIENT_VERTICAL:
3703 self.DrawVerticalGradient(dc, rect, index)
3704 else:
3705 self.DrawHorizontalGradient(dc, rect, index)
3706 else:
3707 oldselstyle = self._selstyle[:]
3708 self._selstyle._normal = True
3709 self.DrawBuiltinStyle(dc, self._selstyle, rect, index, selection)
3710 self._selstyle = oldselstyle
3711
3712 elif style._silver:
3713 if self._selstyle._normal:
3714 self.DrawSilverTheme(dc, rect, index==selection)
3715 else:
3716 oldselstyle = self._selstyle[:]
3717 self._selstyle._normal = True
3718 self.DrawBuiltinStyle(dc, self._selstyle, rect, index, selection)
3719 self._selstyle = oldselstyle
3720
3721
3722 def DrawGradientOnTab(self, dc, rect, col1, col2):
3723 """ Draw A Gradient Coloured Tab. """
3724
3725 dc.SetPen(wx.TRANSPARENT_PEN)
3726
3727 r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
3728 r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
3729
3730 flrect = float(rect.height)
3731
3732 rstep = float((r2 - r1)) / flrect
3733 gstep = float((g2 - g1)) / flrect
3734 bstep = float((b2 - b1)) / flrect
3735
3736 rf, gf, bf = 0, 0, 0
3737
3738 counter = 0
3739
3740 for y in xrange(rect.y+1, rect.y + rect.height):
3741 currCol = (r1 + rf, g1 + gf, b1 + bf)
3742
3743 dc.SetBrush(wx.Brush(currCol, wx.SOLID))
3744 if counter == 0:
3745 xpos = rect.x + 2
3746 xend = rect.width - 4
3747 elif counter == 1:
3748 xpos = rect.x + 1
3749 xend = rect.width - 2
3750 else:
3751 xpos = rect.x
3752 xend = rect.width
3753
3754 counter = counter + 1
3755
3756 dc.DrawRectangle(xpos, y, xend, 1)
3757 rf = rf + rstep
3758 gf = gf + gstep
3759 bf = bf + bstep
3760
3761 self._lastcolour = currCol
3762
3763 def _CalcBestWidth(self, dc):
3764 return max(self._CalcMaxTabWidth(dc), self._CalcSizeToggleBestSize()[0])
3765
3766 def _CalcMaxTabWidth(self, dc):
3767 self._CalcMaxTextHeight(dc)
3768 textWidth = max(self._maxtabwidths)
3769 tabIndex = self._maxtabwidths.index(textWidth)
3770 bmpWidth, bmpHeight = self._CalcTabBitmapSize(tabIndex)
3771 tabrect = self._CalcTabRect(tabIndex, 0, 0, textWidth, bmpWidth, bmpHeight)
3772 # return the width based on the longest label, plus 3 for
3773 # the additional width of the selected tab
3774 return tabrect.width + 3
3775
3776 def _CalcMaxTextHeight(self, dc):
3777 if self._somethingchanged:
3778 minheight, maxfont = self.GetAllTextExtents(dc)
3779 self._minheight = minheight
3780 self._maxfont = maxfont
3781 else:
3782 minheight = self._minheight
3783 maxfont = self._maxfont
3784
3785 dc.SetFont(maxfont)
3786 _, height = dc.GetTextExtent("Aq")
3787 self._maxtextheight = height
3788
3789 def _CalcSizeToggleBestSize(self):
3790 if self._sizeToggleButton:
3791 return self._sizeToggleButton.GetBestSize()
3792 else:
3793 return wx.Size(0,0)
3794
3795 def _CalcTabBitmapPosition(self, tabIndex, bmpWidth, bmpHeight, tabrect):
3796
3797 if self._style & NC_ROTATE:
3798 bmpposx = tabrect.x + (tabrect.width - bmpWidth) / 2
3799 yoffset = self._padding.x
3800 if self._style & NC_LEFT:
3801 bmpposx += 1
3802 bmpposy = tabrect.y + tabrect.height - (yoffset + bmpHeight)
3803 else:
3804 bmpposy = tabrect.y + yoffset
3805 if tabIndex == self.GetSelection():
3806 bmpposx += self._style & NC_LEFT and -1 or 1
3807 else:
3808 bmpposx = tabrect.x + self._padding.x
3809 bmpposy = tabrect.y + (tabrect.height - bmpHeight) / 2
3810 if tabIndex == self.GetSelection() and self._style & NC_TOP:
3811 bmpposy -= 1
3812
3813 return (bmpposx, bmpposy)
3814
3815 def _CalcTabBitmapSize(self, tabIndex):
3816 result = (0, 0)
3817 bmp = self._GetTabBitmap(tabIndex)
3818 bmpOk = bmp.Ok()
3819 if bmpOk:
3820 result = (bmp.GetWidth(), bmp.GetHeight())
3821 return result
3822
3823 def _CalcTabBitmapSpace(self, bmpWidth, bmpHeight):
3824 space = self._padding.x
3825 bmpSpace = self._style & NC_ROTATE and bmpHeight or bmpWidth
3826 if bmpSpace:
3827 space = space + self._padding.x + bmpSpace
3828 return space
3829
3830 def _CalcTabRect(self, tabIndex, posx, posy, textWidth, bmpWidth, bmpHeight):
3831
3832 xpos = posx
3833 if self._style & NC_BOTTOM:
3834 ypos = 1
3835 elif self._style & NC_TOP:
3836 ypos = self.GetSize().y - self._maxtextheight - self._padding.y*2
3837 else:
3838 ypos = posy
3839
3840 xsize = textWidth + self._CalcTabBitmapSpace(bmpWidth, bmpHeight) + \
3841 self._padding.x + self._incrtext[tabIndex] + \
3842 self._CalcXWidth()
3843
3844 ysize = self._maxtextheight + self._padding.y*2
3845 if self._style & NC_TOP:
3846 ysize += 3
3847
3848 if self._style & NC_ROTATE:
3849 xsize, ysize = (ysize, xsize)
3850
3851 if tabIndex == self.GetSelection():
3852 if self._style & NC_TOP or self._style & NC_BOTTOM:
3853 xsize = xsize + self._spacetabs
3854 if tabIndex > 0:
3855 xpos = xpos - self._spacetabs
3856 xsize = xsize + self._spacetabs
3857 if self._style & NC_TOP:
3858 ypos -= 3
3859 ysize = ysize + 2
3860 else:
3861 xsize += 3
3862
3863 if self._style & NC_LEFT:
3864 xpos = self.GetSize().width - xsize
3865 return wx.Rect(xpos, ypos, xsize, ysize)
3866
3867 def _CalcTabTextPosition(self, tabIndex, tabrect, space):
3868 xtextpos = tabrect.x + space + self._incrtext[tabIndex]/2
3869
3870 if self._style & NC_BOTTOM:
3871 ytextpos = self._padding.y
3872 else:
3873 ytextpos = tabrect.y + self._padding.y + 1
3874 if tabIndex == self.GetSelection():
3875 if tabIndex == 0 and self._style & NC_TOP or self._style & NC_BOTTOM:
3876 xtextpos = xtextpos + self._spacetabs/2.0 + 1
3877 if self._style & NC_BOTTOM:
3878 ytextpos += 2
3879 elif self._style & NC_TOP:
3880 ytextpos -= 2
3881
3882 if self._style & NC_ROTATE:
3883 xoffset = ytextpos - tabrect.y
3884 yoffset = xtextpos - tabrect.x
3885 if self._style & NC_LEFT:
3886 xtextpos, ytextpos = (tabrect.x + xoffset - 1,
3887 tabrect.y + tabrect.height - yoffset)
3888 else:
3889 yoffset += self._CalcXWidth()
3890 xtextpos, ytextpos = (tabrect.x + tabrect.width - xoffset,
3891 tabrect.y + yoffset)
3892
3893 return (xtextpos, ytextpos)
3894
3895 def _CalcTabTextWidth(self, dc, tabIndex):
3896 if self._style & NC_FIXED_WIDTH:
3897 result = max(self._maxtabwidths)
3898 else:
3899 dc.SetFont(self.GetPageTextFont(tabIndex))
3900 result, _ = dc.GetTextExtent(self.GetPageText(tabIndex))
3901 return result
3902
3903 def _CalcXRect(self, tabrect):
3904 result = None
3905 drawx, dxstyle = self.GetDrawX()
3906 if drawx:
3907 if dxstyle == 1:
3908 mins = min(self._padding.x, self._padding.y) + 1
3909 mins = min(mins, 6)
3910 xoffset = tabrect.width-mins-3
3911 yoffset = 2
3912 xsize = ysize = mins+1
3913 else:
3914 if self._style & NC_ROTATE:
3915 xoffset = (tabrect.width-self._maxtextheight-self._padding.y/2)/2
3916 yoffset = self._padding.x/2
3917 else:
3918 xoffset = tabrect.width-self._maxtextheight-self._padding.x
3919 yoffset = (tabrect.height-self._maxtextheight-self._padding.y/2)/2
3920 xsize = ysize = self._maxtextheight
3921 result = wx.Rect(tabrect.x+xoffset, tabrect.y+yoffset, xsize, ysize)
3922 return result
3923
3924 def _CalcXWidth(self):
3925 drawx, dxstyle = self.GetDrawX()
3926 if drawx:
3927 if dxstyle == 1:
3928 xxspace = self._padding.x/2
3929 else:
3930 xxspace = self._padding.x + self._maxtextheight
3931 else:
3932 xxspace = 0
3933 return xxspace
3934
3935 def _ClipAtPaperEdge(self, dc, tabrect, tabIndex):
3936 selected = tabIndex == self.GetSelection()
3937 if self._style & NC_TOP:
3938 cliprect = (tabrect.x, tabrect.y, tabrect.width,
3939 selected and tabrect.height - 2 or tabrect.height-3)
3940 elif self._style & NC_LEFT:
3941 cliprect = (tabrect.x, tabrect.y, tabrect.width - 2, tabrect.height)
3942 elif self._style & NC_BOTTOM:
3943 cliprect = (tabrect.x, tabrect.y + 2, tabrect.width, tabrect.height - 2)
3944 else:
3945 cliprect = (tabrect.x + 2, tabrect.y, tabrect.width - 2, tabrect.height)
3946 dc.SetClippingRegion(*cliprect)
3947
3948 def _CreateSizeToggleButton(self):
3949 buttonlabel = self._expanded and "<<" or ">>"
3950 self._sizeToggleButton = wx.Button(self, wx.NewId(),
3951 pos = wx.Point(0,0,), label = buttonlabel, style=wx.BU_EXACTFIT)
3952 font = self._sizeToggleButton.GetFont()
3953 if font.GetPointSize() > 6:
3954 font.SetPointSize(6)
3955 self._sizeToggleButton.SetFont(font)
3956 self.Bind(wx.EVT_BUTTON, self._ToggleSize, self._sizeToggleButton)
3957
3958
3959 def _DrawBackground(self, dc, paintTools):
3960 #background
3961 size = self.GetSize()
3962 dc.SetBrush(paintTools.BackBrush)
3963
3964 if not (self._style & wx.NO_BORDER):
3965 # full border
3966 dc.SetPen(paintTools.BorderPen)
3967 dc.SetPen(paintTools.HighlightPen)
3968 dc.DrawRectangle(0, 0, size.x, size.y)
3969
3970 else:
3971 dc.SetPen(paintTools.BackPen)
3972 dc.DrawRectangle(0, 0, size.x, size.y)
3973 self._DrawPageEdge(dc, paintTools)
3974
3975 def _DrawFocusIndicator(self, dc, paintTools, tabrect):
3976 if self.GetUseFocusIndicator():
3977 dc.SetBrush(wx.TRANSPARENT_BRUSH)
3978 dc.SetPen(paintTools.FocusPen)
3979 dc.DrawRoundedRectangle(tabrect.x+self._padding.x/2, tabrect.y+self._padding.y/2,
3980 tabrect.width-self._padding.x,
3981 tabrect.height-self._padding.y-2, 2)
3982
3983 def _DrawPageEdge(self, dc, paintTools):
3984 if self._style & NC_TOP:
3985 dc.SetPen(paintTools.HighlightPen)
3986 dc.DrawLine(0, self.GetSize().y-1, self.GetSize().x, self.GetSize().y-1)
3987 else:
3988 if not self._tabstyle._normal or self._usegradients:
3989 dc.SetPen(paintTools.HighlightPen)
3990 else:
3991 dc.SetPen(paintTools.BorderPen)
3992 if self._style & NC_BOTTOM:
3993 dc.DrawLine(0, 1, self.GetSize().x, 1)
3994 elif self._style & NC_LEFT:
3995 dc.DrawLine(self.GetSize().width - 1, 0, self.GetSize().width - 1, self.GetSize().height)
3996 elif self._style & NC_RIGHT:
3997 dc.DrawLine(0, 0, 0, self.GetSize().height)
3998
3999 def _DrawTab(self, dc, paintTools, tabrect, tabIndex):
4000 size = self.GetSize()
4001 self._DrawTabGradientOutline(dc, paintTools, tabrect, tabIndex)
4002 self._FillTab(dc, paintTools, tabrect, tabIndex)
4003 self._DrawTabOutline(dc, paintTools, tabrect, tabIndex)
4004 self._DrawTabPageEdge(dc, paintTools, tabrect, tabIndex)
4005 self._HighlightTabEdge(dc, paintTools, tabrect)
4006 self._ShadowTabEdge(dc, paintTools, tabrect)
4007
4008 def _DrawTabBitmap(self, dc, tabIndex, bmpposx, bmpposy):
4009 bmpindex = self.GetPageImage(tabIndex)
4010 if self.IsPageEnabled(tabIndex):
4011 self._imglist.Draw(bmpindex, dc, bmpposx, bmpposy,
4012 wx.IMAGELIST_DRAW_TRANSPARENT, True)
4013 else:
4014 self._grayedlist.Draw(bmpindex, dc, bmpposx, bmpposy,
4015 wx.IMAGELIST_DRAW_TRANSPARENT, True)
4016
4017 def _DrawTabGradientOutline(self, dc, paintTools, tabrect, tabIndex):
4018 if not self._tabstyle._normal or self._usegradients:
4019 if tabIndex != self.GetSelection() and self._style & NC_TOP:
4020 dc.SetBrush(wx.TRANSPARENT_BRUSH)
4021 dc.SetPen(paintTools.ShadowPen)
4022 dc.DrawRoundedRectangle(tabrect.x+1, tabrect.y+1, tabrect.width, tabrect.height-1, 3)
4023
4024 def _DrawTabOutline(self, dc, paintTools, tabrect, tabIndex):
4025 if not self._tabstyle._normal or self._usegradients:
4026 dc.SetBrush(wx.TRANSPARENT_BRUSH)
4027 dc.SetPen(paintTools.HighlightPen)
4028 else:
4029 dc.SetBrush(wx.Brush(self.GetPageColour(tabIndex)))
4030 if self._style & NC_TOP:
4031 dc.SetPen(paintTools.HighlightPen)
4032 else:
4033 dc.SetPen(paintTools.BorderPen)
4034 self._ClipAtPaperEdge(dc, tabrect, tabIndex)
4035 dc.DrawRoundedRectangle(tabrect.x, tabrect.y, tabrect.width, tabrect.height, 3)
4036 dc.DestroyClippingRegion()
4037
4038 def _DrawTabPageEdge(self, dc, paintTools, tabrect, tabIndex):
4039 if not self._tabstyle._normal or self._usegradients:
4040 edgePen = paintTools.HighlightPen
4041 else:
4042 if self._style & NC_TOP:
4043 edgePen = paintTools.HighlightPen
4044 else:
4045 edgePen = paintTools.BorderPen
4046
4047 if tabIndex == self.GetSelection():
4048 # un-paint the line at the paper edge
4049 cancelPen = wx.Pen(self.GetPageColour(tabIndex))
4050 dc.SetPen(cancelPen)
4051 if self._style & NC_BOTTOM:
4052 dc.DrawLine(tabrect.x+1, tabrect.y, tabrect.x + tabrect.width, tabrect.y)
4053 elif self._style & NC_LEFT:
4054 dc.DrawLine(tabrect.x + tabrect.width-1, tabrect.y, tabrect.x + tabrect.width-1, tabrect.y + tabrect.height)
4055 elif self._style & NC_RIGHT:
4056 dc.DrawLine(tabrect.x, tabrect.y, tabrect.x, tabrect.y + tabrect.height)
4057
4058 if tabIndex != self.GetSelection():
4059 if self._style & NC_TOP:
4060 dc.DrawLine(tabrect.x, self.GetSize().y-1, tabrect.x + tabrect.width, self.GetSize().y-1)
4061
4062 # draw sharp corners at the paper edge
4063 dc.SetPen(edgePen)
4064 if self._style & NC_BOTTOM:
4065 dc.DrawLine(tabrect.x, tabrect.y, tabrect.x, tabrect.y + 2)
4066 dc.DrawLine((tabrect.x + tabrect.width)-1, tabrect.y,
4067 (tabrect.x + tabrect.width)-1, tabrect.y + 2)
4068 elif self._style & NC_LEFT:
4069 dc.DrawLine(self.GetSize().width - 2, tabrect.y, self.GetSize().width, tabrect.y)
4070 dc.DrawLine(self.GetSize().width - 2, tabrect.y + tabrect.height - 1, self.GetSize().width, tabrect.y + tabrect.height - 1)
4071 elif self._style & NC_RIGHT:
4072 dc.DrawLine(tabrect.x, tabrect.y, tabrect.x + 2, tabrect.y)
4073 dc.DrawLine(tabrect.x, tabrect.y + tabrect.height - 1, tabrect.x + 2, tabrect.y + tabrect.height - 1)
4074
4075 def _DrawTabText(self, dc, tabIndex, xtextpos, ytextpos):
4076 dc.SetFont(self.GetPageTextFont(tabIndex))
4077 dc.SetTextForeground(self._GetTabTextColour(tabIndex))
4078 dc.SetBrush(wx.TRANSPARENT_BRUSH)
4079 if self._style & NC_ROTATE:
4080 angle = (self._style & NC_LEFT) and 90.0 or 270.0
4081 dc.DrawRotatedText(self.GetPageText(tabIndex), xtextpos, ytextpos, angle)
4082 else:
4083 dc.DrawText(self.GetPageText(tabIndex), xtextpos, ytextpos)
4084
4085 def _DrawX(self, dc, tabrect, xrect, textColour):
4086 drawx, dxstyle = self.GetDrawX()
4087 if drawx:
4088 if dxstyle == 1:
4089 mins = min(self._padding.x, self._padding.y) + 1
4090 mins = min(mins, 6)
4091 dc.SetPen(wx.Pen(textColour, 1))
4092 dc.SetBrush(wx.TRANSPARENT_BRUSH)
4093 dc.DrawLine(xrect.x, xrect.y, tabrect.x+tabrect.width-2, tabrect.y+3+mins)
4094 dc.DrawLine(xrect.x, xrect.y+mins, tabrect.x+tabrect.width-2, tabrect.y+1)
4095 dc.DrawRectangle(xrect.x, xrect.y, xrect.width, xrect.height)
4096 elif dxstyle == 2:
4097 dc.SetPen(wx.Pen(textColour))
4098 dc.SetBrush(wx.Brush(textColour))
4099 dc.DrawRoundedRectangle(xrect.x, xrect.y, xrect.width, xrect.height, 2)
4100 dc.SetPen(wx.Pen(self.GetBackgroundColour(), 2))
4101 dc.DrawLine(xrect.x+2, xrect.y+2, xrect.x+xrect.width-3, xrect.y+xrect.height-3)
4102 dc.DrawLine(xrect.x+2, xrect.y+xrect.height-3, xrect.x+xrect.width-3, xrect.y+2)
4103 else:
4104 self._imglist2.Draw(0, dc, xrect.x, xrect.y, wx.IMAGELIST_DRAW_TRANSPARENT, True)
4105
4106 def _EnhanceMultiSelectedTab(self, dc, tabIndex, tabrect):
4107 dc.SetPen(wx.Pen(self._GetTabTextColour(tabIndex), 1, wx.DOT_DASH))
4108 dc.SetBrush(wx.TRANSPARENT_BRUSH)
4109 dc.DrawRoundedRectangle(tabrect.x+self._padding.x/2+1,
4110 tabrect.y+self._padding.y/2+1,
4111 tabrect.width-self._padding.x-2,
4112 tabrect.height-self._padding.y-2-2, 2)
4113
4114 def _EnhanceSelectedTab(self, dc, paintTools, tabrect):
4115 xselpos = tabrect.x
4116 xselsize = tabrect.width
4117 yselsize = tabrect.height
4118
4119 if self._style & NC_BOTTOM:
4120 yselpos = (tabrect.y + tabrect.height) - 2
4121 elif self._style & NC_TOP:
4122 yselpos = tabrect.y
4123
4124 self._HighlightSelectedTabEdge(dc, paintTools, tabrect)
4125 self._ShadowTabEdge(dc, paintTools, tabrect)
4126 self._DrawFocusIndicator(dc, paintTools, tabrect)
4127
4128 def _FillTab(self, dc, paintTools, tabrect, tabIndex):
4129 if self._usegradients:
4130 self.DrawGradientOnTab(dc, tabrect, self._pages[tabIndex]._firstcolour,
4131 self._pages[tabIndex]._secondcolour)
4132 elif not self._tabstyle._normal:
4133 self.DrawBuiltinStyle(dc, self._tabstyle, tabrect, tabIndex,
4134 self.GetSelection())
4135
4136 def _GetPaintTools(self):
4137 back_colour = self.GetBackgroundColour()
4138 back_brush = wx.Brush(back_colour)
4139 back_pen = wx.Pen(back_colour)
4140
4141 border_pen = self._borderpen
4142 highlightpen = self._highlightpen
4143 if self._tabstyle._normal and not self._usegradients:
4144 highlightpen = self._highlightpen2
4145
4146 shadowpen = self._shadowpen
4147 upperhighpen = self._upperhigh
4148
4149 if self.GetHighlightSelection():
4150 selectionpen = wx.Pen(self._selectioncolour)
4151 selectionEdgePen = wx.Pen(self._selectionedgecolour)
4152 else:
4153 selectionpen = selectionEdgePen = None
4154
4155 x_pen = self.GetDrawX() == 1 and wx.BLACK_PEN or None
4156 focusindpen = self.GetUseFocusIndicator() and self._focusindpen or None
4157
4158 return _TabCtrlPaintTools(back_brush, back_pen, border_pen, highlightpen,
4159 shadowpen, upperhighpen, selectionpen, selectionEdgePen, x_pen,
4160 focusindpen)
4161
4162 def _GetTabBitmap(self, tabIndex):
4163 bmp = wx.NullBitmap
4164 if self.GetPageImage(tabIndex) >= 0:
4165 bmpindex = self.GetPageImage(tabIndex)
4166 if self.IsPageEnabled(tabIndex):
4167 bmp = self._imglist.GetBitmap(bmpindex)
4168 else:
4169 bmp = self._grayedlist.GetBitmap(bmpindex)
4170 return bmp
4171
4172 def _GetTabTextColour(self, tabIndex):
4173 if self.IsPageEnabled(tabIndex):
4174 result = self.GetPageTextColour(tabIndex)
4175 else:
4176 result = self._disabledcolour
4177 return result
4178
4179 def _GetThemePageColour(self, index):
4180 if self._tabstyle._macstyle:
4181 return NC_MAC_LIGHT
4182 elif self._tabstyle._kdetheme:
4183 return kdetheme[0]
4184 elif self._tabstyle._aqua:
4185 if index == self.GetSelection():
4186 return topaqua1[0]
4187 else:
4188 return distaqua[0]
4189 elif self._tabstyle._metal:
4190 intens = (230 + 80 * (self._tabrect[0].y-self._tabrect[0].y+1)/self._tabrect[0].height)
4191 return wx.Colour(intens, intens, intens)
4192 elif self._tabstyle._silver:
4193 if index == self.GetSelection():
4194 return silvertheme1[0]
4195 else:
4196 return silvertheme2[0]
4197 elif self._tabstyle._gradient:
4198 color = wx.WHITE
4199 if self._tabstyle._gradient & ThemeStyle.GRADIENT_VERTICAL:
4200 if self._style & NC_TOP:
4201 color = self._tabstyle.GetSecondGradientColour(index)
4202 elif self._style & NC_BOTTOM:
4203 color = self._tabstyle.GetFirstGradientColour(index)
4204 elif self._tabstyle._gradient & ThemeStyle.GRADIENT_HORIZONTAL and \
4205 self._style & NC_ROTATE:
4206 if self._style & NC_LEFT:
4207 color = self._tabstyle.GetSecondGradientColour(index)
4208 else:
4209 color = self._tabstyle.GetFirstGradientColour(index)
4210 return color
4211
4212 def _HighlightSelectedTabEdge(self, dc, paintTools, tabrect):
4213 if self._style & NC_ROTATE:
4214 yselpos = tabrect.y + 3
4215 yselsize = tabrect.height - 6
4216 xselpos = self._style & NC_RIGHT and tabrect.x + tabrect.width - 1 or tabrect.x
4217 if self.GetHighlightSelection():
4218 dc.SetBrush(paintTools.BackBrush)
4219 dc.SetPen(paintTools.SelectionEdgePen)
4220 dc.DrawLine(xselpos, yselpos, xselpos, yselpos + yselsize)
4221 dc.SetPen(paintTools.SelectionPen)
4222 for band in range(2):
4223 if self._style & NC_RIGHT:
4224 xselpos -= 1
4225 else:
4226 xselpos += 1
4227 yselpos -= 1
4228 yselsize += 2
4229 dc.DrawLine(xselpos, yselpos, xselpos, yselpos + yselsize)
4230 else:
4231 dc.SetPen(paintTools.HighlightPen)
4232 dc.DrawLine(xselpos, yselpos, xselpos, yselpos + yselsize)
4233 else:
4234 xselpos = tabrect.x + 3
4235 xselsize = tabrect.width - 6
4236
4237 if self._style & NC_BOTTOM:
4238 yselpos = tabrect.y + tabrect.height - 1
4239 else:
4240 yselpos = tabrect.y
4241 dc.SetPen(paintTools.HighlightPen)
4242 dc.DrawLine(xselpos, yselpos, xselpos + xselsize, yselpos)
4243
4244 if self.GetHighlightSelection():
4245 dc.SetBrush(paintTools.BackBrush)
4246 dc.SetPen(paintTools.SelectionEdgePen)
4247 dc.DrawLine(xselpos, yselpos, xselpos + xselsize, yselpos)
4248 dc.SetPen(paintTools.SelectionPen)
4249 for band in range(2):
4250 if self._style & NC_BOTTOM:
4251 yselpos -= 1
4252 else:
4253 yselpos += 1
4254 xselpos -= 1
4255 xselsize += 2
4256 dc.DrawLine(xselpos, yselpos, xselpos + xselsize, yselpos)
4257
4258 def _HighlightTabEdge(self, dc, paintTools, tabrect):
4259 if not self._tabstyle._normal or self._usegradients:
4260 if self._style & NC_TOP:
4261 dc.SetPen(paintTools.UpperHighlightPen)
4262 dc.DrawLine(tabrect.x+2, tabrect.y-1, tabrect.x + tabrect.width - 2, tabrect.y-1)
4263 else:
4264 if self._style & NC_TOP:
4265 dc.SetPen(paintTools.HighlightPen)
4266 dc.DrawLine(tabrect.x + 3, tabrect.y, tabrect.x + tabrect.width - 3, tabrect.y)
4267
4268 def _InitExpandableStyles(self, style):
4269 self._expanded = not style & NC_ROTATE
4270 if self._expanded:
4271 self._expandedstyle = style
4272 self._contractedstyle = style | NC_ROTATE
4273 else:
4274 self._contractedstyle = style
4275 self._expandedstyle = (style ^ NC_ROTATE) | NC_FIXED_WIDTH
4276
4277 def _InitExpandableTabStyles(self, style, expanded, tabstyle):
4278 if tabstyle._gradient:
4279 alternatestyle = ThemeStyle()
4280 firstcolor = tabstyle.GetFirstGradientColour()
4281 secondcolor = tabstyle.GetSecondGradientColour()
4282 swapcolors = (tabstyle._gradient & ThemeStyle.GRADIENT_VERTICAL and style & NC_RIGHT and expanded) or \
4283 (tabstyle._gradient & ThemeStyle.GRADIENT_HORIZONTAL and style & NC_RIGHT and not expanded)
4284 if swapcolors:
4285 firstcolor, secondcolor = (secondcolor, firstcolor)
4286 if tabstyle._gradient & ThemeStyle.GRADIENT_VERTICAL:
4287 othergradient = (tabstyle._gradient ^ ThemeStyle.GRADIENT_VERTICAL) | ThemeStyle.GRADIENT_HORIZONTAL
4288 else:
4289 othergradient = (tabstyle._gradient ^ ThemeStyle.GRADIENT_HORIZONTAL) | ThemeStyle.GRADIENT_VERTICAL
4290 alternatestyle.EnableGradientStyle(True, othergradient)
4291 alternatestyle.SetFirstGradientColour(firstcolor)
4292 alternatestyle.SetSecondGradientColour(secondcolor)
4293 if tabstyle._gradient & ThemeStyle.DIFFERENT_GRADIENT_FOR_SELECTED:
4294 firstcolor = tabstyle.GetFirstGradientColour(True)
4295 secondcolor = tabstyle.GetSecondGradientColour(True)
4296 if swapcolors:
4297 firstcolor, secondcolor = (secondcolor, firstcolor)
4298 alternatestyle.SetFirstGradientColourSelected(firstcolor)
4299 alternatestyle.SetSecondGradientColourSelected(secondcolor)
4300 if expanded:
4301 self._expandedtabstyle = tabstyle
4302 self._contractedtabstyle = alternatestyle
4303 else:
4304 self._contractedtabstyle = tabstyle
4305 self._expandedtabstyle = alternatestyle
4306 else:
4307 self._expandedtabstyle = tabstyle
4308 self._contractedtabstyle = tabstyle
4309
4310 def _OnStyleChange(self):
4311 if self._style & NC_TOP or self._style & NC_BOTTOM:
4312 self.SetBestSize((-1, newheight))
4313 else:
4314 self.SetBestSize((self._CalcBestWidth(wx.ClientDC(self)), -1))
4315 self._parent.GetSizer().Layout()
4316 self._somethingchanged = True
4317 self._firsttime = True
4318 self.Refresh()
4319
4320 def _ShadowTabEdge(self, dc, paintTools, tabrect):
4321 dc.SetPen(paintTools.ShadowPen)
4322 if self._style & NC_BOTTOM:
4323 dc.DrawLine((tabrect.x + tabrect.width), tabrect.y+1,
4324 (tabrect.x+tabrect.width), tabrect.y + tabrect.height-4)
4325 elif self._style & NC_TOP:
4326 dc.DrawLine(tabrect.x + tabrect.width, tabrect.y+3,
4327 tabrect.x+tabrect.width, tabrect.y+tabrect.height-4)
4328
4329 def OnPaint(self, event):
4330 """ Handles The wx.EVT_PAINT Event For TabCtrl. """
4331
4332 dc = wx.BufferedPaintDC(self)
4333
4334 if self.GetPageCount() == 0:
4335 event.Skip()
4336 return
4337
4338 pt = self._GetPaintTools()
4339
4340 dc.BeginDrawing()
4341
4342 self._DrawBackground(dc, pt)
4343
4344 self._CalcMaxTextHeight(dc)
4345
4346 posx = self._firsttabpos.x
4347 posy = self._firsttabpos.y
4348
4349 if self._style & NC_LEFT:
4350 _ = 1
4351
4352 if self._firsttime:
4353 if not hasattr(self, "_initrect"):
4354 self._initrect = []
4355 if self.HasSpinButton() and self._fromdnd:
4356 self._firstvisible = self._spinbutton.GetValue()
4357 self._firsttime = False
4358 self._fromdnd = False
4359 else:
4360 self._initrect = []
4361 self._firstvisible = 0
4362 else:
4363 if self.HasSpinButton():
4364 self._firstvisible = self._spinbutton.GetValue()
4365 else:
4366 self._firstvisible = 0
4367
4368 lastvisible = self.GetPageCount()
4369
4370 #and tabs
4371 oncount = -1
4372
4373 self._tabvisible = [1]*self.GetPageCount()
4374
4375 tabrect = []
4376 # some theme style rendering routines expect this to exist, so
4377 # set it now:
4378 self._tabrect = tabrect
4379 Xrect = []
4380
4381 for ii in xrange(self._firstvisible, lastvisible):
4382 if not self._enablehiding or not self._pages[ii]._ishidden:
4383
4384 oncount = oncount + 1
4385
4386 self._tabvisible[ii] = 1
4387
4388 newwidth = self._CalcTabTextWidth(dc, ii)
4389
4390 bmpWidth, bmpHeight = self._CalcTabBitmapSize(ii)
4391
4392 tabrect.append(self._CalcTabRect(ii, posx, posy,
4393 newwidth, bmpWidth, bmpHeight))
4394
4395 self._DrawTab(dc, pt, tabrect[-1], ii)
4396
4397 self._DrawTabText(dc, ii, *self._CalcTabTextPosition(ii,
4398 tabrect[-1], self._CalcTabBitmapSpace(bmpWidth, bmpHeight)))
4399
4400 if bmpWidth:
4401 self._DrawTabBitmap(dc, ii, *self._CalcTabBitmapPosition(ii,
4402 bmpWidth, bmpHeight, tabrect[-1]))
4403
4404 if self.GetSelection() in [ii, ii - 1]:
4405 # Handle this special case on the selected tab and
4406 # on the tab that follows it (if there is one), to ensure
4407 # proper rendering of the selected tab's right edge
4408 self._EnhanceSelectedTab(dc, pt, tabrect[self.GetSelection() - self._firstvisible])
4409
4410 if self.GetDrawX()[0]:
4411 Xrect.append(self._CalcXRect(tabrect[-1]))
4412 self._DrawX(dc, tabrect[-1], Xrect[-1],
4413 self._GetTabTextColour(ii))
4414
4415 if ii in self._selectedtabs:
4416 self._EnhanceMultiSelectedTab(dc, ii, tabrect[-1])
4417
4418 if self._style & NC_TOP or self._style & NC_BOTTOM:
4419 # horizontally positioned tabs along top or bottom
4420 posx = posx + tabrect[-1].width
4421 else:
4422 # vertically stacked tabs along side
4423 posy = posy + tabrect[-1].height
4424
4425 if self._firsttime:
4426 self._initrect.append(tabrect[oncount])
4427
4428 else:
4429
4430 self._tabvisible[ii] = 0
4431
4432 self._xrect = Xrect
4433
4434 if self._firsttime:
4435 self._firsttime = False
4436
4437 self.UpdateMenuButton(self.HasMenuButton())
4438 self.UpdateSpinButton()
4439
4440 if self._enabledragging:
4441 if self._isdragging and not self._isleaving:
4442 self.DrawInsertionMark(dc, self._olddragpos)
4443
4444 dc.EndDrawing()
4445
4446
4447 # ---------------------------------------------------------------------------- #
4448 # Class NotebookCtrl
4449 # This Is The Main Class Implementation
4450 # ---------------------------------------------------------------------------- #
4451
4452 class NotebookCtrl(wx.Panel):
4453 """
4454 Display one or more windows in a notebook.
4455
4456 B{Events}:
4457 - B{EVT_NOTEBOOKCTRL_PAGE_CHANGING}: sent when the active
4458 page in the notebook is changing
4459 - B{EVT_NOTEBOOKCTRL_PAGE_CHANGED}: sent when the active
4460 page in the notebook has changed
4461 - B{EVT_NOTEBOOKCTRL_PAGE_CLOSING}: sent when a page in the
4462 notebook is closing
4463 - B{EVT_NOTEBOOKCTRL_PAGE_DND}: sent when a page has been
4464 dropped onto the notebook in a drag-drop operation
4465 - B{EVT_NOTEBOOKCTRL_PAGE_DCLICK}: sent when the user
4466 double-clicks a tab in the notebook
4467 - B{EVT_NOTEBOOKCTRL_PAGE_RIGHT}: sent when the user
4468 clicks a tab in the notebook with the right mouse
4469 button
4470 - B{EVT_NOTEBOOKCTRL_PAGE_MIDDLE}: sent when the user
4471 clicks a tab in the notebook with the middle mouse
4472 button
4473 """
4474
4475 def __init__(self, parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize,
4476 style=NC_DEFAULT_STYLE, sizer=wx.HORIZONTAL, margin=2, name="NotebookCtrl"):
4477 """
4478 Default Class Constructor.
4479
4480 @param style: Style For The NotebookCtrl, Which May Be:
4481 a) NC_TOP: NotebookCtrl Placed On Top (Default);
4482 b) NC_BOTTOM: NotebookCtrl Placed At The Bottom;
4483 c) NC_LEFT: NotebookCtrl Placed At The Left;
4484 d) NC_RIGHT: NotebookCtrl Placed At The Right;
4485 e) NC_FIXED_WIDTH: All Tabs Have The Same Width;
4486 f) wx.NO_BORDER: Shows No Border For The Control (Default, Looks Better);
4487 g) wx.STATIC_BORDER: Shows A Static Border On The Control.
4488
4489 @param sizer: The Sizer Orientation For The Sizer That Holds
4490 All The Panels: Changing This Style Is Only Useful When You
4491 Use The Tile Method. In This Case, If sizer=wx.HORIZONTAL,
4492 All The Panels Will Be Shown In Columns, While If
4493 sizer=wx.VERTICAL All The Panels Will Be Shown In Rows.
4494
4495 @param margin: An Integer Number Of Pixels That Add Space
4496 Above TabCtrl If style=NC_TOP, Or Below It If
4497 style=NC_BOTTOM
4498 """
4499
4500 wx.Panel.__init__(self, parent, -1, style=wx.NO_FULL_REPAINT_ON_RESIZE |
4501 wx.CLIP_CHILDREN, name=name)
4502
4503 self.nb = TabCtrl(self, -1, pos, size, style)
4504
4505 self._notebookpages = []
4506
4507 if style & NC_TOP == 0 and style & NC_BOTTOM == 0 \
4508 and style & NC_LEFT == 0 and style & NC_RIGHT == 0:
4509 style = style | NC_TOP
4510
4511 if style & wx.NO_BORDER == 0 and \
4512 style & wx.STATIC_BORDER == 0:
4513 style = style | wx.NO_BORDER
4514
4515 self._style = style
4516 self._showcolumns = False
4517 self._showtabs = True
4518 self._sizerstyle = sizer
4519 self._custompanel = None
4520 self._focusswitch = False
4521 self._oldfocus = None
4522
4523 if style & NC_TOP or style & NC_BOTTOM:
4524 self.sizer = wx.BoxSizer(wx.VERTICAL)
4525 self.tabsizer = wx.BoxSizer(wx.VERTICAL)
4526 else:
4527 self.sizer = wx.BoxSizer(wx.HORIZONTAL)
4528 self.tabsizer = wx.BoxSizer(wx.HORIZONTAL)
4529
4530 self.bsizer = wx.BoxSizer(sizer)
4531
4532 if style & NC_TOP or style & NC_BOTTOM:
4533 tabBorderFlag = wx.LEFT | wx.RIGHT
4534 else:
4535 tabBorderFlag = wx.TOP | wx.BOTTOM
4536
4537 if style & NC_TOP or style & NC_LEFT:
4538 self.sizer.Add(self.tabsizer, 0, wx.EXPAND | tabBorderFlag, 2)
4539 self._AddMargin(style, margin)
4540 self.tabsizer.Add(self.nb, 0, wx.EXPAND)
4541 self.sizer.Add(self.bsizer, 1, wx.EXPAND)
4542 elif style & NC_BOTTOM or style & NC_RIGHT:
4543 self.sizer.Add(self.bsizer, 1, wx.EXPAND)
4544 self.sizer.Add(self.tabsizer, 0, wx.EXPAND | tabBorderFlag, 2)
4545 self.tabsizer.Add(self.nb, 0, wx.EXPAND)
4546 self._AddMargin(style, margin)
4547
4548 self.SetSizer(self.sizer)
4549
4550 self.tabsizer.Show(self.nb, False)
4551
4552 self.sizer.Layout()
4553 self.Bind(wx.EVT_MOTION, self.OnMouseMotion)
4554 self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
4555
4556
4557 def OnKeyDown(self, event):
4558 """
4559 Handles The wx.EVT_KEY_DOWN Event For NotebookCtrl. This Is Only Processed
4560 If The User Navigate Through Tabs With Ctrl-Tab Keyboard Navigation.
4561 """
4562
4563 if event.GetKeyCode == wx.WXK_TAB:
4564 if event.ControlDown():
4565 sel = self.GetSelection()
4566 if sel == self.GetPageCount() - 1:
4567 sel = 0
4568 else:
4569 sel = sel + 1
4570
4571 while not self.IsPageEnabled(sel):
4572 sel = sel + 1
4573 if sel == self.GetPageCount() - 1:
4574 sel = 0
4575
4576 self.SetSelection(sel)
4577
4578 event.Skip()
4579
4580
4581 def OnMouseMotion(self, event):
4582 """ Handles The wx.EVT_MOTION Event For NotebookCtrl. """
4583
4584 if self.nb._enabledragging:
4585
4586 if event.Dragging() and not event.RightIsDown() and not event.MiddleIsDown():
4587
4588 tolerance = 2
4589 pt = event.GetPosition()
4590 dx = abs(pt.x - self.nb._dragstartpos.x)
4591 dy = abs(pt.y - self.nb._dragstartpos.y)
4592 if dx <= tolerance and dy <= tolerance:
4593 self.SetCursor(wx.STANDARD_CURSOR)
4594 return
4595
4596 self.SetCursor(self.nb._dragcursor)
4597 self.nb._isdragging = True
4598
4599 else:
4600
4601 self.nb._isdragging = False
4602 self.SetCursor(wx.STANDARD_CURSOR)
4603
4604 if self.nb._showtooltip:
4605 if self.nb._istooltipshown:
4606 pt = event.GetPosition()
4607 self.nb._insidetab = self.nb.GetInsideTab(pt)
4608 if self.nb._insidetab < 0:
4609 try:
4610 self.nb._tipwindow.Destroy()
4611 self.nb._istooltipshown = False
4612 except:
4613 self.nb._istooltipshown = False
4614
4615 self.nb.Refresh()
4616
4617 event.Skip()
4618
4619
4620 def EnableChildFocus(self, enable=True):
4621 """ Enables/Disables Sending EVT_NOTEBOOKCTRL_PAGE_CHANGING When In Tile Mode. """
4622
4623 self._focusswitch = enable
4624
4625
4626 def FindFocusedPage(self, obj):
4627 """ Find Which NotebookCtrl Page Has The Focus Based On Its Child Focus. """
4628
4629 while 1:
4630 if obj in self._notebookpages:
4631 return obj
4632
4633 try:
4634 obj = obj.GetParent()
4635 except:
4636 return None
4637
4638 return None
4639
4640
4641 def OnFocus(self, event):
4642 """ Handles The wx.EVT_CHILD_FOCUS Event For NotebookCtrl. """
4643
4644 if not self._focusswitch:
4645 event.Skip()
4646 return
4647
4648 newfocus = self.FindFocusedPage(event.GetEventObject())
4649
4650 if newfocus == self._oldfocus or newfocus is None:
4651 event.Skip()
4652 return
4653
4654 self._oldfocus = newfocus
4655
4656 eventOut = NotebookCtrlEvent(wxEVT_NOTEBOOKCTRL_PAGE_CHANGING, self.GetId())
4657
4658 nPage = self._notebookpages.index(newfocus)
4659 eventOut.SetSelection(nPage)
4660 eventOut.SetOldSelection(self.GetSelection())
4661 eventOut.SetEventObject(self)
4662
4663 if not self.GetEventHandler().ProcessEvent(eventOut):
4664
4665 # Program Allows The Page Change
4666 self.nb._selection = nPage
4667 eventOut.SetEventType(wxEVT_NOTEBOOKCTRL_PAGE_CHANGED)
4668 eventOut.SetOldSelection(self.nb._selection)
4669 self.GetEventHandler().ProcessEvent(eventOut)
4670
4671 event.Skip()
4672
4673
4674 def AddPage(self, page, text, select=False, img=-1, hidden=False):
4675 """
4676 Add A Page To The Notebook.
4677
4678 @param page: Specifies The New Page;
4679 @param text: The Tab Text;
4680 @param select: Whether The Page Should Be Selected Or Not;
4681 @param img: Specifies The Optional Image Index For The New Page.
4682 """
4683
4684 self.Freeze()
4685
4686 oldselection = self.nb.GetSelection()
4687
4688 if self.GetPageCount() == 0:
4689 if self.GetCustomPage() is not None:
4690 self.bsizer.Detach(self._custompanel)
4691 self._custompanel.Show(False)
4692 self.bsizer.Layout()
4693
4694 self.bsizer.Add(page, 1, wx.EXPAND | wx.ALL, 2)
4695
4696 self.nb.AddPage(text, select, img, hidden)
4697 self._notebookpages.append(page)
4698
4699 page.Bind(wx.EVT_CHILD_FOCUS, self.OnFocus)
4700
4701 if select:
4702 if oldselection >= 0:
4703 self.bsizer.Show(self.GetPage(oldselection), False)
4704
4705 self.nb.SetSelection(self.GetPageCount()-1)
4706 self.bsizer.Layout()
4707 else:
4708 if oldselection >= 0:
4709 self.bsizer.Show(page, False)
4710 else:
4711 self.bsizer.Show(page, True)
4712 self.nb.SetSelection(self.GetPageCount()-1)
4713 self.bsizer.Layout()
4714
4715 if self.GetPageCount() == 1:
4716
4717 self.bsizer.Show(page, True)
4718
4719 if self.nb._hideonsingletab:
4720
4721 self._ShowTabCtrl(False)
4722
4723 else:
4724 self.nb.Show(True)
4725 self._ShowTabCtrl(True)
4726
4727 else:
4728
4729 self.nb.Show(True)
4730 self._ShowTabCtrl(True)
4731
4732 self.bsizer.Layout()
4733 self.sizer.Layout()
4734
4735 self.Thaw()
4736
4737 self.Tile(self._showcolumns)
4738 self.ShowTabs(self._showtabs)
4739
4740
4741 def InsertPage(self, nPage, page, text, select=False, img=-1, hidden=False):
4742 """
4743 Insert A Page Into The Notebook.
4744
4745 @param page: Specifies The New Page;
4746 @param nPage: Specifies The Position For The New Page;
4747 @param text: The Tab Text;
4748 @param select: Whether The Page Should Be Selected Or Not;
4749 @param img: Specifies The Optional Image Index For The New Page.
4750 @param hidden: C{True} to hide the page; C{False} to display it
4751 """
4752
4753 if nPage < 0 or (self.GetSelection() >= 0 and nPage >= self.GetPageCount()):
4754 raise "\nERROR: Invalid Notebook Page In InsertPage: (" + str(nPage) + ")"
4755
4756 self.Freeze()
4757
4758 oldselection = self.nb.GetSelection()
4759
4760 if self.GetPageCount() == 0:
4761 if self.GetCustomPage() is not None:
4762 self.bsizer.Detach(self._custompanel)
4763 self._custompanel.Show(False)
4764
4765 if oldselection >= 0:
4766 self.bsizer.Show(oldselection, False)
4767 self.bsizer.Layout()
4768
4769 if oldselection >= nPage:
4770 oldselection = oldselection + 1
4771
4772 self.nb.InsertPage(nPage, text, select, img, hidden)
4773 self.bsizer.Insert(nPage, page, 1, wx.EXPAND | wx.ALL, 2)
4774 self._notebookpages.insert(nPage, page)
4775 self.bsizer.Layout()
4776
4777 page.Bind(wx.EVT_CHILD_FOCUS, self.OnFocus)
4778
4779 for ii in xrange(self.GetPageCount()):
4780 self.bsizer.Show(ii, False)
4781
4782 self.bsizer.Layout()
4783
4784 if select:
4785 self.bsizer.Show(nPage, True)
4786 self.bsizer.Layout()
4787 else:
4788 if oldselection >= 0:
4789 self.bsizer.Show(oldselection, True)
4790 self.bsizer.Layout()
4791 else:
4792 self.bsizer.Show(nPage, True)
4793
4794 self.bsizer.Layout()
4795
4796 if self.GetPageCount() == 1:
4797
4798 if self.nb._hideonsingletab:
4799
4800 self._ShowTabCtrl(False)
4801
4802 else:
4803
4804 self.nb.Show(True)
4805 self._ShowTabCtrl(True)
4806
4807 else:
4808
4809 self.nb.Show(True)
4810 self._ShowTabCtrl(True)
4811
4812 self.sizer.Layout()
4813
4814 self.Thaw()
4815
4816 self.Tile(self._showcolumns)
4817 self.ShowTabs(self._showtabs)
4818
4819
4820 def GetPage(self, nPage):
4821 """ Returns The Window At The Given Position nPage. """
4822
4823 if nPage < 0 or nPage >= self.GetPageCount():
4824 raise "\nERROR: Invalid Notebook Page In GetPage: (" + str(nPage) + ")"
4825
4826 return self._notebookpages[nPage]
4827
4828
4829 def DeleteAllPages(self):
4830 """ Deletes All NotebookCtrl Pages. """
4831
4832 self.Freeze()
4833
4834 counter = self.GetPageCount() - 1
4835
4836 for ii in xrange(self.GetPageCount()):
4837 self.bsizer.Detach(counter-ii)
4838 panels = self.GetPage(counter-ii)
4839 panels.Destroy()
4840
4841 self.nb.DeleteAllPages()
4842 self._notebookpages = []
4843 self.nb._selection = -1
4844
4845 self.nb.Show(False)
4846
4847 custom = self.GetCustomPage()
4848
4849 if custom is not None:
4850 self.SetCustomPage(custom)
4851 custom.Show(True)
4852
4853 self.bsizer.Layout()
4854
4855 self._ShowTabCtrl(False)
4856
4857 self.sizer.Layout()
4858
4859 self.Thaw()
4860
4861
4862 def DeletePage(self, nPage):
4863 """ Deletes The Page nPage, And The Associated Window. """
4864
4865 if nPage < 0 or nPage >= self.GetPageCount():
4866 raise "\nERROR: Invalid Notebook Page In DeletePage: (" + str(nPage) + ")"
4867
4868 oldselection = self.GetSelection()
4869
4870 self.Freeze()
4871
4872 panel = self.GetPage(nPage)
4873 self.bsizer.Detach(nPage)
4874
4875 self.bsizer.Layout()
4876
4877 self._notebookpages.pop(nPage)
4878 self.nb.DeletePage(nPage)
4879
4880 panel.Destroy()
4881
4882 if self.GetPageCount() > 0:
4883 if oldselection == nPage:
4884 if self.GetSelection() > 0:
4885 self.SetSelection(self.GetSelection()-1)
4886 else:
4887 self.SetSelection(self.GetSelection())
4888 self.bsizer.Show(self.GetSelection())
4889 self.bsizer.Layout()
4890
4891 if self.GetPageCount() == 0:
4892 self.nb.Show(False)
4893 self._ShowTabCtrl(False)
4894
4895 custom = self.GetCustomPage()
4896
4897 if custom is not None:
4898 self.bsizer.Add(custom, 1, wx.EXPAND | wx.ALL, 2)
4899 custom.Show(True)
4900
4901 self.bsizer.Layout()
4902 self.sizer.Layout()
4903 self.Thaw()
4904 return
4905
4906 if self.GetPageCount() == 1:
4907
4908 if self.nb._hideonsingletab:
4909
4910 self._ShowTabCtrl(False)
4911
4912 else:
4913
4914 self.nb.Show(True)
4915 self._ShowTabCtrl(True)
4916
4917 else:
4918
4919 self.nb.Show(True)
4920 self._ShowTabCtrl(True)
4921
4922 self.sizer.Layout()
4923
4924 self.Thaw()
4925
4926 self.Tile(self._showcolumns)
4927 self.ShowTabs(self._showtabs)
4928
4929
4930 def SetSelection(self, nPage):
4931 """
4932 Sets The Current Tab Selection To The Given nPage. This Call Generates The
4933 EVT_NOTEBOOKCTRL_PAGE_CHANGING Event.
4934 """
4935
4936 if nPage < 0 or nPage >= self.GetPageCount():
4937 raise "\nERROR: Invalid Notebook Page In SetSelection: (" + str(nPage) + ")"
4938
4939 oldselection = self.GetSelection()
4940
4941 if oldselection == nPage:
4942 return
4943
4944 self.nb.SetSelection(nPage)
4945
4946 self.Tile(self._showcolumns)
4947 self.ShowTabs(self._showtabs)
4948
4949
4950 def GetPageCount(self):
4951 """ Returns The Number Of Pages In NotebookCtrl. """
4952
4953 return self.nb.GetPageCount()
4954
4955
4956 def GetSelection(self):
4957 """ Returns The Current Selection. """
4958
4959 return self.nb.GetSelection()
4960
4961
4962 def GetImageList(self):
4963 """ Returns The Image List Associated With The NotebookCtrl. """
4964
4965 return self.nb.GetImageList()
4966
4967
4968 def SetImageList(self, imagelist):
4969 """ Associate An Image List To NotebookCtrl. """
4970
4971 self.nb.SetImageList(imagelist)
4972
4973
4974 def AssignImageList(self, imagelist):
4975 """ Associate An Image List To NotebookCtrl. """
4976
4977 self.nb.AssignImageList(imagelist)
4978
4979
4980 def GetPadding(self):
4981 """ Returns The (Horizontal, Vertical) Padding Of The Text Inside Tabs. """
4982
4983 return self.nb.GetPadding()
4984
4985
4986 def SetPadding(self, padding):
4987 """ Sets The (Horizontal, Vertical) Padding Of The Text Inside Tabs. """
4988
4989 self.nb.SetPadding(padding)
4990
4991
4992 def SetUseFocusIndicator(self, focus=True):
4993 """ Globally Enables/Disables Tab Focus Indicator. """
4994
4995 self.nb.SetUseFocusIndicator(focus)
4996
4997
4998 def GetUseFocusIndicator(self):
4999 """ Returns Globally Enable/Disable State For Tab Focus Indicator. """
5000
5001 return self.nb.GetUseFocusIndicator()
5002
5003
5004 def EnablePage(self, nPage, enable=True):
5005 """ Enable/Disable The Given Page nPage. """
5006
5007 if nPage < 0 or nPage >= self.GetPageCount():
5008 raise "\nERROR: Invalid Notebook Page In EnablePage: (" + str(nPage) + ")"
5009
5010 self.nb.EnablePage(nPage, enable)
5011
5012
5013 def IsPageEnabled(self, nPage):
5014 """ Returns Whether A Page Is Enabled Or Not. """
5015
5016 if nPage < 0 or nPage >= self.GetPageCount():
5017 raise "\nERROR: Invalid Notebook Page In IsPageEnabled: (" + str(nPage) + ")"
5018
5019 return self.nb.IsPageEnabled(nPage)
5020
5021
5022 def SetHighlightSelection(self, highlight=True):
5023 """ Globally Enables/Disables Tab Highlighting On Tab Selection. """
5024
5025 self.nb.SetHighlightSelection(highlight)
5026
5027
5028 def GetHighlightSelection(self):
5029 """ Returns Globally Enable/Disable State For Tab Highlighting On Tab Selection. """
5030
5031 return self.nb.GetHighlightSelection()
5032
5033
5034 def SetAnimationImages(self, nPage, imgarray):
5035 """
5036 Sets An Animation List Associated To The Given Page nPage.
5037
5038 @param nPage: The Given Page;
5039 @param imgarray: A List Of Image Indexes Of Images Inside The
5040 ImageList Associated To NotebookCtrl.
5041 """
5042
5043 if nPage < 0 or nPage >= self.GetPageCount():
5044 raise "\nERROR: Invalid Notebook Page In SetAnimationImages: (" + str(nPage) + ")"
5045
5046 if not imgarray:
5047 raise "\nERROR: Invalid Image Array In SetAnimationImages: (" + repr(imgarray) + ")"
5048
5049 if min(imgarray) < 0:
5050 raise "\nERROR: Invalid Image Array In SetAnimationImages: (Min(ImgArray) = " + \
5051 str(min(imgarray)) + " < 0)"
5052
5053 if max(imgarray) > self.GetImageList().GetImageCount() - 1:
5054 raise "\nERROR: Invalid Image Array In SetAnimationImages: (Max(ImgArray) = " + \
5055 str(max(imgarray)) + " > " + str(self.GetImageList().GetImageCount()-1) + ")"
5056
5057 self.nb.SetAnimationImages(nPage, imgarray)
5058
5059
5060 def GetAnimationImages(self, nPage):
5061 """ Returns The Animation Images List Associated To The Given Page nPage. """
5062
5063 if nPage < 0 or nPage >= self.GetPageCount():
5064 raise "\nERROR: Invalid Notebook Page In GetAnimationImages: (" + str(nPage) + ")"
5065
5066 return self.nb.GetAnimationImages(nPage)
5067
5068
5069 def StartAnimation(self, nPage, timer=500):
5070 """ Starts The Animation On The Given Page nPage, With Refreshing Time Rate "timer". """
5071
5072 if nPage < 0 or nPage >= self.GetPageCount():
5073 raise "\nERROR: Invalid Notebook Page In StartAnimation: (" + str(nPage) + ")"
5074
5075 self.nb.StartAnimation(nPage, timer)
5076
5077
5078 def StopAnimation(self, nPage):
5079 """ Stops The Animation On The Given Page nPage. """
5080
5081 if nPage < 0 or nPage >= self.GetPageCount():
5082 raise "\nERROR: Invalid Notebook Page In StopAnimation: (" + str(nPage) + ")"
5083
5084 self.nb.StopAnimation(nPage)
5085
5086
5087 def EnableDragAndDrop(self, enable=True):
5088 """ Globall Enables/Disables Tabs Drag And Drop. """
5089
5090 self.nb.EnableDragAndDrop(enable)
5091
5092
5093 def EnableHiding(self, enable=True):
5094 """ Globally Enables/Disables Hiding On Tabs In Runtime. """
5095
5096 self.nb.EnableHiding(enable)
5097
5098
5099 def SetDrawX(self, drawx=True, style=1, image1=None, image2=None):
5100 """
5101 Globally Enables/Disables The Drawing Of A Closing "X" In The Tab.
5102
5103 @param drawx: C{True} to enable drawing a closing "X"; C{False} to
5104 disable it
5105 @param style: the style of the X to draw when C{drawx} is C{True};
5106 possible values are:
5107 - C{1}: Small "X" At The Top-Right Of The Tab;
5108 - C{2}: Bigger "X" In The Middle Vertical Of The Tab (Like Opera Notebook);
5109 - C{3}: Custom "X" Image Is Drawn On Tabs.
5110 @param image1: if C{style} is C{3}, the image to use when drawing
5111 the X on an unhighlighted tab
5112 @param image2: if C{style} is C{3}, the image to use when drawing
5113 the X on a highlighted tab
5114 """
5115
5116 self.nb.SetDrawX(drawx, style, image1, image2)
5117
5118
5119 def GetDrawX(self):
5120 """
5121 Returns The Enable/Disable State Of Drawing Of A Small "X" At The Top-Right Of
5122 Every Page.
5123 """
5124
5125 return self.nb.GetDrawX()
5126
5127
5128 def SetImageToCloseButton(self, convert=True):
5129 """ Set Whether The Tab Icon Should Be Converted To The Close Button Or Not. """
5130
5131 self.nb.SetImageToCloseButton(convert)
5132
5133
5134 def GetImageToCloseButton(self):
5135 """ Get Whether The Tab Icon Should Be Converted To The Close Button Or Not. """
5136
5137 return self.nb._convertimage
5138
5139
5140 def HideOnSingleTab(self, hide=True):
5141 """ Hides The TabCtrl When There Is Only One Tab In NotebookCtrl. """
5142
5143 self.nb.HideOnSingleTab(hide)
5144
5145 if self.GetPageCount() == 1:
5146 if hide:
5147 self._ShowTabCtrl(False)
5148 else:
5149 self._ShowTabCtrl(True)
5150
5151 self.sizer.Layout()
5152
5153
5154 def SetPagePopupMenu(self, nPage, menu):
5155 """ Sets A Popup Menu Specific To A Single Tab. """
5156
5157 if nPage < 0 or nPage >= self.GetPageCount():
5158 raise "\nERROR: Invalid Notebook Page In SetPagePopupMenu: (" + str(nPage) + ")"
5159
5160 self.nb.SetPagePopupMenu(nPage, menu)
5161
5162
5163 def GetPagePopupMenu(self, nPage):
5164 """ Returns The Popup Menu Associated To A Single Tab. """
5165
5166 if nPage < 0 or nPage >= self.GetPageCount():
5167 raise "\nERROR: Invalid Notebook Page In GetPagePopupMenu: (" + str(nPage) + ")"
5168
5169 return self.nb.GetPagePopupMenu(nPage)
5170
5171
5172 def SetPageToolTip(self, nPage, tooltip="", timer=500, winsize=400):
5173 """
5174 Sets A ToolTip For The Given Page nPage.
5175
5176 @param nPage: The Given Page;
5177 @param tooltip: The ToolTip String;
5178 @param timer: The Timer After Which The Tip Window Is Popped Up;
5179 @param winsize: The Maximum Width Of The Tip Window.
5180 """
5181
5182 if nPage < 0 or nPage >= self.GetPageCount():
5183 raise "\nERROR: Invalid Notebook Page In SetPageToolTip: (" + str(nPage) + ")"
5184
5185 self.nb.SetPageToolTip(nPage, tooltip, timer, winsize)
5186
5187
5188 def GetPageToolTip(self, nPage):
5189 """ Returns A Tuple With All Page ToolTip Parameters. """
5190
5191 if nPage < 0 or nPage >= self.GetPageCount():
5192 raise "\nERROR: Invalid Notebook Page In GetPageToolTip: (" + str(nPage) + ")"
5193
5194 return self.nb.GetPageToolTip(nPage)
5195
5196
5197 def EnableToolTip(self, show=True):
5198 """ Globally Enables/Disables Tab ToolTips. """
5199
5200 self.nb.EnableToolTip(show)
5201
5202
5203 def GetToolTipBackgroundColour(self):
5204 """ Returns The ToolTip Window Background Colour. """
5205
5206 return self.nb.GetToolTipBackgroundColour()
5207
5208
5209 def SetToolTipBackgroundColour(self, colour=None):
5210 """ Sets The ToolTip Window Background Colour. """
5211
5212 if colour is None:
5213 colour = wx.Colour(255, 255, 230)
5214
5215 self.nb.SetToolTipBackgroundColour(colour)
5216
5217
5218 def EnableTabGradients(self, enable=True):
5219 """ Globally Enables/Disables Drawing Of Gradient Coloured Tabs For Each Tab. """
5220
5221 self.nb.EnableTabGradients(enable)
5222
5223
5224 def SetPageFirstGradientColour(self, nPage, colour=None):
5225 """ Sets The Single Tab First Gradient Colour. """
5226
5227 if nPage < 0 or nPage >= self.GetPageCount():
5228 raise "\nERROR: Invalid Notebook Page In SetPageFirstGradientColour: (" + str(nPage) + ")"
5229
5230 if colour is None:
5231 colour = wx.WHITE
5232
5233 self.nb.SetPageFirstGradientColour(nPage, colour)
5234
5235
5236 def SetPageSecondGradientColour(self, nPage, colour=None):
5237 """ Sets The Single Tab Second Gradient Colour. """
5238
5239 if nPage < 0 or nPage >= self.GetPageCount():
5240 raise "\nERROR: Invalid Notebook Page In SetPageSecondGradientColour: (" + str(nPage) + ")"
5241
5242 self.nb.SetPageSecondGradientColour(nPage, colour)
5243
5244
5245 def GetPageFirstGradientColour(self, nPage):
5246 """ Returns The Single Tab First Gradient Colour. """
5247
5248 if nPage < 0 or nPage >= self.GetPageCount():
5249 raise "\nERROR: Invalid Notebook Page In GetPageFirstGradientColour: (" + str(nPage) + ")"
5250
5251 return self.nb.GetPageFirstGradientColour(nPage)
5252
5253
5254 def GetPageSecondGradientColour(self, nPage):
5255 """ Returns The Single Tab Second Gradient Colour. """
5256
5257 if nPage < 0 or nPage >= self.GetPageCount():
5258 raise "\nERROR: Invalid Notebook Page In GetPageSecondGradientColour: (" + str(nPage) + ")"
5259
5260 return self.nb.GetPageSecondGradientColour(nPage)
5261
5262
5263 def CancelTip(self):
5264 """ Destroys The Tip Window (Probably You Won't Need This One. """
5265
5266 self.nb.CancelTip()
5267
5268
5269 def AdvanceSelection(self, forward=True):
5270 """
5271 Cycles Through The Tabs. The Call To This Function Generates The
5272 EVT_NOTEBOOKCTRL_PAGE_CHANGING Event.
5273 """
5274
5275 self.nb.AdvanceSelection(forward)
5276
5277
5278 def SetDefaultPage(self, defaultpage=-1):
5279 """
5280 Sets The Default Page That Will Be Selected When An Active And Selected
5281 Tab Is Made Inactive.
5282 """
5283
5284 if defaultpage >= self.GetPageCount():
5285 raise "\nERROR: Invalid Notebook Page In SetDefaultPage: (" + str(defaultpage) + ")"
5286
5287 self.nb.SetDefaultPage(defaultpage)
5288
5289
5290 def GetDefaultPage(self):
5291 """ Returns The Default Page. """
5292
5293 return self.nb.GetDefaultPage()
5294
5295
5296 def GetPageText(self, nPage):
5297 """ Returns The String For The Given Page nPage. """
5298
5299 if nPage < 0 or nPage >= self.GetPageCount():
5300 raise "\nERROR: Invalid Notebook Page In GetPageText: (" + str(nPage) + ")"
5301
5302 return self.nb.GetPageText(nPage)
5303
5304
5305 def SetPageText(self, nPage, text):
5306 """ Sets The String For The Given Page nPage. """
5307
5308 if nPage < 0 or nPage >= self.GetPageCount():
5309 raise "\nERROR: Invalid Notebook Page In SetPageText: (" + str(nPage) + ")"
5310
5311 self.nb.SetPageText(nPage, text)
5312
5313
5314 def GetPageImage(self, nPage):
5315 """ Returns The Image Index For The Given Page nPage. """
5316
5317 if nPage < 0 or nPage >= self.GetPageCount():
5318 raise "\nERROR: Invalid Notebook Page In GetPageImage: (" + str(nPage) + ")"
5319
5320 return self.nb.GetPageImage(nPage)
5321
5322
5323 def SetPageImage(self, nPage, img):
5324 """ Sets The Image Index For The Given Page nPage. """
5325
5326 if nPage < 0 or nPage >= self.GetPageCount():
5327 raise "\nERROR: Invalid Notebook Page In SetPageImage: (" + str(nPage) + ")"
5328
5329 self.nb.SetPageImage(nPage, img)
5330
5331
5332 def SetPageTextFont(self, nPage, font=None):
5333 """ Sets The Primary Font For The Given Page nPage. """
5334
5335 if nPage < 0 or nPage >= self.GetPageCount():
5336 raise "\nERROR: Invalid Notebook Page In SetPageTextFont: (" + str(nPage) + ")"
5337
5338 if font is None:
5339 font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
5340
5341 self.nb.SetPageTextFont(nPage, font)
5342
5343
5344 def GetPageTextFont(self, nPage):
5345 """ Returns The Primary Font For The Given Page nPage. """
5346
5347 if nPage < 0 or nPage >= self.GetPageCount():
5348 raise "\nERROR: Invalid Notebook Page In GetPageTextFont: (" + str(nPage) + ")"
5349
5350 return self.nb.GetPageTextFont(nPage)
5351
5352
5353 def SetPageTextSecondaryFont(self, nPage, font=None):
5354 """ Sets The Secondary Font For The Given Page nPage. """
5355
5356 if nPage < 0 or nPage >= self.GetPageCount():
5357 raise "\nERROR: Invalid Notebook Page In SetPageTextSecondaryFont: (" + str(nPage) + ")"
5358
5359 if font is None:
5360 font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
5361
5362 self.nb.SetPageTextSecondaryFont(nPage, font)
5363
5364
5365 def GetPageTextSecondaryFont(self, nPage):
5366 """ Returns The Secondary Font For The Given Page nPage. """
5367
5368 if nPage < 0 or nPage >= self.GetPageCount():
5369 raise "\nERROR: Invalid Notebook Page In GetPageTextSecondaryFont: (" + str(nPage) + ")"
5370
5371 return self.nb.GetPageTextSecondaryFont(nPage)
5372
5373
5374 def SetPageTextColour(self, nPage, colour=None):
5375 """ Sets The Text Colour For The Given Page nPage. """
5376
5377 if nPage < 0 or nPage >= self.GetPageCount():
5378 raise "\nERROR: Invalid Notebook Page In SetPageTextColour: (" + str(nPage) + ")"
5379
5380 if colour is None:
5381 colour = wx.BLACK
5382
5383 self.nb.SetPageTextColour(nPage, colour)
5384
5385
5386 def GetPageTextColour(self, nPage):
5387 """ Returns The Text Colour For The Given Page nPage. """
5388
5389 if nPage < 0 or nPage >= self.GetPageCount():
5390 raise "\nERROR: Invalid Notebook Page In GetPageTextColour: (" + str(nPage) + ")"
5391
5392 return self.nb.GetPageTextColour(nPage)
5393
5394
5395 def SetPageColour(self, nPage, colour=None):
5396 """ Sets The Tab Background Colour For The Given Page nPage. """
5397
5398 if nPage < 0 or nPage >= self.GetPageCount():
5399 raise "\nERROR: Invalid Notebook Page In SetPageColour: (" + str(nPage) + ")"
5400
5401 if colour is None:
5402 colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)
5403
5404 self.nb.SetPageColour(nPage, colour)
5405
5406
5407 def GetPageColour(self, nPage):
5408 """ Returns The Tab Background Colour For The Given Page nPage. """
5409
5410 if nPage < 0 or nPage >= self.GetPageCount():
5411 raise "\nERROR: Invalid Notebook Page In GetPageColour: (" + str(nPage) + ")"
5412
5413 return self.nb.GetPageColour(nPage)
5414
5415
5416 def SetTabHeight(self, height=28):
5417 """ Sets The Tabs Height. """
5418
5419 if height <= 0:
5420 raise "\nERROR: Impossible To Set An Height <= 0. "
5421
5422 self.nb.SetTabHeight(height)
5423
5424
5425 def SetControlBackgroundColour(self, colour=None):
5426 """ Sets The TabCtrl Background Colour (Behind The Tabs). """
5427
5428 if colour is None:
5429 colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
5430
5431 self.nb.SetBackgroundColour(colour)
5432
5433
5434 def ApplyTabTheme(self, theme=None):
5435 """ Apply A Particular Theme To Be Drawn On Tabs. """
5436
5437 if theme is None:
5438 theme = ThemeStyle()
5439
5440 self.nb.ApplyTabTheme(theme)
5441
5442
5443 def SetSelectionColour(self, colour=None):
5444 """ Sets The Tab Selection Colour (Thin Line Above The Selected Tab). """
5445
5446 if colour is None:
5447 colour = wx.Colour(255, 180, 0)
5448
5449 self.nb.SetSelectionColour(colour)
5450
5451
5452 def SetContourLineColour(self, colour=None):
5453 """ Sets The Contour Line Colour (Controur Line Around Tabs). """
5454
5455 self.nb.SetContourLineColour(colour)
5456
5457 def Tile(self, show=True, orient=None):
5458 """ Shows Pages In Column/Row Mode (One Panel After The Other In Columns/Rows). """
5459
5460 if self._GetTabCtrlWindow().IsShown() == show and orient is None:
5461 return
5462
5463 self.Freeze()
5464
5465 if orient is not None and show:
5466 if orient == wx.VERTICAL:
5467 norient = wx.HORIZONTAL
5468 else:
5469 norient = wx.VERTICAL
5470
5471 if orient is not None and show:
5472 origorient = self.bsizer.GetOrientation()
5473 if origorient != norient:
5474 for ii in xrange(self.GetPageCount()-1, -1, -1):
5475 self.bsizer.Detach(ii)
5476
5477 self.sizer.Detach(self.bsizer)
5478 self.bsizer.Destroy()
5479
5480 self.bsizer = wx.BoxSizer(norient)
5481
5482 for ii in xrange(self.GetPageCount()):
5483 self.bsizer.Add(self._notebookpages[ii], 1, wx.EXPAND | wx.ALL, 2)
5484
5485 if self._style & NC_TOP:
5486 self.sizer.Add(self.bsizer, 1, wx.EXPAND)
5487 else:
5488 self.sizer.Insert(0, self.bsizer, 1, wx.EXPAND)
5489
5490 self.bsizer.Layout()
5491 self.sizer.Layout()
5492
5493 selection = self.GetSelection()
5494
5495 if show:
5496 self._ShowTabCtrl(False)
5497 if self._style & NC_TOP or self._style & NC_LEFT:
5498 if len(self.nb._selectedtabs) > 0:
5499 for ii in xrange(self.GetPageCount()):
5500 if ii in self.nb._selectedtabs:
5501 self.bsizer.Show(ii, True)
5502 else:
5503 self.bsizer.Show(ii, False)
5504 else:
5505 for ii in xrange(self.GetPageCount()):
5506 if self.IsPageEnabled(ii):
5507 if not self.nb._enablehiding or not self.nb._pages[ii]._ishidden:
5508 self.bsizer.Show(ii, True)
5509 else:
5510 self.bsizer.Show(ii, False)
5511 else:
5512 self.bsizer.Show(ii, False)
5513 else:
5514 if len(self.nb._selectedtabs) > 0:
5515 for ii in xrange(self.GetPageCount()):
5516 if ii in self.nb._selectedtabs:
5517 self.bsizer.Show(ii, True)
5518 else:
5519 for ii in xrange(self.GetPageCount()):
5520 if self.IsPageEnabled(ii):
5521 if not self.nb._enablehiding or not self.nb._pages[ii]._ishidden:
5522 self.bsizer.Show(ii, True)
5523 else:
5524 self.bsizer.Show(ii, False)
5525 else:
5526 self.bsizer.Show(ii, False)
5527 else:
5528 self._ShowTabCtrl(True)
5529 if self._style & NC_TOP or self._style & NC_LEFT:
5530 for ii in xrange(self.GetPageCount()):
5531 self.bsizer.Show(ii, False)
5532 else:
5533 for ii in xrange(self.GetPageCount()):
5534 self.bsizer.Show(ii, False)
5535
5536 if selection < 0:
5537 self.bsizer.Layout()
5538 self.sizer.Layout()
5539 return
5540 else:
5541 self.bsizer.Show(selection, True)
5542 self.bsizer.Layout()
5543
5544 self._showcolumns = show
5545
5546 self.bsizer.Layout()
5547 self.sizer.Layout()
5548
5549 self.Thaw()
5550
5551
5552
5553 def ShowTabs(self, show=True):
5554 """ Shows/Hides Tabs On Request. """
5555
5556 if self._GetTabCtrlWindow().IsShown() == show:
5557 return
5558
5559 if self.GetPageCount() == 0:
5560 return
5561
5562 self.Freeze()
5563
5564 self._ShowTabCtrl(show)
5565
5566 self._showtabs = show
5567
5568 self.sizer.Layout()
5569
5570 self.Thaw()
5571
5572
5573 def GetIndex(self, page):
5574 """ Returns The Page Index (Position) Based On The NotebookCtrl Page Passed. """
5575
5576 if page in self._notebookpages:
5577 return self._notebookpages.index(page)
5578
5579 return -1
5580
5581
5582 def ReparentPage(self, nPage, newParent):
5583 """ Reparents The NotebookCtrl Page nPage To A New Parent. """
5584
5585 if nPage < 0 or (self.GetSelection() >= 0 and nPage >= self.GetPageCount()):
5586 raise "\nERROR: Invalid Notebook Page In ReparentPage: (" + str(nPage) + ")"
5587
5588 page = self.GetPage(nPage)
5589 page.Reparent(newParent)
5590
5591
5592 def ReparentToFrame(self, nPage, createNotebook=False):
5593 """ Reparents The NotebookCtrl Page nPage To A New Frame. """
5594
5595 if nPage < 0 or (self.GetSelection() >= 0 and nPage >= self.GetPageCount()):
5596 raise "\nERROR: Invalid Notebook Page In ReparentToFrame: (" + str(nPage) + ")"
5597
5598 self.Freeze()
5599
5600 infos = self.GetPageInfo(nPage)
5601 panel = self.GetPage(nPage)
5602 text = infos["text"]
5603 oldparent = panel.GetParent()
5604
5605 frame = NCFrame(None, -1, text, nb=self, infos=infos, panel=panel, oldparent=oldparent)
5606
5607 if createNotebook:
5608 nb = NotebookCtrl(frame, -1, style=self._style, sizer=self._sizerstyle)
5609 nb.SetImageList(infos["imagelist"])
5610 self.ReparentToNotebook(nPage, nb)
5611 else:
5612 self.ReparentPage(nPage, frame)
5613
5614 self.nb.DeletePage(nPage, False)
5615
5616 self.bsizer.Detach(nPage)
5617 self.bsizer.Layout()
5618 self.sizer.Layout()
5619
5620 self._notebookpages.pop(nPage)
5621
5622 self.AdvanceSelection()
5623
5624 if self.GetPageCount() == 0:
5625 self._ShowTabCtrl(False)
5626
5627 self.sizer.Layout()
5628
5629 custom = self.GetCustomPage()
5630 if custom is not None:
5631 self.SetCustomPage(custom)
5632
5633 self.Thaw()
5634
5635 frame.Show()
5636
5637
5638 def ReparentToNotebook(self, nPage, notebook, newPage=None):
5639 """ Reparents The NotebookCtrl Page nPage To A New NotebookCtrl. """
5640
5641 if nPage < 0 or (self.GetSelection() >= 0 and nPage >= self.GetPageCount()):
5642 raise "\nERROR: Invalid Notebook Page In ReparentToNotebook: (" + str(nPage) + ")"
5643
5644 if newPage is not None and newPage >= notebook.GetPageCount():
5645 raise "\nERROR: Invalid Notebook New Page In ReparentToNotebook: (" + str(nPage) + ")"
5646
5647 self.Freeze()
5648
5649 infos = self.GetPageInfo(nPage)
5650 panel = self.GetPage(nPage)
5651
5652 self.ReparentPage(nPage, notebook)
5653
5654 if newPage is None:
5655 notebook.AddPage(panel, infos["text"], False, infos["image"])
5656 notebook.SetPageInfo(0, infos)
5657
5658 for attr in attrs:
5659 setattr(notebook, attr, getattr(self.nb, attr))
5660
5661 self.nb.DeletePage(nPage, False)
5662
5663 self.bsizer.Detach(nPage)
5664 self.bsizer.Layout()
5665 self.sizer.Layout()
5666
5667 self._notebookpages.pop(nPage)
5668
5669 self.AdvanceSelection()
5670
5671 if self.GetPageCount() == 0:
5672 self._ShowTabCtrl(False)
5673
5674 self.sizer.Layout()
5675
5676 self.Thaw()
5677
5678
5679 def GetPageInfo(self, nPage):
5680 """ Returns All The Style Information For A Given Page. """
5681
5682 if nPage < 0 or (self.GetSelection() >= 0 and nPage >= self.GetPageCount()):
5683 raise "\nERROR: Invalid Notebook Page In GetPageInfo: (" + str(nPage) + ")"
5684
5685 text = self.GetPageText(nPage)
5686 image = self.GetPageImage(nPage)
5687 font1 = self.GetPageTextFont(nPage)
5688 font2 = self.GetPageTextSecondaryFont(nPage)
5689 fontcolour = self.GetPageTextColour(nPage)
5690 pagecolour = self.GetPageColour(nPage)
5691 enabled = self.IsPageEnabled(nPage)
5692 tooltip, ontime, winsize = self.GetPageToolTip(nPage)
5693 menu = self.GetPagePopupMenu(nPage)
5694 firstcol = self.GetPageFirstGradientColour(nPage)
5695 secondcol = self.GetPageSecondGradientColour(nPage)
5696 ishidden = self.nb._pages[nPage]._ishidden
5697
5698 isanimated = 0
5699 timer = None
5700
5701 if self.nb._timers[nPage].IsRunning():
5702 isanimated = 1
5703 timer = self.nb._timers[nPage].GetInterval()
5704
5705 self.StopAnimation(nPage)
5706 animatedimages = self.GetAnimationImages(nPage)
5707
5708 infos = {"text": text, "image": image, "font1": font1, "font2": font2,
5709 "fontcolour": fontcolour, "pagecolour": pagecolour, "enabled": enabled,
5710 "tooltip": tooltip, "ontime": ontime, "winsize": winsize,
5711 "menu": menu, "isanimated": isanimated, "timer": timer,
5712 "animatedimages": animatedimages, "imagelist": self.nb._imglist,
5713 "firstcol": firstcol, "secondcol": secondcol, "ishidden": ishidden}
5714
5715 return infos
5716
5717
5718 def SetPageInfo(self, nPage, infos):
5719 """ Sets All The Style Information For A Given Page. """
5720
5721 if nPage < 0 or (self.GetSelection() >= 0 and nPage >= self.GetPageCount()):
5722 raise "\nERROR: Invalid Notebook Page In SetPageInfo: (" + str(nPage) + ")"
5723
5724 self.SetPageTextFont(nPage, infos["font1"])
5725 self.SetPageTextSecondaryFont(nPage, infos["font2"])
5726 self.SetPageTextColour(nPage, infos["fontcolour"])
5727 self.SetPageColour(nPage, infos["pagecolour"])
5728 self.EnablePage(nPage, infos["enabled"])
5729 self.SetPageToolTip(nPage, infos["tooltip"], infos["ontime"], infos["winsize"])
5730 self.SetPagePopupMenu(nPage, infos["menu"])
5731 self.SetPageFirstGradientColour(nPage, infos["firstcol"])
5732 self.SetPageSecondGradientColour(nPage, infos["secondcol"])
5733 self.nb._pages[nPage]._ishidden = infos["ishidden"]
5734
5735 if infos["isanimated"] and len(infos["animatedimages"]) > 1:
5736 self.SetAnimationImages(nPage, infos["animatedimages"])
5737 self.StartAnimation(nPage, infos["timer"])
5738
5739
5740 def SetCustomPage(self, panel):
5741 """ Sets A Custom Panel To Show When There Are No Pages Left In NotebookCtrl. """
5742
5743 self.Freeze()
5744
5745 if panel is None:
5746 if self._custompanel is not None:
5747 self.bsizer.Detach(self._custompanel)
5748 self._custompanel.Show(False)
5749
5750 if self.GetPageCount() == 0:
5751 self._ShowTabCtrl(False)
5752 else:
5753 if self.GetPageCount() == 0:
5754 if self._custompanel is not None:
5755 self.bsizer.Detach(self._custompanel)
5756 self._custompanel.Show(False)
5757
5758 self.bsizer.Add(panel, 1, wx.EXPAND | wx.ALL, 2)
5759 panel.Show(True)
5760 self._ShowTabCtrl(False)
5761 else:
5762 panel.Show(False)
5763
5764 self._custompanel = panel
5765
5766 self.bsizer.Layout()
5767 self.sizer.Layout()
5768 self.Thaw()
5769
5770
5771 def GetCustomPage(self):
5772 """ Gets A Custom Panel To Show When There Are No Pages Left In NotebookCtrl. """
5773
5774 return self._custompanel
5775
5776
5777 def HideTab(self, nPage, hide=True):
5778 """ Hides A Tab In The NotebookCtrl. """
5779
5780 self.nb.HideTab(nPage, hide)
5781
5782
5783 def HitTest(self, point, flags=0):
5784 """
5785 Standard NotebookCtrl HitTest() Method. If Called With 2 Outputs, It
5786 Returns The Page Clicked (If Any) And One Of These Flags:
5787
5788 NC_HITTEST_NOWHERE = 0 ==> Hit Not On Tab
5789 NC_HITTEST_ONICON = 1 ==> Hit On Icon
5790 NC_HITTEST_ONLABEL = 2 ==> Hit On Label
5791 NC_HITTEST_ONITEM = 4 ==> Hit Generic, On Item
5792 NC_HITTEST_ONX = 8 ==> Hit On Closing "X" On Every Page
5793 """
5794
5795 return self.nb.HitTest(point, flags)
5796
5797 def _AddMargin(self, style, margin):
5798 if style & NC_TOP or style & NC_BOTTOM:
5799 self.tabsizer.Add((0, margin), 0)
5800 elif style & NC_LEFT or style & NC_RIGHT:
5801 self.tabsizer.Add((margin, 0), 0)
5802
5803 def _GetTabCtrlWindow(self):
5804 if self._style & NC_TOP or self._style & NC_LEFT:
5805 return self.tabsizer.GetItem(1)
5806 else:
5807 return self.tabsizer.GetItem(0)
5808
5809 def _ShowTabCtrl(self, show):
5810 if self._style & NC_TOP:
5811 self.sizer.Show(0, show)
5812 else:
5813 self.sizer.Show(1, show)
5814
5815
5816 # ---------------------------------------------------------------------------- #
5817 # Class TransientTipWindow
5818 # Auxiliary Help Class. Used To Build The Tip Window.
5819 # ---------------------------------------------------------------------------- #
5820
5821 class _PopupWindow:
5822
5823 def _Fill(self, tip, winsize):
5824
5825 panel = wx.Panel(self, -1)
5826 colour = self.GetParent().GetToolTipBackgroundColour()
5827
5828 panel.SetBackgroundColour(colour)
5829
5830 # border from sides and top to text (in pixels)
5831 border = 5
5832 # how much space between text lines
5833 textPadding = 2
5834 max_len = len(tip)
5835 tw = winsize
5836
5837 mylines = tip.split("\n")
5838
5839 sts = wx.StaticText(panel, -1, "\n".join(mylines))
5840 sx, sy = sts.GetBestSize()
5841 sts.SetPosition((2, 2))
5842
5843 panel.SetSize((sx+6, sy+6))
5844 self.SetSize(panel.GetSize())
5845
5846
5847 class TransientTipWindow(_PopupWindow, wx.PopupWindow):
5848
5849 def __init__(self, parent, tip, winsize):
5850
5851 wx.PopupWindow.__init__(self, parent, flags=wx.SIMPLE_BORDER)
5852 self._Fill(tip,winsize)
5853
5854
5855 def ProcessLeftDown(self, evt):
5856
5857 return False
5858
5859
5860 def OnDismiss(self):
5861
5862 return False
5863
5864
5865 class macPopupWindow(wx.Frame):
5866
5867 def __init__(self, parent, flags):
5868
5869 wx.Frame.__init__(self, parent, id=-1, style=flags|wx.FRAME_NO_TASKBAR|wx.STAY_ON_TOP)
5870 self._hideOnActivate = False
5871 #Get the parent frame: could be improved maybe?
5872 self._parentFrame = parent
5873
5874 while True:
5875
5876 parent = self._parentFrame.GetParent()
5877
5878 if parent:
5879 self._parentFrame = parent
5880 else:
5881 break
5882
5883 self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
5884
5885
5886 def Show(self, show=True):
5887
5888 wx.Frame.Show(self,show)
5889
5890 if show:
5891 self._parentFrame.Raise()
5892 self._hideOnActivate = True
5893
5894
5895 def OnActivate(self, evt):
5896 """
5897 Let The User Hide The Tooltip By Clicking On It.
5898 NotebookCtrl Will Destroy It Later.
5899 """
5900
5901 if self._hideOnActivate:
5902 wx.Frame.Show(self,False)
5903
5904
5905 class macTransientTipWindow(_PopupWindow, macPopupWindow):
5906
5907 def __init__(self, parent, tip, winsize):
5908
5909 macPopupWindow.__init__(self, parent, flags=wx.SIMPLE_BORDER)
5910 self._Fill(tip, winsize)
5911
5912
5913 class NCFrame(wx.Frame):
5914
5915 def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition,
5916 size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, nb=None,
5917 panel=None, infos=None, oldparent=None):
5918
5919 wx.Frame.__init__(self, parent, id, title, pos, size, style)
5920
5921 self._infos = infos
5922 self._nb = nb
5923 self._panel = panel
5924 self._oldparent = oldparent
5925
5926 self.Bind(wx.EVT_CLOSE, self.OnClose)
5927
5928
5929 def OnClose(self, event):
5930
5931 try:
5932 infos = self._infos
5933 self._panel.Reparent(self._oldparent)
5934 self._nb.AddPage(self._panel, infos["text"], False, infos["image"])
5935
5936 id = self._nb.GetPageCount() - 1
5937
5938 self._nb.SetPageTextFont(id, infos["font1"])
5939 self._nb.SetPageTextSecondaryFont(id, infos["font2"])
5940 self._nb.SetPageTextColour(id, infos["fontcolour"])
5941 self._nb.SetPageColour(id, infos["pagecolour"])
5942 self._nb.EnablePage(id, infos["enabled"])
5943 self._nb.SetPageToolTip(id, infos["tooltip"], infos["ontime"], infos["winsize"])
5944 self._nb.SetPagePopupMenu(id, infos["menu"])
5945 self._nb.SetPageFirstGradientColour(id, infos["firstcol"])
5946 self._nb.SetPageSecondGradientColour(id, infos["secondcol"])
5947 self._nb._pages[id]._ishidden = infos["ishidden"]
5948
5949 if infos["isanimated"] and len(infos["animatedimages"]) > 1:
5950 self._nb.SetAnimationImages(id, infos["animatedimages"])
5951 self._nb.StartAnimation(id, infos["timer"])
5952
5953 except:
5954 self.Destroy()
5955 event.Skip()
5956 return
5957
5958 self.Destroy()
5959
5960 event.Skip()
5961
5962 class NotebookCtrlWindowHandler(xrc.XmlResourceHandler):
5963 """
5964 Create L{NotebookCtrl} windows defined in Xrc resources.
5965
5966 Below is an example of a resource definition::
5967 <?xml version="1.0" encoding="ISO-8859-1"?>
5968 <resource>
5969 <object class="wxPanel" name="appPanel">
5970 <object class="wxBoxSizer">
5971 <orient>wxVERTICAL</orient>
5972 <object class="sizeritem">
5973 <option>1</option>
5974 <flag>wxEXPAND</flag>
5975 <object class="NotebookCtrl" name="notebook">
5976 <style>wxNO_BORDER | NC_RIGHT | NC_ROTATE | NC_EXPANDABLE </style>
5977 <focus>0</focus>
5978 <highlight>1</highlight>
5979 <tabstyle>NC_GRADIENT_HORIZONTAL | NC_GRADIENT_SELECTION</tabstyle>
5980 <color1>#DCDCDC</color1>
5981 <color2>#F5F5F5</color2>
5982 <selectedcolor1>#C4DADB</selectedcolor1>
5983 <selectedcolor2>#FFFFFF</selectedcolor2>
5984 <custompagecolor>#C0C0C0</custompagecolor>
5985 </object>
5986 </object>
5987 </object>
5988 </object>
5989 </resource>
5990
5991 @undocumented: CanHandle, DoCreateResource, SetupWindow
5992 """
5993 def __init__(self):
5994 """
5995 Create a NotebookCtrlWindowHandler instance.
5996 """
5997 xrc.XmlResourceHandler.__init__(self)
5998 # Specify the window styles recognized by objects of this type
5999 self.AddStyle("wxNO_BORDER", wx.NO_BORDER)
6000 self.AddStyle("wxTAB_TRAVERSAL", wx.TAB_TRAVERSAL)
6001 self.AddStyle("NC_TOP", NC_TOP)
6002 self.AddStyle("NC_BOTTOM", NC_BOTTOM)
6003 self.AddStyle("NC_LEFT", NC_LEFT)
6004 self.AddStyle("NC_RIGHT", NC_RIGHT)
6005 self.AddStyle("NC_FIXED_WIDTH", NC_FIXED_WIDTH)
6006 self.AddStyle("NC_ROTATE", NC_ROTATE)
6007 self.AddStyle("NC_EXPANDABLE", NC_EXPANDABLE)
6008 # More styles, used in the tabstyle parameter
6009 self.AddStyle("NC_AQUA_LIGHT", NC_AQUA_LIGHT)
6010 self.AddStyle("NC_AQUA_DARK", NC_AQUA_DARK)
6011 self.AddStyle("NC_AQUA", NC_AQUA)
6012 self.AddStyle("NC_METAL", NC_METAL)
6013 self.AddStyle("NC_SILVER", NC_SILVER)
6014 self.AddStyle("NC_KDE", NC_KDE)
6015 self.AddStyle("NC_GRADIENT_VERTICAL", NC_GRADIENT_VERTICAL)
6016 self.AddStyle("NC_GRADIENT_HORIZONTAL", NC_GRADIENT_HORIZONTAL)
6017 self.AddStyle("NC_GRADIENT_SELECTION", NC_GRADIENT_SELECTION)
6018
6019 self.AddWindowStyles()
6020
6021 def _CreateResourceInstance(self, parent, id, position, size, style, name):
6022 window = NotebookCtrl(parent, id, position, size=size, style=style, name=name)
6023 return window
6024
6025 def _GetColorParamValue(self, paramName, defaultValue=wx.WHITE):
6026 paramValue = self.GetParamValue(paramName)
6027 if paramValue:
6028 return self.GetColour(paramName)
6029 else:
6030 return defaultValue
6031
6032 def _GetCustomPage(self, window):
6033 customPage = wx.Window(window, -1, style = wx.STATIC_BORDER)
6034 customPage.SetBackgroundColour(self._GetColorParamValue('custompagecolor'))
6035 return customPage
6036
6037 def _GetIntParamValue(self, paramName, defaultValue=0):
6038 paramValue = self.GetParamValue(paramName)
6039 if paramValue:
6040 return int(paramValue)
6041 else:
6042 return defaultValue
6043
6044 def _GetTabTheme(self):
6045 tabstyle = self.GetStyle("tabstyle")
6046
6047 if tabstyle:
6048 result = ThemeStyle()
6049 if tabstyle & NC_GRADIENT_VERTICAL or tabstyle & NC_GRADIENT_HORIZONTAL:
6050 result.EnableGradientStyle(True, tabstyle)
6051 result.SetFirstGradientColour(self._GetColorParamValue('color1'))
6052 result.SetSecondGradientColour(self._GetColorParamValue('color2'))
6053 result.SetFirstGradientColourSelected(self._GetColorParamValue('selectedcolor1'))
6054 result.SetSecondGradientColourSelected(self._GetColorParamValue('selectedcolor2'))
6055 elif tabstyle & NC_AQUA_LIGHT or tabstyle & NC_AQUA_DARK:
6056 result.EnableAquaTheme(True, tabstyle & NC_AQUA_LIGHT and 2 or 1)
6057 elif tabstyle & NC_METAL:
6058 result.EnableMetalTheme(True)
6059 elif tabstyle & NC_KDE:
6060 result.EnableKDETheme(True)
6061 elif tabstyle & NC_SILVER:
6062 result.EnableSilverTheme(True)
6063 else:
6064 result = GetDefaultTabStyle()
6065 return result
6066
6067 # This method and the next one are required for XmlResourceHandlers
6068 def CanHandle(self, node):
6069 return self.IsOfClass(node, "NotebookCtrl")
6070
6071 def DoCreateResource(self):
6072 # NOTE: wxWindows can be created in either a single-phase or
6073 # in a two-phase way. Single phase is what you normally do,
6074 # and two-phase creates the instnace first, and then later
6075 # creates the actual window when the Create method is called.
6076 # (In wxPython the first phase is done using the wxPre*
6077 # function, for example, wxPreFrame, wxPrePanel, etc.)
6078 #
6079 # wxXmlResource supports either method, a premade instance can
6080 # be created and populated by xrc using the appropriate
6081 # LoadOn* method (such as LoadOnPanel) or xrc can create the
6082 # instance too, using the Load* method. However this makes
6083 # the handlers a bit more complex. If you can be sure that a
6084 # particular class will never be loaded using a pre-existing
6085 # instance, then you can make the handle much simpler. I'll
6086 # show both methods below.
6087
6088 # The simple method assumes that there is no existing
6089 # instance. Be sure of that with an assert.
6090 assert self.GetInstance() is None
6091
6092 # Now create the object
6093 window = self._CreateResourceInstance(self.GetParentAsWindow(),
6094 self.GetID(),
6095 self.GetPosition(),
6096 self.GetSize(),
6097 self.GetStyle("style", NC_DEFAULT_STYLE),
6098 self.GetName())
6099
6100 # Set standard window attributes
6101 self.SetupWindow(window)
6102 # Create any child windows of this node
6103 self.CreateChildren(window)
6104
6105 return window
6106
6107 def SetupWindow(self, window):
6108 super(NotebookCtrlWindowHandler, self).SetupWindow(window)
6109 window.ApplyTabTheme(self._GetTabTheme())
6110 window.SetHighlightSelection(self._GetIntParamValue("highlight", 0) != 0)
6111 window.SetUseFocusIndicator(self._GetIntParamValue("focus", 1) != 0)
6112 window.SetCustomPage(self._GetCustomPage(window))