~ubuntu-branches/ubuntu/raring/wxwidgets2.8/raring

« back to all changes in this revision

Viewing changes to wxPython/wx/lib/agw/aui/auibook.py

  • Committer: Package Import Robot
  • Author(s): Stéphane Graber
  • Date: 2012-01-07 13:59:25 UTC
  • mfrom: (1.1.9) (5.1.10 sid)
  • Revision ID: package-import@ubuntu.com-20120107135925-2601miy9ullcon9j
Tags: 2.8.12.1-6ubuntu1
* Resync from Debian, changes that were kept:
  - debian/rules: re-enable mediactrl. This allows libwx_gtk2u_media-2.8 to be
    built, as this is required by some applications (LP: #632984)
  - debian/control: Build-dep on libxt-dev for mediactrl.
  - Patches
    + fix-bashism-in-example
* Add conflict on python-wxgtk2.8 (<< 2.8.12.1-6ubuntu1~) to python-wxversion
  to guarantee upgrade ordering when moving from pycentral to dh_python2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 
18
18
import wx
19
19
import types
 
20
import datetime
20
21
 
21
22
from wx.lib.expando import ExpandoTextCtrl
22
23
 
123
124
        :param `tab`: the actual L{AuiNotebookPage} tab;
124
125
        :param `page_index`: the L{AuiNotebook} page index for the tab.
125
126
        """
126
 
        
 
127
 
127
128
        self._owner = owner
128
129
        self._tabEdited = tab
129
130
        self._pageIndex = page_index
147
148
        if image.IsOk():
148
149
            image_w, image_h = image.GetWidth(), image.GetHeight()
149
150
            image_w += 6
150
 
        
 
151
 
151
152
        dc = wx.ClientDC(self._owner)
152
153
        h = max(image_h, dc.GetMultiLineTextExtent(tab.caption)[1])
153
154
        h = h + 2
154
 
            
 
155
 
155
156
        # FIXME: what are all these hardcoded 4, 8 and 11s really?
156
157
        x += image_w
157
158
        w -= image_w + 4
158
159
 
159
 
        y = (self._tabEdited.rect.height - h)/2 + 1   
 
160
        y = (self._tabEdited.rect.height - h)/2 + 1
160
161
 
161
162
        expandoStyle = wx.WANTS_CHARS
162
163
        if wx.Platform in ["__WXGTK__", "__WXMAC__"]:
165
166
        else:
166
167
            expandoStyle |= wx.SUNKEN_BORDER
167
168
            xSize, ySize = w + 2, h+2
168
 
            
 
169
 
169
170
        ExpandoTextCtrl.__init__(self, self._owner, wx.ID_ANY, self._startValue,
170
171
                                 wx.Point(x, y), wx.Size(xSize, ySize),
171
172
                                 expandoStyle)
174
175
            self.SetFont(owner.GetFont())
175
176
            bs = self.GetBestSize()
176
177
            self.SetSize((-1, bs.height))
177
 
        
 
178
 
178
179
        self.Bind(wx.EVT_CHAR, self.OnChar)
179
180
        self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
180
181
        self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
181
 
    
 
182
 
182
183
 
183
184
    def AcceptChanges(self):
184
185
        """ Accepts/refuses the changes made by the user. """
201
202
 
202
203
        # accepted, do rename the item
203
204
        notebook.SetPageText(self._pageIndex, value)
204
 
        
 
205
 
205
206
        return True
206
207
 
207
208
 
211
212
        if not self._finished:
212
213
 
213
214
            notebook = self._owner.GetParent()
214
 
        
 
215
 
215
216
            self._finished = True
216
217
            self._owner.SetFocus()
217
218
            notebook.ResetTextControl()
218
 
        
 
219
 
219
220
 
220
221
    def OnChar(self, event):
221
222
        """
243
244
 
244
245
        else:
245
246
            event.Skip()
246
 
    
 
247
 
247
248
 
248
249
    def OnKeyUp(self, event):
249
250
        """
274
275
        """
275
276
 
276
277
        if not self._finished and not self._aboutToFinish:
277
 
        
 
278
 
278
279
            # We must finish regardless of success, otherwise we'll get
279
280
            # focus problems:
280
281
            if not self.AcceptChanges():
291
292
 
292
293
        self._owner.GetParent().OnRenameCancelled(self._pageIndex)
293
294
        self.Finish()
294
 
        
295
 
    
 
295
 
 
296
 
296
297
    def item(self):
297
298
        """ Returns the item currently edited. """
298
299
 
324
325
                                        # AUI_NB_CLOSE_ON_ALL_TABS
325
326
        self.control = None             # A control can now be inside a tab
326
327
        self.renamable = False          # If True, a tab can be renamed by a left double-click
327
 
        
 
328
 
328
329
        self.text_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNTEXT)
329
330
 
 
331
        self.access_time = datetime.datetime.now() # Last time this page was selected
 
332
 
330
333
 
331
334
    def IsMultiline(self):
332
335
        """ Returns whether the tab contains multiline text. """
333
336
 
334
337
        return "\n" in self.caption
335
 
    
336
 
        
 
338
 
 
339
 
337
340
# ----------------------------------------------------------------------
338
341
 
339
342
class AuiTabContainerButton(object):
359
362
 
360
363
class CommandNotebookEvent(wx.PyCommandEvent):
361
364
    """ A specialized command event class for events sent by L{AuiNotebook} . """
362
 
    
 
365
 
363
366
    def __init__(self, command_type=None, win_id=0):
364
367
        """
365
368
        Default class constructor.
368
371
        :param `win_id`: the window identification number.
369
372
        """
370
373
 
371
 
        if type(command_type) == types.IntType:    
 
374
        if type(command_type) == types.IntType:
372
375
            wx.PyCommandEvent.__init__(self, command_type, win_id)
373
376
        else:
374
377
            wx.PyCommandEvent.__init__(self, command_type.GetEventType(), command_type.GetId())
375
 
            
 
378
 
376
379
        self.old_selection = -1
377
380
        self.selection = -1
378
381
        self.drag_source = None
381
384
        self.editCancelled = False
382
385
 
383
386
 
384
 
    def Clone(self):
385
 
        """
386
 
        Returns a copy of the event.
387
 
 
388
 
        Any event that is posted to the wxPython event system for later action (via
389
 
        `wx.EvtHandler.AddPendingEvent` or `wx.PostEvent`) must implement this method.
390
 
        All wxPython events fully implement this method, but any derived events
391
 
        implemented by the user should also implement this method just in case they
392
 
        (or some event derived from them) are ever posted.
393
 
 
394
 
        All wxPython events implement a copy constructor, so the easiest way of
395
 
        implementing the L{Clone} function is to implement a copy constructor for a new
396
 
        event (call it `MyEvent`) and then define the L{Clone} function like this::
397
 
 
398
 
            def Clone(self):
399
 
                return MyEvent(self)
400
 
 
401
 
        """
402
 
        
403
 
        return CommandNotebookEvent(self)
404
 
 
405
 
 
406
387
    def SetSelection(self, s):
407
388
        """
408
389
        Sets the selection member variable.
413
394
        self.selection = s
414
395
        self._commandInt = s
415
396
 
416
 
        
 
397
 
417
398
    def GetSelection(self):
418
399
        """ Returns the currently selected page, or -1 if none was selected. """
419
400
 
426
407
 
427
408
        :param `s`: the old selection.
428
409
        """
429
 
        
 
410
 
430
411
        self.old_selection = s
431
412
 
432
 
        
 
413
 
433
414
    def GetOldSelection(self):
434
415
        """
435
416
        Returns the page that was selected before the change, or -1 if none was
437
418
        """
438
419
 
439
420
        return self.old_selection
440
 
    
 
421
 
441
422
 
442
423
    def SetDragSource(self, s):
443
424
        """
448
429
 
449
430
        self.drag_source = s
450
431
 
451
 
        
 
432
 
452
433
    def GetDragSource(self):
453
434
        """ Returns the drag and drop source. """
454
435
 
464
445
 
465
446
        self.dispatched = b
466
447
 
467
 
        
 
448
 
468
449
    def GetDispatched(self):
469
450
        """ Returns whether the event was dispatched (used for automatic L{AuiNotebook} ). """
470
451
 
492
473
 
493
474
        return self.label
494
475
 
495
 
    
 
476
 
496
477
    def SetLabel(self, label):
497
478
        """
498
479
        Sets the label. Useful only for ``EVT_AUINOTEBOOK_END_LABEL_EDIT``.
501
482
        """
502
483
 
503
484
        self.label = label
504
 
    
 
485
 
505
486
 
506
487
# ----------------------------------------------------------------------
507
488
 
508
489
class AuiNotebookEvent(CommandNotebookEvent):
509
490
    """ A specialized command event class for events sent by L{AuiNotebook}. """
510
 
    
 
491
 
511
492
    def __init__(self, command_type=None, win_id=0):
512
493
        """
513
494
        Default class constructor.
524
505
            self.notify = wx.NotifyEvent(command_type.GetEventType(), command_type.GetId())
525
506
 
526
507
 
527
 
    def Clone(self):
528
 
        """
529
 
        Returns a copy of the event.
530
 
 
531
 
        Any event that is posted to the wxPython event system for later action (via
532
 
        `wx.EvtHandler.AddPendingEvent` or `wx.PostEvent`) must implement this method.
533
 
        All wxPython events fully implement this method, but any derived events
534
 
        implemented by the user should also implement this method just in case they
535
 
        (or some event derived from them) are ever posted.
536
 
 
537
 
        All wxPython events implement a copy constructor, so the easiest way of
538
 
        implementing the L{Clone} function is to implement a copy constructor for a new
539
 
        event (call it `MyEvent`) and then define the L{Clone} function like this::
540
 
 
541
 
            def Clone(self):
542
 
                return MyEvent(self)
543
 
 
544
 
        """
545
 
        
546
 
        return AuiNotebookEvent(self)
547
 
 
548
 
        
549
508
    def GetNotifyEvent(self):
550
509
        """ Returns the actual `wx.NotifyEvent`. """
551
 
        
 
510
 
552
511
        return self.notify
553
512
 
554
513
 
579
538
        """
580
539
 
581
540
        self.notify.Allow()
582
 
        
 
541
 
583
542
 
584
543
# ---------------------------------------------------------------------------- #
585
544
# Class TabNavigatorWindow
603
562
 
604
563
        self._selectedItem = -1
605
564
        self._indexMap = []
606
 
        
 
565
 
607
566
        if icon is None:
608
567
            self._bmp = Mondrian.GetBitmap()
609
568
        else:
613
572
            img = self._bmp.ConvertToImage()
614
573
            img.Rescale(16, 16, wx.IMAGE_QUALITY_HIGH)
615
574
            self._bmp = wx.BitmapFromImage(img)
616
 
            
 
575
 
617
576
        sz = wx.BoxSizer(wx.VERTICAL)
618
 
        
 
577
 
619
578
        self._listBox = wx.ListBox(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(200, 150), [], wx.LB_SINGLE | wx.NO_BORDER)
620
 
        
 
579
 
621
580
        mem_dc = wx.MemoryDC()
622
581
        mem_dc.SelectObject(wx.EmptyBitmap(1,1))
623
582
        font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
630
589
        # Out signpost bitmap is 24 pixels
631
590
        if panelHeight < 24:
632
591
            panelHeight = 24
633
 
        
 
592
 
634
593
        self._panel = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(200, panelHeight))
635
594
 
636
595
        sz.Add(self._panel)
637
596
        sz.Add(self._listBox, 1, wx.EXPAND)
638
 
        
 
597
 
639
598
        self.SetSizer(sz)
640
599
 
641
600
        # Connect events to the list box
642
601
        self._listBox.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
643
602
        self._listBox.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey)
644
603
        self._listBox.Bind(wx.EVT_LISTBOX_DCLICK, self.OnItemSelected)
645
 
        
 
604
 
646
605
        # Connect paint event to the panel
647
606
        self._panel.Bind(wx.EVT_PAINT, self.OnPanelPaint)
648
607
        self._panel.Bind(wx.EVT_ERASE_BACKGROUND, self.OnPanelEraseBg)
650
609
        self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
651
610
        self._listBox.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
652
611
        self.PopulateListControl(parent)
653
 
        
 
612
 
654
613
        self.GetSizer().Fit(self)
655
614
        self.GetSizer().SetSizeHints(self)
656
615
        self.GetSizer().Layout()
667
626
 
668
627
        :param `event`: a `wx.KeyEvent` event to be processed.
669
628
        """
670
 
        
 
629
 
671
630
        if event.GetKeyCode() == wx.WXK_CONTROL:
672
631
            self.CloseDialog()
673
632
 
682
641
        selected = self._listBox.GetSelection()
683
642
        bk = self.GetParent()
684
643
        maxItems = bk.GetPageCount()
685
 
            
 
644
 
686
645
        if event.GetDirection():
687
 
        
 
646
 
688
647
            # Select next page
689
648
            if selected == maxItems - 1:
690
649
                itemToSelect = 0
691
650
            else:
692
651
                itemToSelect = selected + 1
693
 
        
 
652
 
694
653
        else:
695
 
        
 
654
 
696
655
            # Previous page
697
656
            if selected == 0:
698
657
                itemToSelect = maxItems - 1
699
658
            else:
700
659
                itemToSelect = selected - 1
701
 
        
 
660
 
702
661
        self._listBox.SetSelection(itemToSelect)
703
662
 
704
663
 
708
667
 
709
668
        :param `book`: the actual L{AuiNotebook}.
710
669
        """
711
 
 
 
670
        # Index of currently selected page
712
671
        selection = book.GetSelection()
 
672
        # Total number of pages
713
673
        count = book.GetPageCount()
714
 
        
715
 
        self._listBox.Append(book.GetPageText(selection))
716
 
        self._indexMap.append(selection)
717
 
        
718
 
        for c in xrange(count):
719
 
        
720
 
            # Skip selected page
721
 
            if c == selection:
722
 
                continue
 
674
        # List of (index, AuiNotebookPage)
 
675
        pages = list(enumerate(book.GetTabContainer().GetPages()))
 
676
        if book.GetAGWWindowStyleFlag() & AUI_NB_ORDER_BY_ACCESS:
 
677
            # Sort pages using last access time. Most recently used is the
 
678
            # first in line
 
679
            pages.sort(
 
680
                key = lambda element: element[1].access_time,
 
681
                reverse = True
 
682
            )
 
683
        else:
 
684
            # Manually add the current selection as first item
 
685
            # Remaining ones are added in the next loop
 
686
            del pages[selection]
 
687
            self._listBox.Append(book.GetPageText(selection))
 
688
            self._indexMap.append(selection)
723
689
 
724
 
            self._listBox.Append(book.GetPageText(c))
725
 
            self._indexMap.append(c)
 
690
        for (index, page) in pages:
 
691
            self._listBox.Append(book.GetPageText(index))
 
692
            self._indexMap.append(index)
726
693
 
727
694
        # Select the next entry after the current selection
728
695
        self._listBox.SetSelection(0)
746
713
 
747
714
        bk = self.GetParent()
748
715
        self._selectedItem = self._listBox.GetSelection()
749
 
        iter = self._indexMap[self._selectedItem]
750
 
        bk.SetSelection(iter)
751
 
 
752
716
        self.EndModal(wx.ID_OK)
753
 
        
 
717
 
 
718
 
 
719
    def GetSelectedPage(self):
 
720
        """ Gets the page index that was selected when the dialog was closed. """
 
721
 
 
722
        return self._indexMap[self._selectedItem]
 
723
 
754
724
 
755
725
    def OnPanelPaint(self, event):
756
726
        """
783
753
        font.SetWeight(wx.BOLD)
784
754
        mem_dc.SetFont(font)
785
755
        fontHeight = mem_dc.GetCharHeight()
786
 
        
 
756
 
787
757
        txtPt.x = bmpPt.x + self._bmp.GetWidth() + 4
788
758
        txtPt.y = (rect.height - fontHeight)/2
789
759
        mem_dc.SetTextForeground(wx.WHITE)
790
760
        mem_dc.DrawText("Opened tabs:", txtPt.x, txtPt.y)
791
761
        mem_dc.SelectObject(wx.NullBitmap)
792
 
        
 
762
 
793
763
        dc.DrawBitmap(bmp, 0, 0)
794
764
 
795
765
 
824
794
        """
825
795
        Default class constructor.
826
796
        Used internally, do not call it in your code!
 
797
 
 
798
        :param `auiNotebook`: the parent L{AuiNotebook} window.        
827
799
        """
828
800
 
829
801
        self._tab_offset = 0
833
805
        self._buttons = []
834
806
        self._pages = []
835
807
        self._tab_close_buttons = []
836
 
        
 
808
 
837
809
        self._rect = wx.Rect()
838
810
        self._auiNotebook = auiNotebook
839
 
        
 
811
 
840
812
        self.AddButton(AUI_BUTTON_LEFT, wx.LEFT)
841
813
        self.AddButton(AUI_BUTTON_RIGHT, wx.RIGHT)
842
814
        self.AddButton(AUI_BUTTON_WINDOWLIST, wx.RIGHT)
846
818
    def SetArtProvider(self, art):
847
819
        """
848
820
        Instructs L{AuiTabContainer} to use art provider specified by parameter `art`
849
 
        for all drawing calls. This allows plugable look-and-feel features. 
 
821
        for all drawing calls. This allows plugable look-and-feel features.
850
822
 
851
823
        :param `art`: an art provider.
852
824
 
853
 
        :note: The previous art provider object, if any, will be deleted by L{AuiTabContainer}.        
 
825
        :note: The previous art provider object, if any, will be deleted by L{AuiTabContainer}.
854
826
        """
855
827
 
856
828
        del self._art
858
830
 
859
831
        if self._art:
860
832
            self._art.SetAGWFlags(self._agwFlags)
861
 
    
 
833
 
862
834
 
863
835
    def GetArtProvider(self):
864
836
        """ Returns the current art provider being used. """
876
848
         Flag name                            Description
877
849
         ==================================== ==================================
878
850
         ``AUI_NB_TOP``                       With this style, tabs are drawn along the top of the notebook
879
 
         ``AUI_NB_LEFT``                      With this style, tabs are drawn along the left of the notebook. Not implemented yet.
880
 
         ``AUI_NB_RIGHT``                     With this style, tabs are drawn along the right of the notebook. Not implemented yet.
881
 
         ``AUI_NB_BOTTOM``                    With this style, tabs are drawn along the bottom of the notebook.
 
851
         ``AUI_NB_LEFT``                      With this style, tabs are drawn along the left of the notebook. Not implemented yet
 
852
         ``AUI_NB_RIGHT``                     With this style, tabs are drawn along the right of the notebook. Not implemented yet
 
853
         ``AUI_NB_BOTTOM``                    With this style, tabs are drawn along the bottom of the notebook
882
854
         ``AUI_NB_TAB_SPLIT``                 Allows the tab control to be split by dragging a tab
883
855
         ``AUI_NB_TAB_MOVE``                  Allows a tab to be moved horizontally by dragging
884
856
         ``AUI_NB_TAB_EXTERNAL_MOVE``         Allows a tab to be moved to another tab control
888
860
         ``AUI_NB_CLOSE_BUTTON``              With this style, a close button is available on the tab bar
889
861
         ``AUI_NB_CLOSE_ON_ACTIVE_TAB``       With this style, a close button is available on the active tab
890
862
         ``AUI_NB_CLOSE_ON_ALL_TABS``         With this style, a close button is available on all tabs
891
 
         ``AUI_NB_MIDDLE_CLICK_CLOSE``        Allows to close AuiNotebook tabs by mouse middle button click
892
 
         ``AUI_NB_SUB_NOTEBOOK``              This style is used by AuiManager to create automatic AuiNotebooks
 
863
         ``AUI_NB_MIDDLE_CLICK_CLOSE``        Allows to close L{AuiNotebook} tabs by mouse middle button click
 
864
         ``AUI_NB_SUB_NOTEBOOK``              This style is used by L{AuiManager} to create automatic AuiNotebooks
893
865
         ``AUI_NB_HIDE_ON_SINGLE_TAB``        Hides the tab window if only one tab is present
894
866
         ``AUI_NB_SMART_TABS``                Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows
895
867
         ``AUI_NB_USE_IMAGES_DROPDOWN``       Uses images on dropdown window list menu instead of check items
896
868
         ``AUI_NB_CLOSE_ON_TAB_LEFT``         Draws the tab close button on the left instead of on the right (a la Camino browser)
897
869
         ``AUI_NB_TAB_FLOAT``                 Allows the floating of single tabs. Known limitation: when the notebook is more or less full screen, tabs cannot be dragged far enough outside of the notebook to become floating pages
898
870
         ``AUI_NB_DRAW_DND_TAB``              Draws an image representation of a tab while dragging (on by default)
 
871
         ``AUI_NB_ORDER_BY_ACCESS``           Tab navigation order by last access time for the tabs
 
872
         ``AUI_NB_NO_TAB_FOCUS``              Don't draw tab focus rectangle
899
873
         ==================================== ==================================
900
874
 
901
875
        :todo: Implementation of flags ``AUI_NB_RIGHT`` and ``AUI_NB_LEFT``.
902
 
        
 
876
 
903
877
        """
904
 
        
 
878
 
905
879
        self._agwFlags = agwFlags
906
880
 
907
881
        # check for new close button settings
913
887
        if agwFlags & AUI_NB_SCROLL_BUTTONS:
914
888
            self.AddButton(AUI_BUTTON_LEFT, wx.LEFT)
915
889
            self.AddButton(AUI_BUTTON_RIGHT, wx.RIGHT)
916
 
        
 
890
 
917
891
        if agwFlags & AUI_NB_WINDOWLIST_BUTTON:
918
892
            self.AddButton(AUI_BUTTON_WINDOWLIST, wx.RIGHT)
919
 
        
 
893
 
920
894
        if agwFlags & AUI_NB_CLOSE_BUTTON:
921
895
            self.AddButton(AUI_BUTTON_CLOSE, wx.RIGHT)
922
896
 
923
897
        if self._art:
924
898
            self._art.SetAGWFlags(self._agwFlags)
925
 
        
 
899
 
926
900
 
927
901
    def GetAGWFlags(self):
928
902
        """
997
971
        if self._art:
998
972
            minMaxTabWidth = self._auiNotebook.GetMinMaxTabWidth()
999
973
            self._art.SetSizingInfo(self._rect.GetSize(), len(self._pages), minMaxTabWidth)
1000
 
        
 
974
 
1001
975
        return True
1002
976
 
1003
977
 
1009
983
        :param `info`: an instance of L{AuiNotebookPage};
1010
984
        :param `idx`: the page insertion index.
1011
985
        """
1012
 
        
 
986
 
1013
987
        page_info = info
1014
988
        page_info.window = page
1015
989
 
1022
996
        if self._art:
1023
997
            minMaxTabWidth = self._auiNotebook.GetMinMaxTabWidth()
1024
998
            self._art.SetSizingInfo(self._rect.GetSize(), len(self._pages), minMaxTabWidth)
1025
 
        
 
999
 
1026
1000
        return True
1027
 
    
 
1001
 
1028
1002
 
1029
1003
    def MovePage(self, page, new_idx):
1030
1004
        """
1033
1007
        :param `page`: the window associated with this tab;
1034
1008
        :param `new_idx`: the new page position.
1035
1009
        """
1036
 
        
 
1010
 
1037
1011
        idx = self.GetIdxFromWindow(page)
1038
1012
        if idx == -1:
1039
1013
            return False
1062
1036
        for page in self._pages:
1063
1037
            if page.window == wnd:
1064
1038
                self._pages.remove(page)
1065
 
                
 
1039
                self._tab_offset = min(self._tab_offset, len(self._pages) - 1)
 
1040
 
1066
1041
                # let the art provider know how many pages we have
1067
1042
                if self._art:
1068
1043
                    self._art.SetSizingInfo(self._rect.GetSize(), len(self._pages), minMaxTabWidth)
1069
1044
 
1070
1045
                return True
1071
 
            
 
1046
 
1072
1047
        return False
1073
1048
 
1074
1049
 
1088
1063
 
1089
1064
        else:
1090
1065
            wnd = wndOrInt
1091
 
            
 
1066
 
1092
1067
        found = False
1093
1068
 
1094
1069
        for indx, page in enumerate(self._pages):
1102
1077
 
1103
1078
 
1104
1079
    def SetNoneActive(self):
1105
 
        """ Sets all the tabs as incative (non-selected). """
 
1080
        """ Sets all the tabs as inactive (non-selected). """
1106
1081
 
1107
 
        for page in self._pages:        
 
1082
        for page in self._pages:
1108
1083
            page.active = False
1109
 
    
 
1084
 
1110
1085
 
1111
1086
    def GetActivePage(self):
1112
1087
        """ Returns the current selected tab or ``wx.NOT_FOUND`` if none is selected. """
1114
1089
        for indx, page in enumerate(self._pages):
1115
1090
            if page.active:
1116
1091
                return indx
1117
 
    
 
1092
 
1118
1093
        return wx.NOT_FOUND
1119
1094
 
1120
1095
 
1137
1112
 
1138
1113
        :param `wnd`: an instance of `wx.Window`.
1139
1114
        """
1140
 
        
 
1115
 
1141
1116
        for indx, page in enumerate(self._pages):
1142
1117
            if page.window == wnd:
1143
1118
                return indx
1176
1151
 
1177
1152
        :param `idx`: the tab index.
1178
1153
        """
1179
 
        
 
1154
 
1180
1155
        if idx < 0 or idx >= len(self._pages):
1181
1156
            return False
1182
1157
 
1190
1165
        :param `idx`: the tab index;
1191
1166
        :param `enable`: ``True`` to enable a tab, ``False`` to disable it.
1192
1167
        """
1193
 
        
 
1168
 
1194
1169
        if idx < 0 or idx >= len(self._pages):
1195
1170
            raise Exception("Invalid Page index")
1196
1171
 
1198
1173
        wnd = self.GetWindowFromIdx(idx)
1199
1174
        wnd.Enable(enable)
1200
1175
 
1201
 
                
 
1176
 
1202
1177
    def AddButton(self, id, location, normal_bitmap=wx.NullBitmap, disabled_bitmap=wx.NullBitmap):
1203
1178
        """
1204
1179
        Adds a button in the tab area.
1212
1187
         ``AUI_BUTTON_WINDOWLIST``       Shows a window list button on the tab area
1213
1188
         ``AUI_BUTTON_LEFT``             Shows a left button on the tab area
1214
1189
         ``AUI_BUTTON_RIGHT``            Shows a right button on the tab area
1215
 
         ==============================  =================================        
 
1190
         ==============================  =================================
1216
1191
 
1217
1192
        :param `location`: the button location. Can be ``wx.LEFT`` or ``wx.RIGHT``;
1218
1193
        :param `normal_bitmap`: the bitmap for an enabled tab;
1235
1210
 
1236
1211
        :param `id`: the button identifier. See L{AddButton} for a list of button identifiers.
1237
1212
 
1238
 
        :see: L{AddButton}        
 
1213
        :see: L{AddButton}
1239
1214
        """
1240
 
        
 
1215
 
1241
1216
        for button in self._buttons:
1242
1217
            if button.id == id:
1243
1218
                self._buttons.remove(button)
1256
1231
 
1257
1232
        :param `offset`: the tab offset.
1258
1233
        """
1259
 
        
 
1234
 
1260
1235
        self._tab_offset = offset
1261
1236
 
1262
1237
 
 
1238
    def MinimizeTabOffset(self, dc, wnd, max_width):
 
1239
        """
 
1240
        Minimize `self._tab_offset` to fit as many tabs as possible in the available space.
 
1241
 
 
1242
        :param `dc`: a `wx.DC` device context;
 
1243
        :param `wnd`: an instance of `wx.Window`;
 
1244
        :param `max_width`: the maximum available width for the tabs.
 
1245
        """
 
1246
 
 
1247
        total_width = 0
 
1248
 
 
1249
        for i, page in reversed(list(enumerate(self._pages))):
 
1250
 
 
1251
            tab_button = self._tab_close_buttons[i]
 
1252
            (tab_width, tab_height), x_extent = self._art.GetTabSize(dc, wnd, page.caption, page.bitmap, page.active, tab_button.cur_state, page.control)
 
1253
            total_width += tab_width
 
1254
 
 
1255
            if total_width > max_width:
 
1256
 
 
1257
                tab_offset = i + 1
 
1258
 
 
1259
                if tab_offset < self._tab_offset and tab_offset < len(self._pages):
 
1260
                    self._tab_offset = tab_offset
 
1261
 
 
1262
                break
 
1263
 
 
1264
        if i == 0:
 
1265
            self._tab_offset = 0
 
1266
 
 
1267
 
1263
1268
    def Render(self, raw_dc, wnd):
1264
1269
        """
1265
 
        Render() renders the tab catalog to the specified `wx.DC`.
1266
 
        It is a virtual function and can be overridden to
1267
 
        provide custom drawing capabilities.
 
1270
        Renders the tab catalog to the specified `wx.DC`.
 
1271
 
 
1272
        It is a virtual function and can be overridden to provide custom drawing
 
1273
        capabilities.
1268
1274
 
1269
1275
        :param `raw_dc`: a `wx.DC` device context;
1270
1276
        :param `wnd`: an instance of `wx.Window`.
1288
1294
 
1289
1295
        if not dc.IsOk():
1290
1296
            return
1291
 
            
 
1297
 
1292
1298
        # find out if size of tabs is larger than can be
1293
1299
        # afforded on screen
1294
1300
        total_width = visible_width = 0
1295
 
        
 
1301
 
1296
1302
        for i in xrange(page_count):
1297
1303
            page = self._pages[i]
1298
 
                
 
1304
 
1299
1305
            # determine if a close button is on this tab
1300
1306
            close_button = False
1301
1307
            if (self._agwFlags & AUI_NB_CLOSE_ON_ALL_TABS and page.hasCloseButton) or \
1302
1308
               (self._agwFlags & AUI_NB_CLOSE_ON_ACTIVE_TAB and page.active and page.hasCloseButton):
1303
 
            
 
1309
 
1304
1310
                close_button = True
1305
1311
 
1306
1312
            control = page.control
1309
1315
                    control.GetSize()
1310
1316
                except wx.PyDeadObjectError:
1311
1317
                    page.control = None
1312
 
                
 
1318
 
1313
1319
            size, x_extent = self._art.GetTabSize(dc, wnd, page.caption, page.bitmap, page.active,
1314
1320
                                                  (close_button and [AUI_BUTTON_STATE_NORMAL] or \
1315
1321
                                                   [AUI_BUTTON_STATE_HIDDEN])[0], page.control)
1319
1325
            else:
1320
1326
                total_width += size[0]
1321
1327
 
1322
 
            if i >= self._tab_offset:            
 
1328
            if i >= self._tab_offset:
1323
1329
                if i+1 < page_count:
1324
1330
                    visible_width += x_extent
1325
1331
                else:
1326
1332
                    visible_width += size[0]
1327
1333
 
1328
1334
        if total_width > self._rect.GetWidth() or self._tab_offset != 0:
1329
 
        
 
1335
 
1330
1336
            # show left/right buttons
1331
1337
            for button in self._buttons:
1332
1338
                if button.id == AUI_BUTTON_LEFT or \
1333
1339
                   button.id == AUI_BUTTON_RIGHT:
1334
 
                
 
1340
 
1335
1341
                    button.cur_state &= ~AUI_BUTTON_STATE_HIDDEN
1336
 
                
 
1342
 
1337
1343
        else:
1338
 
        
 
1344
 
1339
1345
            # hide left/right buttons
1340
1346
            for button in self._buttons:
1341
1347
                if button.id == AUI_BUTTON_LEFT or \
1342
1348
                   button.id == AUI_BUTTON_RIGHT:
1343
 
                    
 
1349
 
1344
1350
                    button.cur_state |= AUI_BUTTON_STATE_HIDDEN
1345
1351
 
1346
1352
        # determine whether left button should be enabled
1350
1356
                    button.cur_state |= AUI_BUTTON_STATE_DISABLED
1351
1357
                else:
1352
1358
                    button.cur_state &= ~AUI_BUTTON_STATE_DISABLED
1353
 
            
 
1359
 
1354
1360
            if button.id == AUI_BUTTON_RIGHT:
1355
1361
                if visible_width < self._rect.GetWidth() - 16*button_count:
1356
1362
                    button.cur_state |= AUI_BUTTON_STATE_DISABLED
1357
1363
                else:
1358
1364
                    button.cur_state &= ~AUI_BUTTON_STATE_DISABLED
1359
 
            
 
1365
 
1360
1366
        # draw background
1361
1367
        self._art.DrawBackground(dc, wnd, self._rect)
1362
1368
 
1366
1372
 
1367
1373
        # draw the buttons on the right side
1368
1374
        offset = self._rect.x + self._rect.width
1369
 
        
1370
 
        for i in xrange(button_count):        
 
1375
 
 
1376
        for i in xrange(button_count):
1371
1377
            button = self._buttons[button_count - i - 1]
1372
1378
 
1373
1379
            if button.location != wx.RIGHT:
1383
1389
 
1384
1390
            offset -= button.rect.GetWidth()
1385
1391
            right_buttons_width += button.rect.GetWidth()
1386
 
        
 
1392
 
1387
1393
        offset = 0
1388
1394
 
1389
1395
        # draw the buttons on the left side
1390
 
        for i in xrange(button_count):        
 
1396
        for i in xrange(button_count):
1391
1397
            button = self._buttons[button_count - i - 1]
1392
1398
 
1393
1399
            if button.location != wx.LEFT:
1401
1407
 
1402
1408
            offset += button.rect.GetWidth()
1403
1409
            left_buttons_width += button.rect.GetWidth()
1404
 
        
 
1410
 
1405
1411
        offset = left_buttons_width
1406
1412
 
1407
1413
        if offset == 0:
1427
1433
                if self._pages[i].control.IsShown():
1428
1434
                    self._pages[i].control.Hide()
1429
1435
 
 
1436
        self.MinimizeTabOffset(dc, wnd, self._rect.GetWidth() - right_buttons_width - offset - 2)
 
1437
 
1430
1438
        # draw the tabs
1431
1439
        active = 999
1432
1440
        active_offset = 0
1433
 
        
 
1441
 
1434
1442
        rect = wx.Rect(*self._rect)
1435
1443
        rect.y = 0
1436
1444
        rect.height = self._rect.height
1437
1445
 
1438
1446
        for i in xrange(self._tab_offset, page_count):
1439
 
        
 
1447
 
1440
1448
            page = self._pages[i]
1441
1449
            tab_button = self._tab_close_buttons[i]
1442
1450
 
1443
1451
            # determine if a close button is on this tab
1444
1452
            if (self._agwFlags & AUI_NB_CLOSE_ON_ALL_TABS and page.hasCloseButton) or \
1445
1453
               (self._agwFlags & AUI_NB_CLOSE_ON_ACTIVE_TAB and page.active and page.hasCloseButton):
1446
 
            
 
1454
 
1447
1455
                if tab_button.cur_state == AUI_BUTTON_STATE_HIDDEN:
1448
 
                
 
1456
 
1449
1457
                    tab_button.id = AUI_BUTTON_CLOSE
1450
1458
                    tab_button.cur_state = AUI_BUTTON_STATE_NORMAL
1451
1459
                    tab_button.location = wx.CENTER
1452
 
                
 
1460
 
1453
1461
            else:
1454
 
            
 
1462
 
1455
1463
                tab_button.cur_state = AUI_BUTTON_STATE_HIDDEN
1456
 
            
 
1464
 
1457
1465
            rect.x = offset
1458
1466
            rect.width = self._rect.width - right_buttons_width - offset - 2
1459
1467
 
1469
1477
 
1470
1478
            offset += x_extent
1471
1479
 
1472
 
        lenPages = len(self._pages)        
 
1480
        lenPages = len(self._pages)
1473
1481
        # make sure to deactivate buttons which are off the screen to the right
1474
1482
        for j in xrange(i+1, len(self._tab_close_buttons)):
1475
1483
            self._tab_close_buttons[j].cur_state = AUI_BUTTON_STATE_HIDDEN
1477
1485
                if self._pages[j-1].control:
1478
1486
                    if self._pages[j-1].control.IsShown():
1479
1487
                        self._pages[j-1].control.Hide()
1480
 
        
 
1488
 
1481
1489
        # draw the active tab again so it stands in the foreground
1482
1490
        if active >= self._tab_offset and active < len(self._pages):
1483
 
        
 
1491
 
1484
1492
            page = self._pages[active]
1485
1493
            tab_button = self._tab_close_buttons[active]
1486
1494
 
1499
1507
        :param `dc`: a `wx.DC` device context;
1500
1508
        :param `wnd`: an instance of `wx.Window` derived window.
1501
1509
        """
1502
 
        
 
1510
 
1503
1511
        if not dc or not dc.IsOk():
1504
1512
            return False
1505
1513
 
1516
1524
            # check further for visibility.
1517
1525
            arrowButtonVisibleCount = 0
1518
1526
            for i in xrange(button_count):
1519
 
            
 
1527
 
1520
1528
                button = self._buttons[i]
1521
1529
                if button.id == AUI_BUTTON_LEFT or \
1522
1530
                   button.id == AUI_BUTTON_RIGHT:
1523
 
                
 
1531
 
1524
1532
                    if button.cur_state & AUI_BUTTON_STATE_HIDDEN == 0:
1525
1533
                        arrowButtonVisibleCount += 1
1526
 
                
 
1534
 
1527
1535
            # Tab must be visible
1528
1536
            if arrowButtonVisibleCount == 0:
1529
1537
                return True
1540
1548
 
1541
1549
        # calculate size of the buttons on the right side
1542
1550
        offset = self._rect.x + self._rect.width
1543
 
        
 
1551
 
1544
1552
        for i in xrange(button_count):
1545
1553
            button = self._buttons[button_count - i - 1]
1546
1554
 
1551
1559
 
1552
1560
            offset -= button.rect.GetWidth()
1553
1561
            right_buttons_width += button.rect.GetWidth()
1554
 
        
 
1562
 
1555
1563
        offset = 0
1556
1564
 
1557
1565
        # calculate size of the buttons on the left side
1565
1573
 
1566
1574
            offset += button.rect.GetWidth()
1567
1575
            left_buttons_width += button.rect.GetWidth()
1568
 
        
 
1576
 
1569
1577
        offset = left_buttons_width
1570
1578
 
1571
1579
        if offset == 0:
1577
1585
 
1578
1586
        # See if the given page is visible at the given tab offset (effectively scroll position)
1579
1587
        for i in xrange(tabOffset, page_count):
1580
 
        
 
1588
 
1581
1589
            page = self._pages[i]
1582
1590
            tab_button = self._tab_close_buttons[i]
1583
1591
 
1591
1599
            offset += x_extent
1592
1600
 
1593
1601
            if i == tabPage:
1594
 
            
 
1602
 
1595
1603
                # If not all of the tab is visible, and supposing there's space to display it all,
1596
1604
                # we could do better so we return False.
1597
1605
                if (self._rect.width - right_buttons_width - offset - 2) <= 0 and (self._rect.width - right_buttons_width - left_buttons_width) > x_extent:
1598
1606
                    return False
1599
1607
                else:
1600
1608
                    return True
1601
 
            
 
1609
 
1602
1610
        # Shouldn't really get here, but if it does, assume the tab is visible to prevent
1603
1611
        # further looping in calling code.
1604
1612
        return True
1610
1618
 
1611
1619
        :param `tabPage`: the tab index;
1612
1620
        :param `win`: an instance of `wx.Window` derived window.
1613
 
        """                
 
1621
        """
1614
1622
 
1615
1623
        dc = wx.ClientDC(win)
1616
 
        
 
1624
 
1617
1625
        if not self.IsTabVisible(tabPage, self.GetTabOffset(), dc, win):
1618
1626
            for i in xrange(len(self._pages)):
1619
1627
                if self.IsTabVisible(tabPage, i, dc, win):
1645
1653
                return page.window
1646
1654
 
1647
1655
        return None
1648
 
    
 
1656
 
1649
1657
 
1650
1658
    def ButtonHitTest(self, x, y):
1651
1659
        """
1652
 
        ButtonHitTest() tests if a button was hit.
 
1660
        Tests if a button was hit.
1653
1661
 
1654
1662
        :param `x`: the mouse `x` position;
1655
1663
        :param `y`: the mouse `y` position.
 
1664
 
 
1665
        :returns: and instance of L{AuiTabContainerButton} if a button was hit, ``None`` otherwise.
1656
1666
        """
1657
1667
 
1658
1668
        if not self._rect.Contains((x,y)):
1660
1670
 
1661
1671
        for button in self._buttons:
1662
1672
            if button.rect.Contains((x,y)) and \
1663
 
               (button.cur_state not in [AUI_BUTTON_STATE_HIDDEN, AUI_BUTTON_STATE_DISABLED]):
 
1673
               (button.cur_state & (AUI_BUTTON_STATE_HIDDEN|AUI_BUTTON_STATE_DISABLED)) == 0:
1664
1674
                return button
1665
 
            
 
1675
 
1666
1676
        for button in self._tab_close_buttons:
1667
1677
            if button.rect.Contains((x,y)) and \
1668
 
               (button.cur_state not in [AUI_BUTTON_STATE_HIDDEN, AUI_BUTTON_STATE_DISABLED]):
1669
 
                return button            
1670
 
            
 
1678
               (button.cur_state & (AUI_BUTTON_STATE_HIDDEN|AUI_BUTTON_STATE_DISABLED)) == 0:
 
1679
                return button
 
1680
 
1671
1681
        return None
1672
1682
 
1673
1683
 
1684
1694
            if page.active:
1685
1695
                page.window.Show(True)
1686
1696
                break
1687
 
            
 
1697
 
1688
1698
        # hide all other pages
1689
1699
        for page in pages:
1690
1700
            if not page.active:
1725
1735
        self._drag_image = None
1726
1736
        self._drag_img_offset = (0, 0)
1727
1737
        self._on_button = False
1728
 
        
 
1738
 
1729
1739
        self.Bind(wx.EVT_PAINT, self.OnPaint)
1730
1740
        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
1731
1741
        self.Bind(wx.EVT_SIZE, self.OnSize)
1756
1766
 
1757
1767
        return wx.BORDER_NONE
1758
1768
 
1759
 
    
 
1769
 
1760
1770
    def OnPaint(self, event):
1761
1771
        """
1762
1772
        Handles the ``wx.EVT_PAINT`` event for L{AuiTabCtrl}.
1763
1773
 
1764
1774
        :param `event`: a `wx.PaintEvent` event to be processed.
1765
1775
        """
1766
 
        
 
1776
 
1767
1777
        dc = wx.PaintDC(self)
1768
1778
        dc.SetFont(self.GetFont())
1769
1779
 
1775
1785
        """
1776
1786
        Handles the ``wx.EVT_ERASE_BACKGROUND`` event for L{AuiTabCtrl}.
1777
1787
 
1778
 
        :param `event`: a `wx.EraseEvent` event to be processed.        
 
1788
        :param `event`: a `wx.EraseEvent` event to be processed.
1779
1789
 
1780
1790
        :note: This is intentionally empty, to reduce flicker.
1781
1791
        """
1782
 
        
1783
 
        pass        
 
1792
 
 
1793
        pass
1784
1794
 
1785
1795
 
1786
1796
    def DoGetBestSize(self):
1788
1798
        Gets the size which best suits the window: for a control, it would be the
1789
1799
        minimal size which doesn't truncate the control, for a panel - the same
1790
1800
        size as it would have after a call to `Fit()`.
1791
 
        
 
1801
 
1792
1802
        :note: Overridden from `wx.PyControl`.
1793
1803
        """
1794
1804
 
1795
1805
        return wx.Size(self._rect.width, self._rect.height)
1796
 
    
 
1806
 
1797
1807
 
1798
1808
    def OnSize(self, event):
1799
1809
        """
1800
1810
        Handles the ``wx.EVT_SIZE`` event for L{AuiTabCtrl}.
1801
1811
 
1802
 
        :param `event`: a `wx.SizeEvent` event to be processed.        
 
1812
        :param `event`: a `wx.SizeEvent` event to be processed.
1803
1813
        """
1804
1814
 
1805
1815
        s = event.GetSize()
1806
1816
        self.SetTabRect(wx.Rect(0, 0, s.GetWidth(), s.GetHeight()))
1807
 
                
 
1817
 
1808
1818
 
1809
1819
    def OnLeftDown(self, event):
1810
1820
        """
1811
1821
        Handles the ``wx.EVT_LEFT_DOWN`` event for L{AuiTabCtrl}.
1812
1822
 
1813
 
        :param `event`: a `wx.MouseEvent` event to be processed.        
 
1823
        :param `event`: a `wx.MouseEvent` event to be processed.
1814
1824
        """
1815
 
        
 
1825
 
1816
1826
        self.CaptureMouse()
1817
1827
        self._click_pt = wx.Point(-1, -1)
1818
1828
        self._is_dragging = False
1820
1830
        self._pressed_button = None
1821
1831
 
1822
1832
        wnd = self.TabHitTest(event.GetX(), event.GetY())
1823
 
        
 
1833
 
1824
1834
        if wnd is not None:
1825
1835
            new_selection = self.GetIdxFromWindow(wnd)
1826
1836
 
1828
1838
            # even if the tab is already active, because they may
1829
1839
            # have multiple tab controls
1830
1840
            if new_selection != self.GetActivePage() or isinstance(self.GetParent(), AuiNotebook):
1831
 
            
 
1841
 
1832
1842
                e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, self.GetId())
1833
1843
                e.SetSelection(new_selection)
1834
1844
                e.SetOldSelection(self.GetActivePage())
1835
1845
                e.SetEventObject(self)
1836
1846
                self.GetEventHandler().ProcessEvent(e)
1837
 
            
 
1847
 
1838
1848
            self._click_pt.x = event.GetX()
1839
1849
            self._click_pt.y = event.GetY()
1840
1850
            self._click_tab = wnd
1841
 
        
 
1851
        else:
 
1852
            page_index = self.GetActivePage()
 
1853
            if page_index != wx.NOT_FOUND:
 
1854
                self.GetWindowFromIdx(page_index).SetFocus()
 
1855
 
1842
1856
        if self._hover_button:
1843
1857
            self._pressed_button = self._hover_button
1844
1858
            self._pressed_button.cur_state = AUI_BUTTON_STATE_PRESSED
1851
1865
        """
1852
1866
        Handles the ``wx.EVT_MOUSE_CAPTURE_LOST`` event for L{AuiTabCtrl}.
1853
1867
 
1854
 
        :param `event`: a `wx.MouseCaptureLostEvent` event to be processed.        
 
1868
        :param `event`: a `wx.MouseCaptureLostEvent` event to be processed.
1855
1869
        """
1856
 
        
 
1870
 
1857
1871
        if self._is_dragging:
1858
1872
            self._is_dragging = False
1859
1873
            self._on_button = False
1862
1876
                self._drag_image.EndDrag()
1863
1877
                del self._drag_image
1864
1878
                self._drag_image = None
1865
 
                
 
1879
 
1866
1880
            event = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_CANCEL_DRAG, self.GetId())
1867
1881
            event.SetSelection(self.GetIdxFromWindow(self._click_tab))
1868
1882
            event.SetOldSelection(event.GetSelection())
1869
1883
            event.SetEventObject(self)
1870
 
            self.GetEventHandler().ProcessEvent(event) 
 
1884
            self.GetEventHandler().ProcessEvent(event)
1871
1885
 
1872
1886
 
1873
1887
    def OnLeftUp(self, event):
1874
1888
        """
1875
1889
        Handles the ``wx.EVT_LEFT_UP`` event for L{AuiTabCtrl}.
1876
1890
 
1877
 
        :param `event`: a `wx.MouseEvent` event to be processed.        
 
1891
        :param `event`: a `wx.MouseEvent` event to be processed.
1878
1892
        """
1879
1893
 
1880
1894
        self._on_button = False
1881
 
        
 
1895
 
1882
1896
        if self._is_dragging:
1883
 
            
1884
 
            self._is_dragging = False
1885
 
            if self._drag_image:
1886
 
                self._drag_image.EndDrag()
1887
 
                del self._drag_image
1888
 
                self._drag_image = None
1889
 
                self.GetParent().Refresh()
1890
1897
 
1891
1898
            if self.HasCapture():
1892
1899
                self.ReleaseMouse()
1893
1900
 
 
1901
            self._is_dragging = False
 
1902
            if self._drag_image:
 
1903
                self._drag_image.EndDrag()
 
1904
                del self._drag_image
 
1905
                self._drag_image = None
 
1906
                self.GetParent().Refresh()
 
1907
 
1894
1908
            evt = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, self.GetId())
1895
1909
            evt.SetSelection(self.GetIdxFromWindow(self._click_tab))
1896
1910
            evt.SetOldSelection(evt.GetSelection())
1899
1913
 
1900
1914
            return
1901
1915
 
 
1916
        self.GetParent()._mgr.HideHint()
 
1917
 
1902
1918
        if self.HasCapture():
1903
1919
            self.ReleaseMouse()
1904
 
    
 
1920
 
 
1921
        if self._hover_button:
 
1922
            self._pressed_button = self._hover_button
 
1923
 
1905
1924
        if self._pressed_button:
1906
 
        
 
1925
 
1907
1926
            # make sure we're still clicking the button
1908
1927
            button = self.ButtonHitTest(event.GetX(), event.GetY())
1909
 
            
 
1928
 
1910
1929
            if button is None:
1911
1930
                return
1912
1931
 
1913
1932
            if button != self._pressed_button:
1914
1933
                self._pressed_button = None
1915
1934
                return
1916
 
            
 
1935
 
1917
1936
            self.Refresh()
1918
1937
            self.Update()
1919
1938
 
1920
1939
            if self._pressed_button.cur_state & AUI_BUTTON_STATE_DISABLED == 0:
1921
 
            
 
1940
 
1922
1941
                evt = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, self.GetId())
1923
1942
                evt.SetSelection(self.GetIdxFromWindow(self._click_tab))
1924
1943
                evt.SetInt(self._pressed_button.id)
1925
1944
                evt.SetEventObject(self)
1926
 
                self.GetEventHandler().ProcessEvent(evt)
1927
 
            
 
1945
                eventHandler = self.GetEventHandler()
 
1946
 
 
1947
                if eventHandler is not None:
 
1948
                    eventHandler.ProcessEvent(evt)
 
1949
 
1928
1950
            self._pressed_button = None
1929
 
        
 
1951
 
1930
1952
        self._click_pt = wx.Point(-1, -1)
1931
1953
        self._is_dragging = False
1932
1954
        self._click_tab = None
1936
1958
        """
1937
1959
        Handles the ``wx.EVT_MIDDLE_UP`` event for L{AuiTabCtrl}.
1938
1960
 
1939
 
        :param `event`: a `wx.MouseEvent` event to be processed.        
 
1961
        :param `event`: a `wx.MouseEvent` event to be processed.
1940
1962
        """
1941
1963
 
 
1964
        eventHandler = self.GetEventHandler()
 
1965
        if not isinstance(eventHandler, AuiTabCtrl):
 
1966
            event.Skip()
 
1967
            return
 
1968
 
1942
1969
        x, y = event.GetX(), event.GetY()
1943
1970
        wnd = self.TabHitTest(x, y)
1944
1971
 
1957
1984
        """
1958
1985
        Handles the ``wx.EVT_MIDDLE_DOWN`` event for L{AuiTabCtrl}.
1959
1986
 
1960
 
        :param `event`: a `wx.MouseEvent` event to be processed.        
 
1987
        :param `event`: a `wx.MouseEvent` event to be processed.
1961
1988
        """
 
1989
 
 
1990
        eventHandler = self.GetEventHandler()
 
1991
        if not isinstance(eventHandler, AuiTabCtrl):
 
1992
            event.Skip()
 
1993
            return
1962
1994
        
1963
1995
        x, y = event.GetX(), event.GetY()
1964
1996
        wnd = self.TabHitTest(x, y)
1978
2010
        """
1979
2011
        Handles the ``wx.EVT_RIGHT_UP`` event for L{AuiTabCtrl}.
1980
2012
 
1981
 
        :param `event`: a `wx.MouseEvent` event to be processed.        
 
2013
        :param `event`: a `wx.MouseEvent` event to be processed.
1982
2014
        """
1983
2015
 
1984
2016
        x, y = event.GetX(), event.GetY()
1999
2031
        """
2000
2032
        Handles the ``wx.EVT_RIGHT_DOWN`` event for L{AuiTabCtrl}.
2001
2033
 
2002
 
        :param `event`: a `wx.MouseEvent` event to be processed.        
 
2034
        :param `event`: a `wx.MouseEvent` event to be processed.
2003
2035
        """
2004
 
        
 
2036
 
2005
2037
        x, y = event.GetX(), event.GetY()
2006
2038
        wnd = self.TabHitTest(x, y)
2007
2039
 
2020
2052
        """
2021
2053
        Handles the ``wx.EVT_LEFT_DCLICK`` event for L{AuiTabCtrl}.
2022
2054
 
2023
 
        :param `event`: a `wx.MouseEvent` event to be processed.        
 
2055
        :param `event`: a `wx.MouseEvent` event to be processed.
2024
2056
        """
2025
 
        
 
2057
 
2026
2058
        x, y = event.GetX(), event.GetY()
2027
2059
        wnd = self.TabHitTest(x, y)
2028
2060
 
2036
2068
            e.SetEventObject(self)
2037
2069
            self.GetEventHandler().ProcessEvent(e)
2038
2070
 
2039
 
    
 
2071
 
2040
2072
    def OnMotion(self, event):
2041
2073
        """
2042
2074
        Handles the ``wx.EVT_MOTION`` event for L{AuiTabCtrl}.
2043
2075
 
2044
 
        :param `event`: a `wx.MouseEvent` event to be processed.        
 
2076
        :param `event`: a `wx.MouseEvent` event to be processed.
2045
2077
        """
2046
2078
 
2047
2079
        pos = event.GetPosition()
2059
2091
 
2060
2092
        if self._on_button:
2061
2093
            return
2062
 
        
 
2094
 
2063
2095
        if button:
2064
 
            
 
2096
 
2065
2097
            if self._hover_button and button != self._hover_button:
2066
2098
                self._hover_button.cur_state = AUI_BUTTON_STATE_NORMAL
2067
2099
                self._hover_button = None
2068
2100
                self.Refresh()
2069
2101
                self.Update()
2070
 
            
 
2102
 
2071
2103
            if button.cur_state != AUI_BUTTON_STATE_HOVER:
2072
2104
                button.cur_state = AUI_BUTTON_STATE_HOVER
2073
2105
                self.Refresh()
2074
2106
                self.Update()
2075
2107
                self._hover_button = button
2076
2108
                return
2077
 
                    
 
2109
 
2078
2110
        else:
2079
 
        
 
2111
 
2080
2112
            if self._hover_button:
2081
2113
                self._hover_button.cur_state = AUI_BUTTON_STATE_NORMAL
2082
2114
                self._hover_button = None
2086
2118
        if not event.LeftIsDown() or self._click_pt == wx.Point(-1, -1):
2087
2119
            return
2088
2120
 
 
2121
        if not self.HasCapture():
 
2122
            return
 
2123
 
2089
2124
        wnd = self.TabHitTest(pos.x, pos.y)
2090
2125
 
2091
2126
        if not self._is_dragging:
2130
2165
            self.GetEventHandler().ProcessEvent(evt2)
2131
2166
            if evt2.GetDispatched():
2132
2167
                return
2133
 
            
 
2168
 
2134
2169
        evt3 = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, self.GetId())
2135
2170
        evt3.SetSelection(self.GetIdxFromWindow(self._click_tab))
2136
2171
        evt3.SetOldSelection(evt3.GetSelection())
2141
2176
            # Apply the drag images offset
2142
2177
            pos -= self._drag_img_offset
2143
2178
            self._drag_image.Move(pos)
2144
 
            
 
2179
 
2145
2180
 
2146
2181
    def OnLeaveWindow(self, event):
2147
2182
        """
2148
2183
        Handles the ``wx.EVT_LEAVE_WINDOW`` event for L{AuiTabCtrl}.
2149
2184
 
2150
 
        :param `event`: a `wx.MouseEvent` event to be processed.        
 
2185
        :param `event`: a `wx.MouseEvent` event to be processed.
2151
2186
        """
2152
 
        
 
2187
 
2153
2188
        if self._hover_button:
2154
2189
            self._hover_button.cur_state = AUI_BUTTON_STATE_NORMAL
2155
2190
            self._hover_button = None
2156
2191
            self.Refresh()
2157
2192
            self.Update()
2158
 
    
 
2193
 
2159
2194
 
2160
2195
    def OnButton(self, event):
2161
2196
        """
2162
2197
        Handles the ``EVT_AUINOTEBOOK_BUTTON`` event for L{AuiTabCtrl}.
2163
2198
 
2164
 
        :param `event`: a L{AuiNotebookEvent} event to be processed.        
 
2199
        :param `event`: a L{AuiNotebookEvent} event to be processed.
2165
2200
        """
2166
 
        
 
2201
 
2167
2202
        button = event.GetInt()
2168
2203
 
2169
2204
        if button == AUI_BUTTON_LEFT or button == AUI_BUTTON_RIGHT:
2170
2205
            if button == AUI_BUTTON_LEFT:
2171
2206
                if self.GetTabOffset() > 0:
2172
 
                
 
2207
 
2173
2208
                    self.SetTabOffset(self.GetTabOffset()-1)
2174
2209
                    self.Refresh()
2175
2210
                    self.Update()
2177
2212
                self.SetTabOffset(self.GetTabOffset()+1)
2178
2213
                self.Refresh()
2179
2214
                self.Update()
2180
 
            
 
2215
 
2181
2216
        elif button == AUI_BUTTON_WINDOWLIST:
2182
2217
            idx = self.GetArtProvider().ShowDropDown(self, self._pages, self.GetActivePage())
2183
 
            
 
2218
 
2184
2219
            if idx != -1:
2185
 
            
 
2220
 
2186
2221
                e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, self.GetId())
2187
2222
                e.SetSelection(idx)
2188
2223
                e.SetOldSelection(self.GetActivePage())
2189
2224
                e.SetEventObject(self)
2190
2225
                self.GetEventHandler().ProcessEvent(e)
2191
 
            
 
2226
 
2192
2227
        else:
2193
2228
            event.Skip()
2194
 
        
 
2229
 
2195
2230
 
2196
2231
    def OnSetFocus(self, event):
2197
2232
        """
2198
2233
        Handles the ``wx.EVT_SET_FOCUS`` event for L{AuiTabCtrl}.
2199
2234
 
2200
 
        :param `event`: a `wx.FocusEvent` event to be processed.        
 
2235
        :param `event`: a `wx.FocusEvent` event to be processed.
2201
2236
        """
2202
2237
 
2203
2238
        self.Refresh()
2207
2242
        """
2208
2243
        Handles the ``wx.EVT_KILL_FOCUS`` event for L{AuiTabCtrl}.
2209
2244
 
2210
 
        :param `event`: a `wx.FocusEvent` event to be processed.        
 
2245
        :param `event`: a `wx.FocusEvent` event to be processed.
2211
2246
        """
2212
2247
 
2213
2248
        self.Refresh()
2214
2249
 
2215
2250
 
2216
2251
    def OnKeyDown(self, event):
 
2252
        """
 
2253
        Handles the ``wx.EVT_KEY_DOWN`` event for L{AuiTabCtrl}.
 
2254
 
 
2255
        :param `event`: a `wx.KeyEvent` event to be processed.
 
2256
        """
2217
2257
 
2218
2258
        key = event.GetKeyCode()
2219
2259
        nb = self.GetParent()
2230
2270
            newPage = 0
2231
2271
            nb.SetSelection(newPage)
2232
2272
            self.SetFocus()
2233
 
        
 
2273
 
2234
2274
        elif key == wx.WXK_END:
2235
2275
            newPage = nb.GetPageCount() - 1
2236
2276
            nb.SetSelection(newPage)
2237
2277
            self.SetFocus()
2238
 
            
 
2278
 
2239
2279
        elif key == wx.WXK_TAB:
2240
2280
            if not event.ControlDown():
2241
2281
                flags = 0
2251
2291
                bForward = bWindowChange = 0
2252
2292
                if not event.ShiftDown(): bForward |= wx.NavigationKeyEvent.IsForward
2253
2293
                if event.CmdDown():       bWindowChange |= wx.NavigationKeyEvent.WinChange
2254
 
                
 
2294
 
2255
2295
                keyEvent = wx.NavigationKeyEvent()
2256
2296
                keyEvent.SetDirection(bForward)
2257
2297
                keyEvent.SetWindowChange(bWindowChange)
2259
2299
                keyEvent.SetEventObject(nb)
2260
2300
 
2261
2301
                if not nb.GetEventHandler().ProcessEvent(keyEvent):
2262
 
                
 
2302
 
2263
2303
                    # Not processed? Do an explicit tab into the page.
2264
2304
                    win = self.GetWindowFromIdx(self.GetActivePage())
2265
2305
                    if win:
2266
2306
                        win.SetFocus()
2267
2307
 
2268
2308
                self.SetFocus()
2269
 
                
 
2309
 
2270
2310
                return
2271
2311
 
2272
2312
        else:
2275
2315
 
2276
2316
    def OnKeyDown2(self, event):
2277
2317
        """
 
2318
        Deprecated.
 
2319
 
2278
2320
        Handles the ``wx.EVT_KEY_DOWN`` event for L{AuiTabCtrl}.
2279
2321
 
2280
 
        :param `event`: a `wx.KeyEvent` event to be processed.        
 
2322
        :param `event`: a `wx.KeyEvent` event to be processed.
 
2323
 
 
2324
        :warning: This method implementation is now deprecated. Refer to L{OnKeyDown}
 
2325
         for the correct one.
2281
2326
        """
2282
2327
 
2283
 
        print event.GetKeyCode(), event.ControlDown()        
2284
2328
        if self.GetActivePage() == -1:
2285
2329
            event.Skip()
2286
2330
            return
2287
 
    
 
2331
 
2288
2332
        # We can't leave tab processing to the system on Windows, tabs and keys
2289
2333
        # get eaten by the system and not processed properly if we specify both
2290
2334
        # wxTAB_TRAVERSAL and wxWANTS_CHARS. And if we specify just wxTAB_TRAVERSAL,
2306
2350
            key = wx.WXK_RIGHT
2307
2351
 
2308
2352
        if key == wx.WXK_TAB or key == wx.WXK_PAGEUP or key == wx.WXK_PAGEDOWN:
2309
 
        
 
2353
 
2310
2354
            bCtrlDown = event.ControlDown()
2311
2355
            bShiftDown = event.ShiftDown()
2312
2356
 
2318
2362
            if not nb or not isinstance(nb, AuiNotebook):
2319
2363
                event.Skip()
2320
2364
                return
2321
 
            
 
2365
 
2322
2366
            keyEvent = wx.NavigationKeyEvent()
2323
2367
            keyEvent.SetDirection(bForward)
2324
2368
            keyEvent.SetWindowChange(bWindowChange)
2326
2370
            keyEvent.SetEventObject(nb)
2327
2371
 
2328
2372
            if not nb.GetEventHandler().ProcessEvent(keyEvent):
2329
 
            
 
2373
 
2330
2374
                # Not processed? Do an explicit tab into the page.
2331
2375
                win = self.GetWindowFromIdx(self.GetActivePage())
2332
2376
                if win:
2333
2377
                    win.SetFocus()
2334
 
            
 
2378
 
2335
2379
            return
2336
 
        
 
2380
 
2337
2381
        if len(self._pages) < 2:
2338
2382
            event.Skip()
2339
2383
            return
2340
 
        
 
2384
 
2341
2385
        newPage = -1
2342
2386
 
2343
2387
        if self.GetLayoutDirection() == wx.Layout_RightToLeft:
2346
2390
        else:
2347
2391
            forwardKey = wx.WXK_RIGHT
2348
2392
            backwardKey = wx.WXK_LEFT
2349
 
        
 
2393
 
2350
2394
        if key == forwardKey:
2351
2395
            if self.GetActivePage() == -1:
2352
2396
                newPage = 0
2353
2397
            elif self.GetActivePage() < len(self._pages) - 1:
2354
2398
                newPage = self.GetActivePage() + 1
2355
 
            
2356
 
        elif key == backwardKey:        
 
2399
 
 
2400
        elif key == backwardKey:
2357
2401
            if self.GetActivePage() == -1:
2358
2402
                newPage = len(self._pages) - 1
2359
2403
            elif self.GetActivePage() > 0:
2360
2404
                newPage = self.GetActivePage() - 1
2361
 
            
 
2405
 
2362
2406
        elif key == wx.WXK_HOME:
2363
2407
            newPage = 0
2364
 
        
 
2408
 
2365
2409
        elif key == wx.WXK_END:
2366
2410
            newPage = len(self._pages) - 1
2367
 
        
 
2411
 
2368
2412
        else:
2369
2413
            event.Skip()
2370
2414
 
2374
2418
            e.SetOldSelection(newPage)
2375
2419
            e.SetEventObject(self)
2376
2420
            self.GetEventHandler().ProcessEvent(e)
2377
 
        
 
2421
 
2378
2422
        else:
2379
2423
            event.Skip()
2380
2424
 
2387
2431
    of the multi-notebook control are all actually children of that control
2388
2432
    (and not grandchildren). TabFrame facilitates this. There is one
2389
2433
    instance of TabFrame for each tab control inside the multi-notebook.
2390
 
    
 
2434
 
2391
2435
    It's important to know that TabFrame is not a real window, but it merely
2392
2436
    used to capture the dimensions/positioning of the internal tab control and
2393
2437
    it's managed page windows.
2400
2444
        """
2401
2445
 
2402
2446
        pre = wx.PrePyWindow()
2403
 
        
 
2447
 
2404
2448
        self._tabs = None
2405
2449
        self._rect = wx.Rect(0, 0, 200, 200)
2406
2450
        self._tab_ctrl_height = 20
2407
 
        self._tab_rect = wx.Rect()        
 
2451
        self._tab_rect = wx.Rect()
2408
2452
        self._parent = parent
2409
 
        
 
2453
 
2410
2454
        self.PostCreate(pre)
2411
 
        
 
2455
 
2412
2456
 
2413
2457
    def SetTabCtrlHeight(self, h):
2414
2458
        """
2416
2460
 
2417
2461
        :param `h`: the tab area height.
2418
2462
        """
2419
 
    
 
2463
 
2420
2464
        self._tab_ctrl_height = h
2421
2465
 
2422
2466
 
2423
2467
    def DoSetSize(self, x, y, width, height, flags=wx.SIZE_AUTO):
2424
 
        """        
 
2468
        """
2425
2469
        Sets the position and size of the window in pixels. The `flags`
2426
2470
        parameter indicates the interpretation of the other params if they are
2427
2471
        equal to -1.
2431
2475
        :param `width`: the window width;
2432
2476
        :param `height`: the window height;
2433
2477
        :param `flags`: may have one of this bit set:
2434
 
   
 
2478
 
2435
2479
         ===================================  ======================================
2436
2480
         Size Flags                           Description
2437
2481
         ===================================  ======================================
2440
2484
         ``wx.SIZE_AUTO_HEIGHT``              A -1 indicates that a class-specific default should be used for the height.
2441
2485
         ``wx.SIZE_USE_EXISTING``             Existing dimensions should be used if -1 values are supplied.
2442
2486
         ``wx.SIZE_ALLOW_MINUS_ONE``          Allow dimensions of -1 and less to be interpreted as real dimensions, not default values.
2443
 
         ``wx.SIZE_FORCE``                    Normally, if the position and the size of the window are already the same as the parameters of this function, nothing is done. but with this flag a window resize may be forced even in this case (supported in wx 2.6.2 and later and only implemented for MSW and ignored elsewhere currently) 
 
2487
         ``wx.SIZE_FORCE``                    Normally, if the position and the size of the window are already the same as the parameters of this function, nothing is done. but with this flag a window resize may be forced even in this case (supported in wx 2.6.2 and later and only implemented for MSW and ignored elsewhere currently)
2444
2488
         ===================================  ======================================
2445
2489
 
2446
2490
        :note: Overridden from `wx.PyControl`.
2454
2498
        """
2455
2499
        Returns the window size.
2456
2500
 
2457
 
        :note: Overridden from `wx.PyControl`.        
 
2501
        :note: Overridden from `wx.PyControl`.
2458
2502
        """
2459
2503
 
2460
2504
        return self._rect.width, self._rect.height
2466
2510
 
2467
2511
        :note: Overridden from `wx.PyControl`.
2468
2512
        """
2469
 
        
 
2513
 
2470
2514
        return self._rect.width, self._rect.height
2471
 
    
 
2515
 
2472
2516
 
2473
2517
    def Show(self, show=True):
2474
2518
        """
2475
2519
        Shows/hides the window.
2476
2520
 
2477
 
        :param `show`: ``True`` to show the window, ``False`` otherwise.        
 
2521
        :param `show`: ``True`` to show the window, ``False`` otherwise.
2478
2522
 
2479
2523
        :note: Overridden from `wx.PyControl`, this method always returns ``False`` as
2480
2524
         L{TabFrame} should never be phisically shown on screen.
2481
2525
        """
2482
 
        
 
2526
 
2483
2527
        return False
2484
2528
 
2485
2529
 
2486
2530
    def DoSizing(self):
2487
2531
        """ Does the actual sizing of the tab control. """
2488
 
    
 
2532
 
2489
2533
        if not self._tabs:
2490
2534
            return
2491
2535
 
2492
2536
        hideOnSingle = ((self._tabs.GetAGWFlags() & AUI_NB_HIDE_ON_SINGLE_TAB) and \
2493
2537
                        self._tabs.GetPageCount() <= 1)
2494
 
        
 
2538
 
2495
2539
        if not hideOnSingle and not self._parent._hide_tabs:
2496
2540
            tab_height = self._tab_ctrl_height
2497
 
            
 
2541
 
2498
2542
            self._tab_rect = wx.Rect(self._rect.x, self._rect.y, self._rect.width, self._tab_ctrl_height)
2499
 
            
2500
 
            if self._tabs.GetAGWFlags() & AUI_NB_BOTTOM:        
 
2543
 
 
2544
            if self._tabs.GetAGWFlags() & AUI_NB_BOTTOM:
2501
2545
                self._tab_rect = wx.Rect(self._rect.x, self._rect.y + self._rect.height - tab_height,
2502
2546
                                         self._rect.width, tab_height)
2503
2547
                self._tabs.SetDimensions(self._rect.x, self._rect.y + self._rect.height - tab_height,
2504
2548
                                         self._rect.width, tab_height)
2505
2549
                self._tabs.SetTabRect(wx.Rect(0, 0, self._rect.width, tab_height))
2506
 
                
 
2550
 
2507
2551
            else:
2508
2552
 
2509
2553
                self._tab_rect = wx.Rect(self._rect.x, self._rect.y, self._rect.width, tab_height)
2510
2554
                self._tabs.SetDimensions(self._rect.x, self._rect.y, self._rect.width, tab_height)
2511
2555
                self._tabs.SetTabRect(wx.Rect(0, 0, self._rect.width, tab_height))
2512
 
            
 
2556
 
2513
2557
            # TODO: elif (GetAGWFlags() & AUI_NB_LEFT)
2514
2558
            # TODO: elif (GetAGWFlags() & AUI_NB_RIGHT)
2515
2559
 
2516
2560
            self._tabs.Refresh()
2517
2561
            self._tabs.Update()
2518
 
            
 
2562
 
2519
2563
        else:
2520
 
            
 
2564
 
2521
2565
            tab_height = 0
2522
2566
            self._tabs.SetDimensions(self._rect.x, self._rect.y, self._rect.width, tab_height)
2523
2567
            self._tabs.SetTabRect(wx.Rect(0, 0, self._rect.width, tab_height))
2524
 
            
 
2568
 
2525
2569
        pages = self._tabs.GetPages()
2526
2570
 
2527
2571
        for page in pages:
2528
 
        
 
2572
 
2529
2573
            height = self._rect.height - tab_height
2530
 
            
2531
 
            if height < 0:            
 
2574
 
 
2575
            if height < 0:
2532
2576
                # avoid passing negative height to wx.Window.SetSize(), this
2533
2577
                # results in assert failures/GTK+ warnings
2534
2578
                height = 0
2535
 
            
 
2579
 
2536
2580
            if self._tabs.GetAGWFlags() & AUI_NB_BOTTOM:
2537
2581
                page.window.SetDimensions(self._rect.x, self._rect.y, self._rect.width, height)
2538
 
            
 
2582
 
2539
2583
            else:
2540
2584
                page.window.SetDimensions(self._rect.x, self._rect.y + tab_height,
2541
2585
                                          self._rect.width, height)
2542
 
            
 
2586
 
2543
2587
            # TODO: elif (GetAGWFlags() & AUI_NB_LEFT)
2544
2588
            # TODO: elif (GetAGWFlags() & AUI_NB_RIGHT)
2545
 
            
 
2589
 
2546
2590
            if repr(page.window.__class__).find("AuiMDIChildFrame") >= 0:
2547
 
                page.window.ApplyMDIChildFrameRect()            
 
2591
                page.window.ApplyMDIChildFrameRect()
2548
2592
 
2549
2593
 
2550
2594
    def Update(self):
2551
2595
        """
2552
2596
        Calling this method immediately repaints the invalidated area of the window
2553
2597
        and all of its children recursively while this would usually only happen when
2554
 
        the flow of control returns to the event loop.  
 
2598
        the flow of control returns to the event loop.
2555
2599
 
2556
2600
        :note: Notice that this function doesn't invalidate any area of the window so
2557
2601
         nothing happens if nothing has been invalidated (i.e. marked as requiring a redraw).
2558
 
         Use `Refresh` first if you want to immediately redraw the window unconditionally.   
 
2602
         Use `Refresh` first if you want to immediately redraw the window unconditionally.
2559
2603
 
2560
2604
        :note: Overridden from `wx.PyControl`.
2561
2605
        """
2594
2638
         chosen by either the windowing system or wxPython, depending on platform;
2595
2639
        :param `style`: the underlying `wx.PyPanel` window style;
2596
2640
        :param `agwStyle`: the AGW-specific window style. This can be a combination of the following bits:
2597
 
        
 
2641
 
2598
2642
         ==================================== ==================================
2599
2643
         Flag name                            Description
2600
2644
         ==================================== ==================================
2601
2645
         ``AUI_NB_TOP``                       With this style, tabs are drawn along the top of the notebook
2602
2646
         ``AUI_NB_LEFT``                      With this style, tabs are drawn along the left of the notebook. Not implemented yet.
2603
2647
         ``AUI_NB_RIGHT``                     With this style, tabs are drawn along the right of the notebook. Not implemented yet.
2604
 
         ``AUI_NB_BOTTOM``                    With this style, tabs are drawn along the bottom of the notebook.
 
2648
         ``AUI_NB_BOTTOM``                    With this style, tabs are drawn along the bottom of the notebook
2605
2649
         ``AUI_NB_TAB_SPLIT``                 Allows the tab control to be split by dragging a tab
2606
2650
         ``AUI_NB_TAB_MOVE``                  Allows a tab to be moved horizontally by dragging
2607
2651
         ``AUI_NB_TAB_EXTERNAL_MOVE``         Allows a tab to be moved to another tab control
2611
2655
         ``AUI_NB_CLOSE_BUTTON``              With this style, a close button is available on the tab bar
2612
2656
         ``AUI_NB_CLOSE_ON_ACTIVE_TAB``       With this style, a close button is available on the active tab
2613
2657
         ``AUI_NB_CLOSE_ON_ALL_TABS``         With this style, a close button is available on all tabs
2614
 
         ``AUI_NB_MIDDLE_CLICK_CLOSE``        Allows to close AuiNotebook tabs by mouse middle button click
2615
 
         ``AUI_NB_SUB_NOTEBOOK``              This style is used by AuiManager to create automatic AuiNotebooks
 
2658
         ``AUI_NB_MIDDLE_CLICK_CLOSE``        Allows to close L{AuiNotebook} tabs by mouse middle button click
 
2659
         ``AUI_NB_SUB_NOTEBOOK``              This style is used by L{AuiManager} to create automatic AuiNotebooks
2616
2660
         ``AUI_NB_HIDE_ON_SINGLE_TAB``        Hides the tab window if only one tab is present
2617
2661
         ``AUI_NB_SMART_TABS``                Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows
2618
2662
         ``AUI_NB_USE_IMAGES_DROPDOWN``       Uses images on dropdown window list menu instead of check items
2619
2663
         ``AUI_NB_CLOSE_ON_TAB_LEFT``         Draws the tab close button on the left instead of on the right (a la Camino browser)
2620
2664
         ``AUI_NB_TAB_FLOAT``                 Allows the floating of single tabs. Known limitation: when the notebook is more or less full screen, tabs cannot be dragged far enough outside of the notebook to become floating pages
2621
2665
         ``AUI_NB_DRAW_DND_TAB``              Draws an image representation of a tab while dragging (on by default)
 
2666
         ``AUI_NB_ORDER_BY_ACCESS``           Tab navigation order by last access time for the tabs
 
2667
         ``AUI_NB_NO_TAB_FOCUS``              Don't draw tab focus rectangle
2622
2668
         ==================================== ==================================
2623
2669
 
2624
2670
         Default value for `agwStyle` is:
2636
2682
        self._requested_tabctrl_height = -1
2637
2683
        self._textCtrl = None
2638
2684
        self._tabBounds = (-1, -1)
 
2685
        self._click_tab = None
2639
2686
 
2640
2687
        wx.PyPanel.__init__(self, parent, id, pos, size, style|wx.BORDER_NONE|wx.TAB_TRAVERSAL)
2641
2688
        self._mgr = framemanager.AuiManager()
2644
2691
        self.InitNotebook(agwStyle)
2645
2692
 
2646
2693
 
 
2694
    def GetTabContainer(self):
 
2695
        """ Returns the instance of L{AuiTabContainer}. """
 
2696
 
 
2697
        return self._tabs
 
2698
 
 
2699
 
2647
2700
    def InitNotebook(self, agwStyle):
2648
2701
        """
2649
 
        InitNotebook() contains common initialization
2650
 
        code called by all constructors.
 
2702
        Contains common initialization code called by all constructors.
2651
2703
 
2652
2704
        :param `agwStyle`: the notebook style.
2653
2705
 
2661
2713
        self._naviIcon = None
2662
2714
        self._imageList = None
2663
2715
        self._last_drag_x = 0
2664
 
        
 
2716
 
2665
2717
        self._normal_font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
2666
2718
        self._selected_font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
2667
2719
        self._selected_font.SetWeight(wx.BOLD)
2690
2742
        self.Bind(EVT_AUINOTEBOOK_DRAG_MOTION, self.OnTabDragMotion,
2691
2743
                  id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500)
2692
2744
        self.Bind(EVT_AUINOTEBOOK_CANCEL_DRAG, self.OnTabCancelDrag,
2693
 
                  id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500)        
 
2745
                  id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500)
2694
2746
        self.Bind(EVT_AUINOTEBOOK_BUTTON, self.OnTabButton,
2695
2747
                  id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500)
2696
2748
        self.Bind(EVT_AUINOTEBOOK_TAB_MIDDLE_DOWN, self.OnTabMiddleDown,
2727
2779
        is restored using L{LoadPerspective}, the entire user interface will return
2728
2780
        to the state it was when the perspective was saved.
2729
2781
        """
2730
 
        
 
2782
 
2731
2783
        # Build list of panes/tabs
2732
2784
        tabs = ""
2733
2785
        all_panes = self._mgr.GetAllPanes()
2734
 
        
 
2786
 
2735
2787
        for pane in all_panes:
2736
2788
 
2737
2789
            if pane.name == "dummy":
2738
2790
                continue
2739
2791
 
2740
2792
            tabframe = pane.window
2741
 
          
 
2793
 
2742
2794
            if tabs:
2743
2795
                tabs += "|"
2744
 
              
 
2796
 
2745
2797
            tabs += pane.name + "="
2746
 
          
 
2798
 
2747
2799
            # add tab id's
2748
2800
            page_count = tabframe._tabs.GetPageCount()
2749
 
          
 
2801
 
2750
2802
            for p in xrange(page_count):
2751
 
          
 
2803
 
2752
2804
                page = tabframe._tabs.GetPage(p)
2753
2805
                page_idx = self._tabs.GetIdxFromWindow(page.window)
2754
 
             
 
2806
 
2755
2807
                if p:
2756
2808
                    tabs += ","
2757
2809
 
2759
2811
                    tabs += "+"
2760
2812
                elif page_idx == self._curpage:
2761
2813
                    tabs += "*"
2762
 
                    
 
2814
 
2763
2815
                tabs += "%u"%page_idx
2764
 
          
 
2816
 
2765
2817
        tabs += "@"
2766
2818
 
2767
2819
        # Add frame perspective
2772
2824
 
2773
2825
    def LoadPerspective(self, layout):
2774
2826
        """
2775
 
        LoadPerspective() loads a layout which was saved with L{SavePerspective}.
 
2827
        Loads a layout which was saved with L{SavePerspective}.
2776
2828
 
2777
2829
        :param `layout`: a string which contains a saved L{AuiNotebook} layout.
2778
2830
        """
2779
 
        
 
2831
 
2780
2832
        # Remove all tab ctrls (but still keep them in main index)
2781
2833
        tab_count = self._tabs.GetPageCount()
2782
2834
        for i in xrange(tab_count):
2796
2848
        sel_page = 0
2797
2849
        tabs = layout[0:layout.index("@")]
2798
2850
        to_break1 = False
2799
 
        
 
2851
 
2800
2852
        while 1:
2801
2853
 
2802
2854
            if "|" not in tabs:
2804
2856
                tab_part = tabs
2805
2857
            else:
2806
2858
                tab_part = tabs[0:tabs.index('|')]
2807
 
          
 
2859
 
2808
2860
            if "=" not in tab_part:
2809
2861
                # No pages in this perspective...
2810
2862
                return False
2829
2881
            # Get list of tab id's and move them to pane
2830
2882
            tab_list = tab_part[tab_part.index("=")+1:]
2831
2883
            to_break2, active_found = False, False
2832
 
            
 
2884
 
2833
2885
            while 1:
2834
2886
                if "," not in tab_list:
2835
2887
                    to_break2 = True
2836
2888
                    tab = tab_list
2837
2889
                else:
2838
 
                    tab = tab_list[0:tab_list.index(",")]                
 
2890
                    tab = tab_list[0:tab_list.index(",")]
2839
2891
                    tab_list = tab_list[tab_list.index(",")+1:]
2840
2892
 
2841
2893
                # Check if this page has an 'active' marker
2845
2897
 
2846
2898
                tab_idx = int(tab)
2847
2899
                if tab_idx >= self.GetPageCount():
2848
 
                    continue
 
2900
                    to_break1 = True
 
2901
                    break
2849
2902
 
2850
2903
                # Move tab to pane
2851
2904
                page = self._tabs.GetPage(tab_idx)
2867
2920
            new_tabs.DoSizing()
2868
2921
            dest_tabs.DoShowHide()
2869
2922
            dest_tabs.Refresh()
2870
 
        
 
2923
 
2871
2924
            if to_break1:
2872
2925
                break
2873
 
            
 
2926
 
2874
2927
            tabs = tabs[tabs.index('|')+1:]
2875
2928
 
2876
2929
        # Load the frame perspective
2890
2943
 
2891
2944
        By default, the tab control height is calculated by measuring the text
2892
2945
        height and bitmap sizes on the tab captions.
2893
 
        
 
2946
 
2894
2947
        Calling this method will override that calculation and set the tab control
2895
2948
        to the specified height parameter. A call to this method will override
2896
2949
        any call to L{SetUniformBitmapSize}. Specifying -1 as the height will
2898
2951
 
2899
2952
        :param `height`: the tab control area height.
2900
2953
        """
2901
 
        
 
2954
 
2902
2955
        self._requested_tabctrl_height = height
2903
2956
 
2904
2957
        # if window is already initialized, recalculate the tab height
2905
2958
        if self._dummy_wnd:
2906
2959
            self.UpdateTabCtrlHeight()
2907
 
        
 
2960
 
2908
2961
 
2909
2962
    def SetUniformBitmapSize(self, size):
2910
2963
        """
2915
2968
        large bitmap is added, the tab control's height will automatically
2916
2969
        increase to accommodate the larger bitmap.
2917
2970
 
2918
 
        :param `size`: an instance of `wx.Size` specifying the tab bitmap size.        
 
2971
        :param `size`: an instance of `wx.Size` specifying the tab bitmap size.
2919
2972
        """
2920
2973
 
2921
2974
        self._requested_bmp_size = wx.Size(*size)
2923
2976
        # if window is already initialized, recalculate the tab height
2924
2977
        if self._dummy_wnd:
2925
2978
            self.UpdateTabCtrlHeight()
2926
 
    
 
2979
 
2927
2980
 
2928
2981
    def UpdateTabCtrlHeight(self, force=False):
2929
2982
        """
2945
2998
 
2946
2999
            all_panes = self._mgr.GetAllPanes()
2947
3000
            for pane in all_panes:
2948
 
    
 
3001
 
2949
3002
                if pane.name == "dummy":
2950
3003
                    continue
2951
 
                
 
3004
 
2952
3005
                tab_frame = pane.window
2953
3006
                tabctrl = tab_frame._tabs
2954
3007
                tab_frame.SetTabCtrlHeight(self._tab_ctrl_height)
2955
3008
                tabctrl.SetArtProvider(art.Clone())
2956
3009
                tab_frame.DoSizing()
2957
 
            
 
3010
 
2958
3011
 
2959
3012
    def UpdateHintWindowSize(self):
2960
3013
        """ Updates the L{AuiManager} hint window size. """
2963
3016
 
2964
3017
        # the placeholder hint window should be set to this size
2965
3018
        info = self._mgr.GetPane("dummy")
2966
 
        
2967
 
        if info.IsOk():        
 
3019
 
 
3020
        if info.IsOk():
2968
3021
            info.MinSize(size)
2969
3022
            info.BestSize(size)
2970
3023
            self._dummy_wnd.SetSize(size)
2971
 
        
 
3024
 
2972
3025
 
2973
3026
    def CalculateNewSplitSize(self):
2974
3027
        """ Calculates the size of the new split. """
2977
3030
        tab_ctrl_count = 0
2978
3031
        all_panes = self._mgr.GetAllPanes()
2979
3032
 
2980
 
        for pane in all_panes:                
 
3033
        for pane in all_panes:
2981
3034
            if pane.name == "dummy":
2982
3035
                continue
2983
 
            
 
3036
 
2984
3037
            tab_ctrl_count += 1
2985
 
        
 
3038
 
2986
3039
        # if there is only one tab control, the first split
2987
3040
        # should happen around the middle
2988
3041
        if tab_ctrl_count < 2:
2989
3042
            new_split_size = self.GetClientSize()
2990
3043
            new_split_size.x /= 2
2991
3044
            new_split_size.y /= 2
2992
 
        
 
3045
 
2993
3046
        else:
2994
 
        
 
3047
 
2995
3048
            # this is in place of a more complicated calculation
2996
3049
            # that needs to be implemented
2997
3050
            new_split_size = wx.Size(180, 180)
2998
 
        
 
3051
 
2999
3052
        return new_split_size
3000
3053
 
3001
3054
 
3023
3076
    def SetAGWWindowStyleFlag(self, agwStyle):
3024
3077
        """
3025
3078
        Sets the AGW-specific style of the window.
3026
 
        
3027
 
        :param `agwStyle`: the new window style.
 
3079
 
 
3080
        :param `agwStyle`: the new window style. This can be a combination of the following bits:
 
3081
 
 
3082
         ==================================== ==================================
 
3083
         Flag name                            Description
 
3084
         ==================================== ==================================
 
3085
         ``AUI_NB_TOP``                       With this style, tabs are drawn along the top of the notebook
 
3086
         ``AUI_NB_LEFT``                      With this style, tabs are drawn along the left of the notebook. Not implemented yet.
 
3087
         ``AUI_NB_RIGHT``                     With this style, tabs are drawn along the right of the notebook. Not implemented yet.
 
3088
         ``AUI_NB_BOTTOM``                    With this style, tabs are drawn along the bottom of the notebook
 
3089
         ``AUI_NB_TAB_SPLIT``                 Allows the tab control to be split by dragging a tab
 
3090
         ``AUI_NB_TAB_MOVE``                  Allows a tab to be moved horizontally by dragging
 
3091
         ``AUI_NB_TAB_EXTERNAL_MOVE``         Allows a tab to be moved to another tab control
 
3092
         ``AUI_NB_TAB_FIXED_WIDTH``           With this style, all tabs have the same width
 
3093
         ``AUI_NB_SCROLL_BUTTONS``            With this style, left and right scroll buttons are displayed
 
3094
         ``AUI_NB_WINDOWLIST_BUTTON``         With this style, a drop-down list of windows is available
 
3095
         ``AUI_NB_CLOSE_BUTTON``              With this style, a close button is available on the tab bar
 
3096
         ``AUI_NB_CLOSE_ON_ACTIVE_TAB``       With this style, a close button is available on the active tab
 
3097
         ``AUI_NB_CLOSE_ON_ALL_TABS``         With this style, a close button is available on all tabs
 
3098
         ``AUI_NB_MIDDLE_CLICK_CLOSE``        Allows to close L{AuiNotebook} tabs by mouse middle button click
 
3099
         ``AUI_NB_SUB_NOTEBOOK``              This style is used by L{AuiManager} to create automatic AuiNotebooks
 
3100
         ``AUI_NB_HIDE_ON_SINGLE_TAB``        Hides the tab window if only one tab is present
 
3101
         ``AUI_NB_SMART_TABS``                Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows
 
3102
         ``AUI_NB_USE_IMAGES_DROPDOWN``       Uses images on dropdown window list menu instead of check items
 
3103
         ``AUI_NB_CLOSE_ON_TAB_LEFT``         Draws the tab close button on the left instead of on the right (a la Camino browser)
 
3104
         ``AUI_NB_TAB_FLOAT``                 Allows the floating of single tabs. Known limitation: when the notebook is more or less full screen, tabs cannot be dragged far enough outside of the notebook to become floating pages
 
3105
         ``AUI_NB_DRAW_DND_TAB``              Draws an image representation of a tab while dragging (on by default)
 
3106
         ``AUI_NB_ORDER_BY_ACCESS``           Tab navigation order by last access time for the tabs
 
3107
         ``AUI_NB_NO_TAB_FOCUS``              Don't draw tab focus rectangle
 
3108
         ==================================== ==================================
3028
3109
 
3029
3110
        :note: Please note that some styles cannot be changed after the window
3030
3111
         creation and that `Refresh` might need to be be called after changing the
3037
3118
 
3038
3119
        # if the control is already initialized
3039
3120
        if self._mgr.GetManagedWindow() == self:
3040
 
        
 
3121
 
3041
3122
            # let all of the tab children know about the new style
3042
3123
 
3043
3124
            all_panes = self._mgr.GetAllPanes()
3060
3141
        :see: L{SetAGWWindowStyleFlag} for a list of possible AGW-specific window styles.
3061
3142
        """
3062
3143
 
3063
 
        return self._agwFlags        
3064
 
        
 
3144
        return self._agwFlags
 
3145
 
3065
3146
 
3066
3147
    def AddPage(self, page, caption, select=False, bitmap=wx.NullBitmap, disabled_bitmap=wx.NullBitmap, control=None):
3067
3148
        """
3092
3173
        :param `disabled_bitmap`: the `wx.Bitmap` to display in the disabled tab;
3093
3174
        :param `control`: a `wx.Window` instance inside a tab (or ``None``).
3094
3175
        """
3095
 
        
 
3176
 
3096
3177
        if not page:
3097
3178
            return False
3098
3179
 
3107
3188
        originalPaneMgr = framemanager.GetManager(page)
3108
3189
        if originalPaneMgr:
3109
3190
            originalPane = originalPaneMgr.GetPane(page)
3110
 
            
 
3191
 
3111
3192
            if originalPane:
3112
3193
                info.hasCloseButton = originalPane.HasCloseButton()
3113
 
        
 
3194
 
3114
3195
        if bitmap.IsOk() and not disabled_bitmap.IsOk():
3115
3196
            disabled_bitmap = MakeDisabledBitmap(bitmap)
3116
3197
            info.dis_bitmap = disabled_bitmap
3119
3200
        # tab must be active
3120
3201
        if self._tabs.GetPageCount() == 0:
3121
3202
            info.active = True
3122
 
            
 
3203
 
3123
3204
        self._tabs.InsertPage(page, info, page_idx)
3124
3205
 
3125
3206
        # if that was the first page added, even if
3139
3220
            force = True
3140
3221
            control.Reparent(active_tabctrl)
3141
3222
            control.Show()
3142
 
            
 
3223
 
3143
3224
        self.UpdateTabCtrlHeight(force=force)
3144
3225
        self.DoSizing()
3145
3226
        active_tabctrl.DoShowHide()
3165
3246
 
3166
3247
        :see: L{RemovePage}
3167
3248
        """
3168
 
        
 
3249
 
3169
3250
        if page_idx >= self._tabs.GetPageCount():
3170
3251
            return False
3171
3252
 
3180
3261
            return False
3181
3262
 
3182
3263
        wnd.Destroy()
3183
 
        
 
3264
 
3184
3265
        return True
3185
3266
 
3186
3267
 
3190
3271
 
3191
3272
        :param `page_idx`: the page index to be removed.
3192
3273
 
3193
 
        :note: L{RemovePage} removes a tab from the multi-notebook, but does not destroys the window.
3194
 
        
 
3274
        :note: L{RemovePage} removes a tab from the multi-notebook, but does not destroy the window.
 
3275
 
3195
3276
        :see: L{DeletePage}
3196
3277
        """
3197
 
        
 
3278
 
3198
3279
        # save active window pointer
3199
3280
        active_wnd = None
3200
3281
        if self._curpage >= 0:
3216
3297
        currentPage = ctrl.GetPage(ctrl_idx)
3217
3298
        is_curpage = (self._curpage == page_idx)
3218
3299
        is_active_in_split = currentPage.active
3219
 
        
 
3300
 
3220
3301
        # remove the tab from main catalog
3221
3302
        if not self._tabs.RemovePage(wnd):
3222
3303
            return False
3225
3306
        ctrl.RemovePage(wnd)
3226
3307
 
3227
3308
        if is_active_in_split:
3228
 
        
 
3309
 
3229
3310
            ctrl_new_page_count = ctrl.GetPageCount()
3230
3311
 
3231
3312
            if ctrl_idx >= ctrl_new_page_count:
3234
3315
            if ctrl_idx >= 0 and ctrl_idx < ctrl.GetPageCount():
3235
3316
 
3236
3317
                ctrl_idx = self.FindNextActiveTab(ctrl_idx, ctrl)
3237
 
                
 
3318
 
3238
3319
                # set new page as active in the tab split
3239
3320
                ctrl.SetActivePage(ctrl_idx)
3240
3321
 
3243
3324
                # pointer of the new active page for activation
3244
3325
                if is_curpage:
3245
3326
                    new_active = ctrl.GetWindowFromIdx(ctrl_idx)
3246
 
                
 
3327
 
3247
3328
        else:
3248
 
        
 
3329
 
3249
3330
            # we are not deleting the active page, so keep it the same
3250
3331
            new_active = active_wnd
3251
 
        
 
3332
 
3252
3333
        if not new_active:
3253
 
        
 
3334
 
3254
3335
            # we haven't yet found a new page to active,
3255
3336
            # so select the next page from the main tab
3256
3337
            # catalogue
3259
3340
                new_active = self._tabs.GetPage(page_idx).window
3260
3341
            if not new_active and self._tabs.GetPageCount() > 0:
3261
3342
                new_active = self._tabs.GetPage(0).window
3262
 
            
 
3343
 
3263
3344
        self.RemoveEmptyTabFrames()
3264
3345
 
3265
3346
        # set new active pane
3295
3376
                return indx
3296
3377
 
3297
3378
        return 0
3298
 
    
 
3379
 
3299
3380
 
3300
3381
    def HideAllTabs(self, hidden=True):
3301
3382
        """
3302
 
        Hides all tabs on the AuiNotebook control.
3303
 
        
 
3383
        Hides all tabs on the L{AuiNotebook} control.
 
3384
 
3304
3385
        :param `hidden`: if ``True`` hides all tabs.
3305
3386
        """
3306
3387
 
3324
3405
        """
3325
3406
 
3326
3407
        return self._sash_dclick_unsplit
3327
 
    
 
3408
 
3328
3409
 
3329
3410
    def SetMinMaxTabWidth(self, minTabWidth, maxTabWidth):
3330
3411
        """
3356
3437
        :note: Minimum and maximum tabs widths are used only when the ``AUI_NB_TAB_FIXED_WIDTH``
3357
3438
         style is present.
3358
3439
 
3359
 
        :see: L{SetMinMaxTabWidth} for more information.         
 
3440
        :see: L{SetMinMaxTabWidth} for more information.
3360
3441
        """
3361
3442
 
3362
3443
        return self._tabBounds
3363
 
    
 
3444
 
3364
3445
 
3365
3446
    def GetPageIndex(self, page_wnd):
3366
3447
        """
3384
3465
 
3385
3466
        # update our own tab catalog
3386
3467
        page_info = self._tabs.GetPage(page_idx)
 
3468
        should_refresh = page_info.caption != text
3387
3469
        page_info.caption = text
3388
3470
 
3389
3471
        # update what's on screen
3390
3472
        ctrl, ctrl_idx = self.FindTab(page_info.window)
3391
3473
        if not ctrl:
3392
3474
            return False
3393
 
        
 
3475
 
3394
3476
        info = ctrl.GetPage(ctrl_idx)
 
3477
        should_refresh = should_refresh or info.caption != text
3395
3478
        info.caption = text
3396
 
        ctrl.Refresh()
3397
 
        ctrl.Update()
 
3479
 
 
3480
        if should_refresh:
 
3481
            ctrl.Refresh()
 
3482
            ctrl.Update()
3398
3483
 
3399
3484
        self.UpdateTabCtrlHeight(force=True)
3400
 
    
 
3485
 
3401
3486
        return True
3402
3487
 
3403
3488
 
3407
3492
 
3408
3493
        :param `page_idx`: the page index.
3409
3494
        """
3410
 
        
 
3495
 
3411
3496
        if page_idx >= self._tabs.GetPageCount():
3412
3497
            return ""
3413
3498
 
3423
3508
        :param `page_idx`: the page index;
3424
3509
        :param `bitmap`: an instance of `wx.Bitmap`.
3425
3510
        """
3426
 
        
 
3511
 
3427
3512
        if page_idx >= self._tabs.GetPageCount():
3428
3513
            return False
3429
3514
 
3430
3515
        # update our own tab catalog
3431
3516
        page_info = self._tabs.GetPage(page_idx)
 
3517
        should_refresh = page_info.bitmap is not bitmap
3432
3518
        page_info.bitmap = bitmap
3433
3519
        if bitmap.IsOk() and not page_info.dis_bitmap.IsOk():
3434
3520
            page_info.dis_bitmap = MakeDisabledBitmap(bitmap)
3440
3526
        ctrl, ctrl_idx = self.FindTab(page_info.window)
3441
3527
        if not ctrl:
3442
3528
            return False
3443
 
        
 
3529
 
3444
3530
        info = ctrl.GetPage(ctrl_idx)
 
3531
        should_refresh = should_refresh or info.bitmap is not bitmap
3445
3532
        info.bitmap = bitmap
3446
3533
        info.dis_bitmap = page_info.dis_bitmap
3447
 
        ctrl.Refresh()
3448
 
        ctrl.Update()
3449
 
        
 
3534
        if should_refresh:
 
3535
            ctrl.Refresh()
 
3536
            ctrl.Update()
 
3537
 
3450
3538
        return True
3451
3539
 
3452
3540
 
3456
3544
 
3457
3545
        :param `page_idx`: the page index.
3458
3546
        """
3459
 
        
 
3547
 
3460
3548
        if page_idx >= self._tabs.GetPageCount():
3461
3549
            return wx.NullBitmap
3462
3550
 
3472
3560
        :param `imageList`: an instance of `wx.ImageList`.
3473
3561
        """
3474
3562
 
3475
 
        self._imageList = imageList        
3476
 
                
 
3563
        self._imageList = imageList
 
3564
 
3477
3565
 
3478
3566
    def AssignImageList(self, imageList):
3479
3567
        """
3488
3576
    def GetImageList(self):
3489
3577
        """ Returns the associated image list (if any). """
3490
3578
 
3491
 
        return self._imageList        
 
3579
        return self._imageList
3492
3580
 
3493
3581
 
3494
3582
    def SetPageImage(self, page, image):
3498
3586
        :param `page`: the page index;
3499
3587
        :param `image`: an index into the image list which was set with L{SetImageList}.
3500
3588
        """
3501
 
        
 
3589
 
3502
3590
        if page >= self._tabs.GetPageCount():
3503
3591
            return False
3504
3592
 
3505
3593
        if not isinstance(image, types.IntType):
3506
3594
            raise Exception("The image parameter must be an integer, you passed " \
3507
3595
                            "%s"%repr(image))
3508
 
        
 
3596
 
3509
3597
        if not self._imageList:
3510
3598
            raise Exception("To use SetPageImage you need to associate an image list " \
3511
3599
                            "Using SetImageList or AssignImageList")
3517
3605
        if image == -1:
3518
3606
            self.SetPageBitmap(page, wx.NullBitmap)
3519
3607
            return
3520
 
        
 
3608
 
3521
3609
        bitmap = self._imageList.GetBitmap(image)
3522
3610
        self.SetPageBitmap(page, bitmap)
3523
3611
 
3548
3636
        :param `page_idx`: the page index;
3549
3637
        :param `colour`: an instance of `wx.Colour`.
3550
3638
        """
3551
 
        
 
3639
 
3552
3640
        if page_idx >= self._tabs.GetPageCount():
3553
3641
            return False
3554
3642
 
3555
3643
        # update our own tab catalog
3556
3644
        page_info = self._tabs.GetPage(page_idx)
 
3645
        should_refresh = page_info.text_colour != colour
3557
3646
        page_info.text_colour = colour
3558
3647
 
3559
3648
        # update what's on screen
3560
3649
        ctrl, ctrl_idx = self.FindTab(page_info.window)
3561
3650
        if not ctrl:
3562
3651
            return False
3563
 
        
 
3652
 
3564
3653
        info = ctrl.GetPage(ctrl_idx)
 
3654
        should_refresh = should_refresh or info.text_colour != colour
3565
3655
        info.text_colour = page_info.text_colour
3566
 
        ctrl.Refresh()
3567
 
        ctrl.Update()
3568
 
        
 
3656
 
 
3657
        if should_refresh:
 
3658
            ctrl.Refresh()
 
3659
            ctrl.Update()
 
3660
 
3569
3661
        return True
3570
3662
 
3571
3663
 
3575
3667
 
3576
3668
        :param `page_idx`: the page index.
3577
3669
        """
3578
 
        
 
3670
 
3579
3671
        if page_idx >= self._tabs.GetPageCount():
3580
3672
            return wx.NullColour
3581
3673
 
3608
3700
            return False
3609
3701
 
3610
3702
        control.Reparent(ctrl)
3611
 
        
 
3703
 
3612
3704
        info = ctrl.GetPage(ctrl_idx)
3613
3705
        info.control = control
3614
3706
        ctrl.Refresh()
3615
3707
        ctrl.Update()
3616
 
        
 
3708
 
3617
3709
        return True
3618
 
        
 
3710
 
3619
3711
 
3620
3712
    def RemoveControlFromPage(self, page_idx):
3621
3713
        """
3631
3723
        if page_info.control is None:
3632
3724
            return False
3633
3725
 
3634
 
        page_info.control.Destroy()        
 
3726
        page_info.control.Destroy()
3635
3727
        page_info.control = None
3636
3728
 
3637
3729
        # tab height might have changed
3641
3733
        ctrl, ctrl_idx = self.FindTab(page_info.window)
3642
3734
        if not ctrl:
3643
3735
            return False
3644
 
        
 
3736
 
3645
3737
        info = ctrl.GetPage(ctrl_idx)
3646
3738
        info.control = None
3647
3739
        ctrl.Refresh()
3648
3740
        ctrl.Update()
3649
 
        
 
3741
 
3650
3742
        return True
3651
 
        
 
3743
 
3652
3744
 
3653
3745
    def SetCloseButton(self, page_idx, hasCloseButton):
3654
3746
        """
3655
3747
        Sets whether a tab should display a close button or not.
3656
 
        
 
3748
 
3657
3749
        :param `page_idx`: the page index;
3658
3750
        :param `hasCloseButton`: ``True`` if the page displays a close button.
3659
3751
 
3665
3757
 
3666
3758
        if self._agwFlags & AUI_NB_CLOSE_ON_ALL_TABS == 0:
3667
3759
            raise Exception("SetCloseButton can only be used with AUI_NB_CLOSE_ON_ALL_TABS style.")
3668
 
        
 
3760
 
3669
3761
        # update our own tab catalog
3670
3762
        page_info = self._tabs.GetPage(page_idx)
3671
3763
        page_info.hasCloseButton = hasCloseButton
3674
3766
        ctrl, ctrl_idx = self.FindTab(page_info.window)
3675
3767
        if not ctrl:
3676
3768
            return False
3677
 
        
 
3769
 
3678
3770
        info = ctrl.GetPage(ctrl_idx)
3679
3771
        info.hasCloseButton = page_info.hasCloseButton
3680
3772
        ctrl.Refresh()
3681
3773
        ctrl.Update()
3682
 
        
 
3774
 
3683
3775
        return True
3684
 
        
 
3776
 
3685
3777
 
3686
3778
    def HasCloseButton(self, page_idx):
3687
3779
        """
3688
3780
        Returns whether a tab displays a close button or not.
3689
 
        
 
3781
 
3690
3782
        :param `page_idx`: the page index.
3691
3783
 
3692
3784
        :note: This can only be called if ``AUI_NB_CLOSE_ON_ALL_TABS`` is specified.
3698
3790
        page_info = self._tabs.GetPage(page_idx)
3699
3791
        return page_info.hasCloseButton
3700
3792
 
3701
 
        
 
3793
 
3702
3794
    def GetSelection(self):
3703
3795
        """ Returns the index of the currently active page, or -1 if none was selected. """
3704
 
        
 
3796
 
3705
3797
        return self._curpage
3706
3798
 
3707
3799
 
3712
3804
            return self.GetPage(self._curpage)
3713
3805
 
3714
3806
        return None
3715
 
    
 
3807
 
3716
3808
 
3717
3809
    def EnsureVisible(self, indx):
3718
3810
        """
3719
3811
        Ensures the input page index `indx` is visible.
3720
 
        
 
3812
 
3721
3813
        :param `indx`: the page index.
3722
3814
        """
3723
3815
 
3724
3816
        self._tabs.MakeTabVisible(indx, self)
3725
 
        
 
3817
 
3726
3818
 
3727
3819
    def SetSelection(self, new_page, force=False):
3728
3820
        """
3731
3823
        :param `new_page`: the index of the new selection;
3732
3824
        :param `force`: whether to force the selection or not.
3733
3825
        """
3734
 
        
3735
3826
        wnd = self._tabs.GetWindowFromIdx(new_page)
 
3827
 
 
3828
        #Update page access time
 
3829
        self._tabs.GetPages()[new_page].access_time = datetime.datetime.now()
 
3830
 
3736
3831
        if not wnd or not self.GetEnabled(new_page):
3737
3832
            return self._curpage
3738
3833
 
3739
3834
        # don't change the page unless necessary
3740
3835
        # however, clicking again on a tab should give it the focus.
3741
3836
        if new_page == self._curpage and not force:
3742
 
        
3743
 
            ctrl, ctrl_idx = self.FindTab(wnd)            
 
3837
 
 
3838
            ctrl, ctrl_idx = self.FindTab(wnd)
3744
3839
            if wx.Window.FindFocus() != ctrl:
3745
3840
                ctrl.SetFocus()
3746
 
            
 
3841
 
3747
3842
            return self._curpage
3748
 
        
 
3843
 
3749
3844
        evt = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, self.GetId())
3750
3845
        evt.SetSelection(new_page)
3751
3846
        evt.SetOldSelection(self._curpage)
3752
3847
        evt.SetEventObject(self)
3753
3848
 
3754
3849
        if not self.GetEventHandler().ProcessEvent(evt) or evt.IsAllowed():
3755
 
        
 
3850
 
3756
3851
            old_curpage = self._curpage
3757
3852
            self._curpage = new_page
3758
3853
 
3762
3857
 
3763
3858
            if not evt.IsAllowed(): # event is no longer allowed after handler
3764
3859
                return self._curpage
3765
 
        
 
3860
 
3766
3861
            ctrl, ctrl_idx = self.FindTab(wnd)
3767
 
            
 
3862
 
3768
3863
            if ctrl:
3769
3864
                self._tabs.SetActivePage(wnd)
3770
3865
                ctrl.SetActivePage(ctrl_idx)
3777
3872
                for pane in all_panes:
3778
3873
                    if pane.name == "dummy":
3779
3874
                        continue
3780
 
                    
 
3875
 
3781
3876
                    tabctrl = pane.window._tabs
3782
3877
                    if tabctrl != ctrl:
3783
3878
                        tabctrl.SetSelectedFont(self._normal_font)
3784
3879
                    else:
3785
3880
                        tabctrl.SetSelectedFont(self._selected_font)
3786
 
                        
 
3881
 
3787
3882
                    tabctrl.Refresh()
3788
3883
                    tabctrl.Update()
3789
 
                
 
3884
 
3790
3885
                # Set the focus to the page if we're not currently focused on the tab.
3791
3886
                # This is Firefox-like behaviour.
3792
3887
                if wnd.IsShownOnScreen() and wx.Window.FindFocus() != ctrl:
3793
3888
                    wnd.SetFocus()
3794
3889
 
3795
3890
                return old_curpage
3796
 
            
 
3891
 
3797
3892
        return self._curpage
3798
3893
 
3799
3894
 
3805
3900
        """
3806
3901
 
3807
3902
        idx = self._tabs.GetIdxFromWindow(win)
3808
 
        
 
3903
 
3809
3904
        if idx == wx.NOT_FOUND:
3810
3905
            raise Exception("invalid notebook page")
3811
3906
 
3812
3907
        if not self.GetEnabled(idx):
3813
3908
            return
3814
 
        
 
3909
 
3815
3910
        # since a tab was clicked, let the parent know that we received
3816
3911
        # the focus, even if we will assign that focus immediately
3817
3912
        # to the child tab in the SetSelection call below
3832
3927
 
3833
3928
        :param `page`: an instance of L{AuiNotebookPage}.
3834
3929
        """
3835
 
        
 
3930
 
3836
3931
        self.SetSelectionToWindow(page.window)
3837
3932
 
3838
3933
 
3866
3961
            raise Exception("invalid notebook page")
3867
3962
 
3868
3963
        return self._tabs.GetPage(page_idx)
3869
 
        
 
3964
 
3870
3965
 
3871
3966
    def GetEnabled(self, page_idx):
3872
3967
        """
3874
3969
 
3875
3970
        :param `page_idx`: the page index.
3876
3971
        """
3877
 
        
 
3972
 
3878
3973
        return self._tabs.GetEnabled(page_idx)
3879
3974
 
3880
3975
 
3889
3984
        self._tabs.EnableTab(page_idx, enable)
3890
3985
        self.Refresh()
3891
3986
 
3892
 
    
 
3987
 
3893
3988
    def DoSizing(self):
3894
3989
        """ Performs all sizing operations in each tab control. """
3895
3990
 
3900
3995
 
3901
3996
            tabframe = pane.window
3902
3997
            tabframe.DoSizing()
3903
 
        
 
3998
 
3904
3999
 
3905
4000
    def GetAuiManager(self):
3906
4001
        """ Returns the associated L{AuiManager}. """
3907
4002
 
3908
4003
        return self._mgr
3909
 
    
 
4004
 
3910
4005
 
3911
4006
    def GetActiveTabCtrl(self):
3912
4007
        """
3918
4013
 
3919
4014
            # find the tab ctrl with the current page
3920
4015
            ctrl, idx = self.FindTab(self._tabs.GetPage(self._curpage).window)
3921
 
            if ctrl:            
 
4016
            if ctrl:
3922
4017
                return ctrl
3923
 
        
 
4018
 
3924
4019
        # no current page, just find the first tab ctrl
3925
4020
        all_panes = self._mgr.GetAllPanes()
3926
4021
        for pane in all_panes:
3929
4024
 
3930
4025
            tabframe = pane.window
3931
4026
            return tabframe._tabs
3932
 
        
 
4027
 
3933
4028
        # If there is no tabframe at all, create one
3934
4029
        tabframe = TabFrame(self)
3935
4030
        tabframe.SetTabCtrlHeight(self._tab_ctrl_height)
3936
4031
        self._tab_id_counter += 1
3937
4032
        tabframe._tabs = AuiTabCtrl(self, self._tab_id_counter)
3938
 
        
 
4033
 
3939
4034
        tabframe._tabs.SetAGWFlags(self._agwFlags)
3940
4035
        tabframe._tabs.SetArtProvider(self._tabs.GetArtProvider().Clone())
3941
4036
        self._mgr.AddPane(tabframe, framemanager.AuiPaneInfo().Center().CaptionVisible(False).
3952
4047
        as the index of the window in the tab control. It returns ``True`` if the
3953
4048
        window was found, otherwise ``False``.
3954
4049
 
3955
 
        :param `page`: an instance of L{AuiNotebookPage}.        
 
4050
        :param `page`: an instance of L{AuiNotebookPage}.
3956
4051
        """
3957
4052
 
3958
4053
        all_panes = self._mgr.GetAllPanes()
3963
4058
            tabframe = pane.window
3964
4059
 
3965
4060
            page_idx = tabframe._tabs.GetIdxFromWindow(page)
3966
 
            
 
4061
 
3967
4062
            if page_idx != -1:
3968
 
            
 
4063
 
3969
4064
                ctrl = tabframe._tabs
3970
4065
                idx = page_idx
3971
4066
                return ctrl, idx
3972
 
            
 
4067
 
3973
4068
        return None, wx.NOT_FOUND
3974
4069
 
3975
4070
 
3982
4077
        :param `direction`: specifies where the pane should go, it should be one of the
3983
4078
         following: ``wx.TOP``, ``wx.BOTTOM``, ``wx.LEFT``, or ``wx.RIGHT``.
3984
4079
        """
3985
 
        
 
4080
 
3986
4081
        cli_size = self.GetClientSize()
3987
4082
 
3988
4083
        # get the page's window pointer
3999
4094
        src_tabs, src_idx = self.FindTab(wnd)
4000
4095
        if not src_tabs:
4001
4096
            return
4002
 
        
 
4097
 
4003
4098
        # choose a split size
4004
4099
        if self.GetPageCount() > 2:
4005
4100
            split_size = self.CalculateNewSplitSize()
4006
 
        else:        
 
4101
        else:
4007
4102
            # because there are two panes, always split them
4008
4103
            # equally
4009
4104
            split_size = self.GetClientSize()
4016
4111
        new_tabs.SetTabCtrlHeight(self._tab_ctrl_height)
4017
4112
        self._tab_id_counter += 1
4018
4113
        new_tabs._tabs = AuiTabCtrl(self, self._tab_id_counter)
4019
 
        
 
4114
 
4020
4115
        new_tabs._tabs.SetArtProvider(self._tabs.GetArtProvider().Clone())
4021
4116
        new_tabs._tabs.SetAGWFlags(self._agwFlags)
4022
4117
        dest_tabs = new_tabs._tabs
4024
4119
        page_info = src_tabs.GetPage(src_idx)
4025
4120
        if page_info.control:
4026
4121
            self.ReparentControl(page_info.control, dest_tabs)
4027
 
        
 
4122
 
4028
4123
        # create a pane info structure with the information
4029
4124
        # about where the pane should be added
4030
4125
        pane_info = framemanager.AuiPaneInfo().Bottom().CaptionVisible(False)
4031
4126
 
4032
4127
        if direction == wx.LEFT:
4033
 
        
 
4128
 
4034
4129
            pane_info.Left()
4035
4130
            mouse_pt = wx.Point(0, cli_size.y/2)
4036
 
        
 
4131
 
4037
4132
        elif direction == wx.RIGHT:
4038
 
        
 
4133
 
4039
4134
            pane_info.Right()
4040
4135
            mouse_pt = wx.Point(cli_size.x, cli_size.y/2)
4041
 
        
 
4136
 
4042
4137
        elif direction == wx.TOP:
4043
 
        
 
4138
 
4044
4139
            pane_info.Top()
4045
4140
            mouse_pt = wx.Point(cli_size.x/2, 0)
4046
 
        
 
4141
 
4047
4142
        elif direction == wx.BOTTOM:
4048
 
        
 
4143
 
4049
4144
            pane_info.Bottom()
4050
4145
            mouse_pt = wx.Point(cli_size.x/2, cli_size.y)
4051
 
        
 
4146
 
4052
4147
        self._mgr.AddPane(new_tabs, pane_info, mouse_pt)
4053
4148
        self._mgr.Update()
4054
4149
 
4055
4150
        # remove the page from the source tabs
4056
4151
        page_info.active = False
4057
 
        
 
4152
 
4058
4153
        src_tabs.RemovePage(page_info.window)
4059
 
        
 
4154
 
4060
4155
        if src_tabs.GetPageCount() > 0:
4061
4156
            src_tabs.SetActivePage(0)
4062
4157
            src_tabs.DoShowHide()
4063
4158
            src_tabs.Refresh()
4064
 
        
 
4159
 
4065
4160
        # add the page to the destination tabs
4066
4161
        dest_tabs.InsertPage(page_info.window, page_info, 0)
4067
4162
 
4068
4163
        if src_tabs.GetPageCount() == 0:
4069
4164
            self.RemoveEmptyTabFrames()
4070
 
        
 
4165
 
4071
4166
        self.DoSizing()
4072
4167
        dest_tabs.DoShowHide()
4073
4168
        dest_tabs.Refresh()
4085
4180
        """ Restores original view after a tab split. """
4086
4181
 
4087
4182
        self.Freeze()
4088
 
        
 
4183
 
4089
4184
        # remember the tab now selected
4090
4185
        nowSelected = self.GetSelection()
4091
4186
        # select first tab as destination
4115
4210
        :param `control`: an instance of `wx.Window`;
4116
4211
        :param `dest_tabs`: the destination L{AuiTabCtrl}.
4117
4212
        """
4118
 
        
 
4213
 
4119
4214
        control.Hide()
4120
4215
        control.Reparent(dest_tabs)
4121
 
        
 
4216
 
4122
4217
 
4123
4218
    def UnsplitDClick(self, part, sash_size, pos):
4124
4219
        """
4158
4253
                pos1.y -= shift
4159
4254
            else:
4160
4255
                pos1.x -= shift
4161
 
                
 
4256
 
4162
4257
            pos1 = self.ClientToScreen(pos1)
4163
4258
            win1 = wx.FindWindowAtPoint(pos1)
4164
4259
 
4199
4294
 
4200
4295
        selection = -1
4201
4296
        page_count = dest_tabs.GetPageCount()
4202
 
        
 
4297
 
4203
4298
        for page in xrange(src_tabs.GetPageCount()-1, -1, -1):
4204
4299
            # remove the page from the source tabs
4205
4300
            page_info = src_tabs.GetPage(page)
4211
4306
            dest_tabs.AddPage(page_info.window, page_info)
4212
4307
            if page_info.control:
4213
4308
                self.ReparentControl(page_info.control, dest_tabs)
4214
 
        
 
4309
 
4215
4310
        self.RemoveEmptyTabFrames()
4216
4311
 
4217
4312
        dest_tabs.DoShowHide()
4220
4315
        self._mgr.Update()
4221
4316
        if selection > 0:
4222
4317
            wx.CallAfter(dest_tabs.MakeTabVisible, selection, self)
4223
 
        
4224
 
    
 
4318
 
 
4319
 
4225
4320
    def OnSize(self, event):
4226
4321
        """
4227
4322
        Handles the ``wx.EVT_SIZE`` event for L{AuiNotebook}.
4228
4323
 
4229
 
        :param `event`: a `wx.SizeEvent` event to be processed.        
 
4324
        :param `event`: a `wx.SizeEvent` event to be processed.
4230
4325
        """
4231
 
        
 
4326
 
4232
4327
        self.UpdateHintWindowSize()
4233
4328
        event.Skip()
4234
4329
 
4237
4332
        """
4238
4333
        Handles the ``EVT_AUINOTEBOOK_PAGE_CHANGING`` event for L{AuiNotebook}.
4239
4334
 
4240
 
        :param `event`: a L{AuiNotebookEvent} event to be processed.        
 
4335
        :param `event`: a L{AuiNotebookEvent} event to be processed.
4241
4336
        """
4242
4337
 
4243
4338
        if self._textCtrl is not None:
4244
4339
            self._textCtrl.StopEditing()
4245
 
        
 
4340
 
4246
4341
        ctrl = event.GetEventObject()
4247
4342
        assert ctrl != None
4248
4343
 
4256
4351
        """
4257
4352
        Handles the ``EVT_AUINOTEBOOK_BG_DCLICK`` event for L{AuiNotebook}.
4258
4353
 
4259
 
        :param `event`: a L{AuiNotebookEvent} event to be processed.        
 
4354
        :param `event`: a L{AuiNotebookEvent} event to be processed.
4260
4355
        """
4261
4356
 
4262
4357
        if self._textCtrl is not None:
4263
4358
            self._textCtrl.StopEditing()
4264
 
        
 
4359
 
4265
4360
        # notify owner that the tabbar background has been double-clicked
4266
4361
        e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, self.GetId())
4267
4362
        e.SetEventObject(self)
4272
4367
        """
4273
4368
        Handles the ``EVT_AUINOTEBOOK_TAB_DCLICK`` event for L{AuiNotebook}.
4274
4369
 
4275
 
        :param `event`: a L{AuiNotebookEvent} event to be processed.        
 
4370
        :param `event`: a L{AuiNotebookEvent} event to be processed.
4276
4371
        """
4277
4372
 
4278
4373
        # notify owner that the tabbar background has been double-clicked
4288
4383
            return
4289
4384
 
4290
4385
        self.EditTab(event.GetSelection())
4291
 
        
 
4386
 
4292
4387
 
4293
4388
    def OnTabBeginDrag(self, event):
4294
4389
        """
4295
4390
        Handles the ``EVT_AUINOTEBOOK_BEGIN_DRAG`` event for L{AuiNotebook}.
4296
4391
 
4297
 
        :param `event`: a L{AuiNotebookEvent} event to be processed.        
 
4392
        :param `event`: a L{AuiNotebookEvent} event to be processed.
4298
4393
        """
4299
4394
 
4300
4395
        tabs = event.GetEventObject()
4308
4403
        """
4309
4404
        Handles the ``EVT_AUINOTEBOOK_DRAG_MOTION`` event for L{AuiNotebook}.
4310
4405
 
4311
 
        :param `event`: a L{AuiNotebookEvent} event to be processed.        
 
4406
        :param `event`: a L{AuiNotebookEvent} event to be processed.
4312
4407
        """
4313
4408
 
4314
4409
        tabs = event.GetEventObject()
4324
4419
 
4325
4420
        src_tabs = event.GetEventObject()
4326
4421
        dest_tabs = self.GetTabCtrlFromPoint(client_pt)
4327
 
        
 
4422
 
4328
4423
        if dest_tabs == src_tabs:
4329
 
            if src_tabs:
4330
 
                src_tabs.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
4331
 
            
 
4424
 
4332
4425
            # always hide the hint for inner-tabctrl drag
4333
4426
            self._mgr.HideHint()
4334
4427
 
4335
4428
            # if tab moving is not allowed, leave
4336
4429
            if not self._agwFlags & AUI_NB_TAB_MOVE:
4337
4430
                return
4338
 
            
 
4431
 
4339
4432
            pt = dest_tabs.ScreenToClient(screen_pt)
4340
4433
 
4341
4434
            # this is an inner-tab drag/reposition
4342
4435
            dest_location_tab = dest_tabs.TabHitTest(pt.x, pt.y)
4343
 
            
 
4436
 
4344
4437
            if dest_location_tab:
4345
 
            
 
4438
 
4346
4439
                src_idx = event.GetSelection()
4347
4440
                dest_idx = dest_tabs.GetIdxFromWindow(dest_location_tab)
4348
4441
 
4350
4443
                if (src_idx == dest_idx) or dest_idx == -1 or \
4351
4444
                   (src_idx > dest_idx and self._last_drag_x <= pt.x) or \
4352
4445
                   (src_idx < dest_idx and self._last_drag_x >= pt.x):
4353
 
                
 
4446
 
4354
4447
                    self._last_drag_x = pt.x
4355
4448
                    return
4356
 
                
 
4449
 
4357
4450
                src_tab = dest_tabs.GetWindowFromIdx(src_idx)
4358
4451
                dest_tabs.MovePage(src_tab, dest_idx)
 
4452
                self._tabs.MovePage(self._tabs.GetPage(src_idx).window, dest_idx)
4359
4453
                dest_tabs.SetActivePage(dest_idx)
4360
4454
                dest_tabs.DoShowHide()
4361
4455
                dest_tabs.Refresh()
4366
4460
        # if external drag is allowed, check if the tab is being dragged
4367
4461
        # over a different AuiNotebook control
4368
4462
        if self._agwFlags & AUI_NB_TAB_EXTERNAL_MOVE:
4369
 
        
 
4463
 
4370
4464
            tab_ctrl = wx.FindWindowAtPoint(screen_pt)
4371
4465
 
4372
4466
            # if we aren't over any window, stop here
4374
4468
                if self._agwFlags & AUI_NB_TAB_FLOAT:
4375
4469
                    if self.IsMouseWellOutsideWindow():
4376
4470
                        hintRect = wx.RectPS(screen_pt, (400, 300))
4377
 
                        # Use CallAfter so we overwrite the hint that might be 
4378
 
                        # shown by our superclass: 
4379
 
                        wx.CallAfter(self._mgr.ShowHint, hintRect) 
 
4471
                        # Use CallAfter so we overwrite the hint that might be
 
4472
                        # shown by our superclass:
 
4473
                        wx.CallAfter(self._mgr.ShowHint, hintRect)
4380
4474
                return
4381
4475
 
4382
4476
            # make sure we are not over the hint window
4384
4478
                while tab_ctrl:
4385
4479
                    if isinstance(tab_ctrl, AuiTabCtrl):
4386
4480
                        break
4387
 
                    
 
4481
 
4388
4482
                    tab_ctrl = tab_ctrl.GetParent()
4389
 
                
 
4483
 
4390
4484
                if tab_ctrl:
4391
4485
                    nb = tab_ctrl.GetParent()
4392
4486
 
4393
4487
                    if nb != self:
4394
 
                    
 
4488
 
4395
4489
                        hint_rect = tab_ctrl.GetClientRect()
4396
4490
                        hint_rect.x, hint_rect.y = tab_ctrl.ClientToScreenXY(hint_rect.x, hint_rect.y)
4397
4491
                        self._mgr.ShowHint(hint_rect)
4398
4492
                        return
4399
 
                    
 
4493
 
4400
4494
            else:
4401
 
            
 
4495
 
4402
4496
                if not dest_tabs:
4403
4497
                    # we are either over a hint window, or not over a tab
4404
4498
                    # window, and there is no where to drag to, so exit
4407
4501
        if self._agwFlags & AUI_NB_TAB_FLOAT:
4408
4502
            if self.IsMouseWellOutsideWindow():
4409
4503
                hintRect = wx.RectPS(screen_pt, (400, 300))
4410
 
                # Use CallAfter so we overwrite the hint that might be 
4411
 
                # shown by our superclass: 
 
4504
                # Use CallAfter so we overwrite the hint that might be
 
4505
                # shown by our superclass:
4412
4506
                wx.CallAfter(self._mgr.ShowHint, hintRect)
4413
4507
                return
4414
 
                        
 
4508
 
4415
4509
        # if there are less than two panes, split can't happen, so leave
4416
4510
        if self._tabs.GetPageCount() < 2:
4417
4511
            return
4420
4514
        if not self._agwFlags & AUI_NB_TAB_SPLIT:
4421
4515
            return
4422
4516
 
4423
 
        if src_tabs:
4424
 
            src_tabs.SetCursor(wx.StockCursor(wx.CURSOR_SIZING))
4425
 
        
4426
4517
        if dest_tabs:
4427
 
            
 
4518
 
4428
4519
            hint_rect = dest_tabs.GetRect()
4429
4520
            hint_rect.x, hint_rect.y = self.ClientToScreenXY(hint_rect.x, hint_rect.y)
4430
4521
            self._mgr.ShowHint(hint_rect)
4431
 
        
 
4522
 
4432
4523
        else:
4433
4524
            rect = self._mgr.CalculateHintRect(self._dummy_wnd, client_pt, zero)
4434
4525
            if rect.IsEmpty():
4435
4526
                self._mgr.HideHint()
4436
4527
                return
4437
 
            
 
4528
 
4438
4529
            hit_wnd = wx.FindWindowAtPoint(screen_pt)
4439
4530
            if hit_wnd and not isinstance(hit_wnd, AuiNotebook):
4440
4531
                tab_frame = self.GetTabFrameFromWindow(hit_wnd)
4447
4538
                    self._mgr.DrawHintRect(self._dummy_wnd, client_pt, zero)
4448
4539
            else:
4449
4540
                self._mgr.DrawHintRect(self._dummy_wnd, client_pt, zero)
4450
 
        
 
4541
 
4451
4542
 
4452
4543
    def OnTabEndDrag(self, event):
4453
4544
        """
4454
4545
        Handles the ``EVT_AUINOTEBOOK_END_DRAG`` event for L{AuiNotebook}.
4455
4546
 
4456
 
        :param `event`: a L{AuiNotebookEvent} event to be processed.        
 
4547
        :param `event`: a L{AuiNotebookEvent} event to be processed.
4457
4548
        """
4458
4549
 
4459
4550
        tabs = event.GetEventObject()
4466
4557
        if not src_tabs:
4467
4558
            raise Exception("no source object?")
4468
4559
 
4469
 
        src_tabs.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
4470
 
 
4471
4560
        # get the mouse position, which will be used to determine the drop point
4472
4561
        mouse_screen_pt = wx.GetMousePosition()
4473
4562
        mouse_client_pt = self.ScreenToClient(mouse_screen_pt)
4477
4566
            tab_ctrl = wx.FindWindowAtPoint(mouse_screen_pt)
4478
4567
 
4479
4568
            while tab_ctrl:
4480
 
            
 
4569
 
4481
4570
                if isinstance(tab_ctrl, AuiTabCtrl):
4482
4571
                    break
4483
 
                
 
4572
 
4484
4573
                tab_ctrl = tab_ctrl.GetParent()
4485
 
            
 
4574
 
4486
4575
            if tab_ctrl:
4487
 
            
 
4576
 
4488
4577
                nb = tab_ctrl.GetParent()
4489
4578
 
4490
4579
                if nb != self:
4491
 
                
 
4580
 
4492
4581
                    # find out from the destination control
4493
4582
                    # if it's ok to drop this tab here
4494
4583
                    e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, self.GetId())
4501
4590
                    nb.GetEventHandler().ProcessEvent(e)
4502
4591
 
4503
4592
                    if not e.IsAllowed():
4504
 
                    
 
4593
 
4505
4594
                        # no answer or negative answer
4506
4595
                        self._mgr.HideHint()
4507
4596
                        return
4508
 
                    
 
4597
 
4509
4598
                    # drop was allowed
4510
4599
                    src_idx = event.GetSelection()
4511
4600
                    src_page = src_tabs.GetWindowFromIdx(src_idx)
4515
4604
                    while p and not p.IsTopLevel():
4516
4605
                        if p == src_page:
4517
4606
                            return
4518
 
                        
 
4607
 
4519
4608
                        p = p.GetParent()
4520
4609
 
4521
4610
                    # get main index of the page
4548
4637
                    # add the page to the new notebook
4549
4638
                    if insert_idx == -1:
4550
4639
                        insert_idx = dest_tabs.GetPageCount()
4551
 
                        
 
4640
 
4552
4641
                    dest_tabs.InsertPage(page_info.window, page_info, insert_idx)
4553
4642
                    nb._tabs.AddPage(page_info.window, page_info)
4554
4643
 
4566
4655
                    e2.SetEventObject(self)
4567
4656
                    self.GetEventHandler().ProcessEvent(e2)
4568
4657
 
 
4658
                    # notify the target notebook that the tab has been dragged
 
4659
                    e3 = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, nb.GetId())
 
4660
                    e3.SetSelection(insert_idx)
 
4661
                    e3.SetOldSelection(insert_idx)
 
4662
                    e3.SetEventObject(nb)
 
4663
                    nb.GetEventHandler().ProcessEvent(e3)
 
4664
 
4569
4665
                    return
4570
4666
 
4571
4667
        if self._agwFlags & AUI_NB_TAB_FLOAT:
4572
 
            self._mgr.HideHint() 
4573
 
            if self.IsMouseWellOutsideWindow(): 
 
4668
            self._mgr.HideHint()
 
4669
            if self.IsMouseWellOutsideWindow():
4574
4670
                # Use CallAfter so we our superclass can deal with the event first
4575
4671
                wx.CallAfter(self.FloatPage, self.GetSelection())
4576
4672
                event.Skip()
4577
4673
                return
4578
 
        
 
4674
 
4579
4675
        # only perform a tab split if it's allowed
4580
4676
        dest_tabs = None
4581
4677
 
4582
4678
        if self._agwFlags & AUI_NB_TAB_SPLIT and self._tabs.GetPageCount() >= 2:
4583
 
        
 
4679
 
4584
4680
            # If the pointer is in an existing tab frame, do a tab insert
4585
4681
            hit_wnd = wx.FindWindowAtPoint(mouse_screen_pt)
4586
4682
            tab_frame = self.GetTabFrameFromTabCtrl(hit_wnd)
4587
4683
            insert_idx = -1
4588
 
            
 
4684
 
4589
4685
            if tab_frame:
4590
 
            
 
4686
 
4591
4687
                dest_tabs = tab_frame._tabs
4592
4688
 
4593
4689
                if dest_tabs == src_tabs:
4595
4691
 
4596
4692
                pt = dest_tabs.ScreenToClient(mouse_screen_pt)
4597
4693
                target = dest_tabs.TabHitTest(pt.x, pt.y)
4598
 
                
4599
 
                if target:                
 
4694
 
 
4695
                if target:
4600
4696
                    insert_idx = dest_tabs.GetIdxFromWindow(target)
4601
 
                
 
4697
 
4602
4698
            else:
4603
 
            
 
4699
 
4604
4700
                zero = wx.Point(0, 0)
4605
4701
                rect = self._mgr.CalculateHintRect(self._dummy_wnd, mouse_client_pt, zero)
4606
 
                
 
4702
 
4607
4703
                if rect.IsEmpty():
4608
4704
                    # there is no suitable drop location here, exit out
4609
4705
                    return
4610
 
                
 
4706
 
4611
4707
                # If there is no tabframe at all, create one
4612
4708
                new_tabs = TabFrame(self)
4613
4709
                new_tabs._rect = wx.RectPS(wx.Point(0, 0), self.CalculateNewSplitSize())
4620
4716
                self._mgr.AddPane(new_tabs, framemanager.AuiPaneInfo().Bottom().CaptionVisible(False), mouse_client_pt)
4621
4717
                self._mgr.Update()
4622
4718
                dest_tabs = new_tabs._tabs
4623
 
                
 
4719
 
4624
4720
            # remove the page from the source tabs
4625
4721
            page_info = src_tabs.GetPage(event.GetSelection())
4626
4722
 
4630
4726
            page_info.active = False
4631
4727
            src_tabs.RemovePage(page_info.window)
4632
4728
 
4633
 
            if src_tabs.GetPageCount() > 0:            
 
4729
            if src_tabs.GetPageCount() > 0:
4634
4730
                src_tabs.SetActivePage(0)
4635
4731
                src_tabs.DoShowHide()
4636
4732
                src_tabs.Refresh()
4640
4736
                insert_idx = dest_tabs.GetPageCount()
4641
4737
 
4642
4738
            dest_tabs.InsertPage(page_info.window, page_info, insert_idx)
4643
 
            
 
4739
 
4644
4740
            if src_tabs.GetPageCount() == 0:
4645
4741
                self.RemoveEmptyTabFrames()
4646
4742
 
4655
4751
            self.SetSelectionToPage(page_info)
4656
4752
 
4657
4753
            self.UpdateHintWindowSize()
4658
 
        
 
4754
 
4659
4755
        # notify owner that the tab has been dragged
4660
4756
        e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, self.GetId())
4661
4757
        e.SetSelection(event.GetSelection())
4668
4764
        """
4669
4765
        Handles the ``EVT_AUINOTEBOOK_CANCEL_DRAG`` event for L{AuiNotebook}.
4670
4766
 
4671
 
        :param `event`: a L{AuiNotebookEvent} event to be processed.        
 
4767
        :param `event`: a L{AuiNotebookEvent} event to be processed.
4672
4768
        """
4673
4769
 
4674
4770
        tabs = event.GetEventObject()
4681
4777
        if not src_tabs:
4682
4778
            raise Exception("no source object?")
4683
4779
 
4684
 
        src_tabs.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
4685
 
 
4686
4780
 
4687
4781
    def IsMouseWellOutsideWindow(self):
4688
4782
        """ Returns whether the mouse is well outside the L{AuiNotebook} screen rectangle. """
4689
 
        
4690
 
        screen_rect = self.GetScreenRect() 
 
4783
 
 
4784
        screen_rect = self.GetScreenRect()
4691
4785
        screen_rect.Inflate(50, 50)
4692
 
        
 
4786
 
4693
4787
        return not screen_rect.Contains(wx.GetMousePosition())
4694
4788
 
4695
4789
 
4700
4794
        :param `page_index`: the index of the page to be floated.
4701
4795
 
4702
4796
        :warning: When the notebook is more or less full screen, tabs cannot be dragged far
4703
 
         enough outside of the notebook to become floating pages.   
 
4797
         enough outside of the notebook to become floating pages.
4704
4798
        """
4705
4799
 
4706
4800
        root_manager = framemanager.GetManager(self)
4707
 
        page_title = self.GetPageText(page_index) 
 
4801
        page_title = self.GetPageText(page_index)
4708
4802
        page_contents = self.GetPage(page_index)
4709
4803
        page_bitmap = self.GetPageBitmap(page_index)
4710
4804
        text_colour = self.GetPageTextColour(page_index)
4711
4805
        info = self.GetPageInfo(page_index)
4712
 
                
 
4806
 
4713
4807
        if root_manager and root_manager != self._mgr:
4714
4808
            root_manager = framemanager.GetManager(self)
4715
4809
 
4732
4826
 
4733
4827
            self.RemovePage(page_index)
4734
4828
            self.RemoveEmptyTabFrames()
4735
 
                            
 
4829
 
4736
4830
            pane_info = framemanager.AuiPaneInfo().Float().FloatingPosition(wx.GetMousePosition()). \
4737
4831
                        FloatingSize(floating_size).BestSize(floating_size).Name("__floating__%s"%page_title). \
4738
4832
                        Caption(page_title).Icon(page_bitmap)
4741
4835
            self.GetActiveTabCtrl().DoShowHide()
4742
4836
            self.DoSizing()
4743
4837
            root_manager.Update()
4744
 
            
 
4838
 
4745
4839
        else:
4746
4840
            frame = wx.Frame(self, title=page_title,
4747
4841
                             style=wx.DEFAULT_FRAME_STYLE|wx.FRAME_TOOL_WINDOW|
4748
 
                                   wx.FRAME_FLOAT_ON_PARENT | wx.FRAME_NO_TASKBAR) 
 
4842
                                   wx.FRAME_FLOAT_ON_PARENT | wx.FRAME_NO_TASKBAR)
4749
4843
 
4750
4844
            if info.control:
4751
4845
                info.control.Reparent(frame)
4752
4846
                info.control.Hide()
4753
 
                
4754
 
            frame.bitmap = page_bitmap            
 
4847
 
 
4848
            frame.bitmap = page_bitmap
4755
4849
            frame.page_index = page_index
4756
4850
            frame.text_colour = text_colour
4757
4851
            frame.control = info.control
4758
 
            page_contents.Reparent(frame) 
4759
 
            frame.Bind(wx.EVT_CLOSE, self.OnCloseFloatingPage) 
4760
 
            frame.Move(wx.GetMousePosition()) 
 
4852
            page_contents.Reparent(frame)
 
4853
            frame.Bind(wx.EVT_CLOSE, self.OnCloseFloatingPage)
 
4854
            frame.Move(wx.GetMousePosition())
4761
4855
            frame.Show()
4762
4856
            self.RemovePage(page_index)
4763
4857
 
4764
4858
            self.RemoveEmptyTabFrames()
4765
4859
 
4766
4860
        wx.CallAfter(self.RemoveEmptyTabFrames)
4767
 
        
 
4861
 
4768
4862
 
4769
4863
    def OnCloseFloatingPage(self, event):
4770
4864
        """
4771
4865
        Handles the ``wx.EVT_CLOSE`` event for a floating page in L{AuiNotebook}.
4772
4866
 
4773
 
        :param `event`: a `wx.CloseEvent` event to be processed.        
 
4867
        :param `event`: a `wx.CloseEvent` event to be processed.
4774
4868
        """
4775
4869
 
4776
4870
        root_manager = framemanager.GetManager(self)
4779
4873
            if pane.name.startswith("__floating__"):
4780
4874
                self.ReDockPage(pane)
4781
4875
                return
4782
 
                
 
4876
 
4783
4877
            event.Skip()
4784
4878
        else:
4785
4879
            event.Skip()
4786
 
            frame = event.GetEventObject() 
4787
 
            page_title = frame.GetTitle() 
4788
 
            page_contents = frame.GetChildren()[-1] 
 
4880
            frame = event.GetEventObject()
 
4881
            page_title = frame.GetTitle()
 
4882
            page_contents = list(frame.GetChildren())[-1]
4789
4883
            page_contents.Reparent(self)
4790
 
            self.InsertPage(frame.page_index, page_contents, page_title, select=True, bitmap=frame.bitmap, control=control)
 
4884
            self.InsertPage(frame.page_index, page_contents, page_title, select=True, bitmap=frame.bitmap, control=frame.control)
4791
4885
 
4792
4886
            if frame.control:
4793
4887
                src_tabs, idx = self.FindTab(page_contents)
4805
4899
        :param `pane`: an instance of L{framemanager.AuiPaneInfo}.
4806
4900
        """
4807
4901
 
4808
 
        root_manager = framemanager.GetManager(self)        
 
4902
        root_manager = framemanager.GetManager(self)
4809
4903
 
4810
4904
        pane.window.__floating_size__ = wx.Size(*pane.floating_size)
4811
4905
        page_index = pane.window.__page_index__
4812
4906
        text_colour = pane.window.__text_colour__
4813
4907
        control = pane.window.__control__
4814
 
        
 
4908
 
4815
4909
        root_manager.DetachPane(pane.window)
4816
4910
        self.InsertPage(page_index, pane.window, pane.caption, True, pane.icon, control=control)
4817
4911
 
4820
4914
        self.DoSizing()
4821
4915
        if control:
4822
4916
            self.UpdateTabCtrlHeight(force=True)
4823
 
            
 
4917
 
4824
4918
        self._mgr.Update()
4825
4919
        root_manager.Update()
4826
 
        
4827
 
        
 
4920
 
 
4921
 
4828
4922
    def GetTabCtrlFromPoint(self, pt):
4829
4923
        """
4830
4924
        Returns the tab control at the specified point.
4842
4936
            tabframe = pane.window
4843
4937
            if tabframe._tab_rect.Contains(pt):
4844
4938
                return tabframe._tabs
4845
 
        
 
4939
 
4846
4940
        return None
4847
4941
 
4848
4942
 
4861
4955
                continue
4862
4956
 
4863
4957
            tabframe = pane.window
4864
 
            if tabframe._tabs == tab_ctrl:            
 
4958
            if tabframe._tabs == tab_ctrl:
4865
4959
                return tabframe
4866
 
            
 
4960
 
4867
4961
        return None
4868
4962
 
4869
4963
 
4883
4977
            for page in tabframe._tabs.GetPages():
4884
4978
                if wnd == page.window:
4885
4979
                    return tabframe
4886
 
            
 
4980
 
4887
4981
        return None
4888
 
    
4889
 
        
 
4982
 
 
4983
 
4890
4984
    def RemoveEmptyTabFrames(self):
4891
4985
        """ Removes all the empty tab frames. """
4892
4986
 
4915
5009
        for pane in all_panes:
4916
5010
            if pane.name == "dummy":
4917
5011
                continue
4918
 
       
 
5012
 
4919
5013
            if pane.dock_direction == AUI_DOCK_CENTRE:
4920
5014
                center_found = True
4921
5015
            if not first_good:
4922
5016
                first_good = pane.window
4923
 
        
 
5017
 
4924
5018
        if not center_found and first_good:
4925
5019
            self._mgr.GetPane(first_good).Centre()
4926
5020
 
4932
5026
        """
4933
5027
        Handles the ``wx.EVT_CHILD_FOCUS`` event for L{AuiNotebook}.
4934
5028
 
4935
 
        :param `event`: a `wx.ChildFocusEvent` event to be processed.        
 
5029
        :param `event`: a `wx.ChildFocusEvent` event to be processed.
4936
5030
        """
4937
 
        
 
5031
 
4938
5032
        # if we're dragging a tab, don't change the current selection.
4939
5033
        # This code prevents a bug that used to happen when the hint window
4940
5034
        # was hidden.  In the bug, the focus would return to the notebook
4942
5036
        # SetSelection, which is not desired turn tab dragging.
4943
5037
 
4944
5038
        event.Skip()
4945
 
        
 
5039
 
4946
5040
        all_panes = self._mgr.GetAllPanes()
4947
5041
        for pane in all_panes:
4948
5042
            if pane.name == "dummy":
4956
5050
##        idx = self._tabs.GetIdxFromWindow(event.GetWindow())
4957
5051
##        if idx != -1 and idx != self._curpage:
4958
5052
##            self.SetSelection(idx)
4959
 
        
 
5053
 
4960
5054
 
4961
5055
    def SetNavigatorIcon(self, bmp):
4962
5056
        """
4964
5058
 
4965
5059
        :param `bmp`: an instance of `wx.Bitmap`.
4966
5060
        """
4967
 
        
 
5061
 
4968
5062
        if isinstance(bmp, wx.Bitmap) and bmp.IsOk():
4969
5063
            # Make sure image is proper size
4970
5064
            if bmp.GetSize() != (16, 16):
4975
5069
        else:
4976
5070
            raise TypeError, "SetNavigatorIcon requires a valid bitmap"
4977
5071
 
4978
 
        
 
5072
 
4979
5073
    def OnNavigationKeyNotebook(self, event):
4980
5074
        """
4981
5075
        Handles the ``wx.EVT_NAVIGATION_KEY`` event for L{AuiNotebook}.
4982
5076
 
4983
 
        :param `event`: a `wx.NavigationKeyEvent` event to be processed.        
 
5077
        :param `event`: a `wx.NavigationKeyEvent` event to be processed.
4984
5078
        """
4985
5079
 
4986
5080
        if event.IsWindowChange():
4989
5083
                    self._popupWin = TabNavigatorWindow(self, self._naviIcon)
4990
5084
                    self._popupWin.SetReturnCode(wx.ID_OK)
4991
5085
                    self._popupWin.ShowModal()
 
5086
                    idx = self._popupWin.GetSelectedPage()
4992
5087
                    self._popupWin.Destroy()
4993
5088
                    self._popupWin = None
 
5089
                    # Need to do CallAfter so that the selection and its
 
5090
                    # associated events get processed outside the context of
 
5091
                    # this key event. Not doing so causes odd issues with the
 
5092
                    # window focus under certain use cases on Windows.
 
5093
                    wx.CallAfter(self.SetSelection, idx, True)
4994
5094
                else:
4995
5095
                    # a dialog is already opened
4996
5096
                    self._popupWin.OnNavigationKey(event)
5000
5100
                # FIXME: the problem with this is that if we have a split notebook,
5001
5101
                # we selection may go all over the place.
5002
5102
                self.AdvanceSelection(event.GetDirection())
5003
 
        
 
5103
 
5004
5104
        else:
5005
5105
            # we get this event in 3 cases
5006
5106
            #
5027
5127
            isFromSelf = event.GetEventObject() == self
5028
5128
 
5029
5129
            if isFromParent or isFromSelf:
5030
 
            
 
5130
 
5031
5131
                # no, it doesn't come from child, case (b) or (c): forward to a
5032
5132
                # page but only if direction is backwards (TAB) or from ourselves,
5033
5133
                if self.GetSelection() != wx.NOT_FOUND and (not event.GetDirection() or isFromSelf):
5034
 
                
 
5134
 
5035
5135
                    # so that the page knows that the event comes from it's parent
5036
5136
                    # and is being propagated downwards
5037
5137
                    event.SetEventObject(self)
5038
5138
 
5039
5139
                    page = self.GetPage(self.GetSelection())
5040
 
                    if not page.GetEventHandler().ProcessEvent(event):                    
 
5140
                    if not page.GetEventHandler().ProcessEvent(event):
5041
5141
                        page.SetFocus()
5042
 
                    
 
5142
 
5043
5143
                    #else: page manages focus inside it itself
5044
 
                
 
5144
 
5045
5145
                else: # otherwise set the focus to the notebook itself
5046
 
                
 
5146
 
5047
5147
                    self.SetFocus()
5048
 
                
 
5148
 
5049
5149
            else:
5050
 
            
 
5150
 
5051
5151
                # send this event back for the 'wraparound' focus.
5052
5152
                winFocus = event.GetCurrentFocus()
5053
5153
 
5060
5160
        """
5061
5161
        Handles the ``EVT_AUINOTEBOOK_BUTTON`` event for L{AuiNotebook}.
5062
5162
 
5063
 
        :param `event`: a L{AuiNotebookEvent} event to be processed.        
 
5163
        :param `event`: a L{AuiNotebookEvent} event to be processed.
5064
5164
        """
5065
5165
 
5066
5166
        tabs = event.GetEventObject()
5071
5171
            selection = event.GetSelection()
5072
5172
 
5073
5173
            if selection == -1:
5074
 
            
 
5174
 
5075
5175
                # if the close button is to the right, use the active
5076
5176
                # page selection to determine which page to close
5077
5177
                selection = tabs.GetActivePage()
5078
5178
 
5079
5179
            if selection == -1 or not tabs.GetEnabled(selection):
5080
5180
                return
5081
 
            
 
5181
 
5082
5182
            if selection != -1:
5083
 
            
 
5183
 
5084
5184
                close_wnd = tabs.GetWindowFromIdx(selection)
5085
5185
 
5086
5186
                if close_wnd.GetName() == "__fake__page__":
5088
5188
                    previous_active, page_status = close_wnd.__previousStatus
5089
5189
                    for page, status in zip(tabs.GetPages(), page_status):
5090
5190
                        page.enabled = status
5091
 
                    
 
5191
 
5092
5192
                    main_idx = self._tabs.GetIdxFromWindow(close_wnd)
5093
5193
                    self.DeletePage(main_idx)
5094
5194
 
5096
5196
                        tabs.SetActivePage(previous_active)
5097
5197
                        page_count = tabs.GetPageCount()
5098
5198
                        selection = -1
5099
 
                        
 
5199
 
5100
5200
                        for page in xrange(page_count):
5101
5201
                            # remove the page from the source tabs
5102
5202
                            page_info = tabs.GetPage(page)
5103
5203
                            if page_info.active:
5104
5204
                                selection = page
5105
5205
                                break
5106
 
        
 
5206
 
5107
5207
                        tabs.DoShowHide()
5108
5208
                        self.DoSizing()
5109
5209
                        tabs.Refresh()
5110
 
                        
 
5210
 
5111
5211
                        if selection >= 0:
5112
5212
                            wx.CallAfter(tabs.MakeTabVisible, selection, self)
5113
 
                                                
 
5213
 
5114
5214
                    # Don't fire the event
5115
 
                    return                        
 
5215
                    return
5116
5216
 
5117
5217
                # ask owner if it's ok to close the tab
5118
5218
                e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, self.GetId())
5126
5226
 
5127
5227
                if repr(close_wnd.__class__).find("AuiMDIChildFrame") >= 0:
5128
5228
                    close_wnd.Close()
5129
 
                
 
5229
 
5130
5230
                else:
5131
5231
                    main_idx = self._tabs.GetIdxFromWindow(close_wnd)
5132
5232
                    self.DeletePage(main_idx)
5133
 
                
 
5233
 
5134
5234
                # notify owner that the tab has been closed
5135
5235
                e2 = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, self.GetId())
5136
5236
                e2.SetSelection(idx)
5141
5241
                    mgr = self.GetAuiManager()
5142
5242
                    win = mgr.GetManagedWindow()
5143
5243
                    win.SendSizeEvent()
5144
 
            
 
5244
 
5145
5245
 
5146
5246
    def OnTabMiddleDown(self, event):
5147
5247
        """
5148
5248
        Handles the ``EVT_AUINOTEBOOK_TAB_MIDDLE_DOWN`` event for L{AuiNotebook}.
5149
5249
 
5150
 
        :param `event`: a L{AuiNotebookEvent} event to be processed.        
 
5250
        :param `event`: a L{AuiNotebookEvent} event to be processed.
5151
5251
        """
5152
 
        
 
5252
 
5153
5253
        tabs = event.GetEventObject()
5154
5254
        if not tabs.GetEnabled(event.GetSelection()):
5155
5255
            return
5167
5267
        """
5168
5268
        Handles the ``EVT_AUINOTEBOOK_TAB_MIDDLE_UP`` event for L{AuiNotebook}.
5169
5269
 
5170
 
        :param `event`: a L{AuiNotebookEvent} event to be processed.        
 
5270
        :param `event`: a L{AuiNotebookEvent} event to be processed.
5171
5271
        """
5172
 
        
 
5272
 
5173
5273
        tabs = event.GetEventObject()
5174
5274
        if not tabs.GetEnabled(event.GetSelection()):
5175
5275
            return
5202
5302
        """
5203
5303
        Handles the ``EVT_AUINOTEBOOK_TAB_RIGHT_DOWN`` event for L{AuiNotebook}.
5204
5304
 
5205
 
        :param `event`: a L{AuiNotebookEvent} event to be processed.        
 
5305
        :param `event`: a L{AuiNotebookEvent} event to be processed.
5206
5306
        """
5207
 
        
 
5307
 
5208
5308
        tabs = event.GetEventObject()
5209
5309
        if not tabs.GetEnabled(event.GetSelection()):
5210
5310
            return
5222
5322
        """
5223
5323
        Handles the ``EVT_AUINOTEBOOK_TAB_RIGHT_UP`` event for L{AuiNotebook}.
5224
5324
 
5225
 
        :param `event`: a L{AuiNotebookEvent} event to be processed.        
 
5325
        :param `event`: a L{AuiNotebookEvent} event to be processed.
5226
5326
        """
5227
5327
 
5228
5328
        tabs = event.GetEventObject()
5278
5378
 
5279
5379
        :note: Overridden from `wx.PyPanel`.
5280
5380
        """
5281
 
    
 
5381
 
5282
5382
        wx.PyPanel.SetFont(self, font)
5283
5383
 
5284
5384
        selectedFont = wx.Font(font.GetPointSize(), font.GetFamily(),
5289
5389
        self.SetSelectedFont(selectedFont)
5290
5390
        self.SetMeasuringFont(selectedFont)
5291
5391
 
 
5392
        # Recalculate tab container size based on new font
 
5393
        self.UpdateTabCtrlHeight(force=False)
 
5394
        self.DoSizing()
 
5395
 
5292
5396
        return True
5293
5397
 
5294
5398
 
5297
5401
 
5298
5402
        return self._tab_ctrl_height
5299
5403
 
5300
 
    
 
5404
 
5301
5405
    def GetHeightForPageHeight(self, pageHeight):
5302
5406
        """
5303
5407
        Gets the height of the notebook for a given page height.
5328
5432
        focusWin = tabCtrl.FindFocus()
5329
5433
        activePage = tabCtrl.GetActivePage()
5330
5434
        lenPages = len(tabCtrl.GetPages())
5331
 
        
 
5435
 
5332
5436
        if lenPages == 1:
5333
5437
            return False
5334
 
        
 
5438
 
5335
5439
        if forward:
5336
5440
            if lenPages > 1:
5337
 
            
 
5441
 
5338
5442
                if activePage == -1 or activePage == lenPages - 1:
5339
5443
                    if not wrap:
5340
5444
                        return False
5341
5445
 
5342
5446
                    newPage = 0
5343
 
                    
 
5447
 
5344
5448
                elif activePage < lenPages - 1:
5345
5449
                    newPage = activePage + 1
5346
 
            
 
5450
 
5347
5451
        else:
5348
 
        
 
5452
 
5349
5453
            if lenPages > 1:
5350
5454
                if activePage == -1 or activePage == 0:
5351
5455
                    if not wrap:
5352
5456
                        return False
5353
5457
 
5354
5458
                    newPage = lenPages - 1
5355
 
                
 
5459
 
5356
5460
                elif activePage > 0:
5357
5461
                    newPage = activePage - 1
5358
5462
 
5359
 
        
 
5463
 
5360
5464
        if newPage != -1:
5361
5465
            if not self.GetEnabled(newPage):
5362
5466
                return False
5366
5470
            e.SetOldSelection(activePage)
5367
5471
            e.SetEventObject(tabCtrl)
5368
5472
            self.GetEventHandler().ProcessEvent(e)
5369
 
        
 
5473
 
5370
5474
##        if focusWin:
5371
5475
##            focusWin.SetFocus()
5372
5476
 
5378
5482
        Shows the window menu for the active tab control associated with this
5379
5483
        notebook, and returns ``True`` if a selection was made.
5380
5484
        """
5381
 
        
 
5485
 
5382
5486
        tabCtrl = self.GetActiveTabCtrl()
5383
5487
        idx = tabCtrl.GetArtProvider().ShowDropDown(tabCtrl, tabCtrl.GetPages(), tabCtrl.GetActivePage())
5384
5488
 
5393
5497
            self.GetEventHandler().ProcessEvent(e)
5394
5498
 
5395
5499
            return True
5396
 
        
 
5500
 
5397
5501
        else:
5398
 
            
 
5502
 
5399
5503
            return False
5400
5504
 
5401
5505
 
5412
5516
         ``AUI_BUTTON_WINDOWLIST``       Shows a window list button on the tab area
5413
5517
         ``AUI_BUTTON_LEFT``             Shows a left button on the tab area
5414
5518
         ``AUI_BUTTON_RIGHT``            Shows a right button on the tab area
5415
 
         ==============================  =================================        
 
5519
         ==============================  =================================
5416
5520
 
5417
5521
        :param `location`: the button location. Can be ``wx.LEFT`` or ``wx.RIGHT``;
5418
5522
        :param `normal_bitmap`: the bitmap for an enabled tab;
5429
5533
 
5430
5534
        :param `id`: the button identifier. See L{AddTabAreaButton} for a list of button identifiers.
5431
5535
 
5432
 
        :see: L{AddTabAreaButton}        
 
5536
        :see: L{AddTabAreaButton}
5433
5537
        """
5434
5538
 
5435
5539
        active_tabctrl = self.GetActiveTabCtrl()
5436
5540
        active_tabctrl.RemoveButton(id)
5437
 
        
5438
 
        
 
5541
 
 
5542
 
5439
5543
    def HasMultiplePages(self):
5440
5544
        """
5441
5545
        This method should be overridden to return ``True`` if this window has multiple pages. All
5461
5565
 
5462
5566
        :param `thumbnail_size`: the maximum size of every page thumbnail.
5463
5567
 
5464
 
        :note: this functionality is currently unavailable on wxMac.        
 
5568
        :note: this functionality is currently unavailable on wxMac.
5465
5569
        """
5466
5570
 
5467
5571
        if wx.Platform == "__WXMAC__":
5479
5583
 
5480
5584
            if not page.enabled:
5481
5585
                continue
5482
 
            
5483
 
            self.SetSelectionToPage(page)            
 
5586
 
 
5587
            self.SetSelectionToPage(page)
5484
5588
            pageText.append(page.caption)
5485
5589
 
5486
5590
            rect = page.window.GetScreenRect()
5490
5594
            if indx == 0:
5491
5595
                il = wx.ImageList(bmp.GetWidth(), bmp.GetHeight(), True)
5492
5596
 
5493
 
            il.Add(bmp)  
 
5597
            il.Add(bmp)
5494
5598
 
5495
5599
        # create the list control
5496
5600
        listCtrl = wx.ListCtrl(self, style=wx.LC_ICON|wx.LC_AUTOARRANGE|wx.LC_HRULES|wx.LC_VRULES,
5503
5607
        # create some items for the list
5504
5608
        for indx, text in enumerate(pageText):
5505
5609
            listCtrl.InsertImageStringItem(10000, text, indx)
5506
 
        
 
5610
 
5507
5611
        self.AddPage(listCtrl, "AuiNotebook Preview", True, bitmap=auinotebook_preview.GetBitmap(), disabled_bitmap=wx.NullBitmap)
5508
5612
        return True
5509
5613
 
5518
5622
 
5519
5623
        if page_idx >= self._tabs.GetPageCount():
5520
5624
            return False
5521
 
        
 
5625
 
5522
5626
        # update our own tab catalog
5523
5627
        page_info = self._tabs.GetPage(page_idx)
5524
5628
        page_info.renamable = renamable
5527
5631
        ctrl, ctrl_idx = self.FindTab(page_info.window)
5528
5632
        if not ctrl:
5529
5633
            return False
5530
 
        
 
5634
 
5531
5635
        info = ctrl.GetPage(ctrl_idx)
5532
5636
        info.renamable = page_info.renamable
5533
 
        
 
5637
 
5534
5638
        return True
5535
 
        
 
5639
 
5536
5640
 
5537
5641
    def IsRenamable(self, page_idx):
5538
5642
        """
5539
5643
        Returns whether a tab can be renamed or not.
5540
 
        
 
5644
 
5541
5645
        :param `page_idx`: the page index.
5542
5646
 
5543
 
        :returns: ``True`` is a page can be renamed, ``False`` otherwise.        
 
5647
        :returns: ``True`` is a page can be renamed, ``False`` otherwise.
5544
5648
        """
5545
5649
 
5546
5650
        if page_idx >= self._tabs.GetPageCount():
5566
5670
        evt.SetLabel("")
5567
5671
        evt.SetEditCanceled(True)
5568
5672
        self.GetEventHandler().ProcessEvent(evt)
5569
 
                
 
5673
 
5570
5674
 
5571
5675
    def OnRenameAccept(self, page_index, value):
5572
5676
        """
5573
5677
        Called by L{TabTextCtrl}, to accept the changes and to send the
5574
5678
        `EVT_AUINOTEBOOK_END_LABEL_EDIT` event.
 
5679
 
 
5680
        :param `page_index`: the page index in the notebook;
 
5681
        :param `value`: the new label for the tab.
5575
5682
        """
5576
5683
 
5577
5684
        evt = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_END_LABEL_EDIT, self.GetId())
5582
5689
 
5583
5690
        return not self.GetEventHandler().ProcessEvent(evt) or evt.IsAllowed()
5584
5691
 
5585
 
                
 
5692
 
5586
5693
    def ResetTextControl(self):
5587
5694
        """ Called by L{TabTextCtrl} when it marks itself for deletion. """
5588
5695
 
5589
5696
        if not self._textCtrl:
5590
5697
            return
5591
 
        
 
5698
 
5592
5699
        self._textCtrl.Destroy()
5593
5700
        self._textCtrl = None
5594
5701
 
5595
5702
        # tab height might have changed
5596
5703
        self.UpdateTabCtrlHeight(force=True)
5597
 
        
 
5704
 
5598
5705
 
5599
5706
    def EditTab(self, page_index):
5600
5707
        """
5601
5708
        Starts the editing of an item label, sending a `EVT_AUINOTEBOOK_BEGIN_LABEL_EDIT` event.
5602
5709
 
5603
 
        :param `page_index`: the page index we want to edit.        
 
5710
        :param `page_index`: the page index we want to edit.
5604
5711
        """
5605
5712
 
5606
5713
        if page_index >= self._tabs.GetPageCount():
5608
5715
 
5609
5716
        if not self.IsRenamable(page_index):
5610
5717
            return False
5611
 
        
5612
 
        page_info = self._tabs.GetPage(page_index)        
 
5718
 
 
5719
        page_info = self._tabs.GetPage(page_index)
5613
5720
        ctrl, ctrl_idx = self.FindTab(page_info.window)
5614
5721
        if not ctrl:
5615
5722
            return False
5620
5727
        if self.GetEventHandler().ProcessEvent(evt) and not evt.IsAllowed():
5621
5728
            # vetoed by user
5622
5729
            return False
5623
 
    
 
5730
 
5624
5731
        if self._textCtrl is not None and page_info != self._textCtrl.item():
5625
5732
            self._textCtrl.StopEditing()
5626
5733