1
# --------------------------------------------------------------------------- #
2
# AUI Library wxPython IMPLEMENTATION
4
# Original C++ Code From Kirix (wxAUI). You Can Find It At:
6
# License: wxWidgets license
8
# http:#www.kirix.com/en/community/opensource/wxaui/about_wxaui.html
10
# Current wxAUI Version Tracked: wxWidgets 2.9.4 SVN HEAD
15
# Andrea Gavana, @ 23 Dec 2005
16
# Latest Revision: 25 Apr 2012, 21.00 GMT
18
# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
21
# andrea.gavana@gmail.com
22
# andrea.gavana@maerskoil.com
24
# Or, Obviously, To The wxPython Mailing List!!!
27
# --------------------------------------------------------------------------- #
33
`framemanager.py` is the central module of the AUI class framework.
35
:class:`AuiManager` manages the panes associated with it for a particular :class:`Frame`, using
36
a pane's :class:`AuiPaneInfo` information to determine each pane's docking and floating
37
behavior. AuiManager uses wxPython' sizer mechanism to plan the layout of each frame.
38
It uses a replaceable dock art class to do all drawing, so all drawing is localized
39
in one area, and may be customized depending on an application's specific needs.
41
AuiManager works as follows: the programmer adds panes to the class, or makes
42
changes to existing pane properties (dock position, floating state, show state, etc...).
43
To apply these changes, AuiManager's :meth:`AuiManager.Update() <AuiManager.Update>` function is called. This batch
44
processing can be used to avoid flicker, by modifying more than one pane at a time,
45
and then "committing" all of the changes at once by calling `Update()`.
47
Panes can be added quite easily::
49
text1 = wx.TextCtrl(self, -1)
50
text2 = wx.TextCtrl(self, -1)
51
self._mgr.AddPane(text1, AuiPaneInfo().Left().Caption("Pane Number One"))
52
self._mgr.AddPane(text2, AuiPaneInfo().Bottom().Caption("Pane Number Two"))
57
Later on, the positions can be modified easily. The following will float an
58
existing pane in a tool window::
60
self._mgr.GetPane(text1).Float()
63
Layers, Rows and Directions, Positions
64
======================================
66
Inside AUI, the docking layout is figured out by checking several pane parameters.
67
Four of these are important for determining where a pane will end up.
69
**Direction** - Each docked pane has a direction, `Top`, `Bottom`, `Left`, `Right`, or `Center`.
70
This is fairly self-explanatory. The pane will be placed in the location specified
73
**Position** - More than one pane can be placed inside of a "dock". Imagine two panes
74
being docked on the left side of a window. One pane can be placed over another.
75
In proportionally managed docks, the pane position indicates it's sequential position,
76
starting with zero. So, in our scenario with two panes docked on the left side, the
77
top pane in the dock would have position 0, and the second one would occupy position 1.
79
**Row** - A row can allow for two docks to be placed next to each other. One of the most
80
common places for this to happen is in the toolbar. Multiple toolbar rows are allowed,
81
the first row being in row 0, and the second in row 1. Rows can also be used on
82
vertically docked panes.
84
**Layer** - A layer is akin to an onion. Layer 0 is the very center of the managed pane.
85
Thus, if a pane is in layer 0, it will be closest to the center window (also sometimes
86
known as the "content window"). Increasing layers "swallow up" all layers of a lower
87
value. This can look very similar to multiple rows, but is different because all panes
88
in a lower level yield to panes in higher levels. The best way to understand layers
89
is by running the AUI sample (`AUI.py`).
92
__author__ = "Andrea Gavana <andrea.gavana@gmail.com>"
93
__date__ = "31 March 2009"
107
from aui_utilities import Clip, PaneCreateStippleBitmap, GetDockingImage, GetSlidingPoints
109
from aui_constants import *
111
# Define this as a translation function
112
_ = wx.GetTranslation
115
if wx.Platform == "__WXMSW__":
122
# wxPython version string
123
_VERSION_STRING = wx.VERSION_STRING
126
wxEVT_AUI_PANE_BUTTON = wx.NewEventType()
127
wxEVT_AUI_PANE_CLOSE = wx.NewEventType()
128
wxEVT_AUI_PANE_MAXIMIZE = wx.NewEventType()
129
wxEVT_AUI_PANE_RESTORE = wx.NewEventType()
130
wxEVT_AUI_RENDER = wx.NewEventType()
131
wxEVT_AUI_FIND_MANAGER = wx.NewEventType()
132
wxEVT_AUI_PANE_MINIMIZE = wx.NewEventType()
133
wxEVT_AUI_PANE_MIN_RESTORE = wx.NewEventType()
134
wxEVT_AUI_PANE_FLOATING = wx.NewEventType()
135
wxEVT_AUI_PANE_FLOATED = wx.NewEventType()
136
wxEVT_AUI_PANE_DOCKING = wx.NewEventType()
137
wxEVT_AUI_PANE_DOCKED = wx.NewEventType()
138
wxEVT_AUI_PANE_ACTIVATED = wx.NewEventType()
139
wxEVT_AUI_PERSPECTIVE_CHANGED = wx.NewEventType()
141
EVT_AUI_PANE_BUTTON = wx.PyEventBinder(wxEVT_AUI_PANE_BUTTON, 0)
142
""" Fires an event when the user left-clicks on a pane button. """
143
EVT_AUI_PANE_CLOSE = wx.PyEventBinder(wxEVT_AUI_PANE_CLOSE, 0)
144
""" A pane in `AuiManager` has been closed. """
145
EVT_AUI_PANE_MAXIMIZE = wx.PyEventBinder(wxEVT_AUI_PANE_MAXIMIZE, 0)
146
""" A pane in `AuiManager` has been maximized. """
147
EVT_AUI_PANE_RESTORE = wx.PyEventBinder(wxEVT_AUI_PANE_RESTORE, 0)
148
""" A pane in `AuiManager` has been restored from a maximized state. """
149
EVT_AUI_RENDER = wx.PyEventBinder(wxEVT_AUI_RENDER, 0)
150
""" Fires an event every time the AUI frame is being repainted. """
151
EVT_AUI_FIND_MANAGER = wx.PyEventBinder(wxEVT_AUI_FIND_MANAGER, 0)
152
""" Used to find which AUI manager is controlling a certain pane. """
153
EVT_AUI_PANE_MINIMIZE = wx.PyEventBinder(wxEVT_AUI_PANE_MINIMIZE, 0)
154
""" A pane in `AuiManager` has been minimized. """
155
EVT_AUI_PANE_MIN_RESTORE = wx.PyEventBinder(wxEVT_AUI_PANE_MIN_RESTORE, 0)
156
""" A pane in `AuiManager` has been restored from a minimized state. """
157
EVT_AUI_PANE_FLOATING = wx.PyEventBinder(wxEVT_AUI_PANE_FLOATING, 0)
158
""" A pane in `AuiManager` is about to be floated. """
159
EVT_AUI_PANE_FLOATED = wx.PyEventBinder(wxEVT_AUI_PANE_FLOATED, 0)
160
""" A pane in `AuiManager` has been floated. """
161
EVT_AUI_PANE_DOCKING = wx.PyEventBinder(wxEVT_AUI_PANE_DOCKING, 0)
162
""" A pane in `AuiManager` is about to be docked. """
163
EVT_AUI_PANE_DOCKED = wx.PyEventBinder(wxEVT_AUI_PANE_DOCKED, 0)
164
""" A pane in `AuiManager` has been docked. """
165
EVT_AUI_PANE_ACTIVATED = wx.PyEventBinder(wxEVT_AUI_PANE_ACTIVATED, 0)
166
""" A pane in `AuiManager` has been activated. """
167
EVT_AUI_PERSPECTIVE_CHANGED = wx.PyEventBinder(wxEVT_AUI_PERSPECTIVE_CHANGED, 0)
168
""" The layout in `AuiManager` has been changed. """
170
# ---------------------------------------------------------------------------- #
172
class AuiDockInfo(object):
173
""" A class to store all properties of a dock. """
177
Default class constructor.
178
Used internally, do not call it in your code!
181
object.__init__(self)
183
self.dock_direction = 0
188
self.resizable = True
191
self.rect = wx.Rect()
197
Returns whether a dock is valid or not.
199
In order to be valid, a dock needs to have a non-zero `dock_direction`.
202
return self.dock_direction != 0
205
def IsHorizontal(self):
206
""" Returns whether the dock is horizontal or not. """
208
return self.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]
211
def IsVertical(self):
212
""" Returns whether the dock is vertical or not. """
214
return self.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT, AUI_DOCK_CENTER]
217
# ---------------------------------------------------------------------------- #
219
class AuiDockingGuideInfo(object):
220
""" A class which holds information about VS2005 docking guide windows. """
222
def __init__(self, other=None):
224
Default class constructor.
225
Used internally, do not call it in your code!
227
:param `other`: another instance of :class:`AuiDockingGuideInfo`.
233
# window representing the docking target
235
# dock direction (top, bottom, left, right, center)
236
self.dock_direction = AUI_DOCK_NONE
239
def Assign(self, other):
241
Assigns the properties of the `other` :class:`AuiDockingGuideInfo` to `self`.
243
:param `other`: another instance of :class:`AuiDockingGuideInfo`.
246
self.host = other.host
247
self.dock_direction = other.dock_direction
252
Hosts a docking guide window.
254
:param `h`: an instance of :class:`AuiDockingGuideWindow` or :class:`AuiDockingHintWindow`.
262
""" Sets the guide window to left docking. """
264
self.dock_direction = AUI_DOCK_LEFT
269
""" Sets the guide window to right docking. """
271
self.dock_direction = AUI_DOCK_RIGHT
276
""" Sets the guide window to top docking. """
278
self.dock_direction = AUI_DOCK_TOP
283
""" Sets the guide window to bottom docking. """
285
self.dock_direction = AUI_DOCK_BOTTOM
290
""" Sets the guide window to center docking. """
292
self.dock_direction = AUI_DOCK_CENTER
297
""" Sets the guide window to centre docking. """
299
self.dock_direction = AUI_DOCK_CENTRE
303
# ---------------------------------------------------------------------------- #
305
class AuiDockUIPart(object):
306
""" A class which holds attributes for a UI part in the interface. """
320
Default class constructor.
321
Used internally, do not call it in your code!
324
self.orientation = wx.VERTICAL
326
self.rect = wx.Rect()
329
# ---------------------------------------------------------------------------- #
331
class AuiPaneButton(object):
332
""" A simple class which describes the caption pane button attributes. """
334
def __init__(self, button_id):
336
Default class constructor.
337
Used internally, do not call it in your code!
339
:param integer `button_id`: the pane button identifier.
342
self.button_id = button_id
345
# ---------------------------------------------------------------------------- #
347
# event declarations/classes
349
class AuiManagerEvent(wx.PyCommandEvent):
350
""" A specialized command event class for events sent by :class:`AuiManager`. """
352
def __init__(self, eventType, id=1):
354
Default class constructor.
356
:param integer `eventType`: the event kind;
357
:param integer `id`: the event identification number.
360
wx.PyCommandEvent.__init__(self, eventType, id)
365
self.veto_flag = False
366
self.canveto_flag = True
370
def SetManager(self, mgr):
372
Associates a :class:`AuiManager` to the current event.
374
:param `mgr`: an instance of :class:`AuiManager`.
380
def SetDC(self, pdc):
382
Associates a :class:`DC` device context to this event.
384
:param `pdc`: a :class:`DC` device context object.
390
def SetPane(self, p):
392
Associates a :class:`AuiPaneInfo` instance to this event.
394
:param `p`: a :class:`AuiPaneInfo` instance.
400
def SetButton(self, b):
402
Associates a :class:`AuiPaneButton` instance to this event.
404
:param `b`: a :class:`AuiPaneButton` instance.
410
def GetManager(self):
411
""" Returns the associated :class:`AuiManager` (if any). """
417
""" Returns the associated :class:`DC` device context (if any). """
423
""" Returns the associated :class:`AuiPaneInfo` structure (if any). """
429
""" Returns the associated :class:`AuiPaneButton` instance (if any). """
434
def Veto(self, veto=True):
436
Prevents the change announced by this event from happening.
438
It is in general a good idea to notify the user about the reasons for
439
vetoing the change because otherwise the applications behaviour (which
440
just refuses to do what the user wants) might be quite surprising.
442
:param bool `veto`: ``True`` to veto the event, ``False`` otherwise.
445
self.veto_flag = veto
449
""" Returns whether the event has been vetoed or not. """
451
return self.veto_flag
454
def SetCanVeto(self, can_veto):
456
Sets whether the event can be vetoed or not.
458
:param bool `can_veto`: ``True`` if the event can be vetoed, ``False`` otherwise.
461
self.canveto_flag = can_veto
465
""" Returns whether the event can be vetoed and has been vetoed. """
467
return self.canveto_flag and self.veto_flag
470
# ---------------------------------------------------------------------------- #
472
class AuiPaneInfo(object):
474
AuiPaneInfo specifies all the parameters for a pane. These parameters specify where
475
the pane is on the screen, whether it is docked or floating, or hidden. In addition,
476
these parameters specify the pane's docked position, floating position, preferred
477
size, minimum size, caption text among many other parameters.
480
optionFloating = 2**0
482
optionLeftDockable = 2**2
483
optionRightDockable = 2**3
484
optionTopDockable = 2**4
485
optionBottomDockable = 2**5
486
optionFloatable = 2**6
488
optionResizable = 2**8
489
optionPaneBorder = 2**9
490
optionCaption = 2**10
491
optionGripper = 2**11
492
optionDestroyOnClose = 2**12
493
optionToolbar = 2**13
495
optionGripperTop = 2**15
496
optionMaximized = 2**16
497
optionDockFixed = 2**17
498
optionNotebookDockable = 2**18
499
optionMinimized = 2**19
500
optionLeftSnapped = 2**20
501
optionRightSnapped = 2**21
502
optionTopSnapped = 2**22
503
optionBottomSnapped = 2**23
505
optionCaptionLeft = 2**25
508
buttonMaximize = 2**27
509
buttonMinimize = 2**28
512
buttonCustom1 = 2**30
513
buttonCustom2 = 2**31
514
buttonCustom3 = 2**32
516
savedHiddenState = 2**33 # used internally
517
actionPane = 2**34 # used internally
518
wasMaximized = 2**35 # used internally
519
needsRestore = 2**36 # used internally
523
""" Default class constructor. """
528
self.dock_direction = AUI_DOCK_LEFT
532
self.minimize_mode = AUI_MINIMIZE_POS_SMART
533
self.floating_pos = wx.Point(-1, -1)
534
self.floating_size = wx.Size(-1, -1)
535
self.best_size = wx.Size(-1, -1)
536
self.min_size = wx.Size(-1, -1)
537
self.max_size = wx.Size(-1, -1)
538
self.dock_proportion = 0
542
self.icon = wx.NullIcon
543
self.rect = wx.Rect()
544
self.notebook_id = -1
545
self.transparent = 255
546
self.needsTransparency = False
547
self.previousDockPos = None
548
self.previousDockSize = 0
550
self.minimize_target = None
555
def dock_direction_get(self):
557
Getter for the `dock_direction`.
559
:see: :meth:`~AuiPaneInfo.dock_direction_set` for a set of valid docking directions.
562
if self.IsMaximized():
563
return AUI_DOCK_CENTER
565
return self._dock_direction
568
def dock_direction_set(self, value):
570
Setter for the `dock_direction`.
572
:param integer `value`: the docking direction. This can be one of the following bits:
574
============================ ======= =============================================
575
Dock Flag Value Description
576
============================ ======= =============================================
577
``AUI_DOCK_NONE`` 0 No docking direction.
578
``AUI_DOCK_TOP`` 1 Top docking direction.
579
``AUI_DOCK_RIGHT`` 2 Right docking direction.
580
``AUI_DOCK_BOTTOM`` 3 Bottom docking direction.
581
``AUI_DOCK_LEFT`` 4 Left docking direction.
582
``AUI_DOCK_CENTER`` 5 Center docking direction.
583
``AUI_DOCK_CENTRE`` 5 Centre docking direction.
584
``AUI_DOCK_NOTEBOOK_PAGE`` 6 Automatic AuiNotebooks docking style.
585
============================ ======= =============================================
589
self._dock_direction = value
591
dock_direction = property(dock_direction_get, dock_direction_set)
595
Returns ``True`` if the :class:`AuiPaneInfo` structure is valid.
597
:note: A pane structure is valid if it has an associated window.
600
return self.window != None
603
def IsMaximized(self):
604
""" Returns ``True`` if the pane is maximized. """
606
return self.HasFlag(self.optionMaximized)
609
def IsMinimized(self):
610
""" Returns ``True`` if the pane is minimized. """
612
return self.HasFlag(self.optionMinimized)
616
""" Returns ``True`` if the pane cannot be resized. """
618
return not self.HasFlag(self.optionResizable)
621
def IsResizeable(self):
622
""" Returns ``True`` if the pane can be resized. """
624
return self.HasFlag(self.optionResizable)
628
""" Returns ``True`` if the pane is currently shown. """
630
return not self.HasFlag(self.optionHidden)
633
def IsFloating(self):
634
""" Returns ``True`` if the pane is floating. """
636
return self.HasFlag(self.optionFloating)
640
""" Returns ``True`` if the pane is docked. """
642
return not self.HasFlag(self.optionFloating)
646
""" Returns ``True`` if the pane contains a toolbar. """
648
return self.HasFlag(self.optionToolbar)
651
def IsTopDockable(self):
653
Returns ``True`` if the pane can be docked at the top
654
of the managed frame.
657
return self.HasFlag(self.optionTopDockable)
660
def IsBottomDockable(self):
662
Returns ``True`` if the pane can be docked at the bottom
663
of the managed frame.
666
return self.HasFlag(self.optionBottomDockable)
669
def IsLeftDockable(self):
671
Returns ``True`` if the pane can be docked at the left
672
of the managed frame.
675
return self.HasFlag(self.optionLeftDockable)
678
def IsRightDockable(self):
680
Returns ``True`` if the pane can be docked at the right
681
of the managed frame.
684
return self.HasFlag(self.optionRightDockable)
687
def IsDockable(self):
688
""" Returns ``True`` if the pane can be docked. """
690
return self.IsTopDockable() or self.IsBottomDockable() or self.IsLeftDockable() or \
691
self.IsRightDockable() or self.IsNotebookDockable()
694
def IsFloatable(self):
696
Returns ``True`` if the pane can be undocked and displayed as a
700
return self.HasFlag(self.optionFloatable)
705
Returns ``True`` if the docked frame can be undocked or moved to
706
another dock position.
709
return self.HasFlag(self.optionMovable)
712
def IsDestroyOnClose(self):
714
Returns ``True`` if the pane should be destroyed when it is closed.
716
Normally a pane is simply hidden when the close button is clicked. Calling :meth:`~AuiPaneInfo.DestroyOnClose`
717
with a ``True`` input parameter will cause the window to be destroyed when the user clicks
718
the pane's close button.
721
return self.HasFlag(self.optionDestroyOnClose)
724
def IsNotebookDockable(self):
726
Returns ``True`` if a pane can be docked on top to another to create a
727
:class:`~lib.agw.aui.auibook.AuiNotebook`.
730
return self.HasFlag(self.optionNotebookDockable)
733
def IsTopSnappable(self):
734
""" Returns ``True`` if the pane can be snapped at the top of the managed frame. """
736
return self.HasFlag(self.optionTopSnapped)
739
def IsBottomSnappable(self):
740
""" Returns ``True`` if the pane can be snapped at the bottom of the managed frame. """
742
return self.HasFlag(self.optionBottomSnapped)
745
def IsLeftSnappable(self):
746
""" Returns ``True`` if the pane can be snapped on the left of the managed frame. """
748
return self.HasFlag(self.optionLeftSnapped)
751
def IsRightSnappable(self):
752
""" Returns ``True`` if the pane can be snapped on the right of the managed frame. """
754
return self.HasFlag(self.optionRightSnapped)
757
def IsSnappable(self):
758
""" Returns ``True`` if the pane can be snapped. """
760
return self.IsTopSnappable() or self.IsBottomSnappable() or self.IsLeftSnappable() or \
761
self.IsRightSnappable()
765
""" Returns ``True`` if the floating pane has a "fly-out" effect. """
767
return self.HasFlag(self.optionFlyOut)
770
def HasCaption(self):
771
""" Returns ``True`` if the pane displays a caption. """
773
return self.HasFlag(self.optionCaption)
776
def HasCaptionLeft(self):
777
""" Returns ``True`` if the pane displays a caption on the left (rotated by 90 degrees). """
779
return self.HasFlag(self.optionCaptionLeft)
782
def HasGripper(self):
783
""" Returns ``True`` if the pane displays a gripper. """
785
return self.HasFlag(self.optionGripper)
789
""" Returns ``True`` if the pane displays a border. """
791
return self.HasFlag(self.optionPaneBorder)
794
def HasCloseButton(self):
795
""" Returns ``True`` if the pane displays a button to close the pane. """
797
return self.HasFlag(self.buttonClose)
800
def HasMaximizeButton(self):
801
""" Returns ``True`` if the pane displays a button to maximize the pane. """
803
return self.HasFlag(self.buttonMaximize)
806
def HasMinimizeButton(self):
807
""" Returns ``True`` if the pane displays a button to minimize the pane. """
809
return self.HasFlag(self.buttonMinimize)
812
def GetMinimizeMode(self):
814
Returns the minimization style for this pane.
816
Possible return values are:
818
============================== ========= ==============================
819
Minimize Mode Flag Hex Value Description
820
============================== ========= ==============================
821
``AUI_MINIMIZE_POS_SMART`` 0x01 Minimizes the pane on the closest tool bar
822
``AUI_MINIMIZE_POS_TOP`` 0x02 Minimizes the pane on the top tool bar
823
``AUI_MINIMIZE_POS_LEFT`` 0x03 Minimizes the pane on its left tool bar
824
``AUI_MINIMIZE_POS_RIGHT`` 0x04 Minimizes the pane on its right tool bar
825
``AUI_MINIMIZE_POS_BOTTOM`` 0x05 Minimizes the pane on its bottom tool bar
826
``AUI_MINIMIZE_POS_TOOLBAR`` 0x06 Minimizes the pane on a target :class:`~lib.agw.aui.auibar.AuiToolBar`
827
``AUI_MINIMIZE_POS_MASK`` 0x17 Mask to filter the position flags
828
``AUI_MINIMIZE_CAPT_HIDE`` 0x0 Hides the caption of the minimized pane
829
``AUI_MINIMIZE_CAPT_SMART`` 0x08 Displays the caption in the best rotation (horizontal or clockwise)
830
``AUI_MINIMIZE_CAPT_HORZ`` 0x10 Displays the caption horizontally
831
``AUI_MINIMIZE_CAPT_MASK`` 0x18 Mask to filter the caption flags
832
============================== ========= ==============================
834
The flags can be filtered with the following masks:
836
============================== ========= ==============================
837
Minimize Mask Flag Hex Value Description
838
============================== ========= ==============================
839
``AUI_MINIMIZE_POS_MASK`` 0x17 Filters the position flags
840
``AUI_MINIMIZE_CAPT_MASK`` 0x18 Filters the caption flags
841
============================== ========= ==============================
845
return self.minimize_mode
848
def HasPinButton(self):
849
""" Returns ``True`` if the pane displays a button to float the pane. """
851
return self.HasFlag(self.buttonPin)
854
def HasGripperTop(self):
855
""" Returns ``True`` if the pane displays a gripper at the top. """
857
return self.HasFlag(self.optionGripperTop)
862
Associate a :class:`Window` derived window to this pane.
864
This normally does not need to be specified, as the window pointer is
865
automatically assigned to the :class:`AuiPaneInfo` structure as soon as it is
866
added to the manager.
868
:param `w`: a :class:`Window` derived window.
875
def Name(self, name):
877
Sets the name of the pane so it can be referenced in lookup functions.
879
If a name is not specified by the user, a random name is assigned to the pane
880
when it is added to the manager.
882
:param `name`: a string specifying the pane name.
886
If you are using :meth:`AuiManager.SavePerspective` and :meth:`AuiManager.LoadPerspective`,
887
you will have to specify a name for your pane using :meth:`~AuiPaneInfo.Name`, as perspectives
888
containing randomly generated names can not be properly restored.
895
def Caption(self, caption):
897
Sets the caption of the pane.
899
:param string `caption`: a string specifying the pane caption.
902
self.caption = caption
908
Sets the pane dock position to the left side of the frame.
910
:note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_LEFT`` as
914
self.dock_direction = AUI_DOCK_LEFT
920
Sets the pane dock position to the right side of the frame.
922
:note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_RIGHT`` as
926
self.dock_direction = AUI_DOCK_RIGHT
932
Sets the pane dock position to the top of the frame.
934
:note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_TOP`` as
938
self.dock_direction = AUI_DOCK_TOP
944
Sets the pane dock position to the bottom of the frame.
946
:note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_BOTTOM`` as
950
self.dock_direction = AUI_DOCK_BOTTOM
956
Sets the pane to the center position of the frame.
958
The centre pane is the space in the middle after all border panes (left, top,
959
right, bottom) are subtracted from the layout.
961
:note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_CENTER`` as
965
self.dock_direction = AUI_DOCK_CENTER
971
Sets the pane to the center position of the frame.
973
The centre pane is the space in the middle after all border panes (left, top,
974
right, bottom) are subtracted from the layout.
976
:note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_CENTRE`` as
980
self.dock_direction = AUI_DOCK_CENTRE
984
def Direction(self, direction):
986
Determines the direction of the docked pane. It is functionally the
987
same as calling :meth:`Left`, :meth:`Right`, :meth:`Top` or :meth:`Bottom`,
988
except that docking direction may be specified programmatically via the parameter `direction`.
990
:param integer `direction`: the direction of the docked pane.
992
:see: :meth:`dock_direction_set` for a list of valid docking directions.
995
self.dock_direction = direction
999
def Layer(self, layer):
1001
Determines the layer of the docked pane.
1003
The dock layer is similar to an onion, the inner-most layer being layer 0. Each
1004
shell moving in the outward direction has a higher layer number. This allows for
1005
more complex docking layout formation.
1007
:param integer `layer`: the layer of the docked pane.
1010
self.dock_layer = layer
1016
Determines the row of the docked pane.
1018
:param integer `row`: the row of the docked pane.
1025
def Position(self, pos):
1027
Determines the position of the docked pane.
1029
:param integer `pos`: the position of the docked pane.
1036
def MinSize(self, arg1=None, arg2=None):
1038
Sets the minimum size of the pane.
1040
This method is split in 2 versions depending on the input type. If `arg1` is
1041
a :class:`Size` object, then :meth:`~AuiPaneInfo.MinSize1` is called. Otherwise, :meth:`~AuiPaneInfo.MinSize2` is called.
1043
:param `arg1`: a :class:`Size` object, a (x, y) tuple or or a `x` coordinate.
1044
:param `arg2`: a `y` coordinate (only if `arg1` is a `x` coordinate, otherwise unused).
1047
if isinstance(arg1, wx.Size):
1048
ret = self.MinSize1(arg1)
1049
elif isinstance(arg1, types.TupleType):
1050
ret = self.MinSize1(wx.Size(*arg1))
1051
elif isinstance(arg1, types.IntType) and arg2 is not None:
1052
ret = self.MinSize2(arg1, arg2)
1054
raise Exception("Invalid argument passed to `MinSize`: arg1=%s, arg2=%s"%(repr(arg1), repr(arg2)))
1059
def MinSize1(self, size):
1061
Sets the minimum size of the pane.
1063
:see: :meth:`MinSize` for an explanation of input parameters.
1065
self.min_size = size
1069
def MinSize2(self, x, y):
1071
Sets the minimum size of the pane.
1073
:see: :meth:`MinSize` for an explanation of input parameters.
1076
self.min_size = wx.Size(x, y)
1080
def MaxSize(self, arg1=None, arg2=None):
1082
Sets the maximum size of the pane.
1084
This method is split in 2 versions depending on the input type. If `arg1` is
1085
a :class:`Size` object, then :meth:`~AuiPaneInfo.MaxSize1` is called. Otherwise, :meth:`~AuiPaneInfo.MaxSize2` is called.
1087
:param `arg1`: a :class:`Size` object, a (x, y) tuple or a `x` coordinate.
1088
:param `arg2`: a `y` coordinate (only if `arg1` is a `x` coordinate, otherwise unused).
1091
if isinstance(arg1, wx.Size):
1092
ret = self.MaxSize1(arg1)
1093
elif isinstance(arg1, types.TupleType):
1094
ret = self.MaxSize1(wx.Size(*arg1))
1095
elif isinstance(arg1, types.IntType) and arg2 is not None:
1096
ret = self.MaxSize2(arg1, arg2)
1098
raise Exception("Invalid argument passed to `MaxSize`: arg1=%s, arg2=%s"%(repr(arg1), repr(arg2)))
1103
def MaxSize1(self, size):
1105
Sets the maximum size of the pane.
1107
:see: :meth:`MaxSize` for an explanation of input parameters.
1110
self.max_size = size
1114
def MaxSize2(self, x, y):
1116
Sets the maximum size of the pane.
1118
:see: :meth:`MaxSize` for an explanation of input parameters.
1121
self.max_size.Set(x,y)
1125
def BestSize(self, arg1=None, arg2=None):
1127
Sets the ideal size for the pane. The docking manager will attempt to use
1128
this size as much as possible when docking or floating the pane.
1130
This method is split in 2 versions depending on the input type. If `arg1` is
1131
a :class:`Size` object, then :meth:`BestSize1` is called. Otherwise, :meth:`BestSize2` is called.
1133
:param `arg1`: a :class:`Size` object, a (x, y) tuple or a `x` coordinate.
1134
:param `arg2`: a `y` coordinate (only if `arg1` is a `x` coordinate, otherwise unused).
1137
if isinstance(arg1, wx.Size):
1138
ret = self.BestSize1(arg1)
1139
elif isinstance(arg1, types.TupleType):
1140
ret = self.BestSize1(wx.Size(*arg1))
1141
elif isinstance(arg1, types.IntType) and arg2 is not None:
1142
ret = self.BestSize2(arg1, arg2)
1144
raise Exception("Invalid argument passed to `BestSize`: arg1=%s, arg2=%s"%(repr(arg1), repr(arg2)))
1149
def BestSize1(self, size):
1151
Sets the best size of the pane.
1153
:see: :meth:`BestSize` for an explanation of input parameters.
1156
self.best_size = size
1160
def BestSize2(self, x, y):
1162
Sets the best size of the pane.
1164
:see: :meth:`BestSize` for an explanation of input parameters.
1167
self.best_size.Set(x,y)
1171
def FloatingPosition(self, pos):
1173
Sets the position of the floating pane.
1175
:param `pos`: a :class:`Point` or a tuple indicating the pane floating position.
1178
self.floating_pos = wx.Point(*pos)
1182
def FloatingSize(self, size):
1184
Sets the size of the floating pane.
1186
:param `size`: a :class:`Size` or a tuple indicating the pane floating size.
1189
self.floating_size = wx.Size(*size)
1194
""" Makes the pane take up the full area."""
1196
return self.SetFlag(self.optionMaximized, True)
1201
Makes the pane minimized in a :class:`~lib.agw.aui.auibar.AuiToolBar`.
1203
Clicking on the minimize button causes a new :class:`~lib.agw.aui.auibar.AuiToolBar` to be created
1204
and added to the frame manager, (currently the implementation is such that
1205
panes at West will have a toolbar at the right, panes at South will have
1206
toolbars at the bottom etc...) and the pane is hidden in the manager.
1208
Clicking on the restore button on the newly created toolbar will result in the
1209
toolbar being removed and the original pane being restored.
1212
return self.SetFlag(self.optionMinimized, True)
1215
def MinimizeMode(self, mode):
1217
Sets the expected minimized mode if the minimize button is visible.
1219
:param integer `mode`: the minimized pane can have a specific position in the work space:
1221
============================== ========= ==============================
1222
Minimize Mode Flag Hex Value Description
1223
============================== ========= ==============================
1224
``AUI_MINIMIZE_POS_SMART`` 0x01 Minimizes the pane on the closest tool bar
1225
``AUI_MINIMIZE_POS_TOP`` 0x02 Minimizes the pane on the top tool bar
1226
``AUI_MINIMIZE_POS_LEFT`` 0x03 Minimizes the pane on its left tool bar
1227
``AUI_MINIMIZE_POS_RIGHT`` 0x04 Minimizes the pane on its right tool bar
1228
``AUI_MINIMIZE_POS_BOTTOM`` 0x05 Minimizes the pane on its bottom tool bar
1229
``AUI_MINIMIZE_POS_TOOLBAR`` 0x06 Minimizes the pane on a target :class:`~lib.agw.aui.auibar.AuiToolBar`
1230
============================== ========= ==============================
1232
The caption of the minimized pane can be displayed in different modes:
1234
============================== ========= ==============================
1235
Caption Mode Flag Hex Value Description
1236
============================== ========= ==============================
1237
``AUI_MINIMIZE_CAPT_HIDE`` 0x0 Hides the caption of the minimized pane
1238
``AUI_MINIMIZE_CAPT_SMART`` 0x08 Displays the caption in the best rotation (horizontal in the top and in
1239
the bottom tool bar or clockwise in the right and in the left tool bar)
1240
``AUI_MINIMIZE_CAPT_HORZ`` 0x10 Displays the caption horizontally
1241
============================== ========= ==============================
1245
In order to use the ``AUI_MINIMIZE_POS_TOOLBAR`` flag, the instance of :class:`AuiManager`
1246
you pass as an input for :meth:`MinimizeTarget` **must** have a real name and not the randomly
1247
generated one. Remember to set the :meth:`Name` property of the toolbar pane before calling this method.
1251
self.minimize_mode = mode
1255
def MinimizeTarget(self, toolbarPane):
1257
Minimizes the panes using a :class:`AuiPaneInfo` as a target. As :class:`AuiPaneInfo` properties
1258
need to be copied back and forth every time the perspective has changed, we
1259
only store the toobar **name**.
1261
:param `toolbarPane`: an instance of :class:`AuiPaneInfo`, containing a :class:`~lib.agw.aui.auibar.AuiToolBar`.
1265
In order to use this functionality (and with the ``AUI_MINIMIZE_POS_TOOLBAR``
1266
flag set), the instance of :class:`AuiPaneInfo` you pass as an input **must** have a real
1267
name and not the randomly generated one. Remember to set the :meth:`Name` property of
1268
the toolbar pane before calling this method.
1272
self.minimize_target = toolbarPane.name
1277
""" Is the reverse of :meth:`Maximize` and :meth:`Minimize`."""
1279
return self.SetFlag(self.optionMaximized or self.optionMinimized, False)
1284
Forces a pane to be fixed size so that it cannot be resized.
1285
After calling :meth:`Fixed`, :meth:`IsFixed` will return ``True``.
1288
return self.SetFlag(self.optionResizable, False)
1291
def Resizable(self, resizable=True):
1293
Allows a pane to be resizable if `resizable` is ``True``, and forces
1294
it to be a fixed size if `resizeable` is ``False``.
1296
If `resizable` is ``False``, this is simply an antonym for :meth:`Fixed`.
1298
:param bool `resizable`: whether the pane will be resizeable or not.
1301
return self.SetFlag(self.optionResizable, resizable)
1304
def Transparent(self, alpha):
1306
Makes the pane transparent when floating.
1308
:param integer `alpha`: a value between 0 and 255 for pane transparency.
1311
if alpha < 0 or alpha > 255:
1312
raise Exception("Invalid transparency value (%s)"%repr(alpha))
1314
self.transparent = alpha
1315
self.needsTransparency = True
1319
""" Indicates that a pane should be docked. It is the opposite of :meth:`Float`. """
1321
if self.IsNotebookPage():
1322
self.notebook_id = -1
1323
self.dock_direction = AUI_DOCK_NONE
1325
return self.SetFlag(self.optionFloating, False)
1329
""" Indicates that a pane should be floated. It is the opposite of :meth:`Dock`. """
1331
if self.IsNotebookPage():
1332
self.notebook_id = -1
1333
self.dock_direction = AUI_DOCK_NONE
1335
return self.SetFlag(self.optionFloating, True)
1340
Indicates that a pane should be hidden.
1342
Calling :meth:`Show(False) <Show>` achieve the same effect.
1345
return self.SetFlag(self.optionHidden, True)
1348
def Show(self, show=True):
1350
Indicates that a pane should be shown.
1352
:param bool `show`: whether the pane should be shown or not.
1355
return self.SetFlag(self.optionHidden, not show)
1358
# By defaulting to 1000, the tab will get placed at the end
1359
def NotebookPage(self, id, tab_position=1000):
1361
Forces a pane to be a notebook page, so that the pane can be
1362
docked on top to another to create a :class:`~lib.agw.aui.auibook.AuiNotebook`.
1364
:param integer `id`: the notebook id;
1365
:param integer `tab_position`: the tab number of the pane once docked in a notebook.
1368
# Remove any floating frame
1370
self.notebook_id = id
1371
self.dock_pos = tab_position
1374
self.dock_direction = AUI_DOCK_NOTEBOOK_PAGE
1379
def NotebookControl(self, id):
1381
Forces a pane to be a notebook control (:class:`~lib.agw.aui.auibook.AuiNotebook`).
1383
:param integer `id`: the notebook id.
1386
self.notebook_id = id
1390
if self.dock_direction == AUI_DOCK_NOTEBOOK_PAGE:
1391
self.dock_direction = AUI_DOCK_NONE
1396
def HasNotebook(self):
1397
""" Returns whether a pane has a :class:`~lib.agw.aui.auibook.AuiNotebook` or not. """
1399
return self.notebook_id >= 0
1402
def IsNotebookPage(self):
1403
""" Returns whether the pane is a notebook page in a :class:`~lib.agw.aui.auibook.AuiNotebook`. """
1405
return self.notebook_id >= 0 and self.dock_direction == AUI_DOCK_NOTEBOOK_PAGE
1408
def IsNotebookControl(self):
1409
""" Returns whether the pane is a notebook control (:class:`~lib.agw.aui.auibook.AuiNotebook`). """
1411
return not self.IsNotebookPage() and self.HasNotebook()
1414
def SetNameFromNotebookId(self):
1415
""" Sets the pane name once docked in a :class:`~lib.agw.aui.auibook.AuiNotebook` using the notebook id. """
1417
if self.notebook_id >= 0:
1418
self.name = "__notebook_%d"%self.notebook_id
1423
def CaptionVisible(self, visible=True, left=False):
1425
Indicates that a pane caption should be visible. If `visible` is ``False``, no pane
1428
:param bool `visible`: whether the caption should be visible or not;
1429
:param bool `left`: whether the caption should be drawn on the left (rotated by 90 degrees) or not.
1433
self.SetFlag(self.optionCaption, False)
1434
return self.SetFlag(self.optionCaptionLeft, visible)
1436
self.SetFlag(self.optionCaptionLeft, False)
1437
return self.SetFlag(self.optionCaption, visible)
1440
def PaneBorder(self, visible=True):
1442
Indicates that a border should be drawn for the pane.
1444
:param bool `visible`: whether the pane border should be visible or not.
1447
return self.SetFlag(self.optionPaneBorder, visible)
1450
def Gripper(self, visible=True):
1452
Indicates that a gripper should be drawn for the pane.
1454
:param bool `visible`: whether the gripper should be visible or not.
1457
return self.SetFlag(self.optionGripper, visible)
1460
def GripperTop(self, attop=True):
1462
Indicates that a gripper should be drawn at the top of the pane.
1464
:param bool `attop`: whether the gripper should be drawn at the top or not.
1467
return self.SetFlag(self.optionGripperTop, attop)
1470
def CloseButton(self, visible=True):
1472
Indicates that a close button should be drawn for the pane.
1474
:param bool `visible`: whether the close button should be visible or not.
1477
return self.SetFlag(self.buttonClose, visible)
1480
def MaximizeButton(self, visible=True):
1482
Indicates that a maximize button should be drawn for the pane.
1484
:param bool `visible`: whether the maximize button should be visible or not.
1487
return self.SetFlag(self.buttonMaximize, visible)
1490
def MinimizeButton(self, visible=True):
1492
Indicates that a minimize button should be drawn for the pane.
1494
:param bool `visible`: whether the minimize button should be visible or not.
1497
return self.SetFlag(self.buttonMinimize, visible)
1500
def PinButton(self, visible=True):
1502
Indicates that a pin button should be drawn for the pane.
1504
:param bool `visible`: whether the pin button should be visible or not.
1507
return self.SetFlag(self.buttonPin, visible)
1510
def DestroyOnClose(self, b=True):
1512
Indicates whether a pane should be destroyed when it is closed.
1514
Normally a pane is simply hidden when the close button is clicked. Setting
1515
`b` to ``True`` will cause the window to be destroyed when the user clicks
1516
the pane's close button.
1518
:param bool `b`: whether the pane should be destroyed when it is closed or not.
1521
return self.SetFlag(self.optionDestroyOnClose, b)
1524
def TopDockable(self, b=True):
1526
Indicates whether a pane can be docked at the top of the frame.
1528
:param bool `b`: whether the pane can be docked at the top or not.
1531
return self.SetFlag(self.optionTopDockable, b)
1534
def BottomDockable(self, b=True):
1536
Indicates whether a pane can be docked at the bottom of the frame.
1538
:param bool `b`: whether the pane can be docked at the bottom or not.
1541
return self.SetFlag(self.optionBottomDockable, b)
1544
def LeftDockable(self, b=True):
1546
Indicates whether a pane can be docked on the left of the frame.
1548
:param bool `b`: whether the pane can be docked at the left or not.
1551
return self.SetFlag(self.optionLeftDockable, b)
1554
def RightDockable(self, b=True):
1556
Indicates whether a pane can be docked on the right of the frame.
1558
:param bool `b`: whether the pane can be docked at the right or not.
1561
return self.SetFlag(self.optionRightDockable, b)
1564
def Floatable(self, b=True):
1566
Sets whether the user will be able to undock a pane and turn it
1567
into a floating window.
1569
:param bool `b`: whether the pane can be floated or not.
1572
return self.SetFlag(self.optionFloatable, b)
1575
def Movable(self, b=True):
1577
Indicates whether a pane can be moved.
1579
:param bool `b`: whether the pane can be moved or not.
1582
return self.SetFlag(self.optionMovable, b)
1585
def NotebookDockable(self, b=True):
1587
Indicates whether a pane can be docked in an automatic :class:`~lib.agw.aui.auibook.AuiNotebook`.
1589
:param bool `b`: whether the pane can be docked in a notebook or not.
1592
return self.SetFlag(self.optionNotebookDockable, b)
1595
def DockFixed(self, b=True):
1597
Causes the containing dock to have no resize sash. This is useful
1598
for creating panes that span the entire width or height of a dock, but should
1599
not be resizable in the other direction.
1601
:param bool `b`: whether the pane will have a resize sash or not.
1604
return self.SetFlag(self.optionDockFixed, b)
1607
def Dockable(self, b=True):
1609
Specifies whether a frame can be docked or not. It is the same as specifying
1610
:meth:`TopDockable` . :meth:`BottomDockable` . :meth:`LeftDockable` . :meth:`RightDockable` .
1612
:param bool `b`: whether the frame can be docked or not.
1615
return self.TopDockable(b).BottomDockable(b).LeftDockable(b).RightDockable(b)
1618
def TopSnappable(self, b=True):
1620
Indicates whether a pane can be snapped at the top of the main frame.
1622
:param bool `b`: whether the pane can be snapped at the top of the main frame or not.
1625
return self.SetFlag(self.optionTopSnapped, b)
1628
def BottomSnappable(self, b=True):
1630
Indicates whether a pane can be snapped at the bottom of the main frame.
1632
:param bool `b`: whether the pane can be snapped at the bottom of the main frame or not.
1635
return self.SetFlag(self.optionBottomSnapped, b)
1638
def LeftSnappable(self, b=True):
1640
Indicates whether a pane can be snapped on the left of the main frame.
1642
:param bool `b`: whether the pane can be snapped at the left of the main frame or not.
1645
return self.SetFlag(self.optionLeftSnapped, b)
1648
def RightSnappable(self, b=True):
1650
Indicates whether a pane can be snapped on the right of the main frame.
1652
:param bool `b`: whether the pane can be snapped at the right of the main frame or not.
1655
return self.SetFlag(self.optionRightSnapped, b)
1658
def Snappable(self, b=True):
1660
Indicates whether a pane can be snapped on the main frame. This is
1661
equivalent as calling :meth:`TopSnappable` . :meth:`BottomSnappable` . :meth:`LeftSnappable` . :meth:`RightSnappable` .
1663
:param bool `b`: whether the pane can be snapped on the main frame or not.
1666
return self.TopSnappable(b).BottomSnappable(b).LeftSnappable(b).RightSnappable(b)
1669
def FlyOut(self, b=True):
1671
Indicates whether a pane, when floating, has a "fly-out" effect
1672
(i.e., floating panes which only show themselves when moused over).
1674
:param bool `b`: whether the pane can be snapped on the main frame or not.
1677
return self.SetFlag(self.optionFlyOut, b)
1680
# Copy over the members that pertain to docking position
1681
def SetDockPos(self, source):
1683
Copies the `source` pane members that pertain to docking position to `self`.
1685
:param AuiPaneInfo `source`: the source pane from where to copy the attributes.
1688
self.dock_direction = source.dock_direction
1689
self.dock_layer = source.dock_layer
1690
self.dock_row = source.dock_row
1691
self.dock_pos = source.dock_pos
1692
self.dock_proportion = source.dock_proportion
1693
self.floating_pos = wx.Point(*source.floating_pos)
1694
self.floating_size = wx.Size(*source.floating_size)
1695
self.rect = wx.Rect(*source.rect)
1700
def DefaultPane(self):
1701
""" Specifies that the pane should adopt the default pane settings. """
1704
state |= self.optionTopDockable | self.optionBottomDockable | \
1705
self.optionLeftDockable | self.optionRightDockable | \
1706
self.optionNotebookDockable | \
1707
self.optionFloatable | self.optionMovable | self.optionResizable | \
1708
self.optionCaption | self.optionPaneBorder | self.buttonClose
1714
def CentrePane(self):
1716
Specifies that the pane should adopt the default center pane settings.
1718
Centre panes usually do not have caption bars. This function provides an easy way of
1719
preparing a pane to be displayed in the center dock position.
1722
return self.CenterPane()
1725
def CenterPane(self):
1727
Specifies that the pane should adopt the default center pane settings.
1729
Centre panes usually do not have caption bars. This function provides an easy way of
1730
preparing a pane to be displayed in the center dock position.
1734
return self.Center().PaneBorder().Resizable()
1737
def ToolbarPane(self):
1738
""" Specifies that the pane should adopt the default toolbar pane settings. """
1743
state |= (self.optionToolbar | self.optionGripper)
1744
state &= ~(self.optionResizable | self.optionCaption | self.optionCaptionLeft)
1746
if self.dock_layer == 0:
1747
self.dock_layer = 10
1754
def Icon(self, icon):
1756
Specifies whether an icon is drawn on the left of the caption text when
1757
the pane is docked. If `icon` is ``None`` or :class:`NullIcon`, no icon is drawn on
1760
:param icon: an icon to draw on the caption space, or ``None``.
1761
:type `icon`: :class:`Icon` or ``None``
1771
def SetFlag(self, flag, option_state):
1773
Turns the property given by `flag` on or off with the `option_state`
1776
:param integer `flag`: the property to set;
1777
:param bool `option_state`: either ``True`` or ``False``.
1789
if flag in [self.buttonClose, self.buttonMaximize, self.buttonMinimize, self.buttonPin]:
1795
def HasFlag(self, flag):
1797
Returns ``True`` if the the property specified by flag is active for the pane.
1799
:param integer `flag`: the property to check for activity.
1802
return (self.state & flag and [True] or [False])[0]
1805
def ResetButtons(self):
1807
Resets all the buttons and recreates them from scratch depending on the
1808
:class:`AuiManager` flags.
1811
floating = self.HasFlag(self.optionFloating)
1814
if not floating and self.HasMinimizeButton():
1815
button = AuiPaneButton(AUI_BUTTON_MINIMIZE)
1816
self.buttons.append(button)
1818
if not floating and self.HasMaximizeButton():
1819
button = AuiPaneButton(AUI_BUTTON_MAXIMIZE_RESTORE)
1820
self.buttons.append(button)
1822
if not floating and self.HasPinButton():
1823
button = AuiPaneButton(AUI_BUTTON_PIN)
1824
self.buttons.append(button)
1826
if self.HasCloseButton():
1827
button = AuiPaneButton(AUI_BUTTON_CLOSE)
1828
self.buttons.append(button)
1831
def CountButtons(self):
1832
""" Returns the number of visible buttons in the docked pane. """
1836
if self.HasCaption() or self.HasCaptionLeft():
1837
if isinstance(wx.GetTopLevelParent(self.window), AuiFloatingFrame):
1840
if self.HasCloseButton():
1842
if self.HasMaximizeButton():
1844
if self.HasMinimizeButton():
1846
if self.HasPinButton():
1852
def IsHorizontal(self):
1853
""" Returns ``True`` if the pane `dock_direction` is horizontal. """
1855
return self.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]
1857
def IsVertical(self):
1858
""" Returns ``True`` if the pane `dock_direction` is vertical. """
1860
return self.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT]
1863
# Null AuiPaneInfo reference
1864
NonePaneInfo = AuiPaneInfo()
1865
""" Null :class:`AuiPaneInfo` reference, an invalid instance of :class:`AuiPaneInfo`. """
1868
# ---------------------------------------------------------------------------- #
1870
class AuiDockingGuide(wx.Frame):
1871
""" Base class for :class:`AuiSingleDockingGuide` and :class:`AuiCenterDockingGuide`."""
1873
def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition,
1874
size=wx.DefaultSize, style=wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP |
1875
wx.FRAME_NO_TASKBAR | wx.NO_BORDER, name="AuiDockingGuide"):
1877
Default class constructor. Used internally, do not call it in your code!
1879
:param `parent`: the :class:`AuiManager` parent;
1880
:param integer `id`: the window identifier. It may take a value of -1 to indicate a default value.
1881
:param string `title`: the caption to be displayed on the frame's title bar.
1882
:param Point `pos`: the window position. A value of (-1, -1) indicates a default position,
1883
chosen by either the windowing system or wxPython, depending on platform.
1884
:param Size `size`: the window size. A value of (-1, -1) indicates a default size, chosen by
1885
either the windowing system or wxPython, depending on platform.
1886
:param integer `style`: the window style.
1887
:param string `name`: the name of the window. This parameter is used to associate a name with the
1888
item, allowing the application user to set Motif resource values for individual windows.
1891
wx.Frame.__init__(self, parent, id, title, pos, size, style, name=name)
1894
def HitTest(self, x, y):
1896
To be overridden by parent classes.
1898
:param integer `x`: the `x` mouse position;
1899
:param integer `y`: the `y` mouse position.
1905
def ValidateNotebookDocking(self, valid):
1907
To be overridden by parent classes.
1909
:param bool `valid`: whether a pane can be docked on top to another to form an automatic
1910
:class:`~lib.agw.aui.auibook.AuiNotebook`.
1915
# ============================================================================
1917
# ============================================================================
1919
# ---------------------------------------------------------------------------
1920
# AuiDockingGuideWindow
1921
# ---------------------------------------------------------------------------
1923
class AuiDockingGuideWindow(wx.Window):
1924
""" Target class for :class:`AuiDockingGuide` and :class:`AuiCenterDockingGuide`. """
1926
def __init__(self, parent, rect, direction=0, center=False, useAero=False):
1928
Default class constructor. Used internally, do not call it in your code!
1930
:param `parent`: the :class:`AuiManager` parent;
1931
:param Rect `rect`: the window rect;
1932
:param integer `direction`: one of ``wx.TOP``, ``wx.BOTTOM``, ``wx.LEFT``, ``wx.RIGHT``,
1934
:param bool `center`: whether the calling class is a :class:`AuiCenterDockingGuide`;
1935
:param bool `useAero`: whether to use the new Aero-style bitmaps or Whidbey-style bitmaps
1936
for the docking guide.
1939
wx.Window.__init__(self, parent, -1, rect.GetPosition(), rect.GetSize(), wx.NO_BORDER)
1941
self._direction = direction
1942
self._center = center
1944
self._useAero = useAero
1946
self._bmp_unfocus, self._bmp_focus = GetDockingImage(direction, useAero, center)
1948
self._currentImage = self._bmp_unfocus
1949
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
1951
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
1952
self.Bind(wx.EVT_PAINT, self.OnPaint)
1955
def SetValid(self, valid):
1957
Sets the docking direction as valid or invalid.
1959
:param bool `valid`: whether the docking direction is allowed or not.
1966
""" Returns whether the docking direction is valid. """
1971
def OnEraseBackground(self, event):
1973
Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`AuiDockingGuideWindow`.
1975
:param `event`: a :class:`EraseEvent` to be processed.
1977
:note: This is intentionally empty to reduce flickering while drawing.
1983
def DrawBackground(self, dc):
1985
Draws the docking guide background.
1987
:param `dc`: a :class:`DC` device context object.
1990
rect = self.GetClientRect()
1992
dc.SetPen(wx.TRANSPARENT_PEN)
1993
dc.SetBrush(wx.Brush(colourTargetBackground))
1994
dc.DrawRectangleRect(rect)
1996
dc.SetPen(wx.Pen(colourTargetBorder))
1998
left = rect.GetLeft()
2000
right = rect.GetRight()
2001
bottom = rect.GetBottom()
2003
if self._direction != wx.CENTER:
2005
if not self._center or self._direction != wx.BOTTOM:
2006
dc.DrawLine(left, top, right+1, top)
2007
if not self._center or self._direction != wx.RIGHT:
2008
dc.DrawLine(left, top, left, bottom+1)
2009
if not self._center or self._direction != wx.LEFT:
2010
dc.DrawLine(right, top, right, bottom+1)
2011
if not self._center or self._direction != wx.TOP:
2012
dc.DrawLine(left, bottom, right+1, bottom)
2014
dc.SetPen(wx.Pen(colourTargetShade))
2016
if self._direction != wx.RIGHT:
2017
dc.DrawLine(left + 1, top + 1, left + 1, bottom)
2018
if self._direction != wx.BOTTOM:
2019
dc.DrawLine(left + 1, top + 1, right, top + 1)
2022
def DrawDottedLine(self, dc, point, length, vertical):
2024
Draws a dotted line (not used if the docking guide images are ok).
2026
:param `dc`: a :class:`DC` device context object;
2027
:param `point`: a :class:`Point` where to start drawing the dotted line;
2028
:param integer `length`: the length of the dotted line;
2029
:param bool `vertical`: whether it is a vertical docking guide window or not.
2032
for i in xrange(0, length, 2):
2033
dc.DrawPoint(point.x, point.y)
2040
def DrawIcon(self, dc):
2042
Draws the docking guide icon (not used if the docking guide images are ok).
2044
:param `dc`: a :class:`DC` device context object.
2047
rect = wx.Rect(*self.GetClientRect())
2052
dc.SetPen(wx.Pen(colourIconBorder))
2053
dc.SetBrush(wx.Brush(colourIconBackground))
2054
dc.DrawRectangleRect(rect)
2056
right1 = rect.GetRight() + 1
2057
bottom1 = rect.GetBottom() + 1
2059
dc.SetPen(wx.Pen(colourIconShadow))
2060
dc.DrawLine(rect.x + 1, bottom1, right1 + 1, bottom1)
2061
dc.DrawLine(right1, rect.y + 1, right1, bottom1 + 1)
2065
if self._direction == wx.TOP:
2066
rect.height -= rect.height / 2
2067
point = rect.GetBottomLeft()
2070
elif self._direction == wx.LEFT:
2071
rect.width -= rect.width / 2
2072
point = rect.GetTopRight()
2073
length = rect.height
2075
elif self._direction == wx.RIGHT:
2076
rect.x += rect.width / 2
2077
rect.width -= rect.width / 2
2078
point = rect.GetTopLeft()
2079
length = rect.height
2081
elif self._direction == wx.BOTTOM:
2082
rect.y += rect.height / 2
2083
rect.height -= rect.height / 2
2084
point = rect.GetTopLeft()
2087
elif self._direction == wx.CENTER:
2089
point = rect.GetTopLeft()
2092
dc.GradientFillLinear(rect, colourIconDockingPart1,
2093
colourIconDockingPart2, self._direction)
2095
dc.SetPen(wx.Pen(colourIconBorder))
2097
if self._direction == wx.CENTER:
2098
self.DrawDottedLine(dc, rect.GetTopLeft(), rect.width, False)
2099
self.DrawDottedLine(dc, rect.GetTopLeft(), rect.height, True)
2100
self.DrawDottedLine(dc, rect.GetBottomLeft(), rect.width, False)
2101
self.DrawDottedLine(dc, rect.GetTopRight(), rect.height, True)
2103
elif self._direction in [wx.TOP, wx.BOTTOM]:
2104
self.DrawDottedLine(dc, point, length, False)
2107
self.DrawDottedLine(dc, point, length, True)
2110
def DrawArrow(self, dc):
2112
Draws the docking guide arrow icon (not used if the docking guide images are ok).
2114
:param `dc`: a :class:`DC` device context object.
2117
rect = self.GetClientRect()
2120
point.x = (rect.GetLeft() + rect.GetRight()) / 2
2121
point.y = (rect.GetTop() + rect.GetBottom()) / 2
2122
rx, ry = wx.Size(), wx.Size()
2124
if self._direction == wx.TOP:
2128
elif self._direction == wx.LEFT:
2132
elif self._direction == wx.RIGHT:
2136
elif self._direction == wx.BOTTOM:
2143
dc.SetPen(wx.Pen(colourIconArrow))
2146
pt1 = wx.Point(point.x - rx.x*i, point.y - rx.y*i)
2147
pt2 = wx.Point(point.x + rx.x*(i+1), point.y + rx.y*(i+1))
2148
dc.DrawLinePoint(pt1, pt2)
2153
def OnPaint(self, event):
2155
Handles the ``wx.EVT_PAINT`` event for :class:`AuiDockingGuideWindow`.
2157
:param `event`: a :class:`PaintEvent` to be processed.
2160
dc = wx.AutoBufferedPaintDC(self)
2161
if self._currentImage.IsOk() and self._valid:
2162
dc.DrawBitmap(self._currentImage, 0, 0, True)
2169
Draws the whole docking guide window (not used if the docking guide images are ok).
2171
:param `dc`: a :class:`DC` device context object.
2174
self.DrawBackground(dc)
2181
def UpdateDockGuide(self, pos):
2183
Updates the docking guide images depending on the mouse position, using focused
2184
images if the mouse is inside the docking guide or unfocused images if it is
2187
:param `pos`: a :class:`Point` mouse position.
2190
inside = self.GetScreenRect().Contains(pos)
2193
image = self._bmp_focus
2195
image = self._bmp_unfocus
2197
if image != self._currentImage:
2198
self._currentImage = image
2203
# ---------------------------------------------------------------------------
2204
# AuiSingleDockingGuide
2205
# ---------------------------------------------------------------------------
2207
class AuiSingleDockingGuide(AuiDockingGuide):
2208
""" A docking guide window for single docking hint (not diamond-shaped HUD). """
2210
def __init__(self, parent, direction=0):
2212
Default class constructor. Used internally, do not call it in your code!
2214
:param `parent`: the :class:`AuiManager` parent;
2215
:param integer `direction`: one of ``wx.TOP``, ``wx.BOTTOM``, ``wx.LEFT``, ``wx.RIGHT``.
2218
self._direction = direction
2220
style = wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP | \
2221
wx.FRAME_NO_TASKBAR | wx.NO_BORDER
2223
# Use of FRAME_SHAPED on wxMac causes the frame to be visible
2224
# breaking the docking hints.
2225
if wx.Platform != '__WXMAC__':
2226
style |= wx.FRAME_SHAPED
2228
AuiDockingGuide.__init__(self, parent, style=style, name="auiSingleDockTarget")
2232
useAero = GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_AERO_DOCKING_GUIDES
2233
useWhidbey = GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_WHIDBEY_DOCKING_GUIDES
2235
self._useAero = useAero or useWhidbey
2239
sizeX, sizeY = aeroguideSizeX, aeroguideSizeY
2241
sizeX, sizeY = whidbeySizeX, whidbeySizeY
2243
sizeX, sizeY = guideSizeX, guideSizeY
2245
if direction not in [wx.TOP, wx.BOTTOM]:
2246
sizeX, sizeY = sizeY, sizeX
2249
self.CreateShapesWithStyle(useWhidbey)
2251
if wx.Platform == "__WXGTK__":
2252
self.Bind(wx.EVT_WINDOW_CREATE, self.SetGuideShape)
2254
self.SetGuideShape()
2256
self.SetSize(self.region.GetBox().GetSize())
2258
self.SetSize((sizeX, sizeY))
2260
self.rect = wx.Rect(0, 0, sizeX, sizeY)
2263
useAero = (useWhidbey and [2] or [1])[0]
2267
self.target = AuiDockingGuideWindow(self, self.rect, direction, False, useAero)
2270
def CreateShapesWithStyle(self, useWhidbey):
2272
Creates the docking guide window shape based on which docking bitmaps are used.
2274
:param bool `useWhidbey`: if ``True``, use Whidbey-style bitmaps; if ``False``, use the
2278
sizeX, sizeY = aeroguideSizeX, aeroguideSizeY
2280
sizeX, sizeY = whidbeySizeX, whidbeySizeY
2282
if self._direction not in [wx.TOP, wx.BOTTOM]:
2283
sizeX, sizeY = sizeY, sizeX
2285
useAero = (useWhidbey and [2] or [1])[0]
2286
bmp, dummy = GetDockingImage(self._direction, useAero, False)
2287
region = wx.RegionFromBitmap(bmp)
2289
self.region = region
2292
def AeroMove(self, pos):
2294
Moves the docking window to the new position. Overridden in children classes.
2296
:param Point `pos`: the new docking guide position.
2302
def SetGuideShape(self, event=None):
2304
Sets the correct shape for the docking guide window.
2306
:param `event`: on wxGTK, a :class:`WindowCreateEvent` event to process.
2309
self.SetShape(self.region)
2311
if event is not None:
2312
# Skip the event on wxGTK
2314
wx.CallAfter(wx.SafeYield, self, True)
2317
def SetShape(self, region):
2319
If the platform supports it, sets the shape of the window to that depicted by `region`.
2320
The system will not display or respond to any mouse event for the pixels that lie
2321
outside of the region. To reset the window to the normal rectangular shape simply call
2322
:meth:`SetShape` again with an empty region.
2324
:param Region `region`: the shape of the frame.
2326
:note: Overridden for wxMAC.
2329
if wx.Platform == '__WXMAC__':
2330
# HACK so we don't crash when SetShape is called
2333
super(AuiSingleDockingGuide, self).SetShape(region)
2336
def SetValid(self, valid):
2338
Sets the docking direction as valid or invalid.
2340
:param bool `valid`: whether the docking direction is allowed or not.
2347
""" Returns whether the docking direction is valid. """
2352
def UpdateDockGuide(self, pos):
2354
Updates the docking guide images depending on the mouse position, using focused
2355
images if the mouse is inside the docking guide or unfocused images if it is
2358
:param Point `pos`: the mouse position.
2361
self.target.UpdateDockGuide(pos)
2364
def HitTest(self, x, y):
2366
Checks if the mouse position is inside the target window rect.
2368
:param integer `x`: the `x` mouse position;
2369
:param integer `y`: the `y` mouse position.
2372
if self.target.GetScreenRect().Contains((x, y)):
2378
# ---------------------------------------------------------------------------
2379
# AuiCenterDockingGuide
2380
# ---------------------------------------------------------------------------
2382
class AuiCenterDockingGuide(AuiDockingGuide):
2383
""" A docking guide window for multiple docking hint (diamond-shaped HUD). """
2385
def __init__(self, parent):
2387
Default class constructor.
2388
Used internally, do not call it in your code!
2390
:param `parent`: the :class:`AuiManager` parent.
2393
AuiDockingGuide.__init__(self, parent, style=wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP |
2394
wx.FRAME_NO_TASKBAR | wx.NO_BORDER | wx.FRAME_SHAPED,
2395
name="auiCenterDockTarget")
2399
self.CreateShapesWithStyle()
2400
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
2402
if wx.Platform == "__WXGTK__":
2403
self.Bind(wx.EVT_WINDOW_CREATE, self.SetGuideShape)
2405
self.SetGuideShape()
2407
self.SetSize(self.region.GetBox().GetSize())
2409
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
2410
self.Bind(wx.EVT_PAINT, self.OnPaint)
2413
def CreateShapesWithStyle(self):
2414
""" Creates the docking guide window shape based on which docking bitmaps are used. """
2416
useAero = (GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_AERO_DOCKING_GUIDES) != 0
2417
useWhidbey = (GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_WHIDBEY_DOCKING_GUIDES) != 0
2426
sizeX, sizeY = aeroguideSizeX, aeroguideSizeY
2428
sizeX, sizeY = whidbeySizeX, whidbeySizeY
2430
sizeX, sizeY = guideSizeX, guideSizeY
2432
rectLeft = wx.Rect(0, sizeY, sizeY, sizeX)
2433
rectTop = wx.Rect(sizeY, 0, sizeX, sizeY)
2434
rectRight = wx.Rect(sizeY+sizeX, sizeY, sizeY, sizeX)
2435
rectBottom = wx.Rect(sizeY, sizeX + sizeY, sizeX, sizeY)
2436
rectCenter = wx.Rect(sizeY, sizeY, sizeX, sizeX)
2438
if not self._useAero:
2440
self.targetLeft = AuiDockingGuideWindow(self, rectLeft, wx.LEFT, True, useAero)
2441
self.targetTop = AuiDockingGuideWindow(self, rectTop, wx.TOP, True, useAero)
2442
self.targetRight = AuiDockingGuideWindow(self, rectRight, wx.RIGHT, True, useAero)
2443
self.targetBottom = AuiDockingGuideWindow(self, rectBottom, wx.BOTTOM, True, useAero)
2444
self.targetCenter = AuiDockingGuideWindow(self, rectCenter, wx.CENTER, True, useAero)
2448
tld = [wx.Point(rectTop.x, rectTop.y+rectTop.height-8),
2449
wx.Point(rectLeft.x+rectLeft.width-8, rectLeft.y),
2450
rectTop.GetBottomLeft()]
2451
# bottom-left diamond
2452
bld = [wx.Point(rectLeft.x+rectLeft.width-8, rectLeft.y+rectLeft.height),
2453
wx.Point(rectBottom.x, rectBottom.y+8),
2454
rectBottom.GetTopLeft()]
2456
trd = [wx.Point(rectTop.x+rectTop.width, rectTop.y+rectTop.height-8),
2457
wx.Point(rectRight.x+8, rectRight.y),
2458
rectRight.GetTopLeft()]
2459
# bottom-right diamond
2460
brd = [wx.Point(rectRight.x+8, rectRight.y+rectRight.height),
2461
wx.Point(rectBottom.x+rectBottom.width, rectBottom.y+8),
2462
rectBottom.GetTopRight()]
2464
self._triangles = [tld[0:2], bld[0:2],
2465
[wx.Point(rectTop.x+rectTop.width-1, rectTop.y+rectTop.height-8),
2466
wx.Point(rectRight.x+7, rectRight.y)],
2467
[wx.Point(rectRight.x+7, rectRight.y+rectRight.height),
2468
wx.Point(rectBottom.x+rectBottom.width-1, rectBottom.y+8)]]
2470
region = wx.Region()
2471
region.UnionRect(rectLeft)
2472
region.UnionRect(rectTop)
2473
region.UnionRect(rectRight)
2474
region.UnionRect(rectBottom)
2475
region.UnionRect(rectCenter)
2476
region.UnionRegion(wx.RegionFromPoints(tld))
2477
region.UnionRegion(wx.RegionFromPoints(bld))
2478
region.UnionRegion(wx.RegionFromPoints(trd))
2479
region.UnionRegion(wx.RegionFromPoints(brd))
2483
self._aeroBmp = aero_dock_pane.GetBitmap()
2484
region = wx.RegionFromBitmap(self._aeroBmp)
2486
self._allAeroBmps = [aero_dock_pane_left.GetBitmap(), aero_dock_pane_top.GetBitmap(),
2487
aero_dock_pane_right.GetBitmap(), aero_dock_pane_bottom.GetBitmap(),
2488
aero_dock_pane_center.GetBitmap(), aero_dock_pane.GetBitmap()]
2489
self._deniedBitmap = aero_denied.GetBitmap()
2490
self._aeroRects = [rectLeft, rectTop, rectRight, rectBottom, rectCenter]
2495
self._aeroBmp = whidbey_dock_pane.GetBitmap()
2496
region = wx.RegionFromBitmap(self._aeroBmp)
2498
self._allAeroBmps = [whidbey_dock_pane_left.GetBitmap(), whidbey_dock_pane_top.GetBitmap(),
2499
whidbey_dock_pane_right.GetBitmap(), whidbey_dock_pane_bottom.GetBitmap(),
2500
whidbey_dock_pane_center.GetBitmap(), whidbey_dock_pane.GetBitmap()]
2501
self._deniedBitmap = whidbey_denied.GetBitmap()
2502
self._aeroRects = [rectLeft, rectTop, rectRight, rectBottom, rectCenter]
2506
self.region = region
2509
def SetGuideShape(self, event=None):
2511
Sets the correct shape for the docking guide window.
2513
:param `event`: on wxGTK, a :class:`WindowCreateEvent` event to process.
2516
self.SetShape(self.region)
2518
if event is not None:
2519
# Skip the event on wxGTK
2521
wx.CallAfter(wx.SafeYield, self, True)
2524
def UpdateDockGuide(self, pos):
2526
Updates the docking guides images depending on the mouse position, using focused
2527
images if the mouse is inside the docking guide or unfocused images if it is
2530
:param Point `pos`: the mouse position.
2533
if not self._useAero:
2534
for target in self.GetChildren():
2535
target.UpdateDockGuide(pos)
2537
lenRects = len(self._aeroRects)
2538
for indx, rect in enumerate(self._aeroRects):
2539
if rect.Contains(pos):
2540
if self._allAeroBmps[indx] != self._aeroBmp:
2541
if indx < lenRects - 1 or (indx == lenRects - 1 and self._valid):
2542
self._aeroBmp = self._allAeroBmps[indx]
2545
self._aeroBmp = self._allAeroBmps[-1]
2550
if self._aeroBmp != self._allAeroBmps[-1]:
2551
self._aeroBmp = self._allAeroBmps[-1]
2555
def HitTest(self, x, y):
2557
Checks if the mouse position is inside the target windows rect.
2559
:param integer `x`: the `x` mouse position;
2560
:param integer `y`: the `y` mouse position.
2563
if not self._useAero:
2564
if self.targetLeft.GetScreenRect().Contains((x, y)):
2566
if self.targetTop.GetScreenRect().Contains((x, y)):
2568
if self.targetRight.GetScreenRect().Contains((x, y)):
2570
if self.targetBottom.GetScreenRect().Contains((x, y)):
2572
if self.targetCenter.IsValid() and self.targetCenter.GetScreenRect().Contains((x, y)):
2575
constants = [wx.LEFT, wx.UP, wx.RIGHT, wx.DOWN, wx.CENTER]
2576
lenRects = len(self._aeroRects)
2577
for indx, rect in enumerate(self._aeroRects):
2578
if rect.Contains((x, y)):
2579
if indx < lenRects or (indx == lenRects-1 and self._valid):
2580
return constants[indx]
2585
def ValidateNotebookDocking(self, valid):
2587
Sets whether a pane can be docked on top of another to create an automatic
2588
:class:`~lib.agw.aui.auibook.AuiNotebook`.
2590
:param bool `valid`: whether a pane can be docked on top to another to form an automatic
2591
:class:`~lib.agw.aui.auibook.AuiNotebook`.
2594
if not self._useAero:
2595
if self.targetCenter.IsValid() != valid:
2596
self.targetCenter.SetValid(valid)
2597
self.targetCenter.Refresh()
2599
if self._valid != valid:
2604
def AeroMove(self, pos):
2606
Moves the docking guide window to the new position.
2608
:param Point `pos`: the new docking guide position.
2611
if not self._useAero:
2614
useWhidbey = (GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_WHIDBEY_DOCKING_GUIDES) != 0
2617
sizeX, sizeY = whidbeySizeX, whidbeySizeY
2619
sizeX, sizeY = aeroguideSizeX, aeroguideSizeY
2621
size = self.GetSize()
2623
leftRect, topRect, rightRect, bottomRect, centerRect = self._aeroRects
2624
thePos = pos + wx.Point((size.x-sizeY)/2, (size.y-sizeX)/2)
2626
centerRect.SetPosition(thePos)
2628
leftRect.SetPosition(thePos + wx.Point(-sizeY, 0))
2629
topRect.SetPosition(thePos + wx.Point(0, -sizeY))
2630
rightRect.SetPosition(thePos + wx.Point(sizeX, 0))
2631
bottomRect.SetPosition(thePos + wx.Point(0, sizeX))
2634
def OnEraseBackground(self, event):
2636
Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`AuiCenterDockingGuide`.
2638
:param `event`: :class:`EraseEvent` to be processed.
2640
:note: This is intentionally empty to reduce flickering while drawing.
2646
def OnPaint(self, event):
2648
Handles the ``wx.EVT_PAINT`` event for :class:`AuiCenterDockingGuide`.
2650
:param `event`: a :class:`PaintEvent` to be processed.
2653
dc = wx.AutoBufferedPaintDC(self)
2656
dc.SetBrush(wx.TRANSPARENT_BRUSH)
2657
dc.SetPen(wx.TRANSPARENT_PEN)
2659
dc.SetBrush(wx.Brush(colourTargetBackground))
2660
dc.SetPen(wx.Pen(colourTargetBorder))
2662
rect = self.GetClientRect()
2663
dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
2666
dc.DrawBitmap(self._aeroBmp, 0, 0, True)
2668
diff = (self._useAero == 2 and [1] or [0])[0]
2669
bmpX, bmpY = self._deniedBitmap.GetWidth(), self._deniedBitmap.GetHeight()
2670
xPos, yPos = (rect.x + (rect.width)/2 - bmpX/2), (rect.y + (rect.height)/2 - bmpY/2)
2671
dc.DrawBitmap(self._deniedBitmap, xPos+1, yPos+diff, True)
2675
dc.SetPen(wx.Pen(colourTargetBorder, 2))
2676
for pts in self._triangles:
2677
dc.DrawLinePoint(pts[0], pts[1])
2680
# ----------------------------------------------------------------------------
2681
# AuiDockingHintWindow
2682
# ----------------------------------------------------------------------------
2684
class AuiDockingHintWindow(wx.Frame):
2685
""" The original wxAUI docking window hint. """
2687
def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition,
2688
size=wx.Size(1, 1), style=wx.FRAME_TOOL_WINDOW | wx.FRAME_FLOAT_ON_PARENT |
2689
wx.FRAME_NO_TASKBAR | wx.NO_BORDER | wx.FRAME_SHAPED,
2690
name="auiHintWindow"):
2692
Default class constructor. Used internally, do not call it in your code!
2694
:param `parent`: the :class:`AuiManager` parent;
2695
:param integer `id`: the window identifier. It may take a value of -1 to indicate a default value.
2696
:param string `title`: the caption to be displayed on the frame's title bar;
2697
:param Point `pos`: the window position. A value of (-1, -1) indicates a default position,
2698
chosen by either the windowing system or wxPython, depending on platform;
2699
:param Size `size`: the window size. A value of (-1, -1) indicates a default size, chosen by
2700
either the windowing system or wxPython, depending on platform;
2701
:param integer `style`: the window style;
2702
:param string `name`: the name of the window. This parameter is used to associate a name with the
2703
item, allowing the application user to set Motif resource values for individual windows.
2705
if wx.Platform == '__WXMAC__' and style & wx.FRAME_SHAPED:
2706
# Having the shaped frame causes the frame to not be visible
2707
# with the transparent style hints.
2708
style -= wx.FRAME_SHAPED
2710
wx.Frame.__init__(self, parent, id, title, pos, size, style, name=name)
2712
self._blindMode = False
2714
self._art = parent.GetEventHandler().GetArtProvider()
2715
background = self._art.GetColour(AUI_DOCKART_HINT_WINDOW_COLOUR)
2716
self.SetBackgroundColour(background)
2718
# Can't set background colour on a frame on wxMac
2719
# so add a panel to set the colour on.
2720
if wx.Platform == '__WXMAC__':
2721
sizer = wx.BoxSizer(wx.HORIZONTAL)
2722
self.panel = wx.Panel(self)
2723
sizer.Add(self.panel, 1, wx.EXPAND)
2724
self.SetSizer(sizer)
2725
self.panel.SetBackgroundColour(background)
2727
self.Bind(wx.EVT_PAINT, self.OnPaint)
2729
self.Bind(wx.EVT_SIZE, self.OnSize)
2732
def MakeVenetianBlinds(self):
2734
Creates the "venetian blind" effect if :class:`AuiManager` has the ``AUI_MGR_VENETIAN_BLINDS_HINT``
2739
size = self.GetClientSize()
2740
region = wx.Region(0, 0, size.x, 1)
2742
for y in xrange(size.y):
2744
# Reverse the order of the bottom 4 bits
2745
j = (y & 8 and [1] or [0])[0] | (y & 4 and [2] or [0])[0] | \
2746
(y & 2 and [4] or [0])[0] | (y & 1 and [8] or [0])[0]
2749
region.Union(0, y, size.x, 1)
2751
self.SetShape(region)
2754
def SetBlindMode(self, agwFlags):
2756
Sets whether venetian blinds or transparent hints will be shown as docking hint.
2757
This depends on the :class:`AuiManager` flags.
2759
:param integer `agwFlags`: the :class:`AuiManager` flags.
2762
self._blindMode = (agwFlags & AUI_MGR_VENETIAN_BLINDS_HINT) != 0
2764
if self._blindMode or not self.CanSetTransparent():
2765
self.MakeVenetianBlinds()
2766
self.SetTransparent(255)
2769
self.SetShape(wx.Region())
2770
if agwFlags & AUI_MGR_HINT_FADE == 0:
2771
self.SetTransparent(80)
2773
self.SetTransparent(0)
2776
def SetShape(self, region):
2778
If the platform supports it, sets the shape of the window to that depicted by `region`.
2779
The system will not display or respond to any mouse event for the pixels that lie
2780
outside of the region. To reset the window to the normal rectangular shape simply call
2781
:meth:`SetShape` again with an empty region.
2783
:param Region `region`: the shape of the frame.
2785
:note: Overridden for wxMAC.
2788
if wx.Platform == '__WXMAC__':
2789
# HACK so we don't crash when SetShape is called
2792
super(AuiDockingHintWindow, self).SetShape(region)
2795
def Show(self, show=True):
2797
Show the hint window.
2799
:param bool `show`: whether to show or hide the hint docking window.
2802
background = self._art.GetColour(AUI_DOCKART_HINT_WINDOW_COLOUR)
2804
if wx.Platform == '__WXMAC__':
2805
self.panel.SetBackgroundColour(background)
2807
self.SetBackgroundColour(background)
2809
super(AuiDockingHintWindow, self).Show(show)
2812
if wx.Platform == '__WXMAC__':
2813
# Need to manually do layout since its a borderless frame.
2817
def OnSize(self, event):
2819
Handles the ``wx.EVT_SIZE`` event for :class:`AuiDockingHintWindow`.
2821
:param `event`: a :class:`SizeEvent` to be processed.
2824
if self._blindMode or not self.CanSetTransparent():
2825
self.MakeVenetianBlinds()
2830
def OnPaint(self, event):
2832
Handles the ``wx.EVT_PAINT`` event for :class:`AuiDockingHintWindow`.
2834
:param `event`: an instance of :class:`PaintEvent` to be processed.
2837
rect = wx.RectPS(wx.Point(0, 0), self.GetSize())
2839
dc = wx.PaintDC(self)
2842
dc.SetBrush(wx.TRANSPARENT_BRUSH)
2843
dc.SetPen(wx.Pen(wx.Colour(60, 60, 60), 5))
2845
dc.DrawRectangleRect(rect)
2848
# ---------------------------------------------------------------------------- #
2850
# -- AuiFloatingFrame class implementation --
2852
class AuiFloatingFrame(wx.MiniFrame):
2853
""" AuiFloatingFrame is the frame class that holds floating panes. """
2855
def __init__(self, parent, owner_mgr, pane=None, id=wx.ID_ANY, title="",
2856
style=wx.FRAME_TOOL_WINDOW | wx.FRAME_FLOAT_ON_PARENT |
2857
wx.FRAME_NO_TASKBAR | wx.CLIP_CHILDREN):
2859
Default class constructor. Used internally, do not call it in your code!
2861
:param `parent`: the :class:`AuiManager` parent;
2862
:param `owner_mgr`: the :class:`AuiManager` that manages the floating pane;
2863
:param `pane`: the :class:`AuiPaneInfo` pane that is about to float;
2864
:param integer `id`: the window identifier. It may take a value of -1 to indicate a default value.
2865
:param string `title`: the caption to be displayed on the frame's title bar.
2866
:param integer `style`: the window style.
2869
if pane and pane.IsResizeable():
2870
style += wx.RESIZE_BORDER
2872
self._is_toolbar = pane.IsToolbar()
2874
self._useNativeMiniframes = False
2875
if AuiManager_UseNativeMiniframes(owner_mgr):
2876
# On wxMac we always use native miniframes
2877
self._useNativeMiniframes = True
2878
style += wx.CAPTION + wx.SYSTEM_MENU
2879
if pane.HasCloseButton():
2880
style += wx.CLOSE_BOX
2881
if pane.HasMaximizeButton():
2882
style += wx.MAXIMIZE_BOX
2883
if pane.HasMinimizeButton():
2884
style += wx.MINIMIZE_BOX
2886
wx.MiniFrame.__init__(self, parent, id, title, pos=pane.floating_pos,
2887
size=pane.floating_size, style=style, name="auiFloatingFrame")
2889
self._fly_timer = wx.Timer(self, wx.ID_ANY)
2890
self._check_fly_timer = wx.Timer(self, wx.ID_ANY)
2892
self.Bind(wx.EVT_CLOSE, self.OnClose)
2893
self.Bind(wx.EVT_SIZE, self.OnSize)
2894
self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
2895
self.Bind(wx.EVT_TIMER, self.OnCheckFlyTimer, self._check_fly_timer)
2896
self.Bind(wx.EVT_TIMER, self.OnFlyTimer, self._fly_timer)
2897
self.Bind(EVT_AUI_FIND_MANAGER, self.OnFindManager)
2899
if self._useNativeMiniframes:
2900
self.Bind(wx.EVT_MOVE, self.OnMoveEvent)
2901
self.Bind(wx.EVT_MOVING, self.OnMoveEvent)
2902
self.Bind(wx.EVT_IDLE, self.OnIdle)
2903
self._useNativeMiniframes = True
2904
self.SetExtraStyle(wx.WS_EX_PROCESS_IDLE)
2906
self.Bind(wx.EVT_MOVE, self.OnMove)
2909
self._send_size = True
2910
self._alpha_amount = 255
2912
self._owner_mgr = owner_mgr
2913
self._moving = False
2914
self._lastDirection = None
2915
self._transparent = 255
2917
self._last_rect = wx.Rect()
2918
self._last2_rect = wx.Rect()
2919
self._last3_rect = wx.Rect()
2921
self._mgr = AuiManager()
2922
self._mgr.SetManagedWindow(self)
2923
self._mgr.SetArtProvider(owner_mgr.GetArtProvider())
2924
self._mgr.SetAGWFlags(owner_mgr.GetAGWFlags())
2927
def CopyAttributes(self, pane):
2929
Copies all the attributes of the input `pane` into another :class:`AuiPaneInfo`.
2931
:param `pane`: the source :class:`AuiPaneInfo` from where to copy attributes.
2934
contained_pane = AuiPaneInfo()
2936
contained_pane.name = pane.name
2937
contained_pane.caption = pane.caption
2938
contained_pane.window = pane.window
2939
contained_pane.frame = pane.frame
2940
contained_pane.state = pane.state
2941
contained_pane.dock_direction = pane.dock_direction
2942
contained_pane.dock_layer = pane.dock_layer
2943
contained_pane.dock_row = pane.dock_row
2944
contained_pane.dock_pos = pane.dock_pos
2945
contained_pane.best_size = wx.Size(*pane.best_size)
2946
contained_pane.min_size = wx.Size(*pane.min_size)
2947
contained_pane.max_size = wx.Size(*pane.max_size)
2948
contained_pane.floating_pos = wx.Point(*pane.floating_pos)
2949
contained_pane.floating_size = wx.Size(*pane.floating_size)
2950
contained_pane.dock_proportion = pane.dock_proportion
2951
contained_pane.buttons = pane.buttons
2952
contained_pane.rect = wx.Rect(*pane.rect)
2953
contained_pane.icon = pane.icon
2954
contained_pane.notebook_id = pane.notebook_id
2955
contained_pane.transparent = pane.transparent
2956
contained_pane.snapped = pane.snapped
2957
contained_pane.minimize_mode = pane.minimize_mode
2958
contained_pane.minimize_target = pane.minimize_target
2960
return contained_pane
2963
def SetPaneWindow(self, pane):
2965
Sets all the properties of a pane.
2967
:param `pane`: the :class:`AuiPaneInfo` to analyze.
2970
self._is_toolbar = pane.IsToolbar()
2971
self._pane_window = pane.window
2973
if isinstance(pane.window, auibar.AuiToolBar):
2974
pane.window.SetAuiManager(self._mgr)
2976
self._pane_window.Reparent(self)
2978
contained_pane = self.CopyAttributes(pane)
2980
contained_pane.Dock().Center().Show(). \
2981
CaptionVisible(False). \
2982
PaneBorder(False). \
2983
Layer(0).Row(0).Position(0)
2985
if not contained_pane.HasGripper() and not self._useNativeMiniframes:
2986
contained_pane.CaptionVisible(True)
2988
indx = self._owner_mgr._panes.index(pane)
2990
# Carry over the minimum size
2991
pane_min_size = pane.window.GetMinSize()
2993
# if the best size is smaller than the min size
2994
# then set the min size to the best size as well
2995
pane_best_size = contained_pane.best_size
2996
if pane_best_size.IsFullySpecified() and (pane_best_size.x < pane_min_size.x or \
2997
pane_best_size.y < pane_min_size.y):
2999
pane_min_size = pane_best_size
3000
self._pane_window.SetMinSize(pane_min_size)
3002
# if the frame window's max size is greater than the min size
3003
# then set the max size to the min size as well
3004
cur_max_size = self.GetMaxSize()
3005
if cur_max_size.IsFullySpecified() and (cur_max_size.x < pane_min_size.x or \
3006
cur_max_size.y < pane_min_size.y):
3007
self.SetMaxSize(pane_min_size)
3009
art_provider = self._mgr.GetArtProvider()
3010
caption_size = art_provider.GetMetric(AUI_DOCKART_CAPTION_SIZE)
3011
button_size = art_provider.GetMetric(AUI_DOCKART_PANE_BUTTON_SIZE) + \
3012
4*art_provider.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE)
3014
min_size = pane.window.GetMinSize()
3016
if min_size.y < caption_size or min_size.x < button_size:
3017
new_x, new_y = min_size.x, min_size.y
3018
if min_size.y < caption_size:
3019
new_y = (pane.IsResizeable() and [2*wx.SystemSettings.GetMetric(wx.SYS_EDGE_Y)+caption_size] or [1])[0]
3020
if min_size.x < button_size:
3021
new_x = (pane.IsResizeable() and [2*wx.SystemSettings.GetMetric(wx.SYS_EDGE_X)+button_size] or [1])[0]
3023
self.SetMinSize((new_x, new_y))
3025
self.SetMinSize(min_size)
3027
self._mgr.AddPane(self._pane_window, contained_pane)
3030
if pane.min_size.IsFullySpecified():
3031
# because SetSizeHints() calls Fit() too (which sets the window
3032
# size to its minimum allowed), we keep the size before calling
3033
# SetSizeHints() and reset it afterwards...
3034
tmp = self.GetSize()
3035
self.GetSizer().SetSizeHints(self)
3038
self.SetTitle(pane.caption)
3040
if pane.floating_size != wx.Size(-1, -1):
3041
self.SetSize(pane.floating_size)
3043
size = pane.best_size
3044
if size == wx.Size(-1, -1):
3045
size = pane.min_size
3046
if size == wx.Size(-1, -1):
3047
size = self._pane_window.GetSize()
3048
if self._owner_mgr and pane.HasGripper():
3049
if pane.HasGripperTop():
3050
size.y += self._owner_mgr._art.GetMetric(AUI_DOCKART_GRIPPER_SIZE)
3052
size.x += self._owner_mgr._art.GetMetric(AUI_DOCKART_GRIPPER_SIZE)
3054
if not self._useNativeMiniframes:
3055
size.y += self._owner_mgr._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
3057
pane.floating_size = size
3059
self.SetClientSize(size)
3061
self._owner_mgr._panes[indx] = pane
3063
self._fly_step = abs(pane.floating_size.y - \
3064
(caption_size + 2*wx.SystemSettings.GetMetric(wx.SYS_EDGE_Y)))/10
3066
self._floating_size = wx.Size(*self.GetSize())
3069
self._check_fly_timer.Start(50)
3072
def GetOwnerManager(self):
3073
""" Returns the :class:`AuiManager` that manages the pane. """
3075
return self._owner_mgr
3078
def OnSize(self, event):
3080
Handles the ``wx.EVT_SIZE`` event for :class:`AuiFloatingFrame`.
3082
:param `event`: a :class:`SizeEvent` to be processed.
3085
if self._owner_mgr and self._send_size:
3086
self._owner_mgr.OnFloatingPaneResized(self._pane_window, event.GetSize())
3089
def OnClose(self, event):
3091
Handles the ``wx.EVT_CLOSE`` event for :class:`AuiFloatingFrame`.
3093
:param `event`: a :class:`CloseEvent` to be processed.
3097
self._owner_mgr.OnFloatingPaneClosed(self._pane_window, event)
3099
if not event.GetVeto():
3100
self._mgr.DetachPane(self._pane_window)
3102
if isinstance(self._pane_window, auibar.AuiToolBar):
3103
self._pane_window.SetAuiManager(self._owner_mgr)
3105
# if we do not do this, then we can crash...
3106
if self._owner_mgr and self._owner_mgr._action_window == self:
3107
self._owner_mgr._action_window = None
3113
def OnActivate(self, event):
3115
Handles the ``wx.EVT_ACTIVATE`` event for :class:`AuiFloatingFrame`.
3117
:param `event`: a :class:`ActivateEvent` to be processed.
3120
if self._owner_mgr and event.GetActive():
3121
self._owner_mgr.OnFloatingPaneActivated(self._pane_window)
3124
def OnMove(self, event):
3126
Handles the ``wx.EVT_MOVE`` event for :class:`AuiFloatingFrame`.
3128
:param `event`: a :class:`MoveEvent` to be processed.
3132
This event is not processed on wxMAC or if :class:`AuiManager` is not using the
3133
``AUI_MGR_USE_NATIVE_MINIFRAMES`` style.
3138
self._owner_mgr.OnFloatingPaneMoved(self._pane_window, event)
3141
def OnMoveEvent(self, event):
3143
Handles the ``wx.EVT_MOVE`` and ``wx.EVT_MOVING`` events for :class:`AuiFloatingFrame`.
3145
:param `event`: a :class:`MoveEvent` to be processed.
3149
This event is only processed on wxMAC or if :class:`AuiManager` is using the
3150
``AUI_MGR_USE_NATIVE_MINIFRAMES`` style.
3153
win_rect = self.GetRect()
3155
if win_rect == self._last_rect:
3158
# skip the first move event
3159
if self._last_rect.IsEmpty():
3160
self._last_rect = wx.Rect(*win_rect)
3163
# As on OSX moving windows are not getting all move events, only sporadically, this difference
3164
# is almost always big on OSX, so avoid this early exit opportunity
3165
if wx.Platform != '__WXMAC__':
3166
# skip if moving too fast to avoid massive redraws and
3167
# jumping hint windows
3168
if abs(win_rect.x - self._last_rect.x) > 3 or abs(win_rect.y - self._last_rect.y) > 3:
3169
self._last3_rect = wx.Rect(*self._last2_rect)
3170
self._last2_rect = wx.Rect(*self._last_rect)
3171
self._last_rect = wx.Rect(*win_rect)
3173
# However still update the internally stored position to avoid
3174
# snapping back to the old one later.
3176
self._owner_mgr.GetPane(self._pane_window).floating_pos = win_rect.GetPosition()
3180
# prevent frame redocking during resize
3181
if self._last_rect.GetSize() != win_rect.GetSize():
3182
self._last3_rect = wx.Rect(*self._last2_rect)
3183
self._last2_rect = wx.Rect(*self._last_rect)
3184
self._last_rect = wx.Rect(*win_rect)
3189
horiz_dist = abs(win_rect.x - self._last3_rect.x)
3190
vert_dist = abs(win_rect.y - self._last3_rect.y)
3192
if vert_dist >= horiz_dist:
3193
if win_rect.y < self._last3_rect.y:
3198
if win_rect.x < self._last3_rect.x:
3203
self._last3_rect = wx.Rect(*self._last2_rect)
3204
self._last2_rect = wx.Rect(*self._last_rect)
3205
self._last_rect = wx.Rect(*win_rect)
3207
if _VERSION_STRING < "2.9":
3208
leftDown = wx.GetMouseState().LeftDown()
3210
leftDown = wx.GetMouseState().LeftIsDown()
3215
if not self._moving:
3216
self.OnMoveStart(event)
3219
if self._last3_rect.IsEmpty():
3222
if event.GetEventType() == wx.wxEVT_MOVING:
3223
self.OnMoving(event.GetRect(), dir)
3225
self.OnMoving(wx.RectPS(event.GetPosition(), self.GetSize()), dir)
3228
def OnIdle(self, event):
3230
Handles the ``wx.EVT_IDLE`` event for :class:`AuiFloatingFrame`.
3232
:param `event`: a :class:`IdleEvent` event to be processed.
3236
This event is only processed on wxMAC if :class:`AuiManager` is using the
3237
``AUI_MGR_USE_NATIVE_MINIFRAMES`` style.
3242
if _VERSION_STRING < "2.9":
3243
leftDown = wx.GetMouseState().LeftDown()
3245
leftDown = wx.GetMouseState().LeftIsDown()
3248
self._moving = False
3249
self.OnMoveFinished()
3254
def OnMoveStart(self, event):
3256
The user has just started moving the floating pane.
3258
:param `event`: an instance of :class:`MouseEvent`.
3262
This event is only processed on wxMAC if :class:`AuiManager` is using the
3263
``AUI_MGR_USE_NATIVE_MINIFRAMES`` style.
3267
# notify the owner manager that the pane has started to move
3269
if self._owner_mgr._from_move:
3271
self._owner_mgr._action_window = self._pane_window
3272
point = wx.GetMousePosition()
3273
action_offset = point - self.GetPosition()
3275
if self._is_toolbar:
3276
self._owner_mgr._toolbar_action_offset = action_offset
3277
self._owner_mgr.OnMotion_DragToolbarPane(point)
3279
self._owner_mgr._action_offset = action_offset
3280
self._owner_mgr.OnMotion_DragFloatingPane(point)
3283
def OnMoving(self, rect, direction):
3285
The user is moving the floating pane.
3287
:param Rect `rect`: the pane client rectangle;
3288
:param integer `direction`: the direction in which the pane is moving, can be one of
3289
``wx.NORTH``, ``wx.SOUTH``, ``wx.EAST`` or ``wx.WEST``.
3293
This event is only processed on wxMAC if :class:`AuiManager` is using the
3294
``AUI_MGR_USE_NATIVE_MINIFRAMES`` style.
3297
# notify the owner manager that the pane is moving
3298
self.OnMoveStart(None)
3299
self._lastDirection = direction
3302
def OnMoveFinished(self):
3304
The user has just finished moving the floating pane.
3308
This method is used only on wxMAC if :class:`AuiManager` is using the
3309
``AUI_MGR_USE_NATIVE_MINIFRAMES`` style.
3313
# notify the owner manager that the pane has finished moving
3315
self._owner_mgr._action_window = self._pane_window
3316
point = wx.GetMousePosition()
3317
if self._is_toolbar:
3318
self._owner_mgr.OnLeftUp_DragToolbarPane(point)
3320
self._owner_mgr.OnLeftUp_DragFloatingPane(point)
3322
self._owner_mgr.OnFloatingPaneMoved(self._pane_window, point)
3325
def OnCheckFlyTimer(self, event):
3327
Handles the ``wx.EVT_TIMER`` event for :class:`AuiFloatingFrame`.
3329
:param `event`: a :class:`TimerEvent` to be processed.
3331
:note: This is used solely for "fly-out" panes.
3335
pane = self._mgr.GetPane(self._pane_window)
3337
if self.IsShownOnScreen():
3341
def OnFindManager(self, event):
3343
Handles the ``EVT_AUI_FIND_MANAGER`` event for :class:`AuiFloatingFrame`.
3345
:param `event`: a :class:`AuiManagerEvent` event to be processed.
3348
event.SetManager(self._owner_mgr)
3352
""" Starts the flying in and out of a floating pane. """
3354
if self._fly_timer.IsRunning():
3357
if _VERSION_STRING < "2.9":
3358
leftDown = wx.GetMouseState().LeftDown()
3360
leftDown = wx.GetMouseState().LeftIsDown()
3365
rect = wx.Rect(*self.GetScreenRect())
3366
rect.Inflate(10, 10)
3368
if rect.Contains(wx.GetMousePosition()):
3371
self._send_size = False
3372
self._fly_timer.Start(5)
3376
self._send_size = False
3377
self._fly_timer.Start(5)
3380
def OnFlyTimer(self, event):
3382
Handles the ``wx.EVT_TIMER`` event for :class:`AuiFloatingFrame`.
3384
:param `event`: a :class:`TimerEvent` to be processed.
3387
current_size = self.GetClientSize()
3388
floating_size = wx.Size(*self._owner_mgr.GetPane(self._pane_window).floating_size)
3390
if floating_size.y == -1:
3391
floating_size = self._floating_size
3394
min_size = self._mgr.GetArtProvider().GetMetric(AUI_DOCKART_CAPTION_SIZE)
3396
if wx.Platform != "__WXMSW__":
3397
min_size += 2*wx.SystemSettings.GetMetric(wx.SYS_EDGE_Y)
3399
if current_size.y - self._fly_step <= min_size:
3400
self.SetClientSize((current_size.x, min_size))
3402
self._fly_timer.Stop()
3403
self._send_size = True
3405
self.SetClientSize((current_size.x, current_size.y-self._fly_step))
3408
if current_size.y + self._fly_step >= floating_size.y:
3409
self.SetClientSize((current_size.x, floating_size.y))
3411
self._fly_timer.Stop()
3412
self._send_size = True
3414
self.SetClientSize((current_size.x, current_size.y+self._fly_step))
3421
""" Actually starts the fading out of the floating pane. """
3424
self._alpha_amount -= 10
3425
if self._alpha_amount <= 0:
3426
self._alpha_amount = 255
3429
self.SetTransparent(self._alpha_amount)
3434
# -- static utility functions --
3436
def DrawResizeHint(dc, rect):
3438
Draws a resize hint while a sash is dragged.
3440
:param Rect `rect`: a rectangle which specifies the sash dimensions.
3443
if wx.Platform == "__WXMSW__" and wx.App.GetComCtl32Version() >= 600:
3444
if wx.GetOsVersion()[1] > 5:
3446
dc.SetPen(wx.Pen("black", 2, wx.SOLID))
3447
dc.SetBrush(wx.TRANSPARENT_BRUSH)
3449
# Draw the nice XP style splitter
3450
dc.SetPen(wx.TRANSPARENT_PEN)
3451
dc.SetBrush(wx.BLACK_BRUSH)
3452
dc.SetLogicalFunction(wx.INVERT)
3453
dc.DrawRectangleRect(rect)
3454
dc.SetLogicalFunction(wx.COPY)
3456
stipple = PaneCreateStippleBitmap()
3457
brush = wx.BrushFromBitmap(stipple)
3459
dc.SetPen(wx.TRANSPARENT_PEN)
3461
dc.SetLogicalFunction(wx.XOR)
3462
dc.DrawRectangleRect(rect)
3465
def CopyDocksAndPanes(src_docks, src_panes):
3467
This utility function creates shallow copies of
3468
the dock and pane info. :class:`AuiManager` usually contain pointers
3469
to :class:`AuiPaneInfo` classes, thus this function is necessary to reliably
3470
reconstruct that relationship in the new dock info and pane info arrays.
3472
:param `src_docks`: a list of :class:`AuiDockInfo` classes;
3473
:param `src_panes`: a list of :class:`AuiPaneInfo` classes.
3476
dest_docks = src_docks
3477
dest_panes = src_panes
3479
for ii in xrange(len(dest_docks)):
3480
dock = dest_docks[ii]
3481
for jj in xrange(len(dock.panes)):
3482
for kk in xrange(len(src_panes)):
3483
if dock.panes[jj] == src_panes[kk]:
3484
dock.panes[jj] = dest_panes[kk]
3486
return dest_docks, dest_panes
3489
def CopyDocksAndPanes2(src_docks, src_panes):
3491
This utility function creates full copies of
3492
the dock and pane info. :class:`AuiManager` usually contain pointers
3493
to :class:`AuiPaneInfo` classes, thus this function is necessary to reliably
3494
reconstruct that relationship in the new dock info and pane info arrays.
3496
:param `src_docks`: a list of :class:`AuiDockInfo` classes;
3497
:param `src_panes`: a list of :class:`AuiPaneInfo` classes.
3502
for ii in xrange(len(src_docks)):
3503
dest_docks.append(AuiDockInfo())
3504
dest_docks[ii].dock_direction = src_docks[ii].dock_direction
3505
dest_docks[ii].dock_layer = src_docks[ii].dock_layer
3506
dest_docks[ii].dock_row = src_docks[ii].dock_row
3507
dest_docks[ii].size = src_docks[ii].size
3508
dest_docks[ii].min_size = src_docks[ii].min_size
3509
dest_docks[ii].resizable = src_docks[ii].resizable
3510
dest_docks[ii].fixed = src_docks[ii].fixed
3511
dest_docks[ii].toolbar = src_docks[ii].toolbar
3512
dest_docks[ii].panes = src_docks[ii].panes
3513
dest_docks[ii].rect = wx.Rect(*src_docks[ii].rect)
3517
for ii in xrange(len(src_panes)):
3518
dest_panes.append(AuiPaneInfo())
3519
dest_panes[ii].name = src_panes[ii].name
3520
dest_panes[ii].caption = src_panes[ii].caption
3521
dest_panes[ii].window = src_panes[ii].window
3522
dest_panes[ii].frame = src_panes[ii].frame
3523
dest_panes[ii].state = src_panes[ii].state
3524
dest_panes[ii].dock_direction = src_panes[ii].dock_direction
3525
dest_panes[ii].dock_layer = src_panes[ii].dock_layer
3526
dest_panes[ii].dock_row = src_panes[ii].dock_row
3527
dest_panes[ii].dock_pos = src_panes[ii].dock_pos
3528
dest_panes[ii].best_size = wx.Size(*src_panes[ii].best_size)
3529
dest_panes[ii].min_size = wx.Size(*src_panes[ii].min_size)
3530
dest_panes[ii].max_size = wx.Size(*src_panes[ii].max_size)
3531
dest_panes[ii].floating_pos = wx.Point(*src_panes[ii].floating_pos)
3532
dest_panes[ii].floating_size = wx.Size(*src_panes[ii].floating_size)
3533
dest_panes[ii].dock_proportion = src_panes[ii].dock_proportion
3534
dest_panes[ii].buttons = src_panes[ii].buttons
3535
dest_panes[ii].rect = wx.Rect(*src_panes[ii].rect)
3536
dest_panes[ii].icon = src_panes[ii].icon
3537
dest_panes[ii].notebook_id = src_panes[ii].notebook_id
3538
dest_panes[ii].transparent = src_panes[ii].transparent
3539
dest_panes[ii].snapped = src_panes[ii].snapped
3540
dest_panes[ii].minimize_mode = src_panes[ii].minimize_mode
3541
dest_panes[ii].minimize_target = src_panes[ii].minimize_target
3543
for ii in xrange(len(dest_docks)):
3544
dock = dest_docks[ii]
3545
for jj in xrange(len(dock.panes)):
3546
for kk in xrange(len(src_panes)):
3547
if dock.panes[jj] == src_panes[kk]:
3548
dock.panes[jj] = dest_panes[kk]
3550
dest_docks[ii] = dock
3552
return dest_docks, dest_panes
3555
def GetMaxLayer(docks, dock_direction):
3557
This is an internal function which returns
3558
the highest layer inside the specified dock.
3560
:param `docks`: a list of :class:`AuiDockInfo`;
3561
:param `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze.
3567
if dock.dock_direction == dock_direction and dock.dock_layer > max_layer and not dock.fixed:
3568
max_layer = dock.dock_layer
3573
def GetMaxRow(panes, dock_direction, dock_layer):
3575
This is an internal function which returns
3576
the highest layer inside the specified dock.
3578
:param `panes`: a list of :class:`AuiPaneInfo`;
3579
:param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze;
3580
:param integer `dock_layer`: the :class:`AuiDockInfo` layer to analyze.
3586
if pane.dock_direction == dock_direction and pane.dock_layer == dock_layer and \
3587
pane.dock_row > max_row:
3588
max_row = pane.dock_row
3593
def DoInsertDockLayer(panes, dock_direction, dock_layer):
3595
This is an internal function that inserts a new dock
3596
layer by incrementing all existing dock layer values by one.
3598
:param `panes`: a list of :class:`AuiPaneInfo`;
3599
:param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze;
3600
:param integer `dock_layer`: the :class:`AuiDockInfo` layer to analyze.
3603
for ii in xrange(len(panes)):
3605
if not pane.IsFloating() and pane.dock_direction == dock_direction and pane.dock_layer >= dock_layer:
3606
pane.dock_layer = pane.dock_layer + 1
3613
def DoInsertDockRow(panes, dock_direction, dock_layer, dock_row):
3615
This is an internal function that inserts a new dock
3616
row by incrementing all existing dock row values by one.
3618
:param `panes`: a list of :class:`AuiPaneInfo`;
3619
:param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze;
3620
:param integer `dock_layer`: the :class:`AuiDockInfo` layer to analyze;
3621
:param integer `dock_row`: the :class:`AuiDockInfo` row to analyze.
3625
if not pane.IsFloating() and pane.dock_direction == dock_direction and \
3626
pane.dock_layer == dock_layer and pane.dock_row >= dock_row:
3632
def DoInsertPane(panes, dock_direction, dock_layer, dock_row, dock_pos):
3634
This is an internal function that inserts a new pane
3635
by incrementing all existing dock position values by one.
3637
:param `panes`: a list of :class:`AuiPaneInfo`;
3638
:param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze;
3639
:param integer `dock_layer`: the :class:`AuiDockInfo` layer to analyze.
3640
:param integer `dock_row`: the :class:`AuiDockInfo` row to analyze;
3641
:param integer `dock_pos`: the :class:`AuiDockInfo` position to analyze.
3644
for ii in xrange(len(panes)):
3646
if not pane.IsFloating() and pane.dock_direction == dock_direction and \
3647
pane.dock_layer == dock_layer and pane.dock_row == dock_row and \
3648
pane.dock_pos >= dock_pos:
3649
pane.dock_pos = pane.dock_pos + 1
3656
def FindDocks(docks, dock_direction, dock_layer=-1, dock_row=-1, reverse=False):
3658
This is an internal function that returns a list of docks which meet
3659
the specified conditions in the parameters and returns a sorted array
3660
(sorted by layer and then row).
3662
:param `docks`: a list of :class:`AuiDockInfo`;
3663
:param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze;
3664
:param integer `dock_layer`: the :class:`AuiDockInfo` layer to analyze.
3665
:param integer `dock_row`: the :class:`AuiDockInfo` row to analyze;
3668
matchDocks = [(d.dock_layer, d.dock_row, d.dock_direction, d) for d in docks if \
3669
(dock_direction == -1 or dock_direction == d.dock_direction) and \
3670
((dock_layer == -1 or dock_layer == d.dock_layer) and \
3671
(dock_row == -1 or dock_row == d.dock_row))]
3673
arr = [x[-1] for x in sorted(matchDocks, reverse=reverse)]
3678
def FindOppositeDocks(docks, dock_direction):
3680
This is an internal function that returns a list of docks
3681
which is related to the opposite direction.
3683
:param `docks`: a list of :class:`AuiDockInfo`;
3684
:param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze;
3687
if dock_direction == AUI_DOCK_LEFT:
3688
arr = FindDocks(docks, AUI_DOCK_RIGHT, -1, -1)
3689
elif dock_direction == AUI_DOCK_TOP:
3690
arr = FindDocks(docks, AUI_DOCK_BOTTOM, -1, -1)
3691
elif dock_direction == AUI_DOCK_RIGHT:
3692
arr = FindDocks(docks, AUI_DOCK_LEFT, -1, -1)
3693
elif dock_direction == AUI_DOCK_BOTTOM:
3694
arr = FindDocks(docks, AUI_DOCK_TOP, -1, -1)
3699
def FindPaneInDock(dock, window):
3701
This method looks up a specified window pointer inside a dock.
3702
If found, the corresponding :class:`AuiDockInfo` pointer is returned, otherwise ``None``.
3704
:param `dock`: a :class:`AuiDockInfo` structure;
3705
:param Window `window`: the window associated to the pane we are seeking.
3708
for p in dock.panes:
3709
if p.window == window:
3715
def GetToolBarDockOffsets(docks):
3717
Returns the toolbar dock offsets (top-left and bottom-right).
3719
:param `docks`: a list of :class:`AuiDockInfo` to analyze.
3722
top_left = wx.Size(0, 0)
3723
bottom_right = wx.Size(0, 0)
3727
dock_direction = dock.dock_direction
3728
if dock_direction == AUI_DOCK_LEFT:
3729
top_left.x += dock.rect.width
3730
bottom_right.x += dock.rect.width
3732
elif dock_direction == AUI_DOCK_TOP:
3733
top_left.y += dock.rect.height
3734
bottom_right.y += dock.rect.height
3736
elif dock_direction == AUI_DOCK_RIGHT:
3737
bottom_right.x += dock.rect.width
3739
elif dock_direction == AUI_DOCK_BOTTOM:
3740
bottom_right.y += dock.rect.height
3742
return top_left, bottom_right
3745
def GetInternalFrameRect(window, docks):
3747
Returns the window rectangle excluding toolbars.
3749
:param `window`: a :class:`Window` derived window;
3750
:param `docks`: a list of :class:`AuiDockInfo` structures.
3753
frameRect = wx.Rect()
3755
frameRect.SetTopLeft(window.ClientToScreen(window.GetClientAreaOrigin()))
3756
frameRect.SetSize(window.GetClientSize())
3758
top_left, bottom_right = GetToolBarDockOffsets(docks)
3760
# make adjustments for toolbars
3761
frameRect.x += top_left.x
3762
frameRect.y += top_left.y
3763
frameRect.width -= bottom_right.x
3764
frameRect.height -= bottom_right.y
3769
def CheckOutOfWindow(window, pt):
3771
Checks if a point is outside the window rectangle.
3773
:param `window`: a :class:`Window` derived window;
3774
:param `pt`: a :class:`Point` object.
3777
auiWindowMargin = 30
3778
marginRect = wx.Rect(*window.GetClientRect())
3779
marginRect.Inflate(auiWindowMargin, auiWindowMargin)
3781
return not marginRect.Contains(pt)
3784
def CheckEdgeDrop(window, docks, pt):
3786
Checks on which edge of a window the drop action has taken place.
3788
:param `window`: a :class:`Window` derived window;
3789
:param `docks`: a list of :class:`AuiDockInfo` structures;
3790
:param `pt`: a :class:`Point` object.
3793
screenPt = window.ClientToScreen(pt)
3794
clientSize = window.GetClientSize()
3795
frameRect = GetInternalFrameRect(window, docks)
3797
if screenPt.y >= frameRect.GetTop() and screenPt.y < frameRect.GetBottom():
3798
if pt.x < auiLayerInsertOffset and pt.x > auiLayerInsertOffset - auiLayerInsertPixels:
3801
if pt.x >= clientSize.x - auiLayerInsertOffset and \
3802
pt.x < clientSize.x - auiLayerInsertOffset + auiLayerInsertPixels:
3805
if screenPt.x >= frameRect.GetLeft() and screenPt.x < frameRect.GetRight():
3806
if pt.y < auiLayerInsertOffset and pt.y > auiLayerInsertOffset - auiLayerInsertPixels:
3809
if pt.y >= clientSize.y - auiLayerInsertOffset and \
3810
pt.y < clientSize.y - auiLayerInsertOffset + auiLayerInsertPixels:
3816
def RemovePaneFromDocks(docks, pane, exc=None):
3818
Removes a pane window from all docks
3819
with a possible exception specified by parameter `exc`.
3821
:param `docks`: a list of :class:`AuiDockInfo` structures;
3822
:param AuiPaneInfo `pane`: the pane to be removed;
3823
:param AuiPaneInfo `exc`: the possible pane exception.
3826
for ii in xrange(len(docks)):
3830
pi = FindPaneInDock(d, pane.window)
3839
def RenumberDockRows(docks):
3841
Takes a dock and assigns sequential numbers
3842
to existing rows. Basically it takes out the gaps so if a
3843
dock has rows with numbers 0, 2, 5, they will become 0, 1, 2.
3845
:param `docks`: a list of :class:`AuiDockInfo` structures.
3848
for ii in xrange(len(docks)):
3851
for jj in xrange(len(dock.panes)):
3852
dock.panes[jj].dock_row = ii
3859
def SetActivePane(panes, active_pane):
3861
Sets the active pane, as well as cycles through
3862
every other pane and makes sure that all others' active flags
3865
:param `panes`: a list of :class:`AuiPaneInfo` structures;
3866
:param AuiPaneInfo `active_pane`: the pane to be made active (if found).
3870
pane.state &= ~AuiPaneInfo.optionActive
3873
if pane.window == active_pane and not pane.IsNotebookPage():
3874
pane.state |= AuiPaneInfo.optionActive
3880
def ShowDockingGuides(guides, show):
3882
Shows or hide the docking guide windows.
3884
:param `guides`: a list of :class:`AuiDockingGuide` classes;
3885
:param bool `show`: whether to show or hide the docking guide windows.
3888
for target in guides:
3890
if show and not target.host.IsShown():
3892
target.host.Update()
3894
elif not show and target.host.IsShown():
3898
def RefreshDockingGuides(guides):
3900
Refreshes the docking guide windows.
3902
:param `guides`: a list of :class:`AuiDockingGuide` classes;
3905
for target in guides:
3906
if target.host.IsShown():
3907
target.host.Refresh()
3910
def PaneSortFunc(p1, p2):
3912
This function is used to sort panes by dock position.
3914
:param AuiPaneInfo `p1`: the first pane instance to compare;
3915
:param AuiPaneInfo `p2`: the second pane instance to compare.
3918
return (p1.dock_pos < p2.dock_pos and [-1] or [1])[0]
3921
def GetNotebookRoot(panes, notebook_id):
3923
Returns the :class:`~lib.agw.aui.auibook.AuiNotebook` which has the specified `notebook_id`.
3925
:param `panes`: a list of :class:`AuiPaneInfo` instances;
3926
:param integer `notebook_id`: the target notebook id.
3929
for paneInfo in panes:
3930
if paneInfo.IsNotebookControl() and paneInfo.notebook_id == notebook_id:
3936
def EscapeDelimiters(s):
3938
Changes ``;`` into ``\`` and ``|`` into ``\|`` in the input string.
3940
:param string `s`: the string to be analyzed.
3942
:note: This is an internal functions which is used for saving perspectives.
3945
result = s.replace(";", "\\")
3946
result = result.replace("|", "|\\")
3951
def IsDifferentDockingPosition(pane1, pane2):
3953
Returns whether `pane1` and `pane2` are in a different docking position
3954
based on pane status, docking direction, docking layer and docking row.
3956
:param `pane1`: a :class:`AuiPaneInfo` instance;
3957
:param `pane2`: another :class:`AuiPaneInfo` instance.
3960
return pane1.IsFloating() != pane2.IsFloating() or \
3961
pane1.dock_direction != pane2.dock_direction or \
3962
pane1.dock_layer != pane2.dock_layer or \
3963
pane1.dock_row != pane2.dock_row
3966
# Convenience function
3967
def AuiManager_HasLiveResize(manager):
3969
Static function which returns if the input `manager` should have "live resize"
3972
:param `manager`: an instance of :class:`AuiManager`.
3976
This method always returns ``True`` on wxMAC as this platform doesn't have
3977
the ability to use :class:`ScreenDC` to draw sashes.
3981
# With Core Graphics on Mac, it's not possible to show sash feedback,
3982
# so we'll always use live update instead.
3984
if wx.Platform == "__WXMAC__":
3987
return (manager.GetAGWFlags() & AUI_MGR_LIVE_RESIZE) == AUI_MGR_LIVE_RESIZE
3990
# Convenience function
3991
def AuiManager_UseNativeMiniframes(manager):
3993
Static function which returns if the input `manager` should use native :class:`MiniFrame` as
3996
:param `manager`: an instance of :class:`AuiManager`.
4000
This method always returns ``True`` on wxMAC as this platform doesn't have
4001
the ability to use custom drawn miniframes.
4005
# With Core Graphics on Mac, it's not possible to show sash feedback,
4006
# so we'll always use live update instead.
4008
if wx.Platform == "__WXMAC__":
4011
return (manager.GetAGWFlags() & AUI_MGR_USE_NATIVE_MINIFRAMES) == AUI_MGR_USE_NATIVE_MINIFRAMES
4014
def GetManager(window):
4016
This function will return the aui manager for a given window.
4018
:param Window `window`: this parameter should be any child window or grand-child
4019
window (and so on) of the frame/window managed by :class:`AuiManager`. The window
4020
does not need to be managed by the manager itself, nor does it even need
4021
to be a child or sub-child of a managed window. It must however be inside
4022
the window hierarchy underneath the managed window.
4025
if not isinstance(wx.GetTopLevelParent(window), AuiFloatingFrame):
4026
if isinstance(window, auibar.AuiToolBar):
4027
return window.GetAuiManager()
4029
evt = AuiManagerEvent(wxEVT_AUI_FIND_MANAGER)
4030
evt.SetManager(None)
4031
evt.ResumePropagation(wx.EVENT_PROPAGATE_MAX)
4033
if not window.GetEventHandler().ProcessEvent(evt):
4036
return evt.GetManager()
4039
# ---------------------------------------------------------------------------- #
4041
class AuiManager(wx.EvtHandler):
4043
AuiManager manages the panes associated with it for a particular :class:`Frame`,
4044
using a pane's :class:`AuiManager` information to determine each pane's docking and
4045
floating behavior. :class:`AuiManager` uses wxPython's sizer mechanism to plan the
4046
layout of each frame. It uses a replaceable dock art class to do all drawing,
4047
so all drawing is localized in one area, and may be customized depending on an
4048
applications' specific needs.
4050
:class:`AuiManager` works as follows: the programmer adds panes to the class, or makes
4051
changes to existing pane properties (dock position, floating state, show state, etc...).
4052
To apply these changes, the :meth:`AuiManager.Update() <AuiManager.Update>` function is called. This batch
4053
processing can be used to avoid flicker, by modifying more than one pane at a time,
4054
and then "committing" all of the changes at once by calling `Update()`.
4056
Panes can be added quite easily::
4058
text1 = wx.TextCtrl(self, -1)
4059
text2 = wx.TextCtrl(self, -1)
4060
self._mgr.AddPane(text1, AuiPaneInfo().Left().Caption("Pane Number One"))
4061
self._mgr.AddPane(text2, AuiPaneInfo().Bottom().Caption("Pane Number Two"))
4066
Later on, the positions can be modified easily. The following will float an
4067
existing pane in a tool window::
4069
self._mgr.GetPane(text1).Float()
4072
**Layers, Rows and Directions, Positions:**
4074
Inside AUI, the docking layout is figured out by checking several pane parameters.
4075
Four of these are important for determining where a pane will end up.
4077
**Direction** - Each docked pane has a direction, `Top`, `Bottom`, `Left`, `Right`, or `Center`.
4078
This is fairly self-explanatory. The pane will be placed in the location specified
4081
**Position** - More than one pane can be placed inside of a "dock". Imagine two panes
4082
being docked on the left side of a window. One pane can be placed over another.
4083
In proportionally managed docks, the pane position indicates it's sequential position,
4084
starting with zero. So, in our scenario with two panes docked on the left side, the
4085
top pane in the dock would have position 0, and the second one would occupy position 1.
4087
**Row** - A row can allow for two docks to be placed next to each other. One of the most
4088
common places for this to happen is in the toolbar. Multiple toolbar rows are allowed,
4089
the first row being in row 0, and the second in row 1. Rows can also be used on
4090
vertically docked panes.
4092
**Layer** - A layer is akin to an onion. Layer 0 is the very center of the managed pane.
4093
Thus, if a pane is in layer 0, it will be closest to the center window (also sometimes
4094
known as the "content window"). Increasing layers "swallow up" all layers of a lower
4095
value. This can look very similar to multiple rows, but is different because all panes
4096
in a lower level yield to panes in higher levels. The best way to understand layers
4097
is by running the AUI sample (`AUI.py`).
4100
def __init__(self, managed_window=None, agwFlags=None):
4102
Default class constructor.
4104
:param Window `managed_window`: specifies the window which should be managed;
4105
:param integer `agwFlags`: specifies options which allow the frame management behavior to be
4106
modified. `agwFlags` can be a combination of the following style bits:
4108
==================================== ==================================
4109
Flag name Description
4110
==================================== ==================================
4111
``AUI_MGR_ALLOW_FLOATING`` Allow floating of panes
4112
``AUI_MGR_ALLOW_ACTIVE_PANE`` If a pane becomes active, "highlight" it in the interface
4113
``AUI_MGR_TRANSPARENT_DRAG`` If the platform supports it, set transparency on a floating pane while it is dragged by the user
4114
``AUI_MGR_TRANSPARENT_HINT`` If the platform supports it, show a transparent hint window when the user is about to dock a floating pane
4115
``AUI_MGR_VENETIAN_BLINDS_HINT`` Show a "venetian blind" effect when the user is about to dock a floating pane
4116
``AUI_MGR_RECTANGLE_HINT`` Show a rectangle hint effect when the user is about to dock a floating pane
4117
``AUI_MGR_HINT_FADE`` If the platform supports it, the hint window will fade in and out
4118
``AUI_MGR_NO_VENETIAN_BLINDS_FADE`` Disables the "venetian blind" fade in and out
4119
``AUI_MGR_LIVE_RESIZE`` Live resize when the user drag a sash
4120
``AUI_MGR_ANIMATE_FRAMES`` Fade-out floating panes when they are closed (all platforms which support frames transparency)
4121
and show a moving rectangle when they are docked (Windows < Vista and GTK only)
4122
``AUI_MGR_AERO_DOCKING_GUIDES`` Use the new Aero-style bitmaps as docking guides
4123
``AUI_MGR_PREVIEW_MINIMIZED_PANES`` Slide in and out minimized panes to preview them
4124
``AUI_MGR_WHIDBEY_DOCKING_GUIDES`` Use the new Whidbey-style bitmaps as docking guides
4125
``AUI_MGR_SMOOTH_DOCKING`` Performs a "smooth" docking of panes (a la PyQT)
4126
``AUI_MGR_USE_NATIVE_MINIFRAMES`` Use miniframes with native caption bar as floating panes instead or custom drawn caption bars (forced on wxMAC)
4127
``AUI_MGR_AUTONB_NO_CAPTION`` Panes that merge into an automatic notebook will not have the pane caption visible
4128
==================================== ==================================
4130
Default value for `agwFlags` is:
4131
``AUI_MGR_DEFAULT`` = ``AUI_MGR_ALLOW_FLOATING`` | ``AUI_MGR_TRANSPARENT_HINT`` | ``AUI_MGR_HINT_FADE`` | ``AUI_MGR_NO_VENETIAN_BLINDS_FADE``
4135
If using the ``AUI_MGR_USE_NATIVE_MINIFRAMES``, double-clicking on a
4136
floating pane caption will not re-dock the pane, but simply maximize it (if
4137
:meth:`AuiPaneInfo.MaximizeButton` has been set to ``True``) or do nothing.
4141
wx.EvtHandler.__init__(self)
4143
self._action = actionNone
4144
self._action_window = None
4145
self._hover_button = None
4146
self._art = dockart.AuiDefaultDockArt()
4147
self._hint_window = None
4148
self._active_pane = None
4149
self._has_maximized = False
4150
self._has_minimized = False
4153
self._dock_constraint_x = 0.3
4154
self._dock_constraint_y = 0.3
4155
self._reserved = None
4162
self._notebooks = []
4164
self._masterManager = None
4165
self._currentDragItem = -1
4166
self._lastknowndocks = {}
4168
self._hint_fadetimer = wx.Timer(self, wx.ID_ANY)
4169
self._hint_fademax = 50
4170
self._last_hint = wx.Rect()
4172
self._from_move = False
4173
self._last_rect = wx.Rect()
4175
if agwFlags is None:
4176
agwFlags = AUI_MGR_DEFAULT
4178
self._agwFlags = agwFlags
4179
self._is_docked = (False, wx.RIGHT, wx.TOP, 0)
4180
self._snap_limits = (15, 15)
4182
if wx.Platform == "__WXMSW__":
4183
self._animation_step = 30.0
4185
self._animation_step = 5.0
4187
self._hint_rect = wx.Rect()
4189
self._preview_timer = wx.Timer(self, wx.ID_ANY)
4190
self._sliding_frame = None
4192
self._autoNBTabArt = tabart.AuiDefaultTabArt()
4193
self._autoNBStyle = AUI_NB_DEFAULT_STYLE | AUI_NB_BOTTOM | \
4194
AUI_NB_SUB_NOTEBOOK | AUI_NB_TAB_EXTERNAL_MOVE
4195
self._autoNBStyle -= AUI_NB_DRAW_DND_TAB
4198
self.SetManagedWindow(managed_window)
4200
self.Bind(wx.EVT_PAINT, self.OnPaint)
4201
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
4202
self.Bind(wx.EVT_SIZE, self.OnSize)
4203
self.Bind(wx.EVT_SET_CURSOR, self.OnSetCursor)
4204
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
4205
self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
4206
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
4207
self.Bind(wx.EVT_MOTION, self.OnMotion)
4208
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
4209
self.Bind(wx.EVT_CHILD_FOCUS, self.OnChildFocus)
4210
self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.OnCaptureLost)
4211
self.Bind(wx.EVT_TIMER, self.OnHintFadeTimer, self._hint_fadetimer)
4212
self.Bind(wx.EVT_TIMER, self.SlideIn, self._preview_timer)
4213
self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
4215
self.Bind(wx.EVT_MOVE, self.OnMove)
4216
self.Bind(wx.EVT_SYS_COLOUR_CHANGED, self.OnSysColourChanged)
4218
self.Bind(EVT_AUI_PANE_BUTTON, self.OnPaneButton)
4219
self.Bind(EVT_AUI_RENDER, self.OnRender)
4220
self.Bind(EVT_AUI_FIND_MANAGER, self.OnFindManager)
4221
self.Bind(EVT_AUI_PANE_MIN_RESTORE, self.OnRestoreMinimizedPane)
4222
self.Bind(EVT_AUI_PANE_DOCKED, self.OnPaneDocked)
4224
self.Bind(auibook.EVT_AUINOTEBOOK_BEGIN_DRAG, self.OnTabBeginDrag)
4225
self.Bind(auibook.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnTabPageClose)
4226
self.Bind(auibook.EVT_AUINOTEBOOK_PAGE_CHANGED, self.OnTabSelected)
4229
def CreateFloatingFrame(self, parent, pane_info):
4231
Creates a floating frame for the windows.
4233
:param Window `parent`: the floating frame parent;
4234
:param `pane_info`: the :class:`AuiPaneInfo` class with all the pane's information.
4237
return AuiFloatingFrame(parent, self, pane_info)
4240
def CanDockPanel(self, p):
4242
Returns whether a pane can be docked or not.
4244
:param `p`: the :class:`AuiPaneInfo` class with all the pane's information.
4247
# is the pane dockable?
4248
if not p.IsDockable():
4251
# if a key modifier is pressed while dragging the frame,
4252
# don't dock the window
4253
return not (wx.GetKeyState(wx.WXK_CONTROL) or wx.GetKeyState(wx.WXK_ALT))
4256
def GetPaneByWidget(self, window):
4258
This version of :meth:`GetPane` looks up a pane based on a 'pane window'.
4260
:param `window`: a :class:`Window` derived window.
4262
:see: :meth:`~AuiManager.GetPane`
4265
for p in self._panes:
4266
if p.window == window:
4272
def GetPaneByName(self, name):
4274
This version of :meth:`GetPane` looks up a pane based on a 'pane name'.
4276
:param string `name`: the pane name.
4278
:see: :meth:`GetPane`
4281
for p in self._panes:
4288
def GetPane(self, item):
4290
Looks up a :class:`AuiPaneInfo` structure based on the supplied window pointer. Upon failure,
4291
:meth:`GetPane` returns an empty :class:`AuiPaneInfo`, a condition which can be checked
4292
by calling :meth:`AuiPaneInfo.IsOk() <AuiPaneInfo.IsOk>`.
4294
The pane info's structure may then be modified. Once a pane's info is modified, :meth:`Update`
4295
must be called to realize the changes in the UI.
4297
:param `item`: either a pane name or a :class:`Window`.
4300
if isinstance(item, basestring):
4301
return self.GetPaneByName(item)
4303
return self.GetPaneByWidget(item)
4306
def GetAllPanes(self):
4307
""" Returns a reference to all the pane info structures. """
4312
def ShowPane(self, window, show):
4314
Shows or hides a pane based on the window passed as input.
4316
:param Window `window`: any subclass or derivation of :class:`Window`;
4317
:param bool `show`: ``True`` to show the pane, ``False`` otherwise.
4320
p = self.GetPane(window)
4323
if p.IsNotebookPage():
4326
notebook = self._notebooks[p.notebook_id]
4327
id = notebook.GetPageIndex(p.window)
4329
notebook.SetSelection(id)
4330
self.ShowPane(notebook, True)
4341
def HitTest(self, x, y):
4343
This is an internal function which determines
4344
which UI item the specified coordinates are over.
4346
:param integer `x`: specifies a x position in client coordinates;
4347
:param integer `y`: specifies a y position in client coordinates.
4352
for item in self._uiparts:
4353
# we are not interested in typeDock, because this space
4354
# isn't used to draw anything, just for measurements
4355
# besides, the entire dock area is covered with other
4356
# rectangles, which we are interested in.
4357
if item.type == AuiDockUIPart.typeDock:
4360
# if we already have a hit on a more specific item, we are not
4361
# interested in a pane hit. If, however, we don't already have
4362
# a hit, returning a pane hit is necessary for some operations
4363
if item.type in [AuiDockUIPart.typePane, AuiDockUIPart.typePaneBorder] and result:
4366
# if the point is inside the rectangle, we have a hit
4367
if item.rect.Contains((x, y)):
4373
def PaneHitTest(self, panes, pt):
4375
Similar to :meth:`HitTest`, but it checks in which :class:`AuiManager` rectangle the
4376
input point belongs to.
4378
:param `panes`: a list of :class:`AuiPaneInfo` instances;
4379
:param Point `pt`: the mouse position.
4382
for paneInfo in panes:
4383
if paneInfo.IsDocked() and paneInfo.IsShown() and paneInfo.rect.Contains(pt):
4389
# SetAGWFlags() and GetAGWFlags() allow the owner to set various
4390
# options which are global to AuiManager
4392
def SetAGWFlags(self, agwFlags):
4394
This method is used to specify :class:`AuiManager` 's settings flags.
4396
:param integer `agwFlags`: specifies options which allow the frame management behavior
4397
to be modified. `agwFlags` can be one of the following style bits:
4399
==================================== ==================================
4400
Flag name Description
4401
==================================== ==================================
4402
``AUI_MGR_ALLOW_FLOATING`` Allow floating of panes
4403
``AUI_MGR_ALLOW_ACTIVE_PANE`` If a pane becomes active, "highlight" it in the interface
4404
``AUI_MGR_TRANSPARENT_DRAG`` If the platform supports it, set transparency on a floating pane while it is dragged by the user
4405
``AUI_MGR_TRANSPARENT_HINT`` If the platform supports it, show a transparent hint window when the user is about to dock a floating pane
4406
``AUI_MGR_VENETIAN_BLINDS_HINT`` Show a "venetian blind" effect when the user is about to dock a floating pane
4407
``AUI_MGR_RECTANGLE_HINT`` Show a rectangle hint effect when the user is about to dock a floating pane
4408
``AUI_MGR_HINT_FADE`` If the platform supports it, the hint window will fade in and out
4409
``AUI_MGR_NO_VENETIAN_BLINDS_FADE`` Disables the "venetian blind" fade in and out
4410
``AUI_MGR_LIVE_RESIZE`` Live resize when the user drag a sash
4411
``AUI_MGR_ANIMATE_FRAMES`` Fade-out floating panes when they are closed (all platforms which support frames transparency)
4412
and show a moving rectangle when they are docked (Windows < Vista and GTK only)
4413
``AUI_MGR_AERO_DOCKING_GUIDES`` Use the new Aero-style bitmaps as docking guides
4414
``AUI_MGR_PREVIEW_MINIMIZED_PANES`` Slide in and out minimized panes to preview them
4415
``AUI_MGR_WHIDBEY_DOCKING_GUIDES`` Use the new Whidbey-style bitmaps as docking guides
4416
``AUI_MGR_SMOOTH_DOCKING`` Performs a "smooth" docking of panes (a la PyQT)
4417
``AUI_MGR_USE_NATIVE_MINIFRAMES`` Use miniframes with native caption bar as floating panes instead or custom drawn caption bars (forced on wxMAC)
4418
``AUI_MGR_AUTONB_NO_CAPTION`` Panes that merge into an automatic notebook will not have the pane caption visible
4419
==================================== ==================================
4423
If using the ``AUI_MGR_USE_NATIVE_MINIFRAMES``, double-clicking on a
4424
floating pane caption will not re-dock the pane, but simply maximize it (if
4425
:meth:`AuiPaneInfo.MaximizeButton` has been set to ``True``) or do nothing.
4429
self._agwFlags = agwFlags
4431
if len(self._guides) > 0:
4432
self.CreateGuideWindows()
4434
if self._hint_window and agwFlags & AUI_MGR_RECTANGLE_HINT == 0:
4435
self.CreateHintWindow()
4438
def GetAGWFlags(self):
4440
Returns the current manager's flags.
4442
:see: :meth:`SetAGWFlags` for a list of possible :class:`AuiManager` flags.
4445
return self._agwFlags
4448
def SetManagedWindow(self, managed_window):
4450
Called to specify the frame or window which is to be managed by :class:`AuiManager`.
4451
Frame management is not restricted to just frames. Child windows or custom
4452
controls are also allowed.
4454
:param Window `managed_window`: specifies the window which should be managed by
4458
if not managed_window:
4459
raise Exception("Specified managed window must be non-null. ")
4463
self._frame = managed_window
4464
self._frame.PushEventHandler(self)
4466
# if the owner is going to manage an MDI parent frame,
4467
# we need to add the MDI client window as the default
4470
if isinstance(self._frame, wx.MDIParentFrame):
4471
mdi_frame = self._frame
4472
client_window = mdi_frame.GetClientWindow()
4474
if not client_window:
4475
raise Exception("Client window is None!")
4477
self.AddPane(client_window, AuiPaneInfo().Name("mdiclient").
4478
CenterPane().PaneBorder(False))
4480
elif isinstance(self._frame, tabmdi.AuiMDIParentFrame):
4482
mdi_frame = self._frame
4483
client_window = mdi_frame.GetClientWindow()
4485
if not client_window:
4486
raise Exception("Client window is None!")
4488
self.AddPane(client_window, AuiPaneInfo().Name("mdiclient").
4489
CenterPane().PaneBorder(False))
4492
def GetManagedWindow(self):
4493
""" Returns the window being managed by :class:`AuiManager`. """
4498
def SetFrame(self, managed_window):
4500
Called to specify the frame or window which is to be managed by :class:`AuiManager`.
4501
Frame management is not restricted to just frames. Child windows or custom
4502
controls are also allowed.
4504
:param Window `managed_window`: specifies the window which should be managed by
4508
This method is now deprecated, use :meth:`SetManagedWindow` instead.
4511
DeprecationWarning("This method is deprecated, use SetManagedWindow instead.")
4512
return self.SetManagedWindow(managed_window)
4517
Returns the window being managed by :class:`AuiManager`.
4520
This method is now deprecated, use :meth:`GetManagedWindow` instead.
4523
DeprecationWarning("This method is deprecated, use GetManagedWindow instead.")
4527
def CreateGuideWindows(self):
4528
""" Creates the VS2005 HUD guide windows. """
4530
self.DestroyGuideWindows()
4532
self._guides.append(AuiDockingGuideInfo().Left().
4533
Host(AuiSingleDockingGuide(self._frame, wx.LEFT)))
4534
self._guides.append(AuiDockingGuideInfo().Top().
4535
Host(AuiSingleDockingGuide(self._frame, wx.TOP)))
4536
self._guides.append(AuiDockingGuideInfo().Right().
4537
Host(AuiSingleDockingGuide(self._frame, wx.RIGHT)))
4538
self._guides.append(AuiDockingGuideInfo().Bottom().
4539
Host(AuiSingleDockingGuide(self._frame, wx.BOTTOM)))
4540
self._guides.append(AuiDockingGuideInfo().Centre().
4541
Host(AuiCenterDockingGuide(self._frame)))
4544
def DestroyGuideWindows(self):
4545
""" Destroys the VS2005 HUD guide windows. """
4547
for guide in self._guides:
4549
guide.host.Destroy()
4554
def CreateHintWindow(self):
4555
""" Creates the standard wxAUI hint window. """
4557
self.DestroyHintWindow()
4559
self._hint_window = AuiDockingHintWindow(self._frame)
4560
self._hint_window.SetBlindMode(self._agwFlags)
4563
def DestroyHintWindow(self):
4564
""" Destroys the standard wxAUI hint window. """
4566
if self._hint_window:
4568
self._hint_window.Destroy()
4569
self._hint_window = None
4574
Uninitializes the framework and should be called before a managed frame or
4575
window is destroyed. :meth:`UnInit` is usually called in the managed :class:`Frame` / :class:`Window`
4578
It is necessary to call this function before the managed frame or window is
4579
destroyed, otherwise the manager cannot remove its custom event handlers
4586
for klass in [self._frame] + list(self._frame.GetChildren()):
4587
handler = klass.GetEventHandler()
4588
if klass is not handler:
4589
if isinstance(handler, AuiManager):
4590
klass.RemoveEventHandler(handler)
4593
def OnDestroy(self, event) :
4595
if self._frame == event.GetEventObject():
4599
def GetArtProvider(self):
4600
""" Returns the current art provider being used. """
4605
def ProcessMgrEvent(self, event):
4607
Process the AUI events sent to the manager.
4609
:param `event`: the event to process, an instance of :class:`AuiManagerEvent`.
4612
# first, give the owner frame a chance to override
4614
if self._frame.GetEventHandler().ProcessEvent(event):
4617
self.ProcessEvent(event)
4620
def FireEvent(self, evtType, pane, canVeto=False):
4622
Fires one of the ``EVT_AUI_PANE_FLOATED`` / ``FLOATING`` / ``DOCKING`` / ``DOCKED`` / ``ACTIVATED`` event.
4624
:param integer `evtType`: one of the aforementioned events;
4625
:param `pane`: the :class:`AuiPaneInfo` instance associated to this event;
4626
:param bool `canVeto`: whether the event can be vetoed or not.
4629
event = AuiManagerEvent(evtType)
4631
event.SetCanVeto(canVeto)
4632
self.ProcessMgrEvent(event)
4637
def CanUseModernDockArt(self):
4639
Returns whether :class:`dockart` can be used (Windows XP / Vista / 7 only,
4640
requires Mark Hammonds's `pywin32 <http://sourceforge.net/projects/pywin32/>`_ package).
4646
# Get the size of a small close button (themed)
4647
hwnd = self._frame.GetHandle()
4648
hTheme = winxptheme.OpenThemeData(hwnd, "Window")
4656
def SetArtProvider(self, art_provider):
4658
Instructs :class:`AuiManager` to use art provider specified by the parameter
4659
`art_provider` for all drawing calls. This allows plugable look-and-feel
4662
:param `art_provider`: a AUI dock art provider.
4664
:note: The previous art provider object, if any, will be deleted by :class:`AuiManager`.
4667
# delete the last art provider, if any
4670
# assign the new art provider
4671
self._art = art_provider
4673
for pane in self.GetAllPanes():
4674
if pane.IsFloating() and pane.frame:
4675
pane.frame._mgr.SetArtProvider(art_provider)
4676
pane.frame._mgr.Update()
4679
def AddPane(self, window, arg1=None, arg2=None, target=None):
4681
Tells the frame manager to start managing a child window. There
4682
are four versions of this function. The first verison allows the full spectrum
4683
of pane parameter possibilities (:meth:`AddPane1`). The second version is used for
4684
simpler user interfaces which do not require as much configuration (:meth:`AddPane2`).
4685
The :meth:`AddPane3` version allows a drop position to be specified, which will determine
4686
where the pane will be added. The :meth:`AddPane4` version allows to turn the target
4687
:class:`AuiPaneInfo` pane into a notebook and the added pane into a page.
4689
In your code, simply call :meth:`AddPane`.
4691
:param Window `window`: the child window to manage;
4692
:param `arg1`: a :class:`AuiPaneInfo` or an integer value (direction);
4693
:param `arg2`: a :class:`AuiPaneInfo` or a :class:`Point` (drop position);
4694
:param `target`: a :class:`AuiPaneInfo` to be turned into a notebook
4695
and new pane added to it as a page. (additionally, target can be any pane in
4696
an existing notebook)
4699
if target in self._panes:
4700
return self.AddPane4(window, arg1, target)
4702
if type(arg1) == type(1):
4708
return self.AddPane2(window, arg1, arg2)
4710
if isinstance(arg2, wx.Point):
4711
return self.AddPane3(window, arg1, arg2)
4713
return self.AddPane1(window, arg1)
4716
def AddPane1(self, window, pane_info):
4717
""" See comments on :meth:`AddPane`. """
4719
# check if the pane has a valid window
4723
# check if the pane already exists
4724
if self.GetPane(pane_info.window).IsOk():
4727
# check if the pane name already exists, this could reveal a
4728
# bug in the library user's application
4729
already_exists = False
4730
if pane_info.name != "" and self.GetPane(pane_info.name).IsOk():
4731
warnings.warn("A pane with the name '%s' already exists in the manager!"%pane_info.name)
4732
already_exists = True
4734
# if the new pane is docked then we should undo maximize
4735
if pane_info.IsDocked():
4736
self.RestoreMaximizedPane()
4738
self._panes.append(pane_info)
4739
pinfo = self._panes[-1]
4741
# set the pane window
4742
pinfo.window = window
4744
# if the pane's name identifier is blank, create a random string
4745
if pinfo.name == "" or already_exists:
4746
pinfo.name = ("%s%08x%08x%08x")%(pinfo.window.GetName(), time.time(),
4747
time.clock(), len(self._panes))
4749
# set initial proportion (if not already set)
4750
if pinfo.dock_proportion == 0:
4751
pinfo.dock_proportion = 100000
4753
floating = isinstance(self._frame, AuiFloatingFrame)
4757
if not floating and pinfo.HasMinimizeButton():
4758
button = AuiPaneButton(AUI_BUTTON_MINIMIZE)
4759
pinfo.buttons.append(button)
4761
if not floating and pinfo.HasMaximizeButton():
4762
button = AuiPaneButton(AUI_BUTTON_MAXIMIZE_RESTORE)
4763
pinfo.buttons.append(button)
4765
if not floating and pinfo.HasPinButton():
4766
button = AuiPaneButton(AUI_BUTTON_PIN)
4767
pinfo.buttons.append(button)
4769
if pinfo.HasCloseButton():
4770
button = AuiPaneButton(AUI_BUTTON_CLOSE)
4771
pinfo.buttons.append(button)
4773
if pinfo.HasGripper():
4774
if isinstance(pinfo.window, auibar.AuiToolBar):
4775
# prevent duplicate gripper -- both AuiManager and AuiToolBar
4776
# have a gripper control. The toolbar's built-in gripper
4777
# meshes better with the look and feel of the control than ours,
4778
# so turn AuiManager's gripper off, and the toolbar's on.
4781
pinfo.SetFlag(AuiPaneInfo.optionGripper, False)
4782
tb.SetGripperVisible(True)
4785
if pinfo.best_size == wx.Size(-1, -1):
4786
pinfo.best_size = pinfo.window.GetClientSize()
4788
if isinstance(pinfo.window, wx.ToolBar):
4789
# GetClientSize() doesn't get the best size for
4790
# a toolbar under some newer versions of wxWidgets,
4791
# so use GetBestSize()
4792
pinfo.best_size = pinfo.window.GetBestSize()
4794
# this is needed for Win2000 to correctly fill toolbar backround
4795
# it should probably be repeated once system colour change happens
4796
if wx.Platform == "__WXMSW__" and pinfo.window.UseBgCol():
4797
pinfo.window.SetBackgroundColour(self.GetArtProvider().GetColour(AUI_DOCKART_BACKGROUND_COLOUR))
4799
if pinfo.min_size != wx.Size(-1, -1):
4800
if pinfo.best_size.x < pinfo.min_size.x:
4801
pinfo.best_size.x = pinfo.min_size.x
4802
if pinfo.best_size.y < pinfo.min_size.y:
4803
pinfo.best_size.y = pinfo.min_size.y
4805
self._panes[-1] = pinfo
4806
if isinstance(window, auibar.AuiToolBar):
4807
window.SetAuiManager(self)
4812
def AddPane2(self, window, direction, caption):
4813
""" See comments on :meth:`AddPane`. """
4815
pinfo = AuiPaneInfo()
4816
pinfo.Caption(caption)
4818
if direction == wx.TOP:
4820
elif direction == wx.BOTTOM:
4822
elif direction == wx.LEFT:
4824
elif direction == wx.RIGHT:
4826
elif direction == wx.CENTER:
4829
return self.AddPane(window, pinfo)
4832
def AddPane3(self, window, pane_info, drop_pos):
4833
""" See comments on :meth:`AddPane`. """
4835
if not self.AddPane(window, pane_info):
4838
pane = self.GetPane(window)
4839
indx = self._panes.index(pane)
4841
ret, pane = self.DoDrop(self._docks, self._panes, pane, drop_pos, wx.Point(0, 0))
4842
self._panes[indx] = pane
4847
def AddPane4(self, window, pane_info, target):
4848
""" See comments on :meth:`AddPane`. """
4850
if not self.AddPane(window, pane_info):
4853
paneInfo = self.GetPane(window)
4855
if not paneInfo.IsNotebookDockable():
4856
return self.AddPane1(window, pane_info)
4857
if not target.IsNotebookDockable() and not target.IsNotebookControl():
4858
return self.AddPane1(window, pane_info)
4860
if not target.HasNotebook():
4861
self.CreateNotebookBase(self._panes, target)
4863
# Add new item to notebook
4864
paneInfo.NotebookPage(target.notebook_id)
4866
# we also want to remove our captions sometimes
4867
self.RemoveAutoNBCaption(paneInfo)
4868
self.UpdateNotebook()
4873
def InsertPane(self, window, pane_info, insert_level=AUI_INSERT_PANE):
4875
This method is used to insert either a previously unmanaged pane window
4876
into the frame manager, or to insert a currently managed pane somewhere else.
4877
:meth:`InsertPane` will push all panes, rows, or docks aside and insert the window
4878
into the position specified by `pane_info`.
4880
Because `pane_info` can specify either a pane, dock row, or dock layer, the
4881
`insert_level` parameter is used to disambiguate this. The parameter `insert_level`
4882
can take a value of ``AUI_INSERT_PANE``, ``AUI_INSERT_ROW`` or ``AUI_INSERT_DOCK``.
4884
:param Window `window`: the window to be inserted and managed;
4885
:param `pane_info`: the insert location for the new window;
4886
:param integer `insert_level`: the insertion level of the new pane.
4890
raise Exception("Invalid window passed to InsertPane.")
4892
# shift the panes around, depending on the insert level
4893
if insert_level == AUI_INSERT_PANE:
4894
self._panes = DoInsertPane(self._panes, pane_info.dock_direction,
4895
pane_info.dock_layer, pane_info.dock_row,
4898
elif insert_level == AUI_INSERT_ROW:
4899
self._panes = DoInsertDockRow(self._panes, pane_info.dock_direction,
4900
pane_info.dock_layer, pane_info.dock_row)
4902
elif insert_level == AUI_INSERT_DOCK:
4903
self._panes = DoInsertDockLayer(self._panes, pane_info.dock_direction,
4904
pane_info.dock_layer)
4906
# if the window already exists, we are basically just moving/inserting the
4907
# existing window. If it doesn't exist, we need to add it and insert it
4908
existing_pane = self.GetPane(window)
4909
indx = self._panes.index(existing_pane)
4911
if not existing_pane.IsOk():
4913
return self.AddPane(window, pane_info)
4917
if pane_info.IsFloating():
4918
existing_pane.Float()
4919
if pane_info.floating_pos != wx.Point(-1, -1):
4920
existing_pane.FloatingPosition(pane_info.floating_pos)
4921
if pane_info.floating_size != wx.Size(-1, -1):
4922
existing_pane.FloatingSize(pane_info.floating_size)
4924
# if the new pane is docked then we should undo maximize
4925
self.RestoreMaximizedPane()
4927
existing_pane.Direction(pane_info.dock_direction)
4928
existing_pane.Layer(pane_info.dock_layer)
4929
existing_pane.Row(pane_info.dock_row)
4930
existing_pane.Position(pane_info.dock_pos)
4932
self._panes[indx] = existing_pane
4937
def DetachPane(self, window):
4939
Tells the :class:`AuiManager` to stop managing the pane specified
4940
by `window`. The window, if in a floated frame, is reparented to the frame
4941
managed by :class:`AuiManager`.
4943
:param Window `window`: the window to be un-managed.
4946
for p in self._panes:
4947
if p.window == window:
4949
# we have a floating frame which is being detached. We need to
4950
# reparent it to self._frame and destroy the floating frame
4953
p.window.SetSize((1, 1))
4954
if p.frame.IsShown():
4957
if self._action_window == p.frame:
4958
self._action_window = None
4960
# reparent to self._frame and destroy the pane
4961
p.window.Reparent(self._frame)
4962
p.frame.SetSizer(None)
4966
elif p.IsNotebookPage():
4967
notebook = self._notebooks[p.notebook_id]
4968
id = notebook.GetPageIndex(p.window)
4969
notebook.RemovePage(id)
4971
# make sure there are no references to this pane in our uiparts,
4972
# just in case the caller doesn't call Update() immediately after
4973
# the DetachPane() call. This prevets obscure crashes which would
4974
# happen at window repaint if the caller forgets to call Update()
4976
for pi in xrange(len(self._uiparts)):
4977
part = self._uiparts[counter]
4979
self._uiparts.pop(counter)
4984
self._panes.remove(p)
4990
def ClosePane(self, pane_info):
4992
Destroys or hides the pane depending on its flags.
4994
:param `pane_info`: a :class:`AuiPaneInfo` instance.
4997
# if we were maximized, restore
4998
if pane_info.IsMaximized():
4999
self.RestorePane(pane_info)
5002
if self._agwFlags & AUI_MGR_ANIMATE_FRAMES:
5003
pane_info.frame.FadeOut()
5005
# first, hide the window
5006
if pane_info.window and pane_info.window.IsShown():
5007
pane_info.window.Show(False)
5009
# make sure that we are the parent of this window
5010
if pane_info.window and pane_info.window.GetParent() != self._frame:
5011
pane_info.window.Reparent(self._frame)
5013
# if we have a frame, destroy it
5015
pane_info.frame.Destroy()
5016
pane_info.frame = None
5018
elif pane_info.IsNotebookPage():
5019
# if we are a notebook page, remove ourselves...
5020
# the code would index out of bounds
5021
# if the last page of a sub-notebook was closed
5022
# because the notebook would be deleted, before this
5024
# This code just prevents an out-of bounds error.
5026
nid = pane_info.notebook_id
5027
if nid >= 0 and nid < len(self._notebooks):
5028
notebook = self._notebooks[nid]
5029
page_idx = notebook.GetPageIndex(pane_info.window)
5031
notebook.RemovePage(page_idx)
5033
# now we need to either destroy or hide the pane
5035
if pane_info.IsDestroyOnClose():
5036
to_destroy = pane_info.window
5037
self.DetachPane(to_destroy)
5039
if isinstance(pane_info.window, auibar.AuiToolBar) and pane_info.IsFloating():
5040
tb = pane_info.window
5041
if pane_info.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT]:
5042
tb.SetAGWWindowStyleFlag(tb.GetAGWWindowStyleFlag() | AUI_TB_VERTICAL)
5044
pane_info.Dock().Hide()
5046
if pane_info.IsNotebookControl():
5048
notebook = self._notebooks[pane_info.notebook_id]
5049
while notebook.GetPageCount():
5050
window = notebook.GetPage(0)
5051
notebook.RemovePage(0)
5052
info = self.GetPane(window)
5054
info.notebook_id = -1
5055
info.dock_direction = AUI_DOCK_NONE
5056
# Note: this could change our paneInfo reference ...
5057
self.ClosePane(info)
5060
to_destroy.Destroy()
5063
def MaximizePane(self, pane_info, savesizes=True):
5065
Maximizes the input pane.
5067
:param `pane_info`: a :class:`AuiPaneInfo` instance.
5068
:param bool `savesizes`: whether to save previous dock sizes.
5072
self.SavePreviousDockSizes(pane_info)
5074
for p in self._panes:
5077
p.SetFlag(p.savedHiddenState, p.HasFlag(p.optionHidden))
5079
if not p.IsToolbar() and not p.IsFloating():
5082
# hide the pane, because only the newly
5083
# maximized pane should show
5086
pane_info.previousDockPos = pane_info.dock_pos
5088
# mark ourselves maximized
5089
pane_info.Maximize()
5091
self._has_maximized = True
5093
# last, show the window
5094
if pane_info.window and not pane_info.window.IsShown():
5095
pane_info.window.Show(True)
5098
def SavePreviousDockSizes(self, pane_info):
5100
Stores the previous dock sizes, to be used in a "restore" action later.
5102
:param `pane_info`: a :class:`AuiPaneInfo` instance.
5105
for d in self._docks:
5108
p.previousDockSize = d.size
5109
if pane_info is not p:
5110
p.SetFlag(p.needsRestore, True)
5113
def RestorePane(self, pane_info):
5115
Restores the input pane from a previous maximized or minimized state.
5117
:param `pane_info`: a :class:`AuiPaneInfo` instance.
5120
# restore all the panes
5121
for p in self._panes:
5122
if not p.IsToolbar():
5123
p.SetFlag(p.optionHidden, p.HasFlag(p.savedHiddenState))
5125
pane_info.SetFlag(pane_info.needsRestore, True)
5127
# mark ourselves non-maximized
5129
self._has_maximized = False
5130
self._has_minimized = False
5132
# last, show the window
5133
if pane_info.window and not pane_info.window.IsShown():
5134
pane_info.window.Show(True)
5137
def RestoreMaximizedPane(self):
5138
""" Restores the current maximized pane (if any). """
5140
# restore all the panes
5141
for p in self._panes:
5147
def ActivatePane(self, window):
5149
Activates the pane to which `window` is associated.
5151
:param `window`: a :class:`Window` derived window.
5154
if self.GetAGWFlags() & AUI_MGR_ALLOW_ACTIVE_PANE:
5156
ret, self._panes = SetActivePane(self._panes, window)
5160
window = window.GetParent()
5162
self.RefreshCaptions()
5163
self.FireEvent(wxEVT_AUI_PANE_ACTIVATED, window, canVeto=False)
5166
def CreateNotebook(self):
5168
Creates an automatic :class:`~lib.agw.aui.auibook.AuiNotebook` when a pane is docked on
5169
top of another pane.
5172
notebook = auibook.AuiNotebook(self._frame, -1, wx.Point(0, 0), wx.Size(0, 0), agwStyle=self._autoNBStyle)
5174
# This is so we can get the tab-drag event.
5175
notebook.GetAuiManager().SetMasterManager(self)
5176
notebook.SetArtProvider(self._autoNBTabArt.Clone())
5177
self._notebooks.append(notebook)
5182
def SetAutoNotebookTabArt(self, art):
5184
Sets the default tab art provider for automatic notebooks.
5186
:param `art`: a tab art provider.
5189
for nb in self._notebooks:
5190
nb.SetArtProvider(art.Clone())
5194
self._autoNBTabArt = art
5197
def GetAutoNotebookTabArt(self):
5198
""" Returns the default tab art provider for automatic notebooks. """
5200
return self._autoNBTabArt
5203
def SetAutoNotebookStyle(self, agwStyle):
5205
Sets the default AGW-specific window style for automatic notebooks.
5207
:param integer `agwStyle`: the underlying :class:`~lib.agw.aui.auibook.AuiNotebook` window style.
5208
This can be a combination of the following bits:
5210
==================================== ==================================
5211
Flag name Description
5212
==================================== ==================================
5213
``AUI_NB_TOP`` With this style, tabs are drawn along the top of the notebook
5214
``AUI_NB_LEFT`` With this style, tabs are drawn along the left of the notebook. Not implemented yet.
5215
``AUI_NB_RIGHT`` With this style, tabs are drawn along the right of the notebook. Not implemented yet.
5216
``AUI_NB_BOTTOM`` With this style, tabs are drawn along the bottom of the notebook
5217
``AUI_NB_TAB_SPLIT`` Allows the tab control to be split by dragging a tab
5218
``AUI_NB_TAB_MOVE`` Allows a tab to be moved horizontally by dragging
5219
``AUI_NB_TAB_EXTERNAL_MOVE`` Allows a tab to be moved to another tab control
5220
``AUI_NB_TAB_FIXED_WIDTH`` With this style, all tabs have the same width
5221
``AUI_NB_SCROLL_BUTTONS`` With this style, left and right scroll buttons are displayed
5222
``AUI_NB_WINDOWLIST_BUTTON`` With this style, a drop-down list of windows is available
5223
``AUI_NB_CLOSE_BUTTON`` With this style, a close button is available on the tab bar
5224
``AUI_NB_CLOSE_ON_ACTIVE_TAB`` With this style, a close button is available on the active tab
5225
``AUI_NB_CLOSE_ON_ALL_TABS`` With this style, a close button is available on all tabs
5226
``AUI_NB_MIDDLE_CLICK_CLOSE`` Allows to close :class:`~lib.agw.aui.auibook.AuiNotebook` tabs by mouse middle button click
5227
``AUI_NB_SUB_NOTEBOOK`` This style is used by :class:`AuiManager` to create automatic AuiNotebooks
5228
``AUI_NB_HIDE_ON_SINGLE_TAB`` Hides the tab window if only one tab is present
5229
``AUI_NB_SMART_TABS`` Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows
5230
``AUI_NB_USE_IMAGES_DROPDOWN`` Uses images on dropdown window list menu instead of check items
5231
``AUI_NB_CLOSE_ON_TAB_LEFT`` Draws the tab close button on the left instead of on the right (a la Camino browser)
5232
``AUI_NB_TAB_FLOAT`` Allows the floating of single tabs. Known limitation: when the notebook is more or less
5233
full screen, tabs cannot be dragged far enough outside of the notebook to become floating pages
5234
``AUI_NB_DRAW_DND_TAB`` Draws an image representation of a tab while dragging (on by default)
5235
``AUI_NB_ORDER_BY_ACCESS`` Tab navigation order by last access time for the tabs
5236
``AUI_NB_NO_TAB_FOCUS`` Don't draw tab focus rectangle
5237
==================================== ==================================
5241
for nb in self._notebooks:
5242
nb.SetAGWWindowStyleFlag(agwStyle)
5246
self._autoNBStyle = agwStyle
5249
def GetAutoNotebookStyle(self):
5251
Returns the default AGW-specific window style for automatic notebooks.
5253
:see: :meth:`SetAutoNotebookStyle` method for a list of possible styles.
5256
return self._autoNBStyle
5259
def SavePaneInfo(self, pane):
5261
This method is similar to :meth:`SavePerspective`, with the exception
5262
that it only saves information about a single pane. It is used in
5263
combination with :meth:`LoadPaneInfo`.
5265
:param `pane`: a :class:`AuiPaneInfo` instance to save.
5268
result = "name=" + EscapeDelimiters(pane.name) + ";"
5269
result += "caption=" + EscapeDelimiters(pane.caption) + ";"
5271
result += "state=%u;"%pane.state
5272
result += "dir=%d;"%pane.dock_direction
5273
result += "layer=%d;"%pane.dock_layer
5274
result += "row=%d;"%pane.dock_row
5275
result += "pos=%d;"%pane.dock_pos
5276
result += "prop=%d;"%pane.dock_proportion
5277
result += "bestw=%d;"%pane.best_size.x
5278
result += "besth=%d;"%pane.best_size.y
5279
result += "minw=%d;"%pane.min_size.x
5280
result += "minh=%d;"%pane.min_size.y
5281
result += "maxw=%d;"%pane.max_size.x
5282
result += "maxh=%d;"%pane.max_size.y
5283
result += "floatx=%d;"%pane.floating_pos.x
5284
result += "floaty=%d;"%pane.floating_pos.y
5285
result += "floatw=%d;"%pane.floating_size.x
5286
result += "floath=%d;"%pane.floating_size.y
5287
result += "notebookid=%d;"%pane.notebook_id
5288
result += "transparent=%d"%pane.transparent
5293
def LoadPaneInfo(self, pane_part, pane):
5295
This method is similar to to :meth:`LoadPerspective`, with the exception that
5296
it only loads information about a single pane. It is used in combination
5297
with :meth:`SavePaneInfo`.
5299
:param string `pane_part`: the string to analyze;
5300
:param `pane`: the :class:`AuiPaneInfo` structure in which to load `pane_part`.
5303
# replace escaped characters so we can
5304
# split up the string easily
5305
pane_part = pane_part.replace("\\|", "\a")
5306
pane_part = pane_part.replace("\\;", "\b")
5308
options = pane_part.split(";")
5309
for items in options:
5311
val_name, value = items.split("=")
5312
val_name = val_name.strip()
5314
if val_name == "name":
5316
elif val_name == "caption":
5317
pane.caption = value
5318
elif val_name == "state":
5319
pane.state = int(value)
5320
elif val_name == "dir":
5321
pane.dock_direction = int(value)
5322
elif val_name == "layer":
5323
pane.dock_layer = int(value)
5324
elif val_name == "row":
5325
pane.dock_row = int(value)
5326
elif val_name == "pos":
5327
pane.dock_pos = int(value)
5328
elif val_name == "prop":
5329
pane.dock_proportion = int(value)
5330
elif val_name == "bestw":
5331
pane.best_size.x = int(value)
5332
elif val_name == "besth":
5333
pane.best_size.y = int(value)
5334
pane.best_size = wx.Size(pane.best_size.x, pane.best_size.y)
5335
elif val_name == "minw":
5336
pane.min_size.x = int(value)
5337
elif val_name == "minh":
5338
pane.min_size.y = int(value)
5339
pane.min_size = wx.Size(pane.min_size.x, pane.min_size.y)
5340
elif val_name == "maxw":
5341
pane.max_size.x = int(value)
5342
elif val_name == "maxh":
5343
pane.max_size.y = int(value)
5344
pane.max_size = wx.Size(pane.max_size.x, pane.max_size.y)
5345
elif val_name == "floatx":
5346
pane.floating_pos.x = int(value)
5347
elif val_name == "floaty":
5348
pane.floating_pos.y = int(value)
5349
pane.floating_pos = wx.Point(pane.floating_pos.x, pane.floating_pos.y)
5350
elif val_name == "floatw":
5351
pane.floating_size.x = int(value)
5352
elif val_name == "floath":
5353
pane.floating_size.y = int(value)
5354
pane.floating_size = wx.Size(pane.floating_size.x, pane.floating_size.y)
5355
elif val_name == "notebookid":
5356
pane.notebook_id = int(value)
5357
elif val_name == "transparent":
5358
pane.transparent = int(value)
5360
raise Exception("Bad perspective string")
5362
# replace escaped characters so we can
5363
# split up the string easily
5364
pane.name = pane.name.replace("\a", "|")
5365
pane.name = pane.name.replace("\b", ";")
5366
pane.caption = pane.caption.replace("\a", "|")
5367
pane.caption = pane.caption.replace("\b", ";")
5368
pane_part = pane_part.replace("\a", "|")
5369
pane_part = pane_part.replace("\b", ";")
5374
def SavePerspective(self):
5376
Saves the entire user interface layout into an encoded string, which can then
5377
be stored by the application (probably using :class:`Config`).
5379
When a perspective is restored using :meth:`LoadPerspective`, the entire user
5380
interface will return to the state it was when the perspective was saved.
5385
for pane in self._panes:
5386
result += self.SavePaneInfo(pane) + "|"
5388
for dock in self._docks:
5389
result = result + ("dock_size(%d,%d,%d)=%d|")%(dock.dock_direction,
5396
def LoadPerspective(self, layout, update=True, restorecaption=False):
5398
Loads a layout which was saved with :meth:`SavePerspective`.
5400
If the `update` flag parameter is ``True``, :meth:`Update` will be
5401
automatically invoked, thus realizing the saved perspective on screen.
5403
:param string `layout`: a string which contains a saved AUI layout;
5404
:param bool `update`: whether to update immediately the window or not;
5405
:param bool `restorecaption`: ``False``, restore from persist storage,
5406
otherwise use the caption defined in code.
5411
# check layout string version
5412
# 'layout1' = wxAUI 0.9.0 - wxAUI 0.9.2
5413
# 'layout2' = wxAUI 0.9.2 (wxWidgets 2.8)
5414
index = input.find("|")
5415
part = input[0:index].strip()
5416
input = input[index+1:]
5418
if part != "layout2":
5421
# mark all panes currently managed as docked and hidden
5422
saveCapt = {} # see restorecaption param
5423
for pane in self._panes:
5425
saveCapt[pane.name] = pane.caption
5427
# clear out the dock array; this will be reconstructed
5430
# replace escaped characters so we can
5431
# split up the string easily
5432
input = input.replace("\\|", "\a")
5433
input = input.replace("\\;", "\b")
5437
pane = AuiPaneInfo()
5438
index = input.find("|")
5439
pane_part = input[0:index].strip()
5440
input = input[index+1:]
5442
# if the string is empty, we're done parsing
5446
if pane_part[0:9] == "dock_size":
5447
index = pane_part.find("=")
5448
val_name = pane_part[0:index]
5449
value = pane_part[index+1:]
5451
index = val_name.find("(")
5452
piece = val_name[index+1:]
5453
index = piece.find(")")
5454
piece = piece[0:index]
5456
vals = piece.split(",")
5458
layer = int(vals[1])
5462
dock = AuiDockInfo()
5463
dock.dock_direction = dir
5464
dock.dock_layer = layer
5467
self._docks.append(dock)
5471
# Undo our escaping as LoadPaneInfo needs to take an unescaped
5472
# name so it can be called by external callers
5473
pane_part = pane_part.replace("\a", "|")
5474
pane_part = pane_part.replace("\b", ";")
5476
pane = self.LoadPaneInfo(pane_part, pane)
5478
p = self.GetPane(pane.name)
5479
# restore pane caption from code
5481
if pane.name in saveCapt:
5482
pane.Caption(saveCapt[pane.name])
5485
if pane.IsNotebookControl():
5486
# notebook controls - auto add...
5487
self._panes.append(pane)
5488
indx = self._panes.index(pane)
5490
# the pane window couldn't be found
5491
# in the existing layout -- skip it
5495
indx = self._panes.index(p)
5496
pane.window = p.window
5497
pane.frame = p.frame
5498
pane.buttons = p.buttons
5499
self._panes[indx] = pane
5501
if isinstance(pane.window, auibar.AuiToolBar) and (pane.IsFloatable() or pane.IsDockable()):
5502
pane.window.SetGripperVisible(True)
5504
for p in self._panes:
5506
self.MinimizePane(p, False)
5514
def GetPanePositionsAndSizes(self, dock):
5516
Returns all the panes positions and sizes in a dock.
5518
:param `dock`: a :class:`AuiDockInfo` instance.
5521
caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
5522
pane_border_size = self._art.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE)
5523
gripper_size = self._art.GetMetric(AUI_DOCKART_GRIPPER_SIZE)
5529
pane_count = len(dock.panes)
5531
# find the pane marked as our action pane
5532
for pane_i in xrange(pane_count):
5533
pane = dock.panes[pane_i]
5534
if pane.HasFlag(AuiPaneInfo.actionPane):
5535
if action_pane != -1:
5536
raise Exception("Too many action panes!")
5537
action_pane = pane_i
5539
# set up each panes default position, and
5540
# determine the size (width or height, depending
5541
# on the dock's orientation) of each pane
5542
for pane in dock.panes:
5543
positions.append(pane.dock_pos)
5546
if pane.HasBorder():
5547
size += pane_border_size*2
5549
if dock.IsHorizontal():
5550
if pane.HasGripper() and not pane.HasGripperTop():
5551
size += gripper_size
5553
if pane.HasCaptionLeft():
5554
size += caption_size
5556
size += pane.best_size.x
5559
if pane.HasGripper() and pane.HasGripperTop():
5560
size += gripper_size
5562
if pane.HasCaption() and not pane.HasCaptionLeft():
5563
size += caption_size
5565
size += pane.best_size.y
5569
# if there is no action pane, just return the default
5570
# positions (as specified in pane.pane_pos)
5571
if action_pane == -1:
5572
return positions, sizes
5575
for pane_i in xrange(action_pane-1, -1, -1):
5576
amount = positions[pane_i+1] - (positions[pane_i] + sizes[pane_i])
5580
positions[pane_i] -= -amount
5582
offset += sizes[pane_i]
5584
# if the dock mode is fixed, make sure none of the panes
5585
# overlap we will bump panes that overlap
5587
for pane_i in xrange(action_pane, pane_count):
5588
amount = positions[pane_i] - offset
5592
positions[pane_i] += -amount
5594
offset += sizes[pane_i]
5596
return positions, sizes
5599
def LayoutAddPane(self, cont, dock, pane, uiparts, spacer_only):
5601
Adds a pane into the existing layout (in an existing dock).
5603
:param `cont`: a :class:`Sizer` object;
5604
:param `dock`: the :class:`AuiDockInfo` structure in which to add the pane;
5605
:param `pane`: the :class:`AuiPaneInfo` instance to add to the dock;
5606
:param `uiparts`: a list of UI parts in the interface;
5607
:param bool `spacer_only`: whether to add a simple spacer or a real window.
5610
sizer_item = wx.SizerItem()
5611
caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
5612
gripper_size = self._art.GetMetric(AUI_DOCKART_GRIPPER_SIZE)
5613
pane_border_size = self._art.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE)
5614
pane_button_size = self._art.GetMetric(AUI_DOCKART_PANE_BUTTON_SIZE)
5616
# find out the orientation of the item (orientation for panes
5617
# is the same as the dock's orientation)
5619
if dock.IsHorizontal():
5620
orientation = wx.HORIZONTAL
5622
orientation = wx.VERTICAL
5624
# this variable will store the proportion
5625
# value that the pane will receive
5626
pane_proportion = pane.dock_proportion
5628
horz_pane_sizer = wx.BoxSizer(wx.HORIZONTAL)
5629
vert_pane_sizer = wx.BoxSizer(wx.VERTICAL)
5631
if pane.HasGripper():
5633
part = AuiDockUIPart()
5634
if pane.HasGripperTop():
5635
sizer_item = vert_pane_sizer.Add((1, gripper_size), 0, wx.EXPAND)
5637
sizer_item = horz_pane_sizer.Add((gripper_size, 1), 0, wx.EXPAND)
5639
part.type = AuiDockUIPart.typeGripper
5643
part.orientation = orientation
5644
part.cont_sizer = horz_pane_sizer
5645
part.sizer_item = sizer_item
5646
uiparts.append(part)
5648
button_count = len(pane.buttons)
5649
button_width_total = button_count*pane_button_size
5650
if button_count >= 1:
5651
button_width_total += 3
5653
caption, captionLeft = pane.HasCaption(), pane.HasCaptionLeft()
5654
button_count = len(pane.buttons)
5657
caption_sizer = wx.BoxSizer(wx.VERTICAL)
5659
# add pane buttons to the caption
5661
for btn_id in xrange(len(pane.buttons)-1, -1, -1):
5662
sizer_item = caption_sizer.Add((caption_size, pane_button_size), 0, wx.EXPAND)
5663
part = AuiDockUIPart()
5664
part.type = AuiDockUIPart.typePaneButton
5667
part.button = pane.buttons[btn_id]
5668
part.orientation = orientation
5669
part.cont_sizer = caption_sizer
5670
part.sizer_item = sizer_item
5671
dummy_parts.append(part)
5673
sizer_item = caption_sizer.Add((caption_size, 1), 1, wx.EXPAND)
5674
vert_pane_sizer = wx.BoxSizer(wx.HORIZONTAL)
5676
# create the caption sizer
5677
part = AuiDockUIPart()
5679
part.type = AuiDockUIPart.typeCaption
5683
part.orientation = orientation
5684
part.cont_sizer = vert_pane_sizer
5685
part.sizer_item = sizer_item
5686
caption_part_idx = len(uiparts)
5687
uiparts.append(part)
5688
uiparts.extend(dummy_parts)
5692
caption_sizer = wx.BoxSizer(wx.HORIZONTAL)
5693
sizer_item = caption_sizer.Add((1, caption_size), 1, wx.EXPAND)
5695
# create the caption sizer
5696
part = AuiDockUIPart()
5698
part.type = AuiDockUIPart.typeCaption
5702
part.orientation = orientation
5703
part.cont_sizer = vert_pane_sizer
5704
part.sizer_item = sizer_item
5705
caption_part_idx = len(uiparts)
5706
uiparts.append(part)
5708
# add pane buttons to the caption
5709
for button in pane.buttons:
5710
sizer_item = caption_sizer.Add((pane_button_size, caption_size), 0, wx.EXPAND)
5711
part = AuiDockUIPart()
5712
part.type = AuiDockUIPart.typePaneButton
5715
part.button = button
5716
part.orientation = orientation
5717
part.cont_sizer = caption_sizer
5718
part.sizer_item = sizer_item
5719
uiparts.append(part)
5721
if caption or captionLeft:
5722
# if we have buttons, add a little space to the right
5723
# of them to ease visual crowding
5724
if button_count >= 1:
5726
caption_sizer.Add((caption_size, 3), 0, wx.EXPAND)
5728
caption_sizer.Add((3, caption_size), 0, wx.EXPAND)
5730
# add the caption sizer
5731
sizer_item = vert_pane_sizer.Add(caption_sizer, 0, wx.EXPAND)
5732
uiparts[caption_part_idx].sizer_item = sizer_item
5734
# add the pane window itself
5735
if spacer_only or not pane.window:
5736
sizer_item = vert_pane_sizer.Add((1, 1), 1, wx.EXPAND)
5738
sizer_item = vert_pane_sizer.Add(pane.window, 1, wx.EXPAND)
5739
vert_pane_sizer.SetItemMinSize(pane.window, (1, 1))
5741
part = AuiDockUIPart()
5742
part.type = AuiDockUIPart.typePane
5746
part.orientation = orientation
5747
part.cont_sizer = vert_pane_sizer
5748
part.sizer_item = sizer_item
5749
uiparts.append(part)
5751
# determine if the pane should have a minimum size if the pane is
5752
# non-resizable (fixed) then we must set a minimum size. Alternatively,
5753
# if the pane.min_size is set, we must use that value as well
5755
min_size = pane.min_size
5757
if min_size == wx.Size(-1, -1):
5758
min_size = pane.best_size
5761
if min_size != wx.Size(-1, -1):
5762
vert_pane_sizer.SetItemMinSize(len(vert_pane_sizer.GetChildren())-1, (min_size.x, min_size.y))
5764
# add the vertical/horizontal sizer (caption, pane window) to the
5765
# horizontal sizer (gripper, vertical sizer)
5766
horz_pane_sizer.Add(vert_pane_sizer, 1, wx.EXPAND)
5768
# finally, add the pane sizer to the dock sizer
5769
if pane.HasBorder():
5770
# allowing space for the pane's border
5771
sizer_item = cont.Add(horz_pane_sizer, pane_proportion,
5772
wx.EXPAND | wx.ALL, pane_border_size)
5773
part = AuiDockUIPart()
5774
part.type = AuiDockUIPart.typePaneBorder
5778
part.orientation = orientation
5779
part.cont_sizer = cont
5780
part.sizer_item = sizer_item
5781
uiparts.append(part)
5783
sizer_item = cont.Add(horz_pane_sizer, pane_proportion, wx.EXPAND)
5788
def LayoutAddDock(self, cont, dock, uiparts, spacer_only):
5790
Adds a dock into the existing layout.
5792
:param `cont`: a :class:`Sizer` object;
5793
:param `dock`: the :class:`AuiDockInfo` structure to add to the layout;
5794
:param `uiparts`: a list of UI parts in the interface;
5795
:param bool `spacer_only`: whether to add a simple spacer or a real window.
5798
sizer_item = wx.SizerItem()
5799
part = AuiDockUIPart()
5801
sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE)
5802
orientation = (dock.IsHorizontal() and [wx.HORIZONTAL] or [wx.VERTICAL])[0]
5804
# resizable bottom and right docks have a sash before them
5805
if not self._has_maximized and not dock.fixed and \
5806
dock.dock_direction in [AUI_DOCK_BOTTOM, AUI_DOCK_RIGHT]:
5808
sizer_item = cont.Add((sash_size, sash_size), 0, wx.EXPAND)
5810
part.type = AuiDockUIPart.typeDockSizer
5811
part.orientation = orientation
5815
part.cont_sizer = cont
5816
part.sizer_item = sizer_item
5817
uiparts.append(part)
5819
# create the sizer for the dock
5820
dock_sizer = wx.BoxSizer(orientation)
5822
# add each pane to the dock
5823
has_maximized_pane = False
5824
pane_count = len(dock.panes)
5828
# figure out the real pane positions we will
5829
# use, without modifying the each pane's pane_pos member
5830
pane_positions, pane_sizes = self.GetPanePositionsAndSizes(dock)
5833
for pane_i in xrange(pane_count):
5835
pane = dock.panes[pane_i]
5836
pane_pos = pane_positions[pane_i]
5838
if pane.IsMaximized():
5839
has_maximized_pane = True
5841
amount = pane_pos - offset
5844
if dock.IsVertical():
5845
sizer_item = dock_sizer.Add((1, amount), 0, wx.EXPAND)
5847
sizer_item = dock_sizer.Add((amount, 1), 0, wx.EXPAND)
5849
part = AuiDockUIPart()
5850
part.type = AuiDockUIPart.typeBackground
5854
part.orientation = (orientation==wx.HORIZONTAL and \
5855
[wx.VERTICAL] or [wx.HORIZONTAL])[0]
5856
part.cont_sizer = dock_sizer
5857
part.sizer_item = sizer_item
5858
uiparts.append(part)
5860
offset = offset + amount
5862
uiparts = self.LayoutAddPane(dock_sizer, dock, pane, uiparts, spacer_only)
5864
offset = offset + pane_sizes[pane_i]
5866
# at the end add a very small stretchable background area
5867
sizer_item = dock_sizer.Add((0, 0), 1, wx.EXPAND)
5868
part = AuiDockUIPart()
5869
part.type = AuiDockUIPart.typeBackground
5873
part.orientation = orientation
5874
part.cont_sizer = dock_sizer
5875
part.sizer_item = sizer_item
5876
uiparts.append(part)
5880
for pane_i in xrange(pane_count):
5882
pane = dock.panes[pane_i]
5884
if pane.IsMaximized():
5885
has_maximized_pane = True
5887
# if this is not the first pane being added,
5888
# we need to add a pane sizer
5889
if not self._has_maximized and pane_i > 0:
5890
sizer_item = dock_sizer.Add((sash_size, sash_size), 0, wx.EXPAND)
5891
part = AuiDockUIPart()
5892
part.type = AuiDockUIPart.typePaneSizer
5894
part.pane = dock.panes[pane_i-1]
5896
part.orientation = (orientation==wx.HORIZONTAL and \
5897
[wx.VERTICAL] or [wx.HORIZONTAL])[0]
5898
part.cont_sizer = dock_sizer
5899
part.sizer_item = sizer_item
5900
uiparts.append(part)
5902
uiparts = self.LayoutAddPane(dock_sizer, dock, pane, uiparts, spacer_only)
5904
if dock.dock_direction == AUI_DOCK_CENTER or has_maximized_pane:
5905
sizer_item = cont.Add(dock_sizer, 1, wx.EXPAND)
5907
sizer_item = cont.Add(dock_sizer, 0, wx.EXPAND)
5909
part = AuiDockUIPart()
5910
part.type = AuiDockUIPart.typeDock
5914
part.orientation = orientation
5915
part.cont_sizer = cont
5916
part.sizer_item = sizer_item
5917
uiparts.append(part)
5919
if dock.IsHorizontal():
5920
cont.SetItemMinSize(dock_sizer, (0, dock.size))
5922
cont.SetItemMinSize(dock_sizer, (dock.size, 0))
5924
# top and left docks have a sash after them
5925
if not self._has_maximized and not dock.fixed and \
5926
dock.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_LEFT]:
5928
sizer_item = cont.Add((sash_size, sash_size), 0, wx.EXPAND)
5930
part = AuiDockUIPart()
5931
part.type = AuiDockUIPart.typeDockSizer
5935
part.orientation = orientation
5936
part.cont_sizer = cont
5937
part.sizer_item = sizer_item
5938
uiparts.append(part)
5943
def LayoutAll(self, panes, docks, uiparts, spacer_only=False, oncheck=True):
5945
Layouts all the UI structures in the interface.
5947
:param `panes`: a list of :class:`AuiPaneInfo` instances;
5948
:param `docks`: a list of :class:`AuiDockInfo` classes;
5949
:param `uiparts`: a list of UI parts in the interface;
5950
:param bool `spacer_only`: whether to add a simple spacer or a real window;
5951
:param bool `oncheck`: whether to store the results in a class member or not.
5954
container = wx.BoxSizer(wx.VERTICAL)
5956
pane_border_size = self._art.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE)
5957
caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
5958
cli_size = self._frame.GetClientSize()
5960
# empty all docks out
5964
# always reset fixed docks' sizes, because
5965
# the contained windows may have been resized
5968
dock_count = len(docks)
5970
# iterate through all known panes, filing each
5971
# of them into the appropriate dock. If the
5972
# pane does not exist in the dock, add it
5975
# don't layout hidden panes.
5978
# find any docks with the same dock direction, dock layer, and
5979
# dock row as the pane we are working on
5980
arr = FindDocks(docks, p.dock_direction, p.dock_layer, p.dock_row)
5986
# dock was not found, so we need to create a new one
5988
d.dock_direction = p.dock_direction
5989
d.dock_layer = p.dock_layer
5990
d.dock_row = p.dock_row
5994
if p.HasFlag(p.needsRestore) and not p.HasFlag(p.wasMaximized):
5996
isHor = dock.IsHorizontal()
5997
sashSize = self._art.GetMetric(AUI_DOCKART_SASH_SIZE)
5999
# get the sizes of any docks that might
6000
# overlap with our restored dock
6002
# make list of widths or heights from the size in the dock rects
6003
sizes = [d.rect[2:][isHor] for \
6004
d in docks if d.IsOk() and \
6005
(d.IsHorizontal() == isHor) and \
6007
d.dock_direction != AUI_DOCK_CENTER]
6009
frameRect = GetInternalFrameRect(self._frame, self._docks)
6011
# set max size allowing for sashes and absolute minimum
6012
maxsize = frameRect[2:][isHor] - sum(sizes) - (len(sizes)*10) - (sashSize*len(sizes))
6013
dock.size = min(p.previousDockSize,maxsize)
6018
if p.HasFlag(p.wasMaximized):
6019
self.MaximizePane(p, savesizes=False)
6020
p.SetFlag(p.wasMaximized, False)
6022
if p.HasFlag(p.needsRestore):
6023
if p.previousDockPos is not None:
6024
DoInsertPane(dock.panes, dock.dock_direction, dock.dock_layer, dock.dock_row, p.previousDockPos)
6025
p.dock_pos = p.previousDockPos
6026
p.previousDockPos = None
6027
p.SetFlag(p.needsRestore, False)
6030
# remove the pane from any existing docks except this one
6031
docks = RemovePaneFromDocks(docks, p, dock)
6033
# pane needs to be added to the dock,
6034
# if it doesn't already exist
6035
if not FindPaneInDock(dock, p.window):
6036
dock.panes.append(p)
6038
# remove the pane from any existing docks
6039
docks = RemovePaneFromDocks(docks, p)
6041
# remove any empty docks
6042
docks = [dock for dock in docks if dock.panes]
6044
dock_count = len(docks)
6045
# configure the docks further
6046
for ii, dock in enumerate(docks):
6047
# sort the dock pane array by the pane's
6048
# dock position (dock_pos), in ascending order
6049
dock.panes.sort(PaneSortFunc)
6050
dock_pane_count = len(dock.panes)
6052
# for newly created docks, set up their initial size
6055
for pane in dock.panes:
6056
pane_size = pane.best_size
6057
if pane_size == wx.Size(-1, -1):
6058
pane_size = pane.min_size
6059
if pane_size == wx.Size(-1, -1) and pane.window:
6060
pane_size = pane.window.GetSize()
6061
if dock.IsHorizontal():
6062
size = max(pane_size.y, size)
6064
size = max(pane_size.x, size)
6066
# add space for the border (two times), but only
6067
# if at least one pane inside the dock has a pane border
6068
for pane in dock.panes:
6069
if pane.HasBorder():
6070
size = size + pane_border_size*2
6073
# if pane is on the top or bottom, add the caption height,
6074
# but only if at least one pane inside the dock has a caption
6075
if dock.IsHorizontal():
6076
for pane in dock.panes:
6077
if pane.HasCaption() and not pane.HasCaptionLeft():
6078
size = size + caption_size
6081
for pane in dock.panes:
6082
if pane.HasCaptionLeft() and not pane.HasCaption():
6083
size = size + caption_size
6086
# new dock's size may not be more than the dock constraint
6087
# parameter specifies. See SetDockSizeConstraint()
6088
max_dock_x_size = int(self._dock_constraint_x*float(cli_size.x))
6089
max_dock_y_size = int(self._dock_constraint_y*float(cli_size.y))
6090
if cli_size <= wx.Size(20, 20):
6091
max_dock_x_size = 10000
6092
max_dock_y_size = 10000
6094
if dock.IsHorizontal():
6095
size = min(size, max_dock_y_size)
6097
size = min(size, max_dock_x_size)
6099
# absolute minimum size for a dock is 10 pixels
6105
# determine the dock's minimum size
6107
plus_caption = False
6108
plus_caption_left = False
6110
for pane in dock.panes:
6111
if pane.min_size != wx.Size(-1, -1):
6112
if pane.HasBorder():
6114
if pane.HasCaption():
6116
if pane.HasCaptionLeft():
6117
plus_caption_left = True
6118
if dock.IsHorizontal():
6119
if pane.min_size.y > dock_min_size:
6120
dock_min_size = pane.min_size.y
6122
if pane.min_size.x > dock_min_size:
6123
dock_min_size = pane.min_size.x
6126
dock_min_size += pane_border_size*2
6127
if plus_caption and dock.IsHorizontal():
6128
dock_min_size += caption_size
6129
if plus_caption_left and dock.IsVertical():
6130
dock_min_size += caption_size
6132
dock.min_size = dock_min_size
6134
# if the pane's current size is less than it's
6135
# minimum, increase the dock's size to it's minimum
6136
if dock.size < dock.min_size:
6137
dock.size = dock.min_size
6139
# determine the dock's mode (fixed or proportional)
6140
# determine whether the dock has only toolbars
6141
action_pane_marked = False
6144
for pane in dock.panes:
6145
if not pane.IsFixed():
6147
if not pane.IsToolbar():
6148
dock.toolbar = False
6149
if pane.HasFlag(AuiPaneInfo.optionDockFixed):
6151
if pane.HasFlag(AuiPaneInfo.actionPane):
6152
action_pane_marked = True
6154
# if the dock mode is proportional and not fixed-pixel,
6155
# reassign the dock_pos to the sequential 0, 1, 2, 3
6156
# e.g. remove gaps like 1, 2, 30, 500
6158
for jj in xrange(dock_pane_count):
6159
pane = dock.panes[jj]
6162
# if the dock mode is fixed, and none of the panes
6163
# are being moved right now, make sure the panes
6164
# do not overlap each other. If they do, we will
6165
# adjust the panes' positions
6166
if dock.fixed and not action_pane_marked:
6167
pane_positions, pane_sizes = self.GetPanePositionsAndSizes(dock)
6169
for jj in xrange(dock_pane_count):
6170
pane = dock.panes[jj]
6171
pane.dock_pos = pane_positions[jj]
6172
amount = pane.dock_pos - offset
6176
pane.dock_pos += -amount
6178
offset += pane_sizes[jj]
6179
dock.panes[jj] = pane
6182
self._docks[ii] = dock
6184
# shrink docks if needed
6185
## docks = self.SmartShrink(docks, AUI_DOCK_TOP)
6186
## docks = self.SmartShrink(docks, AUI_DOCK_LEFT)
6191
# discover the maximum dock layer
6193
dock_count = len(docks)
6195
for ii in xrange(dock_count):
6196
max_layer = max(max_layer, docks[ii].dock_layer)
6201
# create a bunch of box sizers,
6202
# from the innermost level outwards.
6209
for layer in xrange(max_layer+1):
6210
# find any docks in this layer
6211
arr = FindDocks(docks, -1, layer, -1)
6212
# if there aren't any, skip to the next layer
6218
# create a container which will hold this layer's
6219
# docks (top, bottom, left, right)
6220
cont = wx.BoxSizer(wx.VERTICAL)
6222
# find any top docks in this layer
6223
arr = FindDocks(docks, AUI_DOCK_TOP, layer, -1)
6225
uiparts = self.LayoutAddDock(cont, row, uiparts, spacer_only)
6227
# fill out the middle layer (which consists
6228
# of left docks, content area and right docks)
6230
middle = wx.BoxSizer(wx.HORIZONTAL)
6232
# find any left docks in this layer
6233
arr = FindDocks(docks, AUI_DOCK_LEFT, layer, -1)
6235
uiparts = self.LayoutAddDock(middle, row, uiparts, spacer_only)
6237
# add content dock (or previous layer's sizer
6240
# find any center docks
6241
arr = FindDocks(docks, AUI_DOCK_CENTER, -1, -1)
6244
uiparts = self.LayoutAddDock(middle, row, uiparts, spacer_only)
6246
elif not self._has_maximized:
6247
# there are no center docks, add a background area
6248
sizer_item = middle.Add((1, 1), 1, wx.EXPAND)
6249
part = AuiDockUIPart()
6250
part.type = AuiDockUIPart.typeBackground
6254
part.cont_sizer = middle
6255
part.sizer_item = sizer_item
6256
uiparts.append(part)
6258
middle.Add(old_cont, 1, wx.EXPAND)
6260
# find any right docks in this layer
6261
arr = FindDocks(docks, AUI_DOCK_RIGHT, layer, -1, reverse=True)
6263
uiparts = self.LayoutAddDock(middle, row, uiparts, spacer_only)
6265
if len(middle.GetChildren()) > 0:
6266
cont.Add(middle, 1, wx.EXPAND)
6268
# find any bottom docks in this layer
6269
arr = FindDocks(docks, AUI_DOCK_BOTTOM, layer, -1, reverse=True)
6271
uiparts = self.LayoutAddDock(cont, row, uiparts, spacer_only)
6274
# no sizer available, because there are no docks,
6275
# therefore we will create a simple background area
6276
cont = wx.BoxSizer(wx.VERTICAL)
6277
sizer_item = cont.Add((1, 1), 1, wx.EXPAND)
6278
part = AuiDockUIPart()
6279
part.type = AuiDockUIPart.typeBackground
6283
part.cont_sizer = middle
6284
part.sizer_item = sizer_item
6285
uiparts.append(part)
6288
self._uiparts = uiparts
6291
container.Add(cont, 1, wx.EXPAND)
6296
return container, panes, docks, uiparts
6299
def SetDockSizeConstraint(self, width_pct, height_pct):
6301
When a user creates a new dock by dragging a window into a docked position,
6302
often times the large size of the window will create a dock that is unwieldly
6305
:class:`AuiManager` by default limits the size of any new dock to 1/3 of the window
6306
size. For horizontal docks, this would be 1/3 of the window height. For vertical
6307
docks, 1/3 of the width. Calling this function will adjust this constraint value.
6309
The numbers must be between 0.0 and 1.0. For instance, calling :meth:`SetDockSizeConstraint`
6310
with (0.5, 0.5) will cause new docks to be limited to half of the size of the entire
6313
:param float `width_pct`: a number representing the `x` dock size constraint;
6314
:param float `width_pct`: a number representing the `y` dock size constraint.
6317
self._dock_constraint_x = max(0.0, min(1.0, width_pct))
6318
self._dock_constraint_y = max(0.0, min(1.0, height_pct))
6321
def GetDockSizeConstraint(self):
6323
Returns the current dock constraint values.
6325
:see: :meth:`SetDockSizeConstraint`
6328
return self._dock_constraint_x, self._dock_constraint_y
6333
This method is called after any number of changes are made to any of the
6334
managed panes. :meth:`Update` must be invoked after :meth:`AddPane`
6335
or :meth:`InsertPane` are called in order to "realize" or "commit" the changes.
6337
In addition, any number of changes may be made to :class:`AuiManager` structures
6338
(retrieved with :meth:`GetPane`), but to realize the changes, :meth:`Update`
6339
must be called. This construction allows pane flicker to be avoided by updating
6340
the whole layout at one time.
6343
self._hover_button = None
6344
self._action_part = None
6346
# destroy floating panes which have been
6347
# redocked or are becoming non-floating
6348
for p in self._panes:
6349
if p.IsFloating() or not p.frame:
6352
# because the pane is no longer in a floating, we need to
6353
# reparent it to self._frame and destroy the floating frame
6355
p.window.SetSize((1, 1))
6357
# the following block is a workaround for bug #1531361
6358
# (see wxWidgets sourceforge page). On wxGTK (only), when
6359
# a frame is shown/hidden, a move event unfortunately
6360
# also gets fired. Because we may be dragging around
6361
# a pane, we need to cancel that action here to prevent
6363
if self._action_window == p.frame:
6364
if self._frame.HasCapture():
6365
self._frame.ReleaseMouse()
6366
self._action = actionNone
6367
self._action_window = None
6370
if p.frame.IsShown():
6373
if self._action_window == p.frame:
6374
self._action_window = None
6376
# reparent to self._frame and destroy the pane
6377
p.window.Reparent(self._frame)
6378
if isinstance(p.window, auibar.AuiToolBar):
6379
p.window.SetAuiManager(self)
6382
p.frame.SetSizer(None)
6386
# Only the master manager should create/destroy notebooks...
6387
if not self._masterManager:
6388
self.UpdateNotebook()
6390
# delete old sizer first
6391
self._frame.SetSizer(None)
6393
# create a layout for all of the panes
6394
sizer = self.LayoutAll(self._panes, self._docks, self._uiparts, False)
6396
# hide or show panes as necessary,
6397
# and float panes as necessary
6399
pane_count = len(self._panes)
6401
for ii in xrange(pane_count):
6407
# we need to create a frame for this
6408
# pane, which has recently been floated
6409
frame = self.CreateFloatingFrame(self._frame, p)
6411
# on MSW and Mac, if the owner desires transparent dragging, and
6412
# the dragging is happening right now, then the floating
6413
# window should have this style by default
6414
if self._action in [actionDragFloatingPane, actionDragToolbarPane] and \
6415
self._agwFlags & AUI_MGR_TRANSPARENT_DRAG:
6416
frame.SetTransparent(150)
6420
if isinstance(bar, auibar.AuiToolBar):
6421
bar.SetGripperVisible(False)
6422
agwStyle = bar.GetAGWWindowStyleFlag()
6423
bar.SetAGWWindowStyleFlag(agwStyle & ~AUI_TB_VERTICAL)
6426
s = p.window.GetMinSize()
6428
p.FloatingSize(wx.DefaultSize)
6430
frame.SetPaneWindow(p)
6431
p.needsTransparency = True
6432
p.frame = pFrame = frame
6433
if p.IsShown() and not frame.IsShown():
6438
# frame already exists, make sure it's position
6439
# and size reflect the information in AuiPaneInfo
6440
if pFrame.GetPosition() != p.floating_pos or pFrame.GetSize() != p.floating_size:
6441
pFrame.SetDimensions(p.floating_pos.x, p.floating_pos.y,
6442
p.floating_size.x, p.floating_size.y, wx.SIZE_USE_EXISTING)
6444
# update whether the pane is resizable or not
6445
style = p.frame.GetWindowStyleFlag()
6447
style &= ~wx.RESIZE_BORDER
6449
style |= wx.RESIZE_BORDER
6451
p.frame.SetWindowStyleFlag(style)
6453
if pFrame.IsShown() != p.IsShown():
6454
p.needsTransparency = True
6455
pFrame.Show(p.IsShown())
6457
if pFrame.GetTitle() != p.caption:
6458
pFrame.SetTitle(p.caption)
6460
pFrame.SetIcon(wx.IconFromBitmap(p.icon))
6465
# self.SwitchToolBarOrientation(p)
6466
p.best_size = p.window.GetBestSize()
6468
if p.window and not p.IsNotebookPage() and p.window.IsShown() != p.IsShown():
6469
p.window.Show(p.IsShown())
6471
if pFrame and p.needsTransparency:
6472
if pFrame.IsShown() and pFrame._transparent != p.transparent:
6473
pFrame.SetTransparent(p.transparent)
6474
pFrame._transparent = p.transparent
6476
p.needsTransparency = False
6478
# if "active panes" are no longer allowed, clear
6479
# any optionActive values from the pane states
6480
if self._agwFlags & AUI_MGR_ALLOW_ACTIVE_PANE == 0:
6481
p.state &= ~AuiPaneInfo.optionActive
6486
pane_count = len(self._panes)
6488
for p in self._panes:
6490
if p.window and p.IsShown() and p.IsDocked():
6493
old_pane_rects.append(r)
6495
# apply the new sizer
6496
self._frame.SetSizer(sizer)
6497
self._frame.SetAutoLayout(False)
6498
self.DoFrameLayout()
6500
# now that the frame layout is done, we need to check
6501
# the new pane rectangles against the old rectangles that
6502
# we saved a few lines above here. If the rectangles have
6503
# changed, the corresponding panes must also be updated
6504
for ii in xrange(pane_count):
6506
if p.window and p.IsShown() and p.IsDocked():
6507
if p.rect != old_pane_rects[ii]:
6511
if wx.Platform == "__WXMAC__":
6512
self._frame.Refresh()
6516
if not self._masterManager:
6517
e = self.FireEvent(wxEVT_AUI_PERSPECTIVE_CHANGED, None, canVeto=False)
6520
def UpdateNotebook(self):
6521
""" Updates the automatic :class:`~lib.agw.aui.auibook.AuiNotebook` in the layout (if any exists). """
6523
# Workout how many notebooks we need.
6526
# destroy floating panes which have been
6527
# redocked or are becoming non-floating
6528
for paneInfo in self._panes:
6529
if max_notebook < paneInfo.notebook_id:
6530
max_notebook = paneInfo.notebook_id
6532
# We are the master of our domain
6533
extra_notebook = len(self._notebooks)
6536
for i in xrange(extra_notebook, max_notebook):
6537
self.CreateNotebook()
6539
# Remove pages from notebooks that no-longer belong there ...
6540
for nb, notebook in enumerate(self._notebooks):
6541
pages = notebook.GetPageCount()
6542
pageCounter, allPages = 0, pages
6544
# Check each tab ...
6545
for page in xrange(pages):
6547
if page >= allPages:
6550
window = notebook.GetPage(pageCounter)
6551
paneInfo = self.GetPane(window)
6552
if paneInfo.IsOk() and paneInfo.notebook_id != nb:
6553
notebook.RemovePage(pageCounter)
6555
window.Reparent(self._frame)
6563
# Add notebook pages that aren't there already...
6564
for paneInfo in self._panes:
6565
if paneInfo.IsNotebookPage():
6567
title = (paneInfo.caption == "" and [paneInfo.name] or [paneInfo.caption])[0]
6569
notebook = self._notebooks[paneInfo.notebook_id]
6570
page_id = notebook.GetPageIndex(paneInfo.window)
6574
paneInfo.window.Reparent(notebook)
6575
notebook.AddPage(paneInfo.window, title, True, paneInfo.icon)
6577
# Update title and icon ...
6580
notebook.SetPageText(page_id, title)
6581
notebook.SetPageBitmap(page_id, paneInfo.icon)
6585
# Wire-up newly created notebooks
6586
elif paneInfo.IsNotebookControl() and not paneInfo.window:
6587
paneInfo.window = self._notebooks[paneInfo.notebook_id]
6589
# Delete empty notebooks, and convert notebooks with 1 page to
6591
remap_ids = [-1]*len(self._notebooks)
6594
for nb, notebook in enumerate(self._notebooks):
6595
if notebook.GetPageCount() == 1:
6597
# Convert notebook page to pane...
6598
window = notebook.GetPage(0)
6599
child_pane = self.GetPane(window)
6600
notebook_pane = self.GetPane(notebook)
6601
if child_pane.IsOk() and notebook_pane.IsOk():
6603
child_pane.SetDockPos(notebook_pane)
6604
child_pane.window.Hide()
6605
child_pane.window.Reparent(self._frame)
6606
child_pane.frame = None
6607
child_pane.notebook_id = -1
6608
if notebook_pane.IsFloating():
6611
self.DetachPane(notebook)
6613
notebook.RemovePage(0)
6618
raise Exception("Odd notebook docking")
6620
elif notebook.GetPageCount() == 0:
6622
self.DetachPane(notebook)
6627
# Correct page ordering. The original wxPython code
6628
# for this did not work properly, and would misplace
6629
# windows causing errors.
6631
self._notebooks[nb_idx] = notebook
6632
pages = notebook.GetPageCount()
6633
selected = notebook.GetPage(notebook.GetSelection())
6635
# Take each page out of the notebook, group it with
6636
# its current pane, and sort the list by pane.dock_pos
6638
pages_and_panes = []
6639
for idx in reversed(range(pages)):
6640
page = notebook.GetPage(idx)
6641
pane = self.GetPane(page)
6642
pages_and_panes.append((page, pane))
6643
notebook.RemovePage(idx)
6644
sorted_pnp = sorted(pages_and_panes, key=lambda tup: tup[1].dock_pos)
6646
# Grab the attributes from the panes which are ordered
6647
# correctly, and copy those attributes to the original
6648
# panes. (This avoids having to change the ordering
6649
# of self._panes) Then, add the page back into the notebook
6650
sorted_attributes = [self.GetAttributes(tup[1])
6651
for tup in sorted_pnp]
6652
for attrs, tup in zip(sorted_attributes, pages_and_panes):
6654
self.SetAttributes(pane, attrs)
6655
notebook.AddPage(pane.window, pane.caption)
6657
notebook.SetSelection(notebook.GetPageIndex(selected), True)
6662
remap_ids[nb] = nb_idx
6666
nb_count = len(self._notebooks)
6668
if nb_count != nb_idx:
6670
self._notebooks = self._notebooks[0:nb_idx]
6671
for p in self._panes:
6672
if p.notebook_id >= 0:
6673
p.notebook_id = remap_ids[p.notebook_id]
6674
if p.IsNotebookControl():
6675
p.SetNameFromNotebookId()
6677
# Make sure buttons are correct ...
6678
for notebook in self._notebooks:
6683
pages = notebook.GetPageCount()
6684
for page in xrange(pages):
6686
win = notebook.GetPage(page)
6687
pane = self.GetPane(win)
6690
if not pane.HasCloseButton():
6692
if not pane.HasMaximizeButton():
6694
if not pane.HasMinimizeButton():
6697
notebook_pane = self.GetPane(notebook)
6698
if notebook_pane.IsOk():
6699
if notebook_pane.HasMinimizeButton() != want_min:
6701
button = AuiPaneButton(AUI_BUTTON_MINIMIZE)
6702
notebook_pane.state |= AuiPaneInfo.buttonMinimize
6703
notebook_pane.buttons.append(button)
6705
# todo: remove min/max
6707
if notebook_pane.HasMaximizeButton() != want_max:
6709
button = AuiPaneButton(AUI_BUTTON_MAXIMIZE_RESTORE)
6710
notebook_pane.state |= AuiPaneInfo.buttonMaximize
6711
notebook_pane.buttons.append(button)
6713
# todo: remove min/max
6715
if notebook_pane.HasCloseButton() != want_close:
6717
button = AuiPaneButton(AUI_BUTTON_CLOSE)
6718
notebook_pane.state |= AuiPaneInfo.buttonClose
6719
notebook_pane.buttons.append(button)
6721
# todo: remove close
6724
def SmartShrink(self, docks, direction):
6726
Used to intelligently shrink the docks' size (if needed).
6728
:param `docks`: a list of :class:`AuiDockInfo` instances;
6729
:param integer `direction`: the direction in which to shrink.
6732
sashSize = self._art.GetMetric(AUI_DOCKART_SASH_SIZE)
6733
caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
6734
clientSize = self._frame.GetClientSize()
6735
ourDocks = FindDocks(docks, direction, -1, -1)
6736
oppositeDocks = FindOppositeDocks(docks, direction)
6737
oppositeSize = self.GetOppositeDockTotalSize(docks, direction)
6740
for dock in ourDocks:
6741
ourSize += dock.size
6743
if not dock.toolbar:
6746
shrinkSize = ourSize + oppositeSize
6748
if direction == AUI_DOCK_TOP or direction == AUI_DOCK_BOTTOM:
6749
shrinkSize -= clientSize.y
6751
shrinkSize -= clientSize.x
6757
for dock in oppositeDocks:
6758
ourDocks.append(dock)
6762
for dock in ourDocks:
6763
if dock.toolbar or not dock.resizable:
6766
dockRange = dock.size - dock.min_size
6768
if dock.min_size == 0:
6769
dockRange -= sashSize
6770
if direction == AUI_DOCK_TOP or direction == AUI_DOCK_BOTTOM:
6771
dockRange -= caption_size
6773
if dockRange >= shrinkSize:
6775
dock.size -= shrinkSize
6780
dock.size -= dockRange
6781
shrinkSize -= dockRange
6786
def UpdateDockingGuides(self, paneInfo):
6788
Updates the docking guide windows positions and appearance.
6790
:param `paneInfo`: a :class:`AuiPaneInfo` instance.
6793
if len(self._guides) == 0:
6794
self.CreateGuideWindows()
6796
captionSize = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
6797
frameRect = GetInternalFrameRect(self._frame, self._docks)
6798
mousePos = wx.GetMousePosition()
6800
for indx, guide in enumerate(self._guides):
6803
guide_size = guide.host.GetSize()
6805
raise Exception("Invalid docking host")
6807
direction = guide.dock_direction
6809
if direction == AUI_DOCK_LEFT:
6810
pt.x = frameRect.x + guide_size.x / 2 + 16
6811
pt.y = frameRect.y + frameRect.height / 2
6813
elif direction == AUI_DOCK_TOP:
6814
pt.x = frameRect.x + frameRect.width / 2
6815
pt.y = frameRect.y + guide_size.y / 2 + 16
6817
elif direction == AUI_DOCK_RIGHT:
6818
pt.x = frameRect.x + frameRect.width - guide_size.x / 2 - 16
6819
pt.y = frameRect.y + frameRect.height / 2
6821
elif direction == AUI_DOCK_BOTTOM:
6822
pt.x = frameRect.x + frameRect.width / 2
6823
pt.y = frameRect.y + frameRect.height - guide_size.y / 2 - 16
6825
elif direction == AUI_DOCK_CENTER:
6826
rc = paneInfo.window.GetScreenRect()
6827
pt.x = rc.x + rc.width / 2
6828
pt.y = rc.y + rc.height / 2
6829
if paneInfo.HasCaption():
6830
pt.y -= captionSize / 2
6831
elif paneInfo.HasCaptionLeft():
6832
pt.x -= captionSize / 2
6834
# guide will be centered around point 'pt'
6835
targetPosition = wx.Point(pt.x - guide_size.x / 2, pt.y - guide_size.y / 2)
6837
if guide.host.GetPosition() != targetPosition:
6838
guide.host.Move(targetPosition)
6840
guide.host.AeroMove(targetPosition)
6842
if guide.dock_direction == AUI_DOCK_CENTER:
6843
guide.host.ValidateNotebookDocking(paneInfo.IsNotebookDockable())
6845
guide.host.UpdateDockGuide(mousePos)
6847
paneInfo.window.Lower()
6850
def DoFrameLayout(self):
6852
This is an internal function which invokes :meth:`Sizer.Layout() <Sizer.Layout>`
6853
on the frame's main sizer, then measures all the various UI items
6854
and updates their internal rectangles.
6856
:note: This should always be called instead of calling
6857
`self._managed_window.Layout()` directly.
6860
self._frame.Layout()
6862
for part in self._uiparts:
6863
# get the rectangle of the UI part
6864
# originally, this code looked like this:
6865
# part.rect = wx.Rect(part.sizer_item.GetPosition(),
6866
# part.sizer_item.GetSize())
6867
# this worked quite well, with one exception: the mdi
6868
# client window had a "deferred" size variable
6869
# that returned the wrong size. It looks like
6870
# a bug in wx, because the former size of the window
6871
# was being returned. So, we will retrieve the part's
6872
# rectangle via other means
6874
part.rect = part.sizer_item.GetRect()
6875
flag = part.sizer_item.GetFlag()
6876
border = part.sizer_item.GetBorder()
6879
part.rect.y -= border
6880
part.rect.height += border
6882
part.rect.x -= border
6883
part.rect.width += border
6884
if flag & wx.BOTTOM:
6885
part.rect.height += border
6887
part.rect.width += border
6889
if part.type == AuiDockUIPart.typeDock:
6890
part.dock.rect = part.rect
6891
if part.type == AuiDockUIPart.typePane:
6892
part.pane.rect = part.rect
6895
def GetPanePart(self, wnd):
6897
Looks up the pane border UI part of the
6898
pane specified. This allows the caller to get the exact rectangle
6899
of the pane in question, including decorations like caption and border.
6901
:param Window `wnd`: the window to which the pane border belongs to.
6904
for part in self._uiparts:
6905
if part.type == AuiDockUIPart.typePaneBorder and \
6906
part.pane and part.pane.window == wnd:
6909
for part in self._uiparts:
6910
if part.type == AuiDockUIPart.typePane and \
6911
part.pane and part.pane.window == wnd:
6917
def GetDockPixelOffset(self, test):
6919
This is an internal function which returns a dock's offset in pixels from
6920
the left side of the window (for horizontal docks) or from the top of the
6921
window (for vertical docks).
6923
This value is necessary for calculating fixed-pane/toolbar offsets
6924
when they are dragged.
6926
:param `test`: a fake :class:`AuiPaneInfo` for testing purposes.
6929
# the only way to accurately calculate the dock's
6930
# offset is to actually run a theoretical layout
6931
docks, panes = CopyDocksAndPanes2(self._docks, self._panes)
6934
sizer, panes, docks, uiparts = self.LayoutAll(panes, docks, [], True, False)
6935
client_size = self._frame.GetClientSize()
6936
sizer.SetDimension(0, 0, client_size.x, client_size.y)
6939
for part in uiparts:
6940
pos = part.sizer_item.GetPosition()
6941
size = part.sizer_item.GetSize()
6942
part.rect = wx.RectPS(pos, size)
6943
if part.type == AuiDockUIPart.typeDock:
6944
part.dock.rect = part.rect
6949
if test.dock_direction == dock.dock_direction and \
6950
test.dock_layer == dock.dock_layer and \
6951
test.dock_row == dock.dock_row:
6953
if dock.IsVertical():
6961
def GetPartnerDock(self, dock):
6963
Returns the partner dock for the input dock.
6965
:param `dock`: a :class:`AuiDockInfo` instance.
6968
for layer in xrange(dock.dock_layer, -1, -1):
6972
for tmpDock in self._docks:
6974
if tmpDock.dock_layer != layer:
6977
if tmpDock.dock_direction != dock.dock_direction:
6980
if tmpDock.dock_layer < dock.dock_layer:
6982
if not bestDock or tmpDock.dock_row < bestDock.dock_row:
6985
elif tmpDock.dock_row > dock.dock_row:
6987
if not bestDock or tmpDock.dock_row > bestDock.dock_row:
6996
def GetPartnerPane(self, dock, pane):
6998
Returns the partner pane for the input pane. They both need to live
6999
in the same :class:`AuiDockInfo`.
7001
:param `dock`: a :class:`AuiDockInfo` instance;
7002
:param `pane`: a :class:`AuiPaneInfo` class.
7007
for i, tmpPane in enumerate(dock.panes):
7008
if tmpPane.window == pane.window:
7010
elif not tmpPane.IsFixed() and panePosition != -1:
7016
def GetTotalPixSizeAndProportion(self, dock):
7018
Returns the dimensions and proportion of the input dock.
7020
:param `dock`: the :class:`AuiDockInfo` structure to analyze.
7026
# determine the total proportion of all resizable panes,
7027
# and the total size of the dock minus the size of all
7029
for tmpPane in dock.panes:
7031
if tmpPane.IsFixed():
7034
totalProportion += tmpPane.dock_proportion
7036
if dock.IsHorizontal():
7037
totalPixsize += tmpPane.rect.width
7039
totalPixsize += tmpPane.rect.height
7041
## if tmpPane.min_size.IsFullySpecified():
7043
## if dock.IsHorizontal():
7044
## totalPixsize -= tmpPane.min_size.x
7046
## totalPixsize -= tmpPane.min_size.y
7048
return totalPixsize, totalProportion
7051
def GetOppositeDockTotalSize(self, docks, direction):
7053
Returns the dimensions of the dock which lives opposite of the input dock.
7055
:param `docks`: a list of :class:`AuiDockInfo` structures to analyze;
7056
:param integer `direction`: the direction in which to look for the opposite dock.
7059
sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE)
7060
caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
7061
pane_border_size = self._art.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE)
7066
if direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]:
7069
# Get minimum size of the most inner area
7070
for tmpDock in docks:
7072
if tmpDock.dock_layer != 0:
7075
if tmpDock.dock_direction != AUI_DOCK_CENTER and tmpDock.IsVertical() != vertical:
7078
for tmpPane in tmpDock.panes:
7080
minSize = pane_border_size*2 - sash_size
7083
minSize += tmpPane.min_size.y + caption_size
7085
minSize += tmpPane.min_size.x
7087
if minSize > minSizeMax:
7088
minSizeMax = minSize
7090
result += minSizeMax
7092
# Get opposite docks
7093
oppositeDocks = FindOppositeDocks(docks, direction)
7095
# Sum size of the opposite docks and their sashes
7096
for dock in oppositeDocks:
7098
# if it's not a toolbar add the sash_size too
7099
if not dock.toolbar:
7105
def CalculateDockSizerLimits(self, dock):
7107
Calculates the minimum and maximum sizes allowed for the input dock.
7109
:param `dock`: the :class:`AuiDockInfo` structure to analyze.
7112
docks, panes = CopyDocksAndPanes2(self._docks, self._panes)
7114
sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE)
7115
caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
7116
opposite_size = self.GetOppositeDockTotalSize(docks, dock.dock_direction)
7118
for tmpDock in docks:
7120
if tmpDock.dock_direction == dock.dock_direction and \
7121
tmpDock.dock_layer == dock.dock_layer and \
7122
tmpDock.dock_row == dock.dock_row:
7127
sizer, panes, docks, uiparts = self.LayoutAll(panes, docks, [], True, False)
7128
client_size = self._frame.GetClientSize()
7129
sizer.SetDimension(0, 0, client_size.x, client_size.y)
7132
for part in uiparts:
7134
part.rect = wx.RectPS(part.sizer_item.GetPosition(), part.sizer_item.GetSize())
7135
if part.type == AuiDockUIPart.typeDock:
7136
part.dock.rect = part.rect
7141
for tmpDock in docks:
7142
if tmpDock.dock_direction == dock.dock_direction and \
7143
tmpDock.dock_layer == dock.dock_layer and \
7144
tmpDock.dock_row == dock.dock_row:
7149
partnerDock = self.GetPartnerDock(dock)
7152
partnerRange = partnerDock.size - partnerDock.min_size
7153
if partnerDock.min_size == 0:
7154
partnerRange -= sash_size
7155
if dock.IsHorizontal():
7156
partnerRange -= caption_size
7158
direction = dock.dock_direction
7160
if direction == AUI_DOCK_LEFT:
7161
minPix = new_dock.rect.x + new_dock.rect.width
7162
maxPix = dock.rect.x + dock.rect.width
7163
maxPix += partnerRange
7165
elif direction == AUI_DOCK_TOP:
7166
minPix = new_dock.rect.y + new_dock.rect.height
7167
maxPix = dock.rect.y + dock.rect.height
7168
maxPix += partnerRange
7170
elif direction == AUI_DOCK_RIGHT:
7171
minPix = dock.rect.x - partnerRange - sash_size
7172
maxPix = new_dock.rect.x - sash_size
7174
elif direction == AUI_DOCK_BOTTOM:
7175
minPix = dock.rect.y - partnerRange - sash_size
7176
maxPix = new_dock.rect.y - sash_size
7178
return minPix, maxPix
7180
direction = new_dock.dock_direction
7182
if direction == AUI_DOCK_LEFT:
7183
minPix = new_dock.rect.x + new_dock.rect.width
7184
maxPix = client_size.x - opposite_size - sash_size
7186
elif direction == AUI_DOCK_TOP:
7187
minPix = new_dock.rect.y + new_dock.rect.height
7188
maxPix = client_size.y - opposite_size - sash_size
7190
elif direction == AUI_DOCK_RIGHT:
7191
minPix = opposite_size
7192
maxPix = new_dock.rect.x - sash_size
7194
elif direction == AUI_DOCK_BOTTOM:
7195
minPix = opposite_size
7196
maxPix = new_dock.rect.y - sash_size
7198
return minPix, maxPix
7201
def CalculatePaneSizerLimits(self, dock, pane):
7203
Calculates the minimum and maximum sizes allowed for the input pane.
7205
:param `dock`: the :class:`AuiDockInfo` structure to which `pane` belongs to;
7206
:param `pane`: a :class:`AuiPaneInfo` class for which calculation are requested.
7210
if dock.IsHorizontal():
7211
minPix = maxPix = pane.rect.x + 1 + pane.rect.width
7213
minPix = maxPix = pane.rect.y + 1 + pane.rect.height
7215
return minPix, maxPix
7217
totalPixsize, totalProportion = self.GetTotalPixSizeAndProportion(dock)
7218
partnerPane = self.GetPartnerPane(dock, pane)
7220
if dock.IsHorizontal():
7222
minPix = pane.rect.x + 1
7223
maxPix = pane.rect.x + 1 + pane.rect.width
7225
if pane.min_size.IsFullySpecified():
7226
minPix += pane.min_size.x
7231
maxPix += partnerPane.rect.width
7233
if partnerPane.min_size.IsFullySpecified():
7234
maxPix -= partnerPane.min_size.x - 1
7241
minPix = pane.rect.y + 1
7242
maxPix = pane.rect.y + 1 + pane.rect.height
7244
if pane.min_size.IsFullySpecified():
7245
minPix += pane.min_size.y
7250
maxPix += partnerPane.rect.height
7252
if partnerPane.min_size.IsFullySpecified():
7253
maxPix -= partnerPane.min_size.y - 1
7258
return minPix, maxPix
7261
def CheckMovableSizer(self, part):
7263
Checks if a UI part can be actually resized.
7265
:param AuiDockUIPart `part`: a UI part.
7268
# a dock may not be resized if it has a single
7269
# pane which is not resizable
7270
if part.type == AuiDockUIPart.typeDockSizer and part.dock and \
7271
len(part.dock.panes) == 1 and part.dock.panes[0].IsFixed():
7277
# panes that may not be resized should be ignored here
7278
minPix, maxPix = self.CalculatePaneSizerLimits(part.dock, part.pane)
7280
if minPix == maxPix:
7286
def PaneFromTabEvent(self, event):
7288
Returns a :class:`AuiPaneInfo` from a :class:`~lib.agw.aui.auibook.AuiNotebook` event.
7290
:param `event`: a :class:`~lib.agw.aui.auibook.AuiNotebookEvent` event.
7293
obj = event.GetEventObject()
7295
if obj and isinstance(obj, auibook.AuiTabCtrl):
7297
page_idx = obj.GetActivePage()
7300
page = obj.GetPage(page_idx)
7301
window = page.window
7303
return self.GetPane(window)
7305
elif obj and isinstance(obj, auibook.AuiNotebook):
7307
page_idx = event.GetSelection()
7310
window = obj.GetPage(page_idx)
7312
return self.GetPane(window)
7317
def OnTabBeginDrag(self, event):
7319
Handles the ``EVT_AUINOTEBOOK_BEGIN_DRAG`` event.
7321
:param `event`: a :class:`~lib.agw.aui.auibook.AuiNotebookEvent` event to be processed.
7324
if self._masterManager:
7325
self._masterManager.OnTabBeginDrag(event)
7328
paneInfo = self.PaneFromTabEvent(event)
7333
self._action = actionDragFloatingPane
7334
mouse = wx.GetMousePosition()
7336
# set initial float position - may have to think about this
7337
# offset a bit more later ...
7338
self._action_offset = wx.Point(20, 10)
7339
self._toolbar_action_offset = wx.Point(20, 10)
7341
paneInfo.floating_pos = mouse - self._action_offset
7342
paneInfo.dock_pos = AUI_DOCK_NONE
7343
paneInfo.notebook_id = -1
7345
tab = event.GetEventObject()
7347
if tab.HasCapture():
7351
if paneInfo.IsMaximized():
7352
self.RestorePane(paneInfo)
7356
self._action_window = paneInfo.window
7358
self._frame.CaptureMouse()
7359
event.SetDispatched(True)
7367
def OnTabPageClose(self, event):
7369
Handles the ``EVT_AUINOTEBOOK_PAGE_CLOSE`` event.
7371
:param `event`: a :class:`~lib.agw.aui.auibook.AuiNotebookEvent` event to be processed.
7374
if self._masterManager:
7375
self._masterManager.OnTabPageClose(event)
7379
p = self.PaneFromTabEvent(event)
7382
# veto it because we will call "RemovePage" ourselves
7385
# Now ask the app if they really want to close...
7386
# fire pane close event
7387
e = AuiManagerEvent(wxEVT_AUI_PANE_CLOSE)
7390
self.ProcessMgrEvent(e)
7401
def OnTabSelected(self, event):
7403
Handles the ``EVT_AUINOTEBOOK_PAGE_CHANGED`` event.
7405
:param `event`: a :class:`~lib.agw.aui.auibook.AuiNotebookEvent` event to be processed.
7408
if self._masterManager:
7409
self._masterManager.OnTabSelected(event)
7412
obj = event.GetEventObject()
7414
if obj and isinstance(obj, auibook.AuiNotebook):
7417
page = notebook.GetPage(event.GetSelection())
7418
paneInfo = self.GetPane(page)
7421
notebookRoot = GetNotebookRoot(self._panes, paneInfo.notebook_id)
7424
notebookRoot.Caption(paneInfo.caption)
7425
self.RefreshCaptions()
7430
def GetNotebooks(self):
7431
""" Returns all the automatic :class:`~lib.agw.aui.auibook.AuiNotebook` in the :class:`AuiManager`. """
7433
if self._masterManager:
7434
return self._masterManager.GetNotebooks()
7436
return self._notebooks
7439
def SetMasterManager(self, manager):
7441
Sets the master manager for an automatic :class:`~lib.agw.aui.auibook.AuiNotebook`.
7443
:param `manager`: an instance of :class:`AuiManager`.
7446
self._masterManager = manager
7449
def ProcessDockResult(self, target, new_pos):
7451
This is a utility function used by :meth:`DoDrop` - it checks
7452
if a dock operation is allowed, the new dock position is copied into
7453
the target info. If the operation was allowed, the function returns ``True``.
7455
:param `target`: the :class:`AuiPaneInfo` instance to be docked;
7456
:param integer `new_pos`: the new docking position if the docking operation is allowed.
7460
direction = new_pos.dock_direction
7462
if direction == AUI_DOCK_TOP:
7463
allowed = target.IsTopDockable()
7464
elif direction == AUI_DOCK_BOTTOM:
7465
allowed = target.IsBottomDockable()
7466
elif direction == AUI_DOCK_LEFT:
7467
allowed = target.IsLeftDockable()
7468
elif direction == AUI_DOCK_RIGHT:
7469
allowed = target.IsRightDockable()
7474
if target.IsToolbar():
7475
self.SwitchToolBarOrientation(target)
7477
return allowed, target
7480
def SwitchToolBarOrientation(self, pane):
7482
Switches the toolbar orientation from vertical to horizontal and vice-versa.
7483
This is especially useful for vertical docked toolbars once they float.
7485
:param `pane`: an instance of :class:`AuiPaneInfo`, which may have a :class:`~lib.agw.aui.auibar.AuiToolBar`
7486
window associated with it.
7489
if not isinstance(pane.window, auibar.AuiToolBar):
7492
if pane.IsFloating():
7495
toolBar = pane.window
7496
direction = pane.dock_direction
7497
vertical = direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT]
7499
agwStyle = toolBar.GetAGWWindowStyleFlag()
7500
new_agwStyle = agwStyle
7503
new_agwStyle |= AUI_TB_VERTICAL
7505
new_agwStyle &= ~(AUI_TB_VERTICAL)
7507
if agwStyle != new_agwStyle:
7508
toolBar.SetAGWWindowStyleFlag(new_agwStyle)
7509
if not toolBar.GetGripperVisible():
7510
toolBar.SetGripperVisible(True)
7512
s = pane.window.GetMinSize()
7515
if new_agwStyle != agwStyle:
7521
def DoDrop(self, docks, panes, target, pt, offset=wx.Point(0, 0)):
7523
This is an important function. It basically takes a mouse position,
7524
and determines where the panes new position would be. If the pane is to be
7525
dropped, it performs the drop operation using the specified dock and pane
7526
arrays. By specifying copy dock and pane arrays when calling, a "what-if"
7527
scenario can be performed, giving precise coordinates for drop hints.
7529
:param `docks`: a list of :class:`AuiDockInfo` classes;
7530
:param `panes`: a list of :class:`AuiPaneInfo` instances;
7531
:param Point `pt`: a mouse position to check for a drop operation;
7532
:param Point `offset`: a possible offset from the input point `pt`.
7535
if target.IsToolbar():
7536
return self.DoDropToolbar(docks, panes, target, pt, offset)
7537
elif target.IsFloating():
7538
return self.DoDropFloatingPane(docks, panes, target, pt)
7540
return self.DoDropNonFloatingPane(docks, panes, target, pt)
7543
def CopyTarget(self, target):
7545
Copies all the attributes of the input `target` into another :class:`AuiPaneInfo`.
7547
:param `target`: the source :class:`AuiPaneInfo` from where to copy attributes.
7550
drop = AuiPaneInfo()
7551
drop.name = target.name
7552
drop.caption = target.caption
7553
drop.window = target.window
7554
drop.frame = target.frame
7555
drop.state = target.state
7556
drop.dock_direction = target.dock_direction
7557
drop.dock_layer = target.dock_layer
7558
drop.dock_row = target.dock_row
7559
drop.dock_pos = target.dock_pos
7560
drop.best_size = wx.Size(*target.best_size)
7561
drop.min_size = wx.Size(*target.min_size)
7562
drop.max_size = wx.Size(*target.max_size)
7563
drop.floating_pos = wx.Point(*target.floating_pos)
7564
drop.floating_size = wx.Size(*target.floating_size)
7565
drop.dock_proportion = target.dock_proportion
7566
drop.buttons = target.buttons
7567
drop.rect = wx.Rect(*target.rect)
7568
drop.icon = target.icon
7569
drop.notebook_id = target.notebook_id
7570
drop.transparent = target.transparent
7571
drop.snapped = target.snapped
7572
drop.minimize_mode = target.minimize_mode
7573
drop.minimize_target = target.minimize_target
7578
def DoDropToolbar(self, docks, panes, target, pt, offset):
7580
Handles the situation in which the dropped pane contains a toolbar.
7582
:param `docks`: a list of :class:`AuiDockInfo` classes;
7583
:param `panes`: a list of :class:`AuiPaneInfo` instances;
7584
:param AuiPaneInfo `target`: the target pane containing the toolbar;
7585
:param Point `pt`: a mouse position to check for a drop operation;
7586
:param Point `offset`: a possible offset from the input point `pt`.
7589
drop = self.CopyTarget(target)
7591
# The result should always be shown
7594
# Check to see if the toolbar has been dragged out of the window
7595
if CheckOutOfWindow(self._frame, pt):
7596
if self._agwFlags & AUI_MGR_ALLOW_FLOATING and drop.IsFloatable():
7599
return self.ProcessDockResult(target, drop)
7601
# Allow directional change when the cursor leaves this rect
7602
safeRect = wx.Rect(*target.rect)
7603
if target.IsHorizontal():
7604
safeRect.Inflate(100, 50)
7606
safeRect.Inflate(50, 100)
7608
# Check to see if the toolbar has been dragged to edge of the frame
7609
dropDir = CheckEdgeDrop(self._frame, docks, pt)
7613
if dropDir == wx.LEFT:
7614
drop.Dock().Left().Layer(auiToolBarLayer).Row(0). \
7615
Position(pt.y - self.GetDockPixelOffset(drop) - offset.y)
7617
elif dropDir == wx.RIGHT:
7618
drop.Dock().Right().Layer(auiToolBarLayer).Row(0). \
7619
Position(pt.y - self.GetDockPixelOffset(drop) - offset.y)
7621
elif dropDir == wx.TOP:
7622
drop.Dock().Top().Layer(auiToolBarLayer).Row(0). \
7623
Position(pt.x - self.GetDockPixelOffset(drop) - offset.x)
7625
elif dropDir == wx.BOTTOM:
7626
drop.Dock().Bottom().Layer(auiToolBarLayer).Row(0). \
7627
Position(pt.x - self.GetDockPixelOffset(drop) - offset.x)
7629
if not target.IsFloating() and safeRect.Contains(pt) and \
7630
target.dock_direction != drop.dock_direction:
7631
return False, target
7633
return self.ProcessDockResult(target, drop)
7635
# If the windows is floating and out of the client area, do nothing
7636
if drop.IsFloating() and not self._frame.GetClientRect().Contains(pt):
7637
return False, target
7639
# Ok, can't drop on edge - check internals ...
7641
clientSize = self._frame.GetClientSize()
7642
x = Clip(pt.x, 0, clientSize.x - 1)
7643
y = Clip(pt.y, 0, clientSize.y - 1)
7644
part = self.HitTest(x, y)
7646
if not part or not part.dock:
7647
return False, target
7651
# toolbars may only be moved in and to fixed-pane docks,
7652
# otherwise we will try to float the pane. Also, the pane
7653
# should float if being dragged over center pane windows
7654
if not dock.fixed or dock.dock_direction == AUI_DOCK_CENTER:
7656
if (self._agwFlags & AUI_MGR_ALLOW_FLOATING and drop.IsFloatable()) or \
7657
dock.dock_direction not in [AUI_DOCK_CENTER, AUI_DOCK_NONE]:
7658
if drop.IsFloatable():
7661
return self.ProcessDockResult(target, drop)
7663
# calculate the offset from where the dock begins
7664
# to the point where the user dropped the pane
7666
if dock.IsHorizontal():
7667
dockDropOffset = pt.x - dock.rect.x - offset.x
7669
dockDropOffset = pt.y - dock.rect.y - offset.y
7671
drop.Dock().Direction(dock.dock_direction).Layer(dock.dock_layer). \
7672
Row(dock.dock_row).Position(dockDropOffset)
7674
if (pt.y <= dock.rect.GetTop() + 2 and dock.IsHorizontal()) or \
7675
(pt.x <= dock.rect.GetLeft() + 2 and dock.IsVertical()):
7677
if dock.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_LEFT]:
7679
panes = DoInsertDockRow(panes, dock.dock_direction, dock.dock_layer, dock.dock_row)
7683
panes = DoInsertDockRow(panes, dock.dock_direction, dock.dock_layer, dock.dock_row+1)
7684
drop.dock_row = dock.dock_row + 1
7686
if (pt.y >= dock.rect.GetBottom() - 2 and dock.IsHorizontal()) or \
7687
(pt.x >= dock.rect.GetRight() - 2 and dock.IsVertical()):
7689
if dock.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_LEFT]:
7690
panes = DoInsertDockRow(panes, dock.dock_direction, dock.dock_layer, dock.dock_row+1)
7691
drop.dock_row = dock.dock_row+1
7695
panes = DoInsertDockRow(panes, dock.dock_direction, dock.dock_layer, dock.dock_row)
7698
if not target.IsFloating() and safeRect.Contains(pt) and \
7699
target.dock_direction != drop.dock_direction:
7700
return False, target
7702
return self.ProcessDockResult(target, drop)
7705
def DoDropFloatingPane(self, docks, panes, target, pt):
7707
Handles the situation in which the dropped pane contains a normal window.
7709
:param `docks`: a list of :class:`AuiDockInfo` classes;
7710
:param `panes`: a list of :class:`AuiPaneInfo` instances;
7711
:param AuiPaneInfo `target`: the target pane containing the window;
7712
:param Point `pt`: a mouse position to check for a drop operation.
7715
screenPt = self._frame.ClientToScreen(pt)
7716
paneInfo = self.PaneHitTest(panes, pt)
7718
if paneInfo.IsMaximized():
7719
return False, target
7721
if paneInfo.window is None:
7722
return False, target
7724
# search the dock guides.
7725
# reverse order to handle the center first.
7726
for i in xrange(len(self._guides)-1, -1, -1):
7727
guide = self._guides[i]
7729
# do hit testing on the guide
7730
dir = guide.host.HitTest(screenPt.x, screenPt.y)
7732
if dir == -1: # point was outside of the dock guide
7735
if dir == wx.ALL: # target is a single dock guide
7736
return self.DoDropLayer(docks, target, guide.dock_direction)
7738
elif dir == wx.CENTER:
7740
if not target.IsNotebookDockable():
7742
if not paneInfo.IsNotebookDockable() and not paneInfo.IsNotebookControl():
7745
if not paneInfo.HasNotebook():
7747
# Add a new notebook pane with the original as a tab...
7748
self.CreateNotebookBase(panes, paneInfo)
7750
# Add new item to notebook
7751
target.NotebookPage(paneInfo.notebook_id)
7758
insert_dir = paneInfo.dock_direction
7759
insert_layer = paneInfo.dock_layer
7760
insert_row = paneInfo.dock_row
7761
insert_pos = paneInfo.dock_pos
7763
if insert_dir == AUI_DOCK_CENTER:
7767
insert_dir = AUI_DOCK_LEFT
7769
insert_dir = AUI_DOCK_TOP
7770
elif dir == wx.RIGHT:
7771
insert_dir = AUI_DOCK_RIGHT
7772
elif dir == wx.DOWN:
7773
insert_dir = AUI_DOCK_BOTTOM
7775
if insert_dir == AUI_DOCK_LEFT:
7777
drop_pane = (dir == wx.UP or dir == wx.DOWN)
7778
drop_row = (dir == wx.LEFT or dir == wx.RIGHT)
7781
elif dir == wx.DOWN:
7784
elif insert_dir == AUI_DOCK_RIGHT:
7786
drop_pane = (dir == wx.UP or dir == wx.DOWN)
7787
drop_row = (dir == wx.LEFT or dir == wx.RIGHT)
7790
elif dir == wx.DOWN:
7793
elif insert_dir == AUI_DOCK_TOP:
7795
drop_pane = (dir == wx.LEFT or dir == wx.RIGHT)
7796
drop_row = (dir == wx.UP or dir == wx.DOWN)
7799
elif dir == wx.RIGHT:
7802
elif insert_dir == AUI_DOCK_BOTTOM:
7804
drop_pane = (dir == wx.LEFT or dir == wx.RIGHT)
7805
drop_row = (dir == wx.UP or dir == wx.DOWN)
7808
elif dir == wx.RIGHT:
7811
if paneInfo.dock_direction == AUI_DOCK_CENTER:
7812
insert_row = GetMaxRow(panes, insert_dir, insert_layer) + 1
7815
return self.DoDropPane(panes, target, insert_dir, insert_layer, insert_row, insert_pos)
7818
return self.DoDropRow(panes, target, insert_dir, insert_layer, insert_row)
7822
return False, target
7825
def DoDropNonFloatingPane(self, docks, panes, target, pt):
7827
Handles the situation in which the dropped pane is not floating.
7829
:param `docks`: a list of :class:`AuiDockInfo` classes;
7830
:param `panes`: a list of :class:`AuiPaneInfo` instances;
7831
:param AuiPaneInfo `target`: the target pane containing the toolbar;
7832
:param Point `pt`: a mouse position to check for a drop operation.
7835
screenPt = self._frame.ClientToScreen(pt)
7836
clientSize = self._frame.GetClientSize()
7837
frameRect = GetInternalFrameRect(self._frame, self._docks)
7839
drop = self.CopyTarget(target)
7841
# The result should always be shown
7844
part = self.HitTest(pt.x, pt.y)
7847
return False, target
7849
if part.type == AuiDockUIPart.typeDockSizer:
7851
if len(part.dock.panes) != 1:
7852
return False, target
7854
part = self.GetPanePart(part.dock.panes[0].window)
7856
return False, target
7859
return False, target
7861
part = self.GetPanePart(part.pane.window)
7863
return False, target
7865
insert_dock_row = False
7866
insert_row = part.pane.dock_row
7867
insert_dir = part.pane.dock_direction
7868
insert_layer = part.pane.dock_layer
7870
direction = part.pane.dock_direction
7872
if direction == AUI_DOCK_TOP:
7873
if pt.y >= part.rect.y and pt.y < part.rect.y+auiInsertRowPixels:
7874
insert_dock_row = True
7876
elif direction == AUI_DOCK_BOTTOM:
7877
if pt.y > part.rect.y+part.rect.height-auiInsertRowPixels and \
7878
pt.y <= part.rect.y + part.rect.height:
7879
insert_dock_row = True
7881
elif direction == AUI_DOCK_LEFT:
7882
if pt.x >= part.rect.x and pt.x < part.rect.x+auiInsertRowPixels:
7883
insert_dock_row = True
7885
elif direction == AUI_DOCK_RIGHT:
7886
if pt.x > part.rect.x+part.rect.width-auiInsertRowPixels and \
7887
pt.x <= part.rect.x+part.rect.width:
7888
insert_dock_row = True
7890
elif direction == AUI_DOCK_CENTER:
7892
# "new row pixels" will be set to the default, but
7893
# must never exceed 20% of the window size
7894
new_row_pixels_x = auiNewRowPixels
7895
new_row_pixels_y = auiNewRowPixels
7897
if new_row_pixels_x > (part.rect.width*20)/100:
7898
new_row_pixels_x = (part.rect.width*20)/100
7900
if new_row_pixels_y > (part.rect.height*20)/100:
7901
new_row_pixels_y = (part.rect.height*20)/100
7903
# determine if the mouse pointer is in a location that
7904
# will cause a new row to be inserted. The hot spot positions
7905
# are along the borders of the center pane
7908
insert_dock_row = True
7911
if pt.x >= pr.x and pt.x < pr.x + new_row_pixels_x:
7912
insert_dir = AUI_DOCK_LEFT
7913
elif pt.y >= pr.y and pt.y < pr.y + new_row_pixels_y:
7914
insert_dir = AUI_DOCK_TOP
7915
elif pt.x >= pr.x + pr.width - new_row_pixels_x and pt.x < pr.x + pr.width:
7916
insert_dir = AUI_DOCK_RIGHT
7917
elif pt.y >= pr.y+ pr.height - new_row_pixels_y and pt.y < pr.y + pr.height:
7918
insert_dir = AUI_DOCK_BOTTOM
7920
return False, target
7922
insert_row = GetMaxRow(panes, insert_dir, insert_layer) + 1
7926
panes = DoInsertDockRow(panes, insert_dir, insert_layer, insert_row)
7927
drop.Dock().Direction(insert_dir).Layer(insert_layer). \
7928
Row(insert_row).Position(0)
7930
return self.ProcessDockResult(target, drop)
7932
# determine the mouse offset and the pane size, both in the
7933
# direction of the dock itself, and perpendicular to the dock
7935
if part.orientation == wx.VERTICAL:
7937
offset = pt.y - part.rect.y
7938
size = part.rect.GetHeight()
7942
offset = pt.x - part.rect.x
7943
size = part.rect.GetWidth()
7945
drop_position = part.pane.dock_pos
7947
# if we are in the top/left part of the pane,
7948
# insert the pane before the pane being hovered over
7949
if offset <= size/2:
7951
drop_position = part.pane.dock_pos
7952
panes = DoInsertPane(panes,
7953
part.pane.dock_direction,
7954
part.pane.dock_layer,
7958
# if we are in the bottom/right part of the pane,
7959
# insert the pane before the pane being hovered over
7962
drop_position = part.pane.dock_pos+1
7963
panes = DoInsertPane(panes,
7964
part.pane.dock_direction,
7965
part.pane.dock_layer,
7967
part.pane.dock_pos+1)
7971
Direction(part.dock.dock_direction). \
7972
Layer(part.dock.dock_layer).Row(part.dock.dock_row). \
7973
Position(drop_position)
7975
return self.ProcessDockResult(target, drop)
7978
def DoDropLayer(self, docks, target, dock_direction):
7980
Handles the situation in which `target` is a single dock guide.
7982
:param `docks`: a list of :class:`AuiDockInfo` classes;
7983
:param AuiPaneInfo `target`: the target pane;
7984
:param integer `dock_direction`: the docking direction.
7987
drop = self.CopyTarget(target)
7989
if dock_direction == AUI_DOCK_LEFT:
7991
drop_new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_LEFT),
7992
GetMaxLayer(docks, AUI_DOCK_BOTTOM)),
7993
GetMaxLayer(docks, AUI_DOCK_TOP)) + 1
7995
elif dock_direction == AUI_DOCK_TOP:
7997
drop_new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_TOP),
7998
GetMaxLayer(docks, AUI_DOCK_LEFT)),
7999
GetMaxLayer(docks, AUI_DOCK_RIGHT)) + 1
8001
elif dock_direction == AUI_DOCK_RIGHT:
8003
drop_new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_RIGHT),
8004
GetMaxLayer(docks, AUI_DOCK_TOP)),
8005
GetMaxLayer(docks, AUI_DOCK_BOTTOM)) + 1
8007
elif dock_direction == AUI_DOCK_BOTTOM:
8008
drop.Dock().Bottom()
8009
drop_new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_BOTTOM),
8010
GetMaxLayer(docks, AUI_DOCK_LEFT)),
8011
GetMaxLayer(docks, AUI_DOCK_RIGHT)) + 1
8014
return False, target
8017
drop.Dock().Layer(drop_new_layer)
8018
return self.ProcessDockResult(target, drop)
8021
def DoDropPane(self, panes, target, dock_direction, dock_layer, dock_row, dock_pos):
8023
Drop a pane in the interface.
8025
:param `panes`: a list of :class:`AuiPaneInfo` classes;
8026
:param AuiPaneInfo `target`: the target pane;
8027
:param integer `dock_direction`: the docking direction;
8028
:param integer `dock_layer`: the docking layer;
8029
:param integer `dock_row`: the docking row;
8030
:param integer `dock_pos`: the docking position.
8033
drop = self.CopyTarget(target)
8034
panes = DoInsertPane(panes, dock_direction, dock_layer, dock_row, dock_pos)
8036
drop.Dock().Direction(dock_direction).Layer(dock_layer).Row(dock_row).Position(dock_pos)
8037
return self.ProcessDockResult(target, drop)
8040
def DoDropRow(self, panes, target, dock_direction, dock_layer, dock_row):
8042
Insert a row in the interface before dropping.
8044
:param `panes`: a list of :class:`AuiPaneInfo` classes;
8045
:param AuiPaneInfo `target`: the target pane;
8046
:param integer `dock_direction`: the docking direction;
8047
:param integer `dock_layer`: the docking layer;
8048
:param integer `dock_row`: the docking row.
8051
drop = self.CopyTarget(target)
8052
panes = DoInsertDockRow(panes, dock_direction, dock_layer, dock_row)
8054
drop.Dock().Direction(dock_direction).Layer(dock_layer).Row(dock_row).Position(0)
8055
return self.ProcessDockResult(target, drop)
8058
def ShowHint(self, rect):
8060
Shows the AUI hint window.
8062
:param Rect `rect`: the hint rect calculated in advance.
8065
if rect == self._last_hint:
8068
if self._agwFlags & AUI_MGR_RECTANGLE_HINT and wx.Platform != "__WXMAC__":
8070
if self._last_hint != rect:
8071
# remove the last hint rectangle
8072
self._last_hint = wx.Rect(*rect)
8073
self._frame.Refresh()
8074
self._frame.Update()
8076
screendc = wx.ScreenDC()
8077
clip = wx.Region(1, 1, 10000, 10000)
8079
# clip all floating windows, so we don't draw over them
8080
for pane in self._panes:
8081
if pane.IsFloating() and pane.frame.IsShown():
8083
rect2 = wx.Rect(*pane.frame.GetRect())
8084
if wx.Platform == "__WXGTK__":
8085
# wxGTK returns the client size, not the whole frame size
8090
clip.SubtractRect(rect2)
8092
# As we can only hide the hint by redrawing the managed window, we
8093
# need to clip the region to the managed window too or we get
8094
# nasty redrawn problems.
8095
clip.IntersectRect(self._frame.GetRect())
8096
screendc.SetClippingRegionAsRegion(clip)
8098
stipple = PaneCreateStippleBitmap()
8099
brush = wx.BrushFromBitmap(stipple)
8100
screendc.SetBrush(brush)
8101
screendc.SetPen(wx.TRANSPARENT_PEN)
8102
screendc.DrawRectangle(rect.x, rect.y, 5, rect.height)
8103
screendc.DrawRectangle(rect.x+5, rect.y, rect.width-10, 5)
8104
screendc.DrawRectangle(rect.x+rect.width-5, rect.y, 5, rect.height)
8105
screendc.DrawRectangle(rect.x+5, rect.y+rect.height-5, rect.width-10, 5)
8106
RefreshDockingGuides(self._guides)
8110
if not self._hint_window:
8111
self.CreateHintWindow()
8113
if self._hint_window:
8114
self._hint_window.SetRect(rect)
8115
self._hint_window.Show()
8117
self._hint_fadeamt = self._hint_fademax
8119
if self._agwFlags & AUI_MGR_HINT_FADE:
8120
self._hint_fadeamt = 0
8121
self._hint_window.SetTransparent(self._hint_fadeamt)
8123
if self._action == actionDragFloatingPane and self._action_window:
8124
self._action_window.SetFocus()
8126
if self._hint_fadeamt != self._hint_fademax: # Only fade if we need to
8127
# start fade in timer
8128
self._hint_fadetimer.Start(5)
8130
self._last_hint = wx.Rect(*rect)
8134
""" Hides a transparent window hint if there is one. """
8136
# hides a transparent window hint if there is one
8137
if self._hint_window:
8138
self._hint_window.Hide()
8140
self._hint_fadetimer.Stop()
8141
self._last_hint = wx.Rect()
8144
def IsPaneButtonVisible(self, part):
8146
Returns whether a pane button in the pane caption is visible.
8148
:param AuiDockUIPart `part`: the UI part to analyze.
8151
captionRect = wx.Rect()
8153
for temp_part in self._uiparts:
8154
if temp_part.pane == part.pane and \
8155
temp_part.type == AuiDockUIPart.typeCaption:
8156
captionRect = temp_part.rect
8159
return captionRect.ContainsRect(part.rect)
8162
def DrawPaneButton(self, dc, part, pt):
8164
Draws a pane button in the caption (convenience function).
8166
:param `dc`: a :class:`DC` device context object;
8167
:param AuiDockUIPart `part`: the UI part to analyze;
8168
:param Point `pt`: the mouse location.
8171
if not self.IsPaneButtonVisible(part):
8174
state = AUI_BUTTON_STATE_NORMAL
8176
if part.rect.Contains(pt):
8178
if _VERSION_STRING < "2.9":
8179
leftDown = wx.GetMouseState().LeftDown()
8181
leftDown = wx.GetMouseState().LeftIsDown()
8184
state = AUI_BUTTON_STATE_PRESSED
8186
state = AUI_BUTTON_STATE_HOVER
8188
self._art.DrawPaneButton(dc, self._frame, part.button.button_id,
8189
state, part.rect, part.pane)
8192
def RefreshButton(self, part):
8194
Refreshes a pane button in the caption.
8196
:param AuiDockUIPart `part`: the UI part to analyze.
8199
rect = wx.Rect(*part.rect)
8201
self._frame.Refresh(True, rect)
8202
self._frame.Update()
8205
def RefreshCaptions(self):
8206
""" Refreshes all pane captions. """
8208
for part in self._uiparts:
8209
if part.type == AuiDockUIPart.typeCaption:
8210
self._frame.Refresh(True, part.rect)
8211
self._frame.Update()
8214
def CalculateHintRect(self, pane_window, pt, offset):
8216
Calculates the drop hint rectangle.
8218
The method first calls :meth:`DoDrop` to determine the exact position the pane would
8219
be at were if dropped. If the pane would indeed become docked at the
8220
specified drop point, the the rectangle hint will be returned in
8221
screen coordinates. Otherwise, an empty rectangle is returned.
8223
:param Window `pane_window`: it is the window pointer of the pane being dragged;
8224
:param Point `pt`: is the mouse position, in client coordinates;
8225
:param Point `offset`: describes the offset that the mouse is from the upper-left
8226
corner of the item being dragged.
8229
# we need to paint a hint rectangle to find out the exact hint rectangle,
8230
# we will create a new temporary layout and then measure the resulting
8231
# rectangle we will create a copy of the docking structures (self._docks)
8232
# so that we don't modify the real thing on screen
8235
pane = self.GetPane(pane_window)
8237
attrs = self.GetAttributes(pane)
8238
hint = AuiPaneInfo()
8239
hint = self.SetAttributes(hint, attrs)
8241
if hint.name != "__HINT__":
8242
self._oldname = hint.name
8244
hint.name = "__HINT__"
8245
hint.PaneBorder(True)
8249
hint.name = self._oldname
8252
docks, panes = CopyDocksAndPanes2(self._docks, self._panes)
8254
# remove any pane already there which bears the same window
8255
# this happens when you are moving a pane around in a dock
8256
for ii in xrange(len(panes)):
8257
if panes[ii].window == pane_window:
8258
docks = RemovePaneFromDocks(docks, panes[ii])
8262
# find out where the new pane would be
8263
allow, hint = self.DoDrop(docks, panes, hint, pt, offset)
8270
sizer, panes, docks, uiparts = self.LayoutAll(panes, docks, [], True, False)
8272
client_size = self._frame.GetClientSize()
8273
sizer.SetDimension(0, 0, client_size.x, client_size.y)
8278
# For a notebook page, actually look for the notebook itself.
8279
if hint.IsNotebookPage():
8280
id = hint.notebook_id
8282
if pane.IsNotebookControl() and pane.notebook_id==id:
8286
for part in uiparts:
8287
if part.pane and part.pane.name == sought:
8288
rect.Union(wx.RectPS(part.sizer_item.GetPosition(),
8289
part.sizer_item.GetSize()))
8293
# check for floating frame ...
8296
if p.name == sought and p.IsFloating():
8297
return wx.RectPS(p.floating_pos, p.floating_size)
8302
# actually show the hint rectangle on the screen
8303
rect.x, rect.y = self._frame.ClientToScreen((rect.x, rect.y))
8304
if self._frame.GetLayoutDirection() == wx.Layout_RightToLeft:
8305
# Mirror rectangle in RTL mode
8306
rect.x -= rect.GetWidth()
8311
def DrawHintRect(self, pane_window, pt, offset):
8313
Calculates the hint rectangle by calling :meth:`CalculateHintRect`. If there is a
8314
rectangle, it shows it by calling :meth:`ShowHint`, otherwise it hides any hint
8315
rectangle currently shown.
8317
:param Window `pane_window`: it is the window pointer of the pane being dragged;
8318
:param Point `pt`: is the mouse position, in client coordinates;
8319
:param Point `offset`: describes the offset that the mouse is from the upper-left
8320
corner of the item being dragged.
8323
rect = self.CalculateHintRect(pane_window, pt, offset)
8327
self._hint_rect = wx.Rect()
8330
self._hint_rect = wx.Rect(*rect)
8333
def GetPartSizerRect(self, uiparts):
8335
Returns the rectangle surrounding the specified UI parts.
8337
:param list `uiparts`: list of :class:`AuiDockUIPart` parts.
8342
for part in self._uiparts:
8343
if part.pane and part.pane.name == "__HINT__":
8344
rect.Union(wx.RectPS(part.sizer_item.GetPosition(),
8345
part.sizer_item.GetSize()))
8350
def GetAttributes(self, pane):
8352
Returns all the attributes of a :class:`AuiPaneInfo`.
8354
:param `pane`: a :class:`AuiPaneInfo` instance.
8358
attrs.extend([pane.window, pane.frame, pane.state, pane.dock_direction,
8359
pane.dock_layer, pane.dock_pos, pane.dock_row, pane.dock_proportion,
8360
pane.floating_pos, pane.floating_size, pane.best_size,
8361
pane.min_size, pane.max_size, pane.caption, pane.name,
8362
pane.buttons, pane.rect, pane.icon, pane.notebook_id,
8363
pane.transparent, pane.snapped, pane.minimize_mode, pane.minimize_target])
8368
def SetAttributes(self, pane, attrs):
8370
Sets all the attributes contained in `attrs` to a :class:`AuiPaneInfo`.
8372
:param `pane`: a :class:`AuiPaneInfo` instance;
8373
:param list `attrs`: a list of attributes.
8376
pane.window = attrs[0]
8377
pane.frame = attrs[1]
8378
pane.state = attrs[2]
8379
pane.dock_direction = attrs[3]
8380
pane.dock_layer = attrs[4]
8381
pane.dock_pos = attrs[5]
8382
pane.dock_row = attrs[6]
8383
pane.dock_proportion = attrs[7]
8384
pane.floating_pos = attrs[8]
8385
pane.floating_size = attrs[9]
8386
pane.best_size = attrs[10]
8387
pane.min_size = attrs[11]
8388
pane.max_size = attrs[12]
8389
pane.caption = attrs[13]
8390
pane.name = attrs[14]
8391
pane.buttons = attrs[15]
8392
pane.rect = attrs[16]
8393
pane.icon = attrs[17]
8394
pane.notebook_id = attrs[18]
8395
pane.transparent = attrs[19]
8396
pane.snapped = attrs[20]
8397
pane.minimize_mode = attrs[21]
8398
pane.minimize_target = attrs[22]
8403
def OnFloatingPaneResized(self, wnd, size):
8405
Handles the resizing of a floating pane.
8407
:param Window `wnd`: the window managed by the pane;
8408
:param Size `size`: the new pane floating size.
8411
# try to find the pane
8412
pane = self.GetPane(wnd)
8414
raise Exception("Pane window not found")
8417
indx = self._panes.index(pane)
8418
pane.floating_pos = pane.frame.GetPosition()
8419
pane.floating_size = size
8420
self._panes[indx] = pane
8421
if pane.IsSnappable():
8422
self.SnapPane(pane, pane.floating_pos, pane.floating_size, True)
8425
def OnFloatingPaneClosed(self, wnd, event):
8427
Handles the close event of a floating pane.
8429
:param Window `wnd`: the window managed by the pane;
8430
:param `event`: a :class:`CloseEvent` to be processed.
8433
# try to find the pane
8434
pane = self.GetPane(wnd)
8436
raise Exception("Pane window not found")
8438
# fire pane close event
8439
e = AuiManagerEvent(wxEVT_AUI_PANE_CLOSE)
8441
e.SetCanVeto(event.CanVeto())
8442
self.ProcessMgrEvent(e)
8448
# close the pane, but check that it
8449
# still exists in our pane array first
8450
# (the event handler above might have removed it)
8452
check = self.GetPane(wnd)
8454
self.ClosePane(pane)
8457
def OnFloatingPaneActivated(self, wnd):
8459
Handles the activation event of a floating pane.
8461
:param Window `wnd`: the window managed by the pane.
8464
pane = self.GetPane(wnd)
8466
raise Exception("Pane window not found")
8468
if self.GetAGWFlags() & AUI_MGR_ALLOW_ACTIVE_PANE:
8469
ret, self._panes = SetActivePane(self._panes, wnd)
8470
self.RefreshCaptions()
8471
self.FireEvent(wxEVT_AUI_PANE_ACTIVATED, wnd, canVeto=False)
8474
def OnFloatingPaneMoved(self, wnd, eventOrPt):
8476
Handles the move event of a floating pane.
8478
:param Window `wnd`: the window managed by the pane;
8479
:param `eventOrPt`: a :class:`MoveEvent` to be processed or an instance of :class:`Point`.
8482
pane = self.GetPane(wnd)
8484
raise Exception("Pane window not found")
8486
if not pane.IsSnappable():
8489
if isinstance(eventOrPt, wx.Point):
8490
pane_pos = wx.Point(*eventOrPt)
8492
pane_pos = eventOrPt.GetPosition()
8494
pane_size = pane.floating_size
8496
self.SnapPane(pane, pane_pos, pane_size, False)
8499
def SnapPane(self, pane, pane_pos, pane_size, toSnap=False):
8501
Snaps a floating pane to one of the main frame sides.
8503
:param `pane`: a :class:`AuiPaneInfo` instance;
8504
:param Point `pane_pos`: the new pane floating position;
8505
:param Size `pane_size`: the new pane floating size;
8506
:param bool `toSnap`: a bool variable to check if :meth:`SnapPane` was called from
8513
managed_window = self.GetManagedWindow()
8514
wnd_pos = managed_window.GetPosition()
8515
wnd_size = managed_window.GetSize()
8516
snapX, snapY = self._snap_limits
8520
if pane.IsLeftSnappable():
8521
# Check if we can snap to the left
8522
diff = wnd_pos.x - (pane_pos.x + pane_size.x)
8523
if -snapX <= diff <= snapX:
8524
pane.snapped = wx.LEFT
8525
pane.floating_pos = wx.Point(wnd_pos.x-pane_size.x, pane_pos.y)
8526
elif pane.IsTopSnappable():
8527
# Check if we can snap to the top
8528
diff = wnd_pos.y - (pane_pos.y + pane_size.y)
8529
if -snapY <= diff <= snapY:
8530
pane.snapped = wx.TOP
8531
pane.floating_pos = wx.Point(pane_pos.x, wnd_pos.y-pane_size.y)
8532
elif pane.IsRightSnappable():
8533
# Check if we can snap to the right
8534
diff = pane_pos.x - (wnd_pos.x + wnd_size.x)
8535
if -snapX <= diff <= snapX:
8536
pane.snapped = wx.RIGHT
8537
pane.floating_pos = wx.Point(wnd_pos.x + wnd_size.x, pane_pos.y)
8538
elif pane.IsBottomSnappable():
8539
# Check if we can snap to the bottom
8540
diff = pane_pos.y - (wnd_pos.y + wnd_size.y)
8541
if -snapY <= diff <= snapY:
8542
pane.snapped = wx.BOTTOM
8543
pane.floating_pos = wx.Point(pane_pos.x, wnd_pos.y + wnd_size.y)
8545
self.RepositionPane(pane, wnd_pos, wnd_size)
8548
def RepositionPane(self, pane, wnd_pos, wnd_size):
8550
Repositions a pane after the main frame has been moved/resized.
8552
:param `pane`: a :class:`AuiPaneInfo` instance;
8553
:param Point `wnd_pos`: the main frame position;
8554
:param Size `wnd_size`: the main frame size.
8557
pane_pos = pane.floating_pos
8558
pane_size = pane.floating_size
8562
floating_pos = wx.Point(wnd_pos.x - pane_size.x, pane_pos.y)
8563
elif snap == wx.TOP:
8564
floating_pos = wx.Point(pane_pos.x, wnd_pos.y - pane_size.y)
8565
elif snap == wx.RIGHT:
8566
floating_pos = wx.Point(wnd_pos.x + wnd_size.x, pane_pos.y)
8567
elif snap == wx.BOTTOM:
8568
floating_pos = wx.Point(pane_pos.x, wnd_pos.y + wnd_size.y)
8571
if pane_pos != floating_pos:
8572
pane.floating_pos = floating_pos
8573
self._from_move = True
8574
pane.frame.SetPosition(pane.floating_pos)
8575
self._from_move = False
8578
def OnGripperClicked(self, pane_window, start, offset):
8580
Handles the mouse click on the pane gripper.
8582
:param Window `pane_window`: the window managed by the pane;
8583
:param Point `start`: the mouse-click position;
8584
:param Point `offset`: an offset point from the `start` position.
8587
# try to find the pane
8588
paneInfo = self.GetPane(pane_window)
8590
if not paneInfo.IsOk():
8591
raise Exception("Pane window not found")
8593
if self.GetAGWFlags() & AUI_MGR_ALLOW_ACTIVE_PANE:
8594
# set the caption as active
8595
ret, self._panes = SetActivePane(self._panes, pane_window)
8596
self.RefreshCaptions()
8597
self.FireEvent(wxEVT_AUI_PANE_ACTIVATED, pane_window, canVeto=False)
8599
self._action_part = None
8600
self._action_pane = paneInfo
8601
self._action_window = pane_window
8602
self._action_start = start
8603
self._action_offset = offset
8604
self._toolbar_action_offset = wx.Point(*self._action_offset)
8606
self._frame.CaptureMouse()
8608
if paneInfo.IsDocked():
8609
self._action = actionClickCaption
8611
if paneInfo.IsToolbar():
8612
self._action = actionDragToolbarPane
8614
self._action = actionDragFloatingPane
8618
windowPt = paneInfo.frame.GetRect().GetTopLeft()
8619
originPt = paneInfo.frame.ClientToScreen(wx.Point())
8620
self._action_offset += originPt - windowPt
8621
self._toolbar_action_offset = wx.Point(*self._action_offset)
8623
if self._agwFlags & AUI_MGR_TRANSPARENT_DRAG:
8624
paneInfo.frame.SetTransparent(150)
8626
if paneInfo.IsToolbar():
8627
self._frame.SetCursor(wx.StockCursor(wx.CURSOR_SIZING))
8630
def OnRender(self, event):
8632
Draws all of the pane captions, sashes, backgrounds, captions, grippers, pane borders and buttons.
8633
It renders the entire user interface. It binds the ``EVT_AUI_RENDER`` event.
8635
:param `event`: an instance of :class:`AuiManagerEvent`.
8638
# if the frame is about to be deleted, don't bother
8639
if not self._frame or self._frame.IsBeingDeleted():
8642
if not self._frame.GetSizer():
8645
mouse = wx.GetMouseState()
8646
mousePos = wx.Point(mouse.GetX(), mouse.GetY())
8647
point = self._frame.ScreenToClient(mousePos)
8652
for part in self._uiparts:
8654
# don't draw hidden pane items or items that aren't windows
8655
if part.sizer_item and ((not part.sizer_item.IsWindow() and \
8656
not part.sizer_item.IsSpacer() and \
8657
not part.sizer_item.IsSizer()) or \
8658
not part.sizer_item.IsShown()):
8664
if ptype in [AuiDockUIPart.typeDockSizer, AuiDockUIPart.typePaneSizer]:
8665
art.DrawSash(dc, self._frame, part.orientation, part.rect)
8667
elif ptype == AuiDockUIPart.typeBackground:
8668
art.DrawBackground(dc, self._frame, part.orientation, part.rect)
8670
elif ptype == AuiDockUIPart.typeCaption:
8671
art.DrawCaption(dc, self._frame, part.pane.caption, part.rect, part.pane)
8673
elif ptype == AuiDockUIPart.typeGripper:
8674
art.DrawGripper(dc, self._frame, part.rect, part.pane)
8676
elif ptype == AuiDockUIPart.typePaneBorder:
8677
art.DrawBorder(dc, self._frame, part.rect, part.pane)
8679
elif ptype == AuiDockUIPart.typePaneButton:
8680
self.DrawPaneButton(dc, part, point)
8683
def Repaint(self, dc=None):
8685
Repaints the entire frame decorations (sashes, borders, buttons and so on).
8686
It renders the entire user interface.
8688
:param `dc`: if not ``None``, an instance of :class:`PaintDC`.
8691
w, h = self._frame.GetClientSize()
8693
# Figure out which dc to use; if one
8694
# has been specified, use it, otherwise
8697
client_dc = wx.ClientDC(self._frame)
8700
# If the frame has a toolbar, the client area
8701
# origin will not be (0, 0).
8702
pt = self._frame.GetClientAreaOrigin()
8703
if pt.x != 0 or pt.y != 0:
8704
dc.SetDeviceOrigin(pt.x, pt.y)
8706
# Render all the items
8710
def Render(self, dc):
8712
Fires a render event, which is normally handled by :meth:`OnRender`. This allows the
8713
render function to be overridden via the render event.
8715
This can be useful for painting custom graphics in the main window.
8716
Default behavior can be invoked in the overridden function by calling
8719
:param `dc`: a :class:`DC` device context object.
8722
e = AuiManagerEvent(wxEVT_AUI_RENDER)
8725
self.ProcessMgrEvent(e)
8728
def OnCaptionDoubleClicked(self, pane_window):
8730
Handles the mouse double click on the pane caption.
8732
:param Window `pane_window`: the window managed by the pane.
8735
# try to find the pane
8736
paneInfo = self.GetPane(pane_window)
8737
if not paneInfo.IsOk():
8738
raise Exception("Pane window not found")
8740
if not paneInfo.IsFloatable() or not paneInfo.IsDockable() or \
8741
self._agwFlags & AUI_MGR_ALLOW_FLOATING == 0:
8744
indx = self._panes.index(paneInfo)
8747
if paneInfo.IsFloating():
8748
if paneInfo.name.startswith("__floating__"):
8749
# It's a floating tab from a AuiNotebook
8750
notebook = paneInfo.window.__aui_notebook__
8751
notebook.ReDockPage(paneInfo)
8756
e = self.FireEvent(wxEVT_AUI_PANE_DOCKING, paneInfo, canVeto=True)
8759
ShowDockingGuides(self._guides, False)
8762
win_rect = paneInfo.frame.GetRect()
8764
if paneInfo.IsToolbar():
8765
paneInfo = self.SwitchToolBarOrientation(paneInfo)
8767
e = self.FireEvent(wxEVT_AUI_PANE_DOCKED, paneInfo, canVeto=False)
8771
e = self.FireEvent(wxEVT_AUI_PANE_FLOATING, paneInfo, canVeto=True)
8776
if paneInfo.IsMaximized():
8777
self.RestorePane(paneInfo)
8779
if paneInfo.floating_pos == wx.Point(-1, -1):
8780
captionSize = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE)
8781
paneInfo.floating_pos = pane_window.GetScreenPosition()
8782
paneInfo.floating_pos.y -= captionSize
8785
e = self.FireEvent(wxEVT_AUI_PANE_FLOATED, paneInfo, canVeto=False)
8787
self._panes[indx] = paneInfo
8790
if win_rect and self._agwFlags & AUI_MGR_ANIMATE_FRAMES:
8791
paneInfo = self.GetPane(pane_window)
8792
pane_rect = paneInfo.window.GetScreenRect()
8793
self.AnimateDocking(win_rect, pane_rect)
8796
def OnPaint(self, event):
8798
Handles the ``wx.EVT_PAINT`` event for :class:`AuiManager`.
8800
:param `event`: an instance of :class:`PaintEvent` to be processed.
8803
dc = wx.PaintDC(self._frame)
8807
def OnEraseBackground(self, event):
8809
Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`AuiManager`.
8811
:param `event`: :class:`EraseEvent` to be processed.
8813
:note: This is intentionally empty (excluding wxMAC) to reduce
8814
flickering while drawing.
8817
if wx.Platform == "__WXMAC__":
8821
def OnSize(self, event):
8823
Handles the ``wx.EVT_SIZE`` event for :class:`AuiManager`.
8825
:param `event`: a :class:`SizeEvent` to be processed.
8829
if isinstance(self._frame, AuiFloatingFrame) and self._frame.IsShownOnScreen():
8835
self.DoFrameLayout()
8836
if wx.Platform == "__WXMAC__":
8837
self._frame.Refresh()
8841
if isinstance(self._frame, wx.MDIParentFrame) or isinstance(self._frame, tabmdi.AuiMDIClientWindow) \
8842
or isinstance(self._frame, tabmdi.AuiMDIParentFrame):
8843
# for MDI parent frames, this event must not
8844
# be "skipped". In other words, the parent frame
8845
# must not be allowed to resize the client window
8846
# after we are finished processing sizing changes
8852
# For the snap to screen...
8856
def OnFindManager(self, event):
8858
Handles the ``EVT_AUI_FIND_MANAGER`` event for :class:`AuiManager`.
8860
:param `event`: a :class:`AuiManagerEvent` event to be processed.
8863
# Initialize to None
8864
event.SetManager(None)
8869
# See it this window wants to overwrite
8870
self._frame.ProcessEvent(event)
8872
# if no, it must be us
8873
if not event.GetManager():
8874
event.SetManager(self)
8877
def OnSetCursor(self, event):
8879
Handles the ``wx.EVT_SET_CURSOR`` event for :class:`AuiManager`.
8881
:param `event`: a :class:`SetCursorEvent` to be processed.
8885
part = self.HitTest(event.GetX(), event.GetY())
8886
cursor = wx.NullCursor
8889
if part.type in [AuiDockUIPart.typeDockSizer, AuiDockUIPart.typePaneSizer]:
8891
if not self.CheckMovableSizer(part):
8894
if part.orientation == wx.VERTICAL:
8895
cursor = wx.StockCursor(wx.CURSOR_SIZEWE)
8897
cursor = wx.StockCursor(wx.CURSOR_SIZENS)
8899
elif part.type == AuiDockUIPart.typeGripper:
8900
cursor = wx.StockCursor(wx.CURSOR_SIZING)
8902
event.SetCursor(cursor)
8905
def UpdateButtonOnScreen(self, button_ui_part, event):
8907
Updates/redraws the UI part containing a pane button.
8909
:param AuiDockUIPart `button_ui_part`: the UI part the button belongs to;
8910
:param `event`: a :class:`MouseEvent` to be processed.
8913
hit_test = self.HitTest(*event.GetPosition())
8915
if not hit_test or not button_ui_part:
8918
state = AUI_BUTTON_STATE_NORMAL
8920
if hit_test == button_ui_part:
8921
if event.LeftDown():
8922
state = AUI_BUTTON_STATE_PRESSED
8924
state = AUI_BUTTON_STATE_HOVER
8926
if event.LeftDown():
8927
state = AUI_BUTTON_STATE_HOVER
8929
# now repaint the button with hover state
8930
cdc = wx.ClientDC(self._frame)
8932
# if the frame has a toolbar, the client area
8933
# origin will not be (0,0).
8934
pt = self._frame.GetClientAreaOrigin()
8935
if pt.x != 0 or pt.y != 0:
8936
cdc.SetDeviceOrigin(pt.x, pt.y)
8939
self._art.DrawPaneButton(cdc, self._frame,
8940
button_ui_part.button.button_id,
8942
button_ui_part.rect, hit_test.pane)
8945
def OnLeftDown(self, event):
8947
Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`AuiManager`.
8949
:param `event`: a :class:`MouseEvent` to be processed.
8952
part = self.HitTest(*event.GetPosition())
8958
self._currentDragItem = -1
8960
if part.type in [AuiDockUIPart.typeDockSizer, AuiDockUIPart.typePaneSizer]:
8962
if not self.CheckMovableSizer(part):
8965
self._action = actionResize
8966
self._action_part = part
8967
self._action_pane = None
8968
self._action_rect = wx.Rect()
8969
self._action_start = wx.Point(event.GetX(), event.GetY())
8970
self._action_offset = wx.Point(event.GetX() - part.rect.x,
8971
event.GetY() - part.rect.y)
8973
# draw the resize hint
8974
rect = wx.RectPS(self._frame.ClientToScreen(part.rect.GetPosition()),
8975
part.rect.GetSize())
8977
self._action_rect = wx.Rect(*rect)
8979
if not AuiManager_HasLiveResize(self):
8980
if wx.Platform == "__WXMAC__":
8981
dc = wx.ClientDC(self._frame)
8985
DrawResizeHint(dc, rect)
8987
self._frame.CaptureMouse()
8989
elif part.type == AuiDockUIPart.typePaneButton:
8990
if self.IsPaneButtonVisible(part):
8991
self._action = actionClickButton
8992
self._action_part = part
8993
self._action_pane = None
8994
self._action_start = wx.Point(*event.GetPosition())
8995
self._frame.CaptureMouse()
8997
self.RefreshButton(part)
8999
elif part.type in [AuiDockUIPart.typeCaption, AuiDockUIPart.typeGripper]:
9001
# if we are managing a AuiFloatingFrame window, then
9002
# we are an embedded AuiManager inside the AuiFloatingFrame.
9003
# We want to initiate a toolbar drag in our owner manager
9004
if isinstance(part.pane.window.GetParent(), AuiFloatingFrame):
9005
rootManager = GetManager(part.pane.window)
9009
offset = wx.Point(event.GetX() - part.rect.x, event.GetY() - part.rect.y)
9010
rootManager.OnGripperClicked(part.pane.window, event.GetPosition(), offset)
9012
if wx.Platform != "__WXMAC__":
9016
def OnLeftDClick(self, event):
9018
Handles the ``wx.EVT_LEFT_DCLICK`` event for :class:`AuiManager`.
9020
:param `event`: a :class:`MouseEvent` to be processed.
9023
part = self.HitTest(event.GetX(), event.GetY())
9025
if part and part.type == AuiDockUIPart.typeCaption:
9026
if isinstance(part.pane.window.GetParent(), AuiFloatingFrame):
9027
rootManager = GetManager(part.pane.window)
9031
rootManager.OnCaptionDoubleClicked(part.pane.window)
9033
elif part and part.type in [AuiDockUIPart.typeDockSizer, AuiDockUIPart.typePaneSizer]:
9034
# Handles double click on AuiNotebook sashes to unsplit
9035
sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE)
9036
for child in part.cont_sizer.GetChildren():
9038
win = child.GetSizer().GetContainingWindow()
9039
if isinstance(win, auibook.AuiNotebook):
9040
win.UnsplitDClick(part, sash_size, event.GetPosition())
9046
def DoEndResizeAction(self, event):
9048
Ends a resize action, or for live update, resizes the sash.
9050
:param `event`: a :class:`MouseEvent` to be processed.
9053
clientPt = event.GetPosition()
9054
screenPt = self._frame.ClientToScreen(clientPt)
9056
return self.RestrictResize(clientPt, screenPt, createDC=False)
9059
def RestrictResize(self, clientPt, screenPt, createDC):
9060
""" Common method between :meth:`DoEndResizeAction` and :meth:`OnLeftUp_Resize`. """
9062
dock = self._action_part.dock
9063
pane = self._action_part.pane
9066
if wx.Platform == "__WXMAC__":
9067
dc = wx.ClientDC(self._frame)
9071
DrawResizeHint(dc, self._action_rect)
9072
self._action_rect = wx.Rect()
9074
newPos = clientPt - self._action_offset
9076
if self._action_part.type == AuiDockUIPart.typeDockSizer:
9077
minPix, maxPix = self.CalculateDockSizerLimits(dock)
9079
if not self._action_part.pane:
9081
minPix, maxPix = self.CalculatePaneSizerLimits(dock, pane)
9083
if self._action_part.orientation == wx.HORIZONTAL:
9084
newPos.y = Clip(newPos.y, minPix, maxPix)
9086
newPos.x = Clip(newPos.x, minPix, maxPix)
9088
if self._action_part.type == AuiDockUIPart.typeDockSizer:
9090
partnerDock = self.GetPartnerDock(dock)
9091
sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE)
9093
direction = dock.dock_direction
9095
if direction == AUI_DOCK_LEFT:
9096
new_dock_size = newPos.x - dock.rect.x
9098
elif direction == AUI_DOCK_TOP:
9099
new_dock_size = newPos.y - dock.rect.y
9101
elif direction == AUI_DOCK_RIGHT:
9102
new_dock_size = dock.rect.x + dock.rect.width - newPos.x - sash_size
9104
elif direction == AUI_DOCK_BOTTOM:
9105
new_dock_size = dock.rect.y + dock.rect.height - newPos.y - sash_size
9107
deltaDockSize = new_dock_size - dock.size
9110
if deltaDockSize > partnerDock.size - sash_size:
9111
deltaDockSize = partnerDock.size - sash_size
9113
partnerDock.size -= deltaDockSize
9115
dock.size += deltaDockSize
9120
# determine the new pixel size that the user wants
9121
# this will help us recalculate the pane's proportion
9122
if dock.IsHorizontal():
9123
oldPixsize = pane.rect.width
9124
newPixsize = oldPixsize + newPos.x - self._action_part.rect.x
9127
oldPixsize = pane.rect.height
9128
newPixsize = oldPixsize + newPos.y - self._action_part.rect.y
9130
totalPixsize, totalProportion = self.GetTotalPixSizeAndProportion(dock)
9131
partnerPane = self.GetPartnerPane(dock, pane)
9133
# prevent division by zero
9134
if totalPixsize <= 0 or totalProportion <= 0 or not partnerPane:
9137
# adjust for the surplus
9138
while (oldPixsize > 0 and totalPixsize > 10 and \
9139
oldPixsize*totalProportion/totalPixsize < pane.dock_proportion):
9143
# calculate the new proportion of the pane
9145
newProportion = newPixsize*totalProportion/totalPixsize
9146
newProportion = Clip(newProportion, 1, totalProportion)
9147
deltaProp = newProportion - pane.dock_proportion
9149
if partnerPane.dock_proportion - deltaProp < 1:
9150
deltaProp = partnerPane.dock_proportion - 1
9151
newProportion = pane.dock_proportion + deltaProp
9153
# borrow the space from our neighbor pane to the
9154
# right or bottom (depending on orientation)
9155
partnerPane.dock_proportion -= deltaProp
9156
pane.dock_proportion = newProportion
9163
def OnLeftUp(self, event):
9165
Handles the ``wx.EVT_LEFT_UP`` event for :class:`AuiManager`.
9167
:param `event`: a :class:`MouseEvent` to be processed.
9170
if self._action == actionResize:
9171
## self._frame.Freeze()
9172
self.OnLeftUp_Resize(event)
9173
## self._frame.Thaw()
9175
elif self._action == actionClickButton:
9176
self.OnLeftUp_ClickButton(event)
9178
elif self._action == actionDragFloatingPane:
9179
self.OnLeftUp_DragFloatingPane(event)
9181
elif self._action == actionDragToolbarPane:
9182
self.OnLeftUp_DragToolbarPane(event)
9184
elif self._action == actionDragMovablePane:
9185
self.OnLeftUp_DragMovablePane(event)
9191
if self._frame.HasCapture():
9192
self._frame.ReleaseMouse()
9193
except wx.PyDeadObjectError:
9196
self._action = actionNone
9199
def OnMotion(self, event):
9201
Handles the ``wx.EVT_MOTION`` event for :class:`AuiManager`.
9203
:param `event`: a :class:`MouseEvent` to be processed.
9206
if self._action == actionResize:
9207
self.OnMotion_Resize(event)
9209
elif self._action == actionClickCaption:
9210
self.OnMotion_ClickCaption(event)
9212
elif self._action == actionDragFloatingPane:
9213
self.OnMotion_DragFloatingPane(event)
9215
elif self._action == actionDragToolbarPane:
9216
self.OnMotion_DragToolbarPane(event)
9218
elif self._action == actionDragMovablePane:
9219
self.OnMotion_DragMovablePane(event)
9222
self.OnMotion_Other(event)
9225
def OnLeaveWindow(self, event):
9227
Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`AuiManager`.
9229
:param `event`: a :class:`MouseEvent` to be processed.
9232
if self._hover_button:
9233
self.RefreshButton(self._hover_button)
9234
self._hover_button = None
9237
def OnCaptureLost(self, event):
9239
Handles the ``wx.EVT_MOUSE_CAPTURE_LOST`` event for :class:`AuiManager`.
9241
:param `event`: a :class:`MouseCaptureLostEvent` to be processed.
9244
# cancel the operation in progress, if any
9245
if self._action != actionNone:
9246
self._action = actionNone
9250
def OnHintFadeTimer(self, event):
9252
Handles the ``wx.EVT_TIMER`` event for :class:`AuiManager`.
9254
:param `event`: a :class:`TimerEvent` to be processed.
9257
if not self._hint_window or self._hint_fadeamt >= self._hint_fademax:
9258
self._hint_fadetimer.Stop()
9261
self._hint_fadeamt += 4
9262
self._hint_window.SetTransparent(self._hint_fadeamt)
9265
def OnMove(self, event):
9267
Handles the ``wx.EVT_MOVE`` event for :class:`AuiManager`.
9269
:param `event`: a :class:`MoveEvent` to be processed.
9272
if event is not None:
9275
if isinstance(self._frame, AuiFloatingFrame) and self._frame.IsShownOnScreen():
9278
docked, hAlign, vAlign, monitor = self._is_docked
9282
for pane in self._panes:
9283
if pane.IsSnappable():
9284
if pane.IsFloating() and pane.IsShown():
9285
self.SnapPane(pane, pane.floating_pos, pane.floating_size, True)
9288
def OnSysColourChanged(self, event):
9290
Handles the ``wx.EVT_SYS_COLOUR_CHANGED`` event for :class:`AuiManager`.
9292
:param `event`: a :class:`SysColourChangedEvent` to be processed.
9295
# This event is probably triggered by a theme change
9296
# so we have to re-init the art provider.
9302
self._frame.Refresh()
9305
def OnChildFocus(self, event):
9307
Handles the ``wx.EVT_CHILD_FOCUS`` event for :class:`AuiManager`.
9309
:param `event`: a :class:`ChildFocusEvent` to be processed.
9312
# when a child pane has it's focus set, we should change the
9313
# pane's active state to reflect this. (this is only true if
9314
# active panes are allowed by the owner)
9316
window = event.GetWindow()
9317
if isinstance(window, wx.Dialog):
9318
# Ignore EVT_CHILD_FOCUS events originating from dialogs not
9321
elif isinstance(window.GetParent(), AuiFloatingFrame):
9322
rootManager = GetManager(window)
9327
rootManager.ActivatePane(window)
9332
def OnMotion_ClickCaption(self, event):
9334
Sub-handler for the :meth:`OnMotion` event.
9336
:param `event`: a :class:`MouseEvent` to be processed.
9339
clientPt = event.GetPosition()
9340
screenPt = self._frame.ClientToScreen(clientPt)
9342
drag_x_threshold = wx.SystemSettings.GetMetric(wx.SYS_DRAG_X)
9343
drag_y_threshold = wx.SystemSettings.GetMetric(wx.SYS_DRAG_Y)
9345
if not self._action_pane:
9348
# we need to check if the mouse is now being dragged
9349
if not (abs(clientPt.x - self._action_start.x) > drag_x_threshold or \
9350
abs(clientPt.y - self._action_start.y) > drag_y_threshold):
9354
# dragged -- we need to change the mouse action to 'drag'
9355
if self._action_pane.IsToolbar():
9356
self._action = actionDragToolbarPane
9357
self._action_window = self._action_pane.window
9359
elif self._action_pane.IsFloatable() and self._agwFlags & AUI_MGR_ALLOW_FLOATING:
9361
e = self.FireEvent(wxEVT_AUI_PANE_FLOATING, self._action_pane, canVeto=True)
9365
self._action = actionDragFloatingPane
9367
# set initial float position
9368
self._action_pane.floating_pos = screenPt - self._action_offset
9371
if self._action_pane.IsMaximized():
9372
self.RestorePane(self._action_pane)
9374
self._action_pane.Hide()
9375
self._action_pane.Float()
9376
if wx.Platform == "__WXGTK__":
9377
self._action_pane.Show()
9379
e = self.FireEvent(wxEVT_AUI_PANE_FLOATED, self._action_pane, canVeto=False)
9381
if not self._action_pane.frame:
9384
self._action_window = self._action_pane.window
9386
# adjust action offset for window frame
9387
windowPt = self._action_pane.frame.GetRect().GetTopLeft()
9388
originPt = self._action_pane.frame.ClientToScreen(wx.Point())
9389
self._toolbar_action_offset = originPt - windowPt
9391
if self._agwFlags & AUI_MGR_USE_NATIVE_MINIFRAMES:
9392
originPt = windowPt + wx.Point(3, 3)
9394
self._action_offset += originPt - windowPt
9396
# action offset is used here to make it feel "natural" to the user
9397
# to drag a docked pane and suddenly have it become a floating frame.
9398
# Sometimes, however, the offset where the user clicked on the docked
9399
# caption is bigger than the width of the floating frame itself, so
9400
# in that case we need to set the action offset to a sensible value
9401
frame_size = self._action_pane.frame.GetSize()
9402
if self._action_offset.x > frame_size.x * 2 / 3:
9403
self._action_offset.x = frame_size.x / 2
9404
if self._action_offset.y > frame_size.y * 2 / 3:
9405
self._action_offset.y = frame_size.y / 2
9407
self.OnMotion_DragFloatingPane(event)
9408
if wx.Platform != "__WXGTK__":
9409
self._action_pane.Show()
9413
elif self._action_pane.IsMovable():
9414
self._action = actionDragMovablePane
9415
self._action_window = self._action_pane.window
9418
def OnMotion_Resize(self, event):
9420
Sub-handler for the :meth:`OnMotion` event.
9422
:param `event`: a :class:`MouseEvent` to be processed.
9425
if AuiManager_HasLiveResize(self):
9426
if self._currentDragItem != -1:
9427
self._action_part = self._uiparts[self._currentDragItem]
9429
self._currentDragItem = self._uiparts.index(self._action_part)
9431
if self._frame.HasCapture():
9432
self._frame.ReleaseMouse()
9434
self.DoEndResizeAction(event)
9435
self._frame.CaptureMouse()
9438
if not self._action_part or not self._action_part.dock or not self._action_part.orientation:
9441
clientPt = event.GetPosition()
9442
screenPt = self._frame.ClientToScreen(clientPt)
9444
dock = self._action_part.dock
9445
pos = self._action_part.rect.GetPosition()
9447
if self._action_part.type == AuiDockUIPart.typeDockSizer:
9448
minPix, maxPix = self.CalculateDockSizerLimits(dock)
9450
if not self._action_part.pane:
9453
pane = self._action_part.pane
9454
minPix, maxPix = self.CalculatePaneSizerLimits(dock, pane)
9456
if self._action_part.orientation == wx.HORIZONTAL:
9457
pos.y = Clip(clientPt.y - self._action_offset.y, minPix, maxPix)
9459
pos.x = Clip(clientPt.x - self._action_offset.x, minPix, maxPix)
9461
hintrect = wx.RectPS(self._frame.ClientToScreen(pos), self._action_part.rect.GetSize())
9463
if hintrect != self._action_rect:
9465
if wx.Platform == "__WXMAC__":
9466
dc = wx.ClientDC(self._frame)
9470
DrawResizeHint(dc, self._action_rect)
9471
DrawResizeHint(dc, hintrect)
9472
self._action_rect = wx.Rect(*hintrect)
9475
def OnLeftUp_Resize(self, event):
9477
Sub-handler for the :meth:`OnLeftUp` event.
9479
:param `event`: a :class:`MouseEvent` to be processed.
9482
if self._currentDragItem != -1 and AuiManager_HasLiveResize(self):
9483
self._action_part = self._uiparts[self._currentDragItem]
9485
if self._frame.HasCapture():
9486
self._frame.ReleaseMouse()
9488
self.DoEndResizeAction(event)
9489
self._currentDragItem = -1
9492
if not self._action_part or not self._action_part.dock:
9495
clientPt = event.GetPosition()
9496
screenPt = self._frame.ClientToScreen(clientPt)
9498
return self.RestrictResize(clientPt, screenPt, createDC=True)
9501
def OnLeftUp_ClickButton(self, event):
9503
Sub-handler for the :meth:`OnLeftUp` event.
9505
:param `event`: a :class:`MouseEvent` to be processed.
9508
self._hover_button = None
9510
if self._action_part:
9511
self.RefreshButton(self._action_part)
9513
# make sure we're still over the item that was originally clicked
9514
if self._action_part == self.HitTest(*event.GetPosition()):
9516
# fire button-click event
9517
e = AuiManagerEvent(wxEVT_AUI_PANE_BUTTON)
9519
e.SetPane(self._action_part.pane)
9520
e.SetButton(self._action_part.button.button_id)
9521
self.ProcessMgrEvent(e)
9524
def CheckPaneMove(self, pane):
9526
Checks if a pane has moved by a visible amount.
9528
:param `pane`: an instance of :class:`AuiPaneInfo`.
9531
win_rect = pane.frame.GetRect()
9532
win_rect.x, win_rect.y = pane.floating_pos
9534
if win_rect == self._last_rect:
9537
# skip the first move event
9538
if self._last_rect.IsEmpty():
9539
self._last_rect = wx.Rect(*win_rect)
9542
# skip if moving too fast to avoid massive redraws and
9543
# jumping hint windows
9544
if abs(win_rect.x - self._last_rect.x) > 10 or \
9545
abs(win_rect.y - self._last_rect.y) > 10:
9546
self._last_rect = wx.Rect(*win_rect)
9552
def OnMotion_DragFloatingPane(self, eventOrPt):
9554
Sub-handler for the :meth:`OnMotion` event.
9556
:param `event`: a :class:`MouseEvent` to be processed.
9560
if isinstance(eventOrPt, wx.Point):
9561
clientPt = self._frame.ScreenToClient(eventOrPt)
9562
screenPt = wx.Point(*eventOrPt)
9565
clientPt = eventOrPt.GetPosition()
9566
screenPt = self._frame.ClientToScreen(clientPt)
9568
framePos = wx.Point()
9570
# try to find the pane
9571
pane = self.GetPane(self._action_window)
9573
raise Exception("Pane window not found")
9575
# update floating position
9576
if pane.IsFloating():
9577
diff = pane.floating_pos - (screenPt - self._action_offset)
9578
pane.floating_pos = screenPt - self._action_offset
9580
framePos = pane.floating_pos
9582
# Move the pane window
9585
if diff.x != 0 or diff.y != 0:
9586
if wx.Platform == "__WXMSW__" and (self._agwFlags & AUI_MGR_TRANSPARENT_DRAG) == 0: # and not self.CheckPaneMove(pane):
9588
# HACK: Terrible hack on wxMSW (!)
9589
pane.frame.SetTransparent(254)
9591
self._from_move = True
9592
pane.frame.Move(pane.floating_pos)
9593
self._from_move = False
9595
if self._agwFlags & AUI_MGR_TRANSPARENT_DRAG:
9596
pane.frame.SetTransparent(150)
9598
# calculate the offset from the upper left-hand corner
9599
# of the frame to the mouse pointer
9600
action_offset = screenPt - framePos
9602
# is the pane dockable?
9603
if not self.CanDockPanel(pane):
9605
ShowDockingGuides(self._guides, False)
9608
for paneInfo in self._panes:
9610
if not paneInfo.IsDocked() or not paneInfo.IsShown():
9612
if paneInfo.IsToolbar() or paneInfo.IsNotebookControl():
9614
if paneInfo.IsMaximized():
9617
if paneInfo.IsNotebookPage():
9619
notebookRoot = GetNotebookRoot(self._panes, paneInfo.notebook_id)
9621
if not notebookRoot or not notebookRoot.IsDocked():
9624
rc = paneInfo.window.GetScreenRect()
9625
if rc.Contains(screenPt):
9626
if rc.height < 20 or rc.width < 20:
9629
self.UpdateDockingGuides(paneInfo)
9630
ShowDockingGuides(self._guides, True)
9633
self.DrawHintRect(pane.window, clientPt, action_offset)
9636
def OnMotion_DragMovablePane(self, eventOrPt):
9638
Sub-handler for the :meth:`OnMotion` event.
9640
:param `event`: a :class:`MouseEvent` to be processed.
9643
# Try to find the pane.
9644
pane = self.GetPane(self._action_window)
9646
raise Exception("Pane window not found")
9648
# Draw a hint for where the window will be moved.
9649
if isinstance(eventOrPt, wx.Point):
9650
pt = wx.Point(*eventOrPt)
9652
pt = eventOrPt.GetPosition()
9654
self.DrawHintRect(self._action_window, pt, wx.Point(0, 0))
9657
self._frame.Update()
9660
def OnLeftUp_DragFloatingPane(self, eventOrPt):
9662
Sub-handler for the :meth:`OnLeftUp` event.
9664
:param `event`: a :class:`MouseEvent` to be processed.
9667
if isinstance(eventOrPt, wx.Point):
9668
clientPt = self._frame.ScreenToClient(eventOrPt)
9669
screenPt = wx.Point(*eventOrPt)
9671
clientPt = eventOrPt.GetPosition()
9672
screenPt = self._frame.ClientToScreen(clientPt)
9674
# try to find the pane
9675
paneInfo = self.GetPane(self._action_window)
9676
if not paneInfo.IsOk():
9677
raise Exception("Pane window not found")
9683
# calculate the offset from the upper left-hand corner
9684
# of the frame to the mouse pointer
9685
framePos = paneInfo.frame.GetPosition()
9686
action_offset = screenPt - framePos
9688
# is the pane dockable?
9689
if self.CanDockPanel(paneInfo):
9690
# do the drop calculation
9691
indx = self._panes.index(paneInfo)
9692
ret, paneInfo = self.DoDrop(self._docks, self._panes, paneInfo, clientPt, action_offset)
9695
e = self.FireEvent(wxEVT_AUI_PANE_DOCKING, paneInfo, canVeto=True)
9698
ShowDockingGuides(self._guides, False)
9701
e = self.FireEvent(wxEVT_AUI_PANE_DOCKED, paneInfo, canVeto=False)
9703
if self._agwFlags & AUI_MGR_SMOOTH_DOCKING:
9704
self.SmoothDock(paneInfo)
9706
self._panes[indx] = paneInfo
9708
# if the pane is still floating, update it's floating
9709
# position (that we store)
9710
if paneInfo.IsFloating():
9711
paneInfo.floating_pos = paneInfo.frame.GetPosition()
9712
if paneInfo.frame._transparent != paneInfo.transparent or self._agwFlags & AUI_MGR_TRANSPARENT_DRAG:
9713
paneInfo.frame.SetTransparent(paneInfo.transparent)
9714
paneInfo.frame._transparent = paneInfo.transparent
9716
elif self._has_maximized:
9717
self.RestoreMaximizedPane()
9719
# reorder for dropping to a new notebook
9720
# (caution: this code breaks the reference!)
9721
tempPaneInfo = self.CopyTarget(paneInfo)
9722
self._panes.remove(paneInfo)
9723
self._panes.append(tempPaneInfo)
9728
if tempPaneInfo.IsFloating():
9729
self.SnapPane(tempPaneInfo, tempPaneInfo.floating_pos, tempPaneInfo.floating_size, False)
9732
ShowDockingGuides(self._guides, False)
9735
def OnLeftUp_DragMovablePane(self, event):
9737
Sub-handler for the :meth:`OnLeftUp` event.
9739
:param `event`: a :class:`MouseEvent` to be processed.
9742
# Try to find the pane.
9743
paneInfo = self.GetPane(self._action_window)
9744
if not paneInfo.IsOk():
9745
raise Exception("Pane window not found")
9747
# Hide the hint as it is no longer needed.
9750
# is the pane dockable?
9751
if self.CanDockPanel(paneInfo):
9752
# Move the pane to new position.
9753
pt = event.GetPosition()
9754
# do the drop calculation
9755
indx = self._panes.index(paneInfo)
9756
ret, paneInfo = self.DoDrop(self._docks, self._panes, paneInfo, pt, wx.Point(0,0))
9759
e = self.FireEvent(wxEVT_AUI_PANE_DOCKING, paneInfo, canVeto=True)
9762
ShowDockingGuides(self._guides, False)
9765
e = self.FireEvent(wxEVT_AUI_PANE_DOCKED, paneInfo, canVeto=False)
9767
if self._agwFlags & AUI_MGR_SMOOTH_DOCKING:
9768
self.SmoothDock(paneInfo)
9770
self._panes[indx] = paneInfo
9773
# Update the layout to realize new position and e.g. form notebooks if needed.
9776
if self.GetAGWFlags() & AUI_MGR_ALLOW_ACTIVE_PANE:
9777
# Ensure active before doing actual display.
9778
ret, self._panes = SetActivePane(self._panes, paneInfo.window)
9780
# Make changes visible to user.
9783
# Cancel the action and release the mouse.
9784
self._action = actionNone
9785
self._frame.ReleaseMouse()
9786
self._action_window = None
9789
def OnMotion_DragToolbarPane(self, eventOrPt):
9791
Sub-handler for the :meth:`OnMotion` event.
9793
:param `event`: a :class:`MouseEvent` to be processed.
9797
if isinstance(eventOrPt, wx.Point):
9798
clientPt = self._frame.ScreenToClient(eventOrPt)
9799
screenPt = wx.Point(*eventOrPt)
9802
clientPt = eventOrPt.GetPosition()
9803
screenPt = self._frame.ClientToScreen(clientPt)
9805
pane = self.GetPane(self._action_window)
9807
raise Exception("Pane window not found")
9809
pane.state |= AuiPaneInfo.actionPane
9810
indx = self._panes.index(pane)
9813
wasFloating = pane.IsFloating()
9814
# is the pane dockable?
9815
if self.CanDockPanel(pane):
9816
# do the drop calculation
9817
ret, pane = self.DoDrop(self._docks, self._panes, pane, clientPt, self._action_offset)
9819
# update floating position
9820
if pane.IsFloating():
9821
pane.floating_pos = screenPt - self._toolbar_action_offset
9823
# move the pane window
9825
if wx.Platform == "__WXMSW__" and (self._agwFlags & AUI_MGR_TRANSPARENT_DRAG) == 0: # and not self.CheckPaneMove(pane):
9827
# HACK: Terrible hack on wxMSW (!)
9828
pane.frame.SetTransparent(254)
9830
self._from_move = True
9831
pane.frame.Move(pane.floating_pos)
9832
self._from_move = False
9834
if self._agwFlags & AUI_MGR_TRANSPARENT_DRAG:
9835
pane.frame.SetTransparent(150)
9837
self._panes[indx] = pane
9838
if ret and wasFloating != pane.IsFloating() or (ret and not wasFloating):
9839
wx.CallAfter(self.Update)
9841
# when release the button out of the window.
9842
# TODO: a better fix is needed.
9844
if _VERSION_STRING < "2.9":
9845
leftDown = wx.GetMouseState().LeftDown()
9847
leftDown = wx.GetMouseState().LeftIsDown()
9850
self._action = actionNone
9851
self.OnLeftUp_DragToolbarPane(eventOrPt)
9854
def OnMotion_Other(self, event):
9856
Sub-handler for the :meth:`OnMotion` event.
9858
:param `event`: a :class:`MouseEvent` to be processed.
9861
part = self.HitTest(*event.GetPosition())
9863
if part and part.type == AuiDockUIPart.typePaneButton \
9864
and self.IsPaneButtonVisible(part):
9865
if part != self._hover_button:
9867
if self._hover_button:
9868
self.RefreshButton(self._hover_button)
9870
self._hover_button = part
9871
self.RefreshButton(part)
9875
if self._hover_button:
9876
self.RefreshButton(self._hover_button)
9880
self._hover_button = None
9883
def OnLeftUp_DragToolbarPane(self, eventOrPt):
9885
Sub-handler for the :meth:`OnLeftUp` event.
9887
:param `event`: a :class:`MouseEvent` to be processed.
9891
if isinstance(eventOrPt, wx.Point):
9892
clientPt = self._frame.ScreenToClient(eventOrPt)
9893
screenPt = wx.Point(*eventOrPt)
9896
clientPt = eventOrPt.GetPosition()
9897
screenPt = self._frame.ClientToScreen(clientPt)
9899
# try to find the pane
9900
pane = self.GetPane(self._action_window)
9902
raise Exception("Pane window not found")
9904
if pane.IsFloating():
9905
pane.floating_pos = pane.frame.GetPosition()
9906
if pane.frame._transparent != pane.transparent or self._agwFlags & AUI_MGR_TRANSPARENT_DRAG:
9907
pane.frame.SetTransparent(pane.transparent)
9908
pane.frame._transparent = pane.transparent
9910
# save the new positions
9911
docks = FindDocks(self._docks, pane.dock_direction, pane.dock_layer, pane.dock_row)
9914
pane_positions, pane_sizes = self.GetPanePositionsAndSizes(dock)
9916
for i in xrange(len(dock.panes)):
9917
dock.panes[i].dock_pos = pane_positions[i]
9919
pane.state &= ~AuiPaneInfo.actionPane
9923
def OnPaneButton(self, event):
9925
Handles the ``EVT_AUI_PANE_BUTTON`` event for :class:`AuiManager`.
9927
:param `event`: a :class:`AuiManagerEvent` event to be processed.
9931
raise Exception("Pane Info passed to AuiManager.OnPaneButton must be non-null")
9935
if event.button == AUI_BUTTON_CLOSE:
9937
if isinstance(pane.window.GetParent(), AuiFloatingFrame):
9938
rootManager = GetManager(pane.window)
9942
if rootManager != self:
9946
# fire pane close event
9947
e = AuiManagerEvent(wxEVT_AUI_PANE_CLOSE)
9949
e.SetPane(event.pane)
9950
self.ProcessMgrEvent(e)
9954
# close the pane, but check that it
9955
# still exists in our pane array first
9956
# (the event handler above might have removed it)
9958
check = self.GetPane(pane.window)
9960
self.ClosePane(pane)
9964
# mn this performs the minimizing of a pane
9965
elif event.button == AUI_BUTTON_MINIMIZE:
9966
e = AuiManagerEvent(wxEVT_AUI_PANE_MINIMIZE)
9968
e.SetPane(event.pane)
9969
self.ProcessMgrEvent(e)
9972
self.MinimizePane(pane)
9974
elif event.button == AUI_BUTTON_MAXIMIZE_RESTORE and not pane.IsMaximized():
9976
# fire pane close event
9977
e = AuiManagerEvent(wxEVT_AUI_PANE_MAXIMIZE)
9979
e.SetPane(event.pane)
9980
self.ProcessMgrEvent(e)
9984
self.MaximizePane(pane)
9987
elif event.button == AUI_BUTTON_MAXIMIZE_RESTORE and pane.IsMaximized():
9989
# fire pane close event
9990
e = AuiManagerEvent(wxEVT_AUI_PANE_RESTORE)
9992
e.SetPane(event.pane)
9993
self.ProcessMgrEvent(e)
9997
self.RestorePane(pane)
10000
elif event.button == AUI_BUTTON_PIN:
10002
if self._agwFlags & AUI_MGR_ALLOW_FLOATING and pane.IsFloatable():
10003
e = self.FireEvent(wxEVT_AUI_PANE_FLOATING, pane, canVeto=True)
10008
e = self.FireEvent(wxEVT_AUI_PANE_FLOATED, pane, canVeto=False)
10013
def MinimizePane(self, paneInfo, mgrUpdate=True):
10015
Minimizes a pane in a newly and automatically created :class:`~lib.agw.aui.auibar.AuiToolBar`.
10017
Clicking on the minimize button causes a new :class:`~lib.agw.aui.auibar.AuiToolBar` to be created
10018
and added to the frame manager (currently the implementation is such that
10019
panes at West will have a toolbar at the right, panes at South will have
10020
toolbars at the bottom etc...) and the pane is hidden in the manager.
10022
Clicking on the restore button on the newly created toolbar will result in the
10023
toolbar being removed and the original pane being restored.
10025
:param `paneInfo`: a :class:`AuiPaneInfo` instance for the pane to be minimized;
10026
:param bool `mgrUpdate`: ``True`` to call :meth:`Update` to realize the new layout,
10027
``False`` otherwise.
10031
The `mgrUpdate` parameter is currently only used while loading perspectives using
10032
:meth:`LoadPerspective`, as minimized panes were not correctly taken into account before.
10036
if not paneInfo.IsToolbar():
10038
if paneInfo.IsMinimized() and mgrUpdate:
10039
# We are already minimized
10042
# Basically the idea is this.
10044
# 1) create a toolbar, with a restore button
10046
# 2) place the new toolbar in the toolbar area representative of the location of the pane
10047
# (NORTH/SOUTH/EAST/WEST, central area always to the right)
10049
# 3) Hide the minimizing pane
10051
# personalize the toolbar style
10053
tbStyle = AUI_TB_DEFAULT_STYLE
10054
posMask = paneInfo.minimize_mode & AUI_MINIMIZE_POS_MASK
10055
captMask = paneInfo.minimize_mode & AUI_MINIMIZE_CAPT_MASK
10056
dockDirection = paneInfo.dock_direction
10058
tbStyle |= AUI_TB_TEXT
10060
if posMask == AUI_MINIMIZE_POS_TOOLBAR:
10061
minimize_toolbar = self.GetPane(paneInfo.minimize_target)
10062
if not minimize_toolbar.IsOk():
10063
posMask = AUI_MINIMIZE_POS_SMART
10064
if paneInfo.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]:
10065
tbStyle |= AUI_TB_HORZ_LAYOUT
10067
elif paneInfo.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT, AUI_DOCK_CENTER]:
10068
tbStyle |= AUI_TB_VERTICAL
10069
if captMask == AUI_MINIMIZE_CAPT_SMART:
10070
tbStyle |= AUI_TB_CLOCKWISE
10072
minimize_toolbar = minimize_toolbar.window
10074
elif posMask == AUI_MINIMIZE_POS_SMART:
10075
if paneInfo.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]:
10076
tbStyle |= AUI_TB_HORZ_LAYOUT
10078
elif paneInfo.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT, AUI_DOCK_CENTER]:
10079
tbStyle |= AUI_TB_VERTICAL
10080
if captMask == AUI_MINIMIZE_CAPT_SMART:
10081
tbStyle |= AUI_TB_CLOCKWISE
10083
elif posMask in [AUI_MINIMIZE_POS_TOP, AUI_MINIMIZE_POS_BOTTOM]:
10084
tbStyle |= AUI_TB_HORZ_LAYOUT
10085
if posMask == AUI_MINIMIZE_POS_TOP:
10086
dockDirection = AUI_DOCK_TOP
10088
dockDirection = AUI_DOCK_BOTTOM
10091
tbStyle |= AUI_TB_VERTICAL
10092
if captMask == AUI_MINIMIZE_CAPT_SMART:
10093
tbStyle |= AUI_TB_CLOCKWISE
10094
if posMask == AUI_MINIMIZE_POS_LEFT:
10095
dockDirection = AUI_DOCK_LEFT
10096
elif posMask == AUI_MINIMIZE_POS_RIGHT:
10097
dockDirection = AUI_DOCK_RIGHT
10098
elif posMask == AUI_MINIMIZE_POS_BOTTOM:
10099
dockDirection = AUI_DOCK_BOTTOM
10101
# Create a new toolbar
10102
# give it the same name as the minimized pane with _min appended
10104
win_rect = paneInfo.window.GetScreenRect()
10106
if posMask != AUI_MINIMIZE_POS_TOOLBAR:
10107
minimize_toolbar = auibar.AuiToolBar(self.GetManagedWindow(), agwStyle=tbStyle)
10108
minimize_toolbar.Hide()
10109
minimize_toolbar.SetToolBitmapSize(wx.Size(16, 16))
10111
if paneInfo.icon and paneInfo.icon.IsOk():
10112
restore_bitmap = paneInfo.icon
10114
restore_bitmap = self._art._restore_bitmap
10116
if posMask == AUI_MINIMIZE_POS_TOOLBAR:
10117
xsize, ysize = minimize_toolbar.GetToolBitmapSize()
10118
if xsize != restore_bitmap.GetWidth():
10119
img = restore_bitmap.ConvertToImage()
10120
img.Rescale(xsize, ysize, wx.IMAGE_QUALITY_HIGH)
10121
restore_bitmap = img.ConvertToBitmap()
10124
if posMask == AUI_MINIMIZE_POS_TOOLBAR:
10125
target = paneInfo.name
10127
minimize_toolbar.AddSimpleTool(ID_RESTORE_FRAME, paneInfo.caption, restore_bitmap,
10128
_(u"Restore %s")%paneInfo.caption, target=target)
10129
minimize_toolbar.SetAuiManager(self)
10130
minimize_toolbar.Realize()
10131
toolpanelname = paneInfo.name + "_min"
10133
if paneInfo.IsMaximized():
10134
paneInfo.SetFlag(paneInfo.wasMaximized, True)
10136
if posMask != AUI_MINIMIZE_POS_TOOLBAR:
10138
if dockDirection == AUI_DOCK_TOP:
10139
self.AddPane(minimize_toolbar, AuiPaneInfo(). \
10140
Name(toolpanelname).Caption(paneInfo.caption). \
10141
ToolbarPane().Top().BottomDockable(False). \
10142
LeftDockable(False).RightDockable(False).DestroyOnClose())
10144
elif dockDirection == AUI_DOCK_BOTTOM:
10145
self.AddPane(minimize_toolbar, AuiPaneInfo(). \
10146
Name(toolpanelname).Caption(paneInfo.caption). \
10147
ToolbarPane().Bottom().TopDockable(False). \
10148
LeftDockable(False).RightDockable(False).DestroyOnClose())
10150
elif dockDirection == AUI_DOCK_LEFT:
10151
self.AddPane(minimize_toolbar, AuiPaneInfo(). \
10152
Name(toolpanelname).Caption(paneInfo.caption). \
10153
ToolbarPane().Left().TopDockable(False). \
10154
BottomDockable(False).RightDockable(False).DestroyOnClose())
10156
elif dockDirection in [AUI_DOCK_RIGHT, AUI_DOCK_CENTER]:
10157
self.AddPane(minimize_toolbar, AuiPaneInfo(). \
10158
Name(toolpanelname).Caption(paneInfo.caption). \
10159
ToolbarPane().Right().TopDockable(False). \
10160
LeftDockable(False).BottomDockable(False).DestroyOnClose())
10162
arr = FindDocks(self._docks, paneInfo.dock_direction, paneInfo.dock_layer, paneInfo.dock_row)
10166
paneInfo.previousDockSize = dock.size
10168
paneInfo.previousDockPos = paneInfo.dock_pos
10170
# mark ourselves minimized
10171
paneInfo.Minimize()
10172
paneInfo.Show(False)
10173
self._has_minimized = True
10174
# last, hide the window
10175
if paneInfo.window and paneInfo.window.IsShown():
10176
paneInfo.window.Show(False)
10178
minimize_toolbar.Show()
10182
if self._agwFlags & AUI_MGR_ANIMATE_FRAMES:
10183
self.AnimateDocking(win_rect, minimize_toolbar.GetScreenRect())
10186
def OnRestoreMinimizedPane(self, event):
10188
Handles the ``EVT_AUI_PANE_MIN_RESTORE`` event for :class:`AuiManager`.
10190
:param `event`: an instance of :class:`AuiManagerEvent` to be processed.
10193
self.RestoreMinimizedPane(event.pane)
10196
def OnPaneDocked(self, event):
10198
Handles the ``EVT_AUI_PANE_DOCKED`` event for :class:`AuiManager`.
10200
:param `event`: an instance of :class:`AuiManagerEvent` to be processed.
10204
self.RemoveAutoNBCaption(event.GetPane())
10207
def CreateNotebookBase(self, panes, paneInfo):
10209
Creates an auto-notebook base from a pane, and then add that pane as a page.
10211
:param list `panes`: set of panes to append new notebook base pane to
10212
:param AuiPaneInfo `paneInfo`: the pane to be converted to a new notebook.
10215
# Create base notebook pane ...
10216
nbid = len(self._notebooks)
10218
baseInfo = AuiPaneInfo()
10219
baseInfo.SetDockPos(paneInfo).NotebookControl(nbid). \
10220
CloseButton(False).SetNameFromNotebookId(). \
10221
NotebookDockable(False).Floatable(paneInfo.IsFloatable())
10222
baseInfo.best_size = paneInfo.best_size
10223
panes.append(baseInfo)
10225
# add original pane as tab ...
10226
paneInfo.NotebookPage(nbid)
10229
def RemoveAutoNBCaption(self, pane):
10231
Removes the caption on newly created automatic notebooks.
10233
:param `pane`: an instance of :class:`AuiPaneInfo` (the target notebook).
10236
if self._agwFlags & AUI_MGR_AUTONB_NO_CAPTION == 0:
10239
def RemoveCaption():
10240
""" Sub-function used to remove the pane caption on automatic notebooks. """
10242
if pane.HasNotebook():
10243
notebook = self._notebooks[pane.notebook_id]
10244
self.GetPane(notebook).CaptionVisible(False).PaneBorder(False)
10247
# it seems the notebook isnt created by this stage, so remove
10248
# the caption a moment later
10249
wx.CallAfter(RemoveCaption)
10253
def RestoreMinimizedPane(self, paneInfo):
10255
Restores a previously minimized pane.
10257
:param `paneInfo`: a :class:`AuiPaneInfo` instance for the pane to be restored.
10260
panename = paneInfo.name
10262
if paneInfo.minimize_mode & AUI_MINIMIZE_POS_TOOLBAR:
10263
pane = self.GetPane(panename)
10266
panename = panename[0:-4]
10269
pane = self.GetPane(panename)
10270
pane.SetFlag(pane.needsRestore, True)
10272
if not pane.IsOk():
10273
panename = paneInfo.name
10274
pane = self.GetPane(panename)
10275
paneInfo = self.GetPane(panename + "_min")
10276
if not paneInfo.IsOk():
10277
# Already minimized
10281
if not pane.IsMinimized():
10285
if pane.HasFlag(pane.wasMaximized):
10286
self.SavePreviousDockSizes(pane)
10288
self.ShowPane(pane.window, True)
10290
self._has_minimized = False
10291
pane.SetFlag(pane.optionMinimized, False)
10294
targetName = pane.minimize_target
10295
toolbarPane = self.GetPane(targetName)
10296
toolbar = toolbarPane.window
10297
item = toolbar.FindToolByLabel(pane.caption)
10298
toolbar.DeleteTool(item.id)
10300
paneInfo.window.Show(False)
10301
self.DetachPane(paneInfo.window)
10302
paneInfo.Show(False)
10308
def AnimateDocking(self, win_rect, pane_rect):
10310
Animates the minimization/docking of a pane a la Eclipse, using a :class:`ScreenDC`
10311
to draw a "moving docking rectangle" on the screen.
10313
:param Rect `win_rect`: the original pane screen rectangle;
10314
:param Rect `pane_rect`: the newly created toolbar/pane screen rectangle.
10316
:note: This functionality is not available on wxMAC as this platform doesn't have
10317
the ability to use :class:`ScreenDC` to draw on-screen and on Windows > Vista.
10320
if wx.Platform == "__WXMAC__":
10321
# No wx.ScreenDC on the Mac...
10323
if wx.Platform == "__WXMSW__" and wx.GetOsVersion()[1] > 5:
10324
# No easy way to handle this on Vista...
10327
xstart, ystart = win_rect.x, win_rect.y
10328
xend, yend = pane_rect.x, pane_rect.y
10330
step = self.GetAnimationStep()
10332
wstep = int(abs(win_rect.width - pane_rect.width)/step)
10333
hstep = int(abs(win_rect.height - pane_rect.height)/step)
10334
xstep = int(win_rect.x - pane_rect.x)/step
10335
ystep = int(win_rect.y - pane_rect.y)/step
10338
dc.SetLogicalFunction(wx.INVERT)
10339
dc.SetBrush(wx.TRANSPARENT_BRUSH)
10340
dc.SetPen(wx.LIGHT_GREY_PEN)
10342
for i in xrange(int(step)):
10343
width, height = win_rect.width - i*wstep, win_rect.height - i*hstep
10344
x, y = xstart - i*xstep, ystart - i*ystep
10345
new_rect = wx.Rect(x, y, width, height)
10346
dc.DrawRoundedRectangleRect(new_rect, 3)
10349
dc.DrawRoundedRectangleRect(new_rect, 3)
10352
def SmoothDock(self, paneInfo):
10354
This method implements a smooth docking effect for floating panes, similar to
10355
what the PyQT library does with its floating windows.
10357
:param `paneInfo`: an instance of :class:`AuiPaneInfo`.
10359
:note: The smooth docking effect can only be used if you set the ``AUI_MGR_SMOOTH_DOCKING``
10360
style to :class:`AuiManager`.
10363
if paneInfo.IsToolbar():
10366
if not paneInfo.frame or self._hint_rect.IsEmpty():
10369
hint_rect = self._hint_rect
10370
win_rect = paneInfo.frame.GetScreenRect()
10372
xstart, ystart = win_rect.x, win_rect.y
10373
xend, yend = hint_rect.x, hint_rect.y
10375
step = self.GetAnimationStep()/3
10377
wstep = int((win_rect.width - hint_rect.width)/step)
10378
hstep = int((win_rect.height - hint_rect.height)/step)
10379
xstep = int((win_rect.x - hint_rect.x))/step
10380
ystep = int((win_rect.y - hint_rect.y))/step
10382
for i in xrange(int(step)):
10383
width, height = win_rect.width - i*wstep, win_rect.height - i*hstep
10384
x, y = xstart - i*xstep, ystart - i*ystep
10385
new_rect = wx.Rect(x, y, width, height)
10386
paneInfo.frame.SetRect(new_rect)
10390
def SetSnapLimits(self, x, y):
10392
Modifies the snap limits used when snapping the `managed_window` to the screen
10393
(using :meth:`SnapToScreen`) or when snapping the floating panes to one side of the
10394
`managed_window` (using :meth:`SnapPane`).
10396
To change the limit after which the `managed_window` or the floating panes are
10397
automatically stickled to the screen border (or to the `managed_window` side),
10398
set these two variables. Default values are 15 pixels.
10400
:param integer `x`: the minimum horizontal distance below which the snap occurs;
10401
:param integer `y`: the minimum vertical distance below which the snap occurs.
10404
self._snap_limits = (x, y)
10410
Snaps the main frame to specified position on the screen.
10412
:see: :meth:`SnapToScreen`
10415
snap, hAlign, vAlign, monitor = self._is_docked
10419
managed_window = self.GetManagedWindow()
10420
snap_pos = self.GetSnapPosition()
10421
wnd_pos = managed_window.GetPosition()
10422
snapX, snapY = self._snap_limits
10424
if abs(snap_pos.x - wnd_pos.x) < snapX and abs(snap_pos.y - wnd_pos.y) < snapY:
10425
managed_window.SetPosition(snap_pos)
10428
def SnapToScreen(self, snap=True, monitor=0, hAlign=wx.RIGHT, vAlign=wx.TOP):
10430
Snaps the main frame to specified position on the screen.
10432
:param bool `snap`: whether to snap the main frame or not;
10433
:param integer `monitor`: the monitor display in which snapping the window;
10434
:param integer `hAlign`: the horizontal alignment of the snapping position;
10435
:param integer `vAlign`: the vertical alignment of the snapping position.
10439
self._is_docked = (False, wx.RIGHT, wx.TOP, 0)
10442
displayCount = wx.Display.GetCount()
10443
if monitor > displayCount:
10444
raise Exception("Invalid monitor selected: you only have %d monitors"%displayCount)
10446
self._is_docked = (True, hAlign, vAlign, monitor)
10447
self.GetManagedWindow().SetPosition(self.GetSnapPosition())
10450
def GetSnapPosition(self):
10451
""" Returns the main frame snapping position. """
10453
snap, hAlign, vAlign, monitor = self._is_docked
10455
display = wx.Display(monitor)
10456
area = display.GetClientArea()
10457
size = self.GetManagedWindow().GetSize()
10460
if hAlign == wx.LEFT:
10462
elif hAlign == wx.CENTER:
10463
pos.x = area.x + (area.width - size.x)/2
10465
pos.x = area.x + area.width - size.x
10467
if vAlign == wx.TOP:
10469
elif vAlign == wx.CENTER:
10470
pos.y = area.y + (area.height - size.y)/2
10472
pos.y = area.y + area.height - size.y
10477
def GetAnimationStep(self):
10478
""" Returns the animation step speed (a float) to use in :meth:`AnimateDocking`. """
10480
return self._animation_step
10483
def SetAnimationStep(self, step):
10485
Sets the animation step speed (a float) to use in :meth:`AnimateDocking`.
10487
:param float `step`: the animation speed.
10490
self._animation_step = float(step)
10493
def RequestUserAttention(self, pane_window):
10495
Requests the user attention by intermittently highlighting the pane caption.
10497
:param Window `pane_window`: the window managed by the pane;
10500
# try to find the pane
10501
paneInfo = self.GetPane(pane_window)
10502
if not paneInfo.IsOk():
10503
raise Exception("Pane window not found")
10505
dc = wx.ClientDC(self._frame)
10507
# if the frame is about to be deleted, don't bother
10508
if not self._frame or self._frame.IsBeingDeleted():
10511
if not self._frame.GetSizer():
10514
for part in self._uiparts:
10515
if part.pane == paneInfo:
10516
self._art.RequestUserAttention(dc, self._frame, part.pane.caption, part.rect, part.pane)
10517
self._frame.RefreshRect(part.rect, True)
10521
def StartPreviewTimer(self, toolbar):
10523
Starts a timer for sliding in and out a minimized pane.
10525
:param `toolbar`: the :class:`~lib.agw.aui.auibar.AuiToolBar` containing the minimized pane tool.
10528
toolbar_pane = self.GetPane(toolbar)
10529
toolbar_name = toolbar_pane.name
10531
pane_name = toolbar_name[0:-4]
10533
self._sliding_pane = self.GetPane(pane_name)
10534
self._sliding_rect = toolbar.GetScreenRect()
10535
self._sliding_direction = toolbar_pane.dock_direction
10536
self._sliding_frame = None
10538
self._preview_timer.Start(1000, wx.TIMER_ONE_SHOT)
10541
def StopPreviewTimer(self):
10542
""" Stops a timer for sliding in and out a minimized pane. """
10544
if self._preview_timer.IsRunning():
10545
self._preview_timer.Stop()
10548
self._sliding_pane = None
10551
def SlideIn(self, event):
10553
Handles the ``wx.EVT_TIMER`` event for :class:`AuiManager`.
10555
:param `event`: a :class:`TimerEvent` to be processed.
10557
:note: This is used solely for sliding in and out minimized panes.
10560
window = self._sliding_pane.window
10561
self._sliding_frame = wx.MiniFrame(None, -1, title=_("Pane Preview"),
10562
style=wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP |
10563
wx.FRAME_NO_TASKBAR | wx.CAPTION)
10564
window.Reparent(self._sliding_frame)
10565
self._sliding_frame.SetSize((0, 0))
10567
self._sliding_frame.Show()
10569
size = window.GetBestSize()
10571
startX, startY, stopX, stopY = GetSlidingPoints(self._sliding_rect, size, self._sliding_direction)
10576
for i in xrange(0, stopX, step):
10578
self._sliding_frame.SetDimensions(startX, startY, window_size, stopY)
10579
self._sliding_frame.Refresh()
10580
self._sliding_frame.Update()
10583
self._sliding_frame.SetDimensions(startX, startY, stopX, stopY)
10584
self._sliding_frame.Refresh()
10585
self._sliding_frame.Update()
10588
def SlideOut(self):
10590
Slides out a preview of a minimized pane.
10592
:note: This is used solely for sliding in and out minimized panes.
10595
if not self._sliding_frame:
10598
window = self._sliding_frame.GetChildren()[0]
10599
size = window.GetBestSize()
10601
startX, startY, stopX, stopY = GetSlidingPoints(self._sliding_rect, size, self._sliding_direction)
10606
for i in xrange(stopX, 0, -step):
10608
self._sliding_frame.SetDimensions(startX, startY, window_size, stopY)
10609
self._sliding_frame.Refresh()
10610
self._sliding_frame.Update()
10611
self._frame.RefreshRect(wx.Rect(startX+window_size, startY, step, stopY))
10612
self._frame.Update()
10615
self._sliding_frame.SetDimensions(startX, startY, 0, stopY)
10618
window.Reparent(self._frame)
10620
self._sliding_frame.Hide()
10621
self._sliding_frame.Destroy()
10622
self._sliding_frame = None
10623
self._sliding_pane = None
10626
class AuiManager_DCP(AuiManager):
10628
A class similar to :class:`AuiManager` but with a Dummy Center Pane (**DCP**).
10629
The code for this class is still flickery due to the call to :func:`CallAfter`
10630
and the double-update call.
10633
def __init__(self, *args, **keys):
10634
""" See :meth:`AuiManager.__init__` for the class construction. """
10636
AuiManager.__init__(self, *args, **keys)
10637
self.hasDummyPane = False
10640
def _createDummyPane(self):
10641
""" Creates a Dummy Center Pane (**DCP**). """
10643
if self.hasDummyPane:
10646
self.hasDummyPane = True
10647
dummy = wx.Panel(self.GetManagedWindow())
10648
info = AuiPaneInfo().CenterPane().NotebookDockable(True).Name('dummyCenterPane').DestroyOnClose(True)
10649
self.AddPane(dummy, info)
10652
def _destroyDummyPane(self):
10653
""" Destroys the Dummy Center Pane (**DCP**). """
10655
if not self.hasDummyPane:
10658
self.hasDummyPane = False
10659
self.ClosePane(self.GetPane('dummyCenterPane'))
10664
This method is called after any number of changes are made to any of the
10665
managed panes. :meth:`Update` must be invoked after :meth:`AuiManager.AddPane` or
10666
:meth:`AuiManager.InsertPane` are called in order to "realize" or "commit" the changes.
10668
In addition, any number of changes may be made to :class:`AuiManager` structures
10669
(retrieved with :meth:`AuiManager.GetPane`), but to realize the changes,
10670
:meth:`Update` must be called. This construction allows pane flicker to
10671
be avoided by updating the whole layout at one time.
10674
AuiManager.Update(self)
10676
# check if there's already a center pane (except our dummy pane)
10677
dummyCenterPane = self.GetPane('dummyCenterPane')
10678
haveCenterPane = any((pane != dummyCenterPane) and (pane.dock_direction == AUI_DOCK_CENTER) and
10679
not pane.IsFloating() and pane.IsShown() for pane in self.GetAllPanes())
10681
if self.hasDummyPane:
10682
# there's our dummy pane and also another center pane, therefor let's remove our dummy
10684
self._destroyDummyPane()
10688
# if we get here, there's no center pane, create our dummy
10689
if not self.hasDummyPane:
10690
self._createDummyPane()