From 22f93a602f3584ddc6ba68114556212c90307a50 Mon Sep 17 00:00:00 2001 From: Pierre Date: Fri, 11 Jan 2013 10:21:58 +0100 Subject: [PATCH] remove agw --- agw/__init__.py | 121 - agw/aui/__init__.py | 290 -- agw/aui/aui_constants.py | 2588 ---------- agw/aui/aui_switcherdialog.py | 1216 ----- agw/aui/aui_utilities.py | 678 --- agw/aui/auibar.py | 3926 --------------- agw/aui/auibook.py | 5736 ---------------------- agw/aui/dockart.py | 1162 ----- agw/aui/framemanager.py | 10385 ---------------------------------------- agw/aui/tabart.py | 2777 ----------- agw/aui/tabmdi.py | 666 --- iramuteq.py | 4 +- layout.py | 3 +- profile_segment.py | 3 +- 14 files changed, 6 insertions(+), 29549 deletions(-) delete mode 100644 agw/__init__.py delete mode 100644 agw/aui/__init__.py delete mode 100644 agw/aui/aui_constants.py delete mode 100644 agw/aui/aui_switcherdialog.py delete mode 100644 agw/aui/aui_utilities.py delete mode 100644 agw/aui/auibar.py delete mode 100644 agw/aui/auibook.py delete mode 100644 agw/aui/dockart.py delete mode 100644 agw/aui/framemanager.py delete mode 100644 agw/aui/tabart.py delete mode 100644 agw/aui/tabmdi.py diff --git a/agw/__init__.py b/agw/__init__.py deleted file mode 100644 index a2dcee6..0000000 --- a/agw/__init__.py +++ /dev/null @@ -1,121 +0,0 @@ -""" -This is the Advanced Generic Widgets package (AGW). It provides many -custom-drawn wxPython controls: some of them can be used as a replacement -of the platform native controls, others are simply an addition to the -already rich wxPython widgets set. - - -Description: - -AGW contains many different modules, listed below. Items labelled with -an asterisk were already present in `wx.lib` before: - -- AdvancedSplash: reproduces the behaviour of `wx.SplashScreen`, with more - advanced features like custom shapes and text animations; -- AquaButton: this is another custom-drawn button class which - *approximatively* mimics the behaviour of Aqua buttons on the Mac; -- AUI: a pure-Python implementation of `wx.aui`, with many bug fixes and - new features like HUD docking and L{AuiNotebook} tab arts; -- BalloonTip: allows you to display tooltips in a balloon style window - (actually a frame), similarly to the Windows XP balloon help; -- ButtonPanel (*): a panel with gradient background shading with the - possibility to add buttons and controls still respecting the gradient - background; -- CubeColourDialog: an alternative implementation of `wx.ColourDialog`, it - offers different functionalities like colour wheel and RGB cube; -- CustomTreeCtrl (*): mimics the behaviour of `wx.TreeCtrl`, with almost the - same base functionalities plus a bunch of enhancements and goodies; -- FlatMenu: as the name implies, it is a generic menu implementation, - offering the same `wx.MenuBar`/`wx.Menu`/`wx.ToolBar` capabilities and much more; -- FlatNotebook (*): a full implementation of the `wx.Notebook`, and designed - to be a drop-in replacement for `wx.Notebook` with enhanced capabilities; -- FloatSpin: this class implements a floating point spinctrl, cabable (in - theory) of handling infinite-precision floating point numbers; -- FoldPanelBar (*): a control that contains multiple panels that can be - expanded or collapsed a la Windows Explorer/Outlook command bars; -- FourWaySplitter: this is a layout manager which manages four children like - four panes in a window, similar to many CAD software interfaces; -- GenericMessageDialog: it is a possible replacement for the standard - `wx.MessageDialog`, with a fancier look and extended functionalities; -- GradientButton: another custom-drawn button class which mimics Windows CE - mobile gradient buttons, using a tri-vertex blended gradient background; -- HyperLinkCtrl (*): this widget acts line an hyper link in a typical browser; -- HyperTreeList: a class that mimics the behaviour of `wx.gizmos.TreeListCtrl`, - with almost the same base functionalities plus some more enhancements; -- KnobCtrl: a widget which lets the user select a numerical value by - rotating it, like a slider with a wheel shape; -- LabelBook and FlatImageBook: these are a quasi-full implementations of - `wx.ListBook`, with additional features; -- MultiDirDialog: it represents a possible replacement for `wx.DirDialog`, - with the additional ability of selecting multiple folders at once and a - fancier look; -- PeakMeter: this widget mimics the behaviour of LED equalizers that are - usually found in stereos and MP3 players; -- PersistentControls: widgets which automatically save their state - when they are destroyed and restore it when they are recreated, even during - another program invocation; -- PieCtrl and ProgressPie: these are simple classes that reproduce the - behavior of a pie chart, in a static or progress-gauge-like way; -- PyBusyInfo: constructs a busy info window and displays a message in it: - it is similar to `wx.BusyInfo`; -- PyCollapsiblePane: a pure Python implementation of the original wxWidgets - C++ code of `wx.CollapsiblePane`, with customizable buttons; -- PyGauge: a generic `wx.Gauge` implementation, it supports the determinate - mode functions as `wx.Gauge`; -- PyProgress: it is similar to `wx.ProgressDialog` in indeterminated mode, but - with a different gauge appearance and a different spinning behavior; -- RibbonBar: the RibbonBar library is a set of classes for writing a ribbon - user interface, similar to the user interface present in recent versions - of Microsoft Office; -- RulerCtrl: it implements a ruler window that can be placed on top, bottom, - left or right to any wxPython widget. It is somewhat similar to the rulers - you can find in text editors software; -- ShapedButton: this class tries to fill the lack of "custom shaped" controls - in wxPython. It can be used to build round buttons or elliptic buttons; -- SpeedMeter: this widget tries to reproduce the behavior of some car - controls (but not only), by creating an "angular" control; -- SuperToolTip: a class that mimics the behaviour of `wx.TipWindow` and - generic tooltips, with many features and highly customizable; -- ThumbnailCtrl: a widget that can be used to display a series of images - in a "thumbnail" format; it mimics, for example, the Windows Explorer - behavior when you select the "view thumbnails" option; -- ToasterBox: a cross-platform widget to make the creation of MSN-style - "toaster" popups easier; -- UltimateListCtrl: mimics the behaviour of `wx.ListCtrl`, with almost the same - base functionalities plus some more enhancements; -- ZoomBar: a class that *appoximatively* mimics the behaviour of the Mac Dock, - inside a `wx.Panel`. - - -Bugs and Limitations: many, patches and fixes welcome :-D - -See the demos for an example of what AGW can do, and on how to use it. - -Copyright: Andrea Gavana - -License: Same as the version of wxPython you are using it with. - -SVN for latest code: -http://svn.wxwidgets.org/viewvc/wx/wxPython/3rdParty/AGW/ - -Mailing List: -wxpython-users@lists.wxwidgets.org - -My personal web page: -http://xoomer.alice.it/infinity77 - -Please let me know if you are using AGW! - -You can contact me at: - -andrea.gavana@gmail.com -gavana@kpo.kz - -AGW version: 0.9.1 - -Last updated: 10 Mar 2011, 15.00 GMT - -""" - -__version__ = "0.9.1" -__author__ = "Andrea Gavana " diff --git a/agw/aui/__init__.py b/agw/aui/__init__.py deleted file mode 100644 index e5f1abf..0000000 --- a/agw/aui/__init__.py +++ /dev/null @@ -1,290 +0,0 @@ -""" -AUI is an Advanced User Interface library that aims to implement "cutting-edge" -interface usability and design features so developers can quickly and easily create -beautiful and usable application interfaces. - - -Vision and Design Principles -============================ - -AUI attempts to encapsulate the following aspects of the user interface: - -* **Frame Management**: Frame management provides the means to open, move and hide common - controls that are needed to interact with the document, and allow these configurations - to be saved into different perspectives and loaded at a later time. - -* **Toolbars**: Toolbars are a specialized subset of the frame management system and should - behave similarly to other docked components. However, they also require additional - functionality, such as "spring-loaded" rebar support, "chevron" buttons and end-user - customizability. - -* **Modeless Controls**: Modeless controls expose a tool palette or set of options that - float above the application content while allowing it to be accessed. Usually accessed - by the toolbar, these controls disappear when an option is selected, but may also be - "torn off" the toolbar into a floating frame of their own. - -* **Look and Feel**: Look and feel encompasses the way controls are drawn, both when shown - statically as well as when they are being moved. This aspect of user interface design - incorporates "special effects" such as transparent window dragging as well as frame animation. - -AUI adheres to the following principles: - -- Use native floating frames to obtain a native look and feel for all platforms; -- Use existing wxPython code where possible, such as sizer implementation for frame management; -- Use standard wxPython coding conventions. - - -Usage -===== - -The following example shows a simple implementation that uses L{AuiManager} to manage -three text controls in a frame window:: - - class MyFrame(wx.Frame): - - def __init__(self, parent, id=-1, title="AUI Test", pos=wx.DefaultPosition, - size=(800, 600), style=wx.DEFAULT_FRAME_STYLE): - - wx.Frame.__init__(self, parent, id, title, pos, size, style) - - self._mgr = aui.AuiManager() - - # notify AUI which frame to use - self._mgr.SetManagedWindow(self) - - # create several text controls - text1 = wx.TextCtrl(self, -1, "Pane 1 - sample text", - wx.DefaultPosition, wx.Size(200,150), - wx.NO_BORDER | wx.TE_MULTILINE) - - text2 = wx.TextCtrl(self, -1, "Pane 2 - sample text", - wx.DefaultPosition, wx.Size(200,150), - wx.NO_BORDER | wx.TE_MULTILINE) - - text3 = wx.TextCtrl(self, -1, "Main content window", - wx.DefaultPosition, wx.Size(200,150), - wx.NO_BORDER | wx.TE_MULTILINE) - - # add the panes to the manager - self._mgr.AddPane(text1, AuiPaneInfo().Left().Caption("Pane Number One")) - self._mgr.AddPane(text2, AuiPaneInfo().Bottom().Caption("Pane Number Two")) - self._mgr.AddPane(text3, AuiPaneInfo().CenterPane()) - - # tell the manager to "commit" all the changes just made - self._mgr.Update() - - self.Bind(wx.EVT_CLOSE, self.OnClose) - - - def OnClose(self, event): - - # deinitialize the frame manager - self._mgr.UnInit() - - self.Destroy() - event.Skip() - - - # our normal wxApp-derived class, as usual - - app = wx.PySimpleApp() - - frame = MyFrame(None) - app.SetTopWindow(frame) - frame.Show() - - app.MainLoop() - - -What's New -========== - -Current wxAUI Version Tracked: wxWidgets 2.9.0 (SVN HEAD) - -The wxPython AUI version fixes the following bugs or implement the following -missing features (the list is not exhaustive): - -- Visual Studio 2005 style docking: http://www.kirix.com/forums/viewtopic.php?f=16&t=596 -- Dock and Pane Resizing: http://www.kirix.com/forums/viewtopic.php?f=16&t=582 -- Patch concerning dock resizing: http://www.kirix.com/forums/viewtopic.php?f=16&t=610 -- Patch to effect wxAuiToolBar orientation switch: http://www.kirix.com/forums/viewtopic.php?f=16&t=641 -- AUI: Core dump when loading a perspective in wxGTK (MSW OK): http://www.kirix.com/forums/viewtopic.php?f=15&t=627 -- wxAuiNotebook reordered AdvanceSelection(): http://www.kirix.com/forums/viewtopic.php?f=16&t=617 -- Vertical Toolbar Docking Issue: http://www.kirix.com/forums/viewtopic.php?f=16&t=181 -- Patch to show the resize hint on mouse-down in aui: http://trac.wxwidgets.org/ticket/9612 -- The Left/Right and Top/Bottom Docks over draw each other: http://trac.wxwidgets.org/ticket/3516 -- MinSize() not honoured: http://trac.wxwidgets.org/ticket/3562 -- Layout problem with wxAUI: http://trac.wxwidgets.org/ticket/3597 -- Resizing children ignores current window size: http://trac.wxwidgets.org/ticket/3908 -- Resizing panes under Vista does not repaint background: http://trac.wxwidgets.org/ticket/4325 -- Resize sash resizes in response to click: http://trac.wxwidgets.org/ticket/4547 -- "Illegal" resizing of the AuiPane? (wxPython): http://trac.wxwidgets.org/ticket/4599 -- Floating wxAUIPane Resize Event doesn't update its position: http://trac.wxwidgets.org/ticket/9773 -- Don't hide floating panels when we maximize some other panel: http://trac.wxwidgets.org/ticket/4066 -- wxAUINotebook incorrect ALLOW_ACTIVE_PANE handling: http://trac.wxwidgets.org/ticket/4361 -- Page changing veto doesn't work, (patch supplied): http://trac.wxwidgets.org/ticket/4518 -- Show and DoShow are mixed around in wxAuiMDIChildFrame: http://trac.wxwidgets.org/ticket/4567 -- wxAuiManager & wxToolBar - ToolBar Of Size Zero: http://trac.wxwidgets.org/ticket/9724 -- wxAuiNotebook doesn't behave properly like a container as far as...: http://trac.wxwidgets.org/ticket/9911 -- Serious layout bugs in wxAUI: http://trac.wxwidgets.org/ticket/10620 -- wAuiDefaultTabArt::Clone() should just use copy contructor: http://trac.wxwidgets.org/ticket/11388 -- Drop down button for check tool on wxAuiToolbar: http://trac.wxwidgets.org/ticket/11139 - -Plus the following features: - -- AuiManager: - - (a) Implementation of a simple minimize pane system: Clicking on this minimize button causes a new - AuiToolBar to be created and added to the frame manager, (currently the implementation is such - that panes at West will have a toolbar at the right, panes at South will have toolbars at the - bottom etc...) and the pane is hidden in the manager. - Clicking on the restore button on the newly created toolbar will result in the toolbar being - removed and the original pane being restored; - (b) Panes can be docked on top of each other to form `AuiNotebooks`; `AuiNotebooks` tabs can be torn - off to create floating panes; - (c) On Windows XP, use the nice sash drawing provided by XP while dragging the sash; - (d) Possibility to set an icon on docked panes; - (e) Possibility to draw a sash visual grip, for enhanced visualization of sashes; - (f) Implementation of a native docking art (`ModernDockArt`). Windows XP only, **requires** Mark Hammond's - pywin32 package (winxptheme); - (g) Possibility to set a transparency for floating panes (a la Paint .NET); - (h) Snapping the main frame to the screen in any positin specified by horizontal and vertical - alignments; - (i) Snapping floating panes on left/right/top/bottom or any combination of directions, a la Winamp; - (j) "Fly-out" floating panes, i.e. panes which show themselves only when the mouse hover them; - (k) Ability to set custom bitmaps for pane buttons (close, maximize, etc...); - (l) Implementation of the style ``AUI_MGR_ANIMATE_FRAMES``, which fade-out floating panes when - they are closed (all platforms which support frames transparency) and show a moving rectangle - when they are docked and minimized (Windows < Vista and GTK only); - (m) A pane switcher dialog is available to cycle through existing AUI panes; - (n) Some flags which allow to choose the orientation and the position of the minimized panes; - (o) The functions [Get]MinimizeMode() in `AuiPaneInfo` which allow to set/get the flags described above; - (p) Events like ``EVT_AUI_PANE_DOCKING``, ``EVT_AUI_PANE_DOCKED``, ``EVT_AUI_PANE_FLOATING`` and ``EVT_AUI_PANE_FLOATED`` are - available for all panes *except* toolbar panes; - (q) Implementation of the RequestUserAttention method for panes; - (r) Ability to show the caption bar of docked panes on the left instead of on the top (with caption - text rotated by 90 degrees then). This is similar to what `wxDockIt` did. To enable this feature on any - given pane, simply call `CaptionVisible(True, left=True)`; - (s) New Aero-style docking guides: you can enable them by using the `AuiManager` style ``AUI_MGR_AERO_DOCKING_GUIDES``; - (t) A slide-in/slide-out preview of minimized panes can be seen by enabling the `AuiManager` style - ``AUI_MGR_PREVIEW_MINIMIZED_PANES`` and by hovering with the mouse on the minimized pane toolbar tool; - (u) New Whidbey-style docking guides: you can enable them by using the `AuiManager` style ``AUI_MGR_WHIDBEY_DOCKING_GUIDES``; - (v) Native of custom-drawn mini frames can be used as floating panes, depending on the ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style; - (w) A "smooth docking effect" can be obtained by using the ``AUI_MGR_SMOOTH_DOCKING`` style (similar to PyQT docking style). - -| - -- AuiNotebook: - - (a) Implementation of the style ``AUI_NB_HIDE_ON_SINGLE_TAB``, a la `wx.lib.agw.flatnotebook`; - (b) Implementation of the style ``AUI_NB_SMART_TABS``, a la `wx.lib.agw.flatnotebook`; - (c) Implementation of the style ``AUI_NB_USE_IMAGES_DROPDOWN``, which allows to show tab images - on the tab dropdown menu instead of bare check menu items (a la `wx.lib.agw.flatnotebook`); - (d) 6 different tab arts are available, namely: - - (1) Default "glossy" theme (as in `wx.aui.AuiNotebook`) - (2) Simple theme (as in `wx.aui.AuiNotebook`) - (3) Firefox 2 theme - (4) Visual Studio 2003 theme (VC71) - (5) Visual Studio 2005 theme (VC81) - (6) Google Chrome theme - - (e) Enabling/disabling tabs; - (f) Setting the colour of the tab's text; - (g) Implementation of the style ``AUI_NB_CLOSE_ON_TAB_LEFT``, which draws the tab close button on - the left instead of on the right (a la Camino browser); - (h) Ability to save and load perspectives in `AuiNotebook` (experimental); - (i) Possibility to add custom buttons in the `AuiNotebook` tab area; - (j) Implementation of the style ``AUI_NB_TAB_FLOAT``, which allows the floating of single tabs. - Known limitation: when the notebook is more or less full screen, tabs cannot be dragged far - enough outside of the notebook to become floating pages; - (k) Implementation of the style ``AUI_NB_DRAW_DND_TAB`` (on by default), which draws an image - representation of a tab while dragging; - (l) Implementation of the `AuiNotebook` unsplit functionality, which unsplit a splitted AuiNotebook - when double-clicking on a sash; - (m) Possibility to hide all the tabs by calling `HideAllTAbs`; - (n) wxPython controls can now be added inside page tabs by calling `AddControlToPage`, and they can be - removed by calling `RemoveControlFromPage`; - (o) Possibility to preview all the pages in a `AuiNotebook` (as thumbnails) by using the `NotebookPreview` - method of `AuiNotebook`; - (p) Tab labels can be edited by calling the `SetRenamable` method on a `AuiNotebook` page; - (q) Support for multi-lines tab labels in `AuiNotebook`; - (r) Support for setting minimum and maximum tab widths for fixed width tabs; - (s) Implementation of the style ``AUI_NB_ORDER_BY_ACCESS``, which orders the tabs by last access time - inside the Tab Navigator dialog; - (t) Implementation of the style ``AUI_NB_NO_TAB_FOCUS``, allowing the developer not to draw the tab - focus rectangle on tne `AuiNotebook` tabs. - -| - -- AuiToolBar: - - (a) ``AUI_TB_PLAIN_BACKGROUND`` style that allows to easy setup a plain background to the AUI toolbar, - without the need to override drawing methods. This style contrasts with the default behaviour - of the `wx.aui.AuiToolBar` that draws a background gradient and this break the window design when - putting it within a control that has margin between the borders and the toolbar (example: put - `wx.aui.AuiToolBar` within a `wx.StaticBoxSizer` that has a plain background); - (b) `AuiToolBar` allow item alignment: http://trac.wxwidgets.org/ticket/10174; - (c) `AUIToolBar` `DrawButton()` improvement: http://trac.wxwidgets.org/ticket/10303; - (d) `AuiToolBar` automatically assign new id for tools: http://trac.wxwidgets.org/ticket/10173; - (e) `AuiToolBar` Allow right-click on any kind of button: http://trac.wxwidgets.org/ticket/10079; - (f) `AuiToolBar` idle update only when visible: http://trac.wxwidgets.org/ticket/10075; - (g) Ability of creating `AuiToolBar` tools with [counter]clockwise rotation. This allows to propose a - variant of the minimizing functionality with a rotated button which keeps the caption of the pane - as label; - (h) Allow setting the alignment of all tools in a toolbar that is expanded. - - -TODOs -===== - -- Documentation, documentation and documentation; -- Fix `tabmdi.AuiMDIParentFrame` and friends, they do not work correctly at present; -- Allow specification of `CaptionLeft()` to `AuiPaneInfo` to show the caption bar of docked panes - on the left instead of on the top (with caption text rotated by 90 degrees then). This is - similar to what `wxDockIt` did - DONE; -- Make developer-created `AuiNotebooks` and automatic (framemanager-created) `AuiNotebooks` behave - the same way (undocking of tabs) - DONE, to some extent; -- Find a way to dock panes in already floating panes (`AuiFloatingFrames`), as they already have - their own `AuiManager`; -- Add more gripper styles (see, i.e., PlusDock 4.0); -- Add an "AutoHide" feature to docked panes, similar to fly-out floating panes (see, i.e., PlusDock 4.0); -- Add events for panes when they are about to float or to be docked (something like - ``EVT_AUI_PANE_FLOATING/ED`` and ``EVT_AUI_PANE_DOCKING/ED``) - DONE, to some extent; -- Implement the 4-ways splitter behaviour for horizontal and vertical sashes if they intersect; -- Extend `tabart.py` with more aui tab arts; -- Implement ``AUI_NB_LEFT`` and ``AUI_NB_RIGHT`` tab locations in `AuiNotebook`; -- Move `AuiDefaultToolBarArt` into a separate module (as with `tabart.py` and `dockart.py`) and - provide more arts for toolbars (maybe from `wx.lib.agw.flatmenu`?) -- Support multiple-rows/multiple columns toolbars; -- Integrate as much as possible with `wx.lib.agw.flatmenu`, from dropdown menus in `AuiNotebook` to - toolbars and menu positioning; -- Possibly handle minimization of panes in a different way (or provide an option to switch to - another way of minimizing panes); -- Clean up/speed up the code, especially time-consuming for-loops; -- Possibly integrate `wxPyRibbon` (still on development), at least on Windows. - - -License And Version -=================== - -AUI library is distributed under the wxPython license. - -Latest revision: Andrea Gavana @ 10 Mar 2011, 15.00 GMT - -Version 1.3. - -""" - -__author__ = "Andrea Gavana " -__date__ = "31 March 2009" - - -from aui_constants import * -from aui_utilities import * -from auibar import * -from auibook import * -from tabart import * -from dockart import * -from framemanager import * -from tabmdi import * diff --git a/agw/aui/aui_constants.py b/agw/aui/aui_constants.py deleted file mode 100644 index 38f183d..0000000 --- a/agw/aui/aui_constants.py +++ /dev/null @@ -1,2588 +0,0 @@ -""" -This module contains all the constants used by wxPython-AUI. - -Especially important and meaningful are constants for AuiManager, AuiDockArt and -AuiNotebook. -""" - -__author__ = "Andrea Gavana " -__date__ = "31 March 2009" - - -import wx -from wx.lib.embeddedimage import PyEmbeddedImage - -# ------------------------- # -# - AuiNotebook Constants - # -# ------------------------- # - -# For tabart -# -------------- - -vertical_border_padding = 4 -""" Border padding used in drawing tabs. """ - -if wx.Platform == "__WXMAC__": - nb_close_bits = "\xFF\xFF\xFF\xFF\x0F\xFE\x03\xF8\x01\xF0\x19\xF3" \ - "\xB8\xE3\xF0\xE1\xE0\xE0\xF0\xE1\xB8\xE3\x19\xF3" \ - "\x01\xF0\x03\xF8\x0F\xFE\xFF\xFF" - """ AuiNotebook close button image on wxMAC. """ - -elif wx.Platform == "__WXGTK__": - nb_close_bits = "\xff\xff\xff\xff\x07\xf0\xfb\xef\xdb\xed\x8b\xe8" \ - "\x1b\xec\x3b\xee\x1b\xec\x8b\xe8\xdb\xed\xfb\xef" \ - "\x07\xf0\xff\xff\xff\xff\xff\xff" - """ AuiNotebook close button image on wxGTK. """ - -else: - nb_close_bits = "\xff\xff\xff\xff\xff\xff\xff\xff\xe7\xf3\xcf\xf9" \ - "\x9f\xfc\x3f\xfe\x3f\xfe\x9f\xfc\xcf\xf9\xe7\xf3" \ - "\xff\xff\xff\xff\xff\xff\xff\xff" - """ AuiNotebook close button image on wxMSW. """ - -nb_left_bits = "\xff\xff\xff\xff\xff\xff\xff\xfe\x7f\xfe\x3f\xfe\x1f" \ - "\xfe\x0f\xfe\x1f\xfe\x3f\xfe\x7f\xfe\xff\xfe\xff\xff" \ - "\xff\xff\xff\xff\xff\xff" -""" AuiNotebook left button image. """ - -nb_right_bits = "\xff\xff\xff\xff\xff\xff\xdf\xff\x9f\xff\x1f\xff\x1f" \ - "\xfe\x1f\xfc\x1f\xfe\x1f\xff\x9f\xff\xdf\xff\xff\xff" \ - "\xff\xff\xff\xff\xff\xff" -""" AuiNotebook right button image. """ - -nb_list_bits = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x0f" \ - "\xf8\xff\xff\x0f\xf8\x1f\xfc\x3f\xfe\x7f\xff\xff\xff" \ - "\xff\xff\xff\xff\xff\xff" -""" AuiNotebook windows list button image. """ - - -#---------------------------------------------------------------------- -tab_active_center = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAAEAAAAbCAYAAAC9WOV0AAAABHNCSVQICAgIfAhkiAAAADNJ" - "REFUCJltzMEJwDAUw9DHX6OLdP/Bop4KDc3F2EIYrsFtrZow8GnH6OD1zvRTajvY2QMHIhNx" - "jUhuAgAAAABJRU5ErkJggg==") -""" Center active tab image for the Chrome tab art. """ - -#---------------------------------------------------------------------- -tab_active_left = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAbCAYAAACjkdXHAAAABHNCSVQICAgIfAhkiAAAAglJ" - "REFUOI2Nkk9rE0EYh5/J7mpW06xE2iSmeFHxEoqIAc/FQ5CKgn4DP4KlIQG/QVsQbBEKgop+" - "Anvy4rV4bLT2JCGJPVXqwaZJd+f1kN26WTfJDrzszDLPPL/5o0jeFGAC54A0YKmEYAo4DzjA" - "LHAZmElqtIGrhmEsvtzcfPNtb6/V6524SWALKBiGsfhxe/uzFhGth5XEmgVubWxsvA1Az68k" - "1nngYbPZ7ASg69c06wxwe3V9/b3reVqHwGmwCZRs2370fX//wIuA0+CLwEKj0XilZTSu602G" - "FcP7vLe7+7XlRaCgPw62gGv5fP6p63raiwFdLWKOgdNArl6vV1UqpQgcYdcYbwooAPfb7c7h" - "mTWmUjGwCWTL5fL1K6VSLiqQyMTYyLVa/UEwe9IC0chFYKnb/XnkeiIDV+Q0UsG/qNkCnEql" - "crNQLDpaxpskJnYayD1bXl4S/xrDoPLHKjQOmsHwlCuHv44+ZJ2sLTrGGqzg7zEc+VK1Wl1w" - "HMcG0DFxw6sFsRVwAZhdWak9FoRJ+w2HCKzzwN3jXv+daVmGDkdWoMKb9fumHz0DFFfX1p5Y" - "lmXo6N0G48jzVEDOt97pdA9ezOXzGU+PzBmN6VuDqyoDN3Z2vjyfKxQynhYkJuJ/L02Ara3X" - "n3602r8HrpaTUy3HAy1/+hNq8O+r+q4WETirmFMNBwm3v+gdmytKNIUpAAAAAElFTkSuQmCC") -""" Left active tab image for the Chrome tab art. """ - -#---------------------------------------------------------------------- -tab_active_right = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAbCAYAAACjkdXHAAAABHNCSVQICAgIfAhkiAAAAkpJ" - "REFUOI2NlM1rU0EUxX9zZ5KaWq3GKKnGutC0FEWCWAWLRUOxBetK/wdp6Re6F6TFXXGhuFdw" - "b7dCQUUpiFt1XbB2q7Uf1iTvunjzkpe0afNgmLnDnHvOPe/OWCALtAFC+Cktfha4CRwBDnhg" - "BQhaSrK19bf89dv35WfPX7y01haBbiAFmH3BlUA1Gm8WFt75BFkg0TK4VAl0Y3NL5+efvgIK" - "wOH92EVjxRljGBi4VgTOeLDbk7kcqEZju1TWX7/Xgtm5J6+BS8ChvdilLhAhkUya4eFbxVQq" - "1e3ZbUtgg8GKJd/Tk70/NjYCHCPsgX1kV8K5VA70z8amfvy0tAwMAcebSRfijikY8ez5/OlM" - "JrOncbIjp4K1lmRb0sw8eDgCpAm7rwlz46YIzjpGb48WveyDNPhDfCOuHmNwzpHL5dK9fX3n" - "mkmvaxJiayOCWMvM1PSdZtJrhiloLJMYIeESDFwf7Acyu0mXGLYmX0PpYi3ZbFdnoVDoBTpp" - "uCxCjFob1tYKzlnGJyZHd5Mu6uVGkqvMCmCwzjE4eOMqcALoINauUic37hjhLXPWcTSdThWL" - "QxcJX5yqdGk4H/cP9a4755iYnLpL+M/b8e0qjafrekb9TUskuNx/5TzQ5Y1zO9yOZEd1R7OI" - "JdXebh/Pzt3zCToAMZv/AjU1orDWWKAGVJVSqcTqysp6X+/ZaeAL8KNac9wsVQ8yNeOsdZw8" - "let4/2HpEdAPXDAb20HLj7xqeHT158ra4uLbz2bdg03krmetxrH9KDAmHP8Bn0j1t/01UV0A" - "AAAASUVORK5CYII=") -""" Right active tab image for the Chrome tab art. """ - -#---------------------------------------------------------------------- -tab_close = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABHNCSVQICAgIfAhkiAAAAI9J" - "REFUKJG90MEKAWEUxfEfM4rxAFIommzZzNb7v4BsLJTsiGQlYjHfME3flrO75/xvnXv5p/qY" - "R/wcWTUktWCKFbrYB6/AAhecmwunAI/RwQAjbLGpoFakwjLATxzqMLQjC68A3/FohkljLkKN" - "Ha4YKg8+VkBag3Pll9a1GikmuPk+4qMMs0jFMXoR/0d6A9JRFV/jxY+iAAAAAElFTkSuQmCC") -""" Normal close button image for the Chrome tab art. """ - -#---------------------------------------------------------------------- -tab_close_h = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABHNCSVQICAgIfAhkiAAAAOlJ" - "REFUKJGVkiFuw0AQRd849hUS7iPUwGEllhyjYJ+gaK9Q4CsY9QTFIY4shQQucI8Q7l6h3Z0S" - "r7UgjdrPZvVm52k0wpJLWe4y51qgVpECQFQnYPzabN4ra2cAAbgWxZMmyavAkTtROIn33fM0" - "fcilLHep92+/wXHTd5K8JJlzbYD3w8C2aVZo2zTsh4FF5Zg516ZAHYBb35MbszbkxnDr+3hQ" - "napIIUv1eT6vYPggvAGoSJE88r6XVFQnRA7BOdYIk8IUUZ1SYAQOsXOskRsT1+P/11pZO4v3" - "ncLpESzed5W1c1jQn0/jBzPfck1qdmfjAAAAAElFTkSuQmCC") -""" Hover close button image for the Chrome tab art. """ - -#---------------------------------------------------------------------- -tab_close_p = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABHNCSVQICAgIfAhkiAAAASxJ" - "REFUKJF9kbFLQlEYxX/nvbs55OAkiJAE7k7Nibo9xf+hrTlyr3Boipb+BCGq0bApJEQcG0Ms" - "aQ0Lmq5+Dc+nDtbZ7uHce37fd8VSlWwh50PfRKqClWJXI8y6bu5uHj5e3wEEcJDP75txLBSx" - "RYbdS7QfJ5PnsJIt5BbB4hQjkrQtjxlFILOXyvQDH/qmUCSJznDAYetkFTxsndAZDggkhCIf" - "+qaLmWP1bu8oN+qrC+VGnd7t3bpKqrp4wBjl+ux8FUweSLwlXCnYCv2PHGgE1BLmTYykad2i" - "kcOsi1TbZN7EKDfq67NZV5VsIeedvzQjCv5YK8R/4bw7Cl+/P7920+kJkBEq/hWWaPem45cQ" - "YDybTfdSmf5CizckwHaAH9ATZldu7i560/ELwC+6RXdU6KzezAAAAABJRU5ErkJggg==") -""" Pressed close button image for the Chrome tab art. """ - -#---------------------------------------------------------------------- -tab_inactive_center = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAAEAAAAbCAYAAAC9WOV0AAAABHNCSVQICAgIfAhkiAAAAElJ" - "REFUCJlVyiEOgDAUBNHp3qmX5iYkyMpqBAaFILRdDGn4qybZB98yy3ZZrRu1PpABAQiDSLN+" - "h4NLEU8CBAfoPHZUywr3M/wCTz8c3/qQrUcAAAAASUVORK5CYII=") -""" Center inactive tab image for the Chrome tab art. """ - -#---------------------------------------------------------------------- -tab_inactive_left = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAbCAYAAACjkdXHAAAABHNCSVQICAgIfAhkiAAAAf5J" - "REFUOI2llE1rE1EUhp8bZwyhaZomk5DaD40hSWPQVkTd6KIIEUWlLqTEhTaLulBQ6sfKjeBC" - "ECULXQku/Alx7d6/U1EQae45LjJpJ5NOnOKBgYG5z33Px3sG/iPMIc87QAmYBZKHgdOu69a2" - "3/W2yrVGK5vPLTlxFV3Xrb3+8v1Ntd5oiSpWBmnEidKT972tar3R6ovSt4qoxoIdoFipNlpW" - "B6AVRYFEHNWn3a8dz/PK1rIHEgN2UpnMseVTK7fUGBME48CFe88+3sh5+SXr1xmMSbABvJXz" - "l9siYAVGWJ0Mu/OVZr5Q8CpWfFWzD2Imj2qu/fhtG4wRVUIZg0bDBsgtn15dt6qIKKBDQZ81" - "kWmnzly6OZ+ZzhSt7jfK6CBjFMwEk5TWOy82AVQGhzVUb5RJEkC2fLK6JgIiPhioeZJJUhev" - "3j2RTqdzooqge2ojCxwxqrnrG4/uq4Ida3HgAjMOJ4CZSq1+RVBUzCgQinDDstfa282jyeTU" - "rhUGF4CJgMPKhbXbmw9VFfG7fBA4LCao7AAzi8cXz1kF0dENMqH38KgWnnd7nSMJxxE5wI4+" - "MHyCaeeAYvPshQ0RJby3wVSDHxxgAVh99elb9/evndmfP3boW2FsqGNhMMCdBy8/fJ5KZ6at" - "qL+3Q1dEzFkNGMX82ZWh18e0/vVT/wuFmdYVv/ruKgAAAABJRU5ErkJggg==") -""" Left inactive tab image for the Chrome tab art. """ - -#---------------------------------------------------------------------- -tab_inactive_right = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAbCAYAAACjkdXHAAAABHNCSVQICAgIfAhkiAAAAhBJ" - "REFUOI2llM9rE1EQxz8zb1dSTKNuYtW01kQDRoKFWi9FEEq1IooUUWoPokWCtVqkR69KsSBU" - "8OJRPOhBxZNe/At6FBER/HFUPEq1IGn3ecgm2ZjdJODCHPY9vvP9fufNDPzHZ4DDQBrYBKwB" - "ftfoJys/Kw9ef/1y8/6rh67rHgKS3WLl6cqqtcCGD58+vn+zdPXorUql8g5Y7wTWdd+y4Vus" - "teQK+yfKi8/KwM5umBXAAgioCIP54gTQBzgdwTbsQZR0JpOfXXw+0w27hn9EBGMcyRcPnulJ" - "pbKd2JvACKgKnpcePH99+TSwvT3YEphusKsqB4ZHp4FMNWUn5loSEVSFbZ63b8eeUhpwu5Md" - "JBFRjHHk7LXb08CuNuAaZTgEEaFQHJoEvDjpakOYmnURUFWSvam+0ujJfqAnmlnABhG2jlTZ" - "j19YuEzMm7dUu34hihrDQG7vGLCViPq0VruuvdquyWSvN3xsKhclvbXaoUQiihFlfLJ8iYiq" - "O/EtUC2xGGF3vjAObAnI6stCsZbYCLwnEonNY+dulALvHWSH2YN2PXLq4hz/9HpjnmOs18DZ" - "bP9IIL0+afV5juqzRgLFcV1n9u6LGWAgWnaMBFHBOIbi0MgU1S3jAcjyyw9xqpvzWou1Pj++" - "f/t8b/7EAvBW5u48agU37abWs99rv1YfL81fkT8V34YxbZ696d4CfwEszZSZx6Z26wAAAABJ" - "RU5ErkJggg==") -""" Right inactive tab image for the Chrome tab art. """ - -# For auibook -# ----------- - -AuiBaseTabCtrlId = 5380 -""" Base window identifier for AuiTabCtrl. """ - -AUI_NB_TOP = 1 << 0 -""" With this style, tabs are drawn along the top of the notebook. """ -AUI_NB_LEFT = 1 << 1 # not implemented yet -""" With this style, tabs are drawn along the left of the notebook. -Not implemented yet. """ -AUI_NB_RIGHT = 1 << 2 # not implemented yet -""" With this style, tabs are drawn along the right of the notebook. -Not implemented yet. """ -AUI_NB_BOTTOM = 1 << 3 -""" With this style, tabs are drawn along the bottom of the notebook. """ -AUI_NB_TAB_SPLIT = 1 << 4 -""" Allows the tab control to be split by dragging a tab. """ -AUI_NB_TAB_MOVE = 1 << 5 -""" Allows a tab to be moved horizontally by dragging. """ -AUI_NB_TAB_EXTERNAL_MOVE = 1 << 6 -""" Allows a tab to be moved to another tab control. """ -AUI_NB_TAB_FIXED_WIDTH = 1 << 7 -""" With this style, all tabs have the same width. """ -AUI_NB_SCROLL_BUTTONS = 1 << 8 -""" With this style, left and right scroll buttons are displayed. """ -AUI_NB_WINDOWLIST_BUTTON = 1 << 9 -""" With this style, a drop-down list of windows is available. """ -AUI_NB_CLOSE_BUTTON = 1 << 10 -""" With this style, a close button is available on the tab bar. """ -AUI_NB_CLOSE_ON_ACTIVE_TAB = 1 << 11 -""" With this style, a close button is available on the active tab. """ -AUI_NB_CLOSE_ON_ALL_TABS = 1 << 12 -""" With this style, a close button is available on all tabs. """ -AUI_NB_MIDDLE_CLICK_CLOSE = 1 << 13 -""" Allows to close `AuiNotebook` tabs by mouse middle button click. """ -AUI_NB_SUB_NOTEBOOK = 1 << 14 -""" This style is used by `AuiManager` to create automatic `AuiNotebooks`. """ -AUI_NB_HIDE_ON_SINGLE_TAB = 1 << 15 -""" Hides the tab window if only one tab is present. """ -AUI_NB_SMART_TABS = 1 << 16 -""" Use `Smart Tabbing`, like ``Alt`` + ``Tab`` on Windows. """ -AUI_NB_USE_IMAGES_DROPDOWN = 1 << 17 -""" Uses images on dropdown window list menu instead of check items. """ -AUI_NB_CLOSE_ON_TAB_LEFT = 1 << 18 -""" Draws the tab close button on the left instead of on the right -(a la Camino browser). """ -AUI_NB_TAB_FLOAT = 1 << 19 -""" Allows the floating of single tabs. -Known limitation: when the notebook is more or less full screen, tabs -cannot be dragged far enough outside of the notebook to become -floating pages. """ -AUI_NB_DRAW_DND_TAB = 1 << 20 -""" Draws an image representation of a tab while dragging. """ -AUI_NB_ORDER_BY_ACCESS = 1 << 21 -""" Tab navigation order by last access time. """ -AUI_NB_NO_TAB_FOCUS = 1 << 22 -""" Don't draw tab focus rectangle. """ - -AUI_NB_DEFAULT_STYLE = AUI_NB_TOP | AUI_NB_TAB_SPLIT | AUI_NB_TAB_MOVE | \ - AUI_NB_SCROLL_BUTTONS | AUI_NB_CLOSE_ON_ACTIVE_TAB | \ - AUI_NB_MIDDLE_CLICK_CLOSE | AUI_NB_DRAW_DND_TAB -""" Default `AuiNotebook` style. """ - -#---------------------------------------------------------------------- -Mondrian = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAHFJ" - "REFUWIXt1jsKgDAQRdF7xY25cpcWC60kioI6Fm/ahHBCMh+BRmGMnAgEWnvPpzK8dvrFCCCA" - "coD8og4c5Lr6WB3Q3l1TBwLYPuF3YS1gn1HphgEEEABcKERrGy0E3B0HFJg7C1N/f/kTBBBA" - "+Vi+AMkgFEvBPD17AAAAAElFTkSuQmCC") -""" Default icon for the Smart Tabbing dialog. """ - -# -------------------------- # -# - FrameManager Constants - # -# -------------------------- # - -# Docking Styles -AUI_DOCK_NONE = 0 -""" No docking direction. """ -AUI_DOCK_TOP = 1 -""" Top docking direction. """ -AUI_DOCK_RIGHT = 2 -""" Right docking direction. """ -AUI_DOCK_BOTTOM = 3 -""" Bottom docking direction. """ -AUI_DOCK_LEFT = 4 -""" Left docking direction. """ -AUI_DOCK_CENTER = 5 -""" Center docking direction. """ -AUI_DOCK_CENTRE = AUI_DOCK_CENTER -""" Centre docking direction. """ -AUI_DOCK_NOTEBOOK_PAGE = 6 -""" Automatic AuiNotebooks docking style. """ - -# Floating/Dragging Styles -AUI_MGR_ALLOW_FLOATING = 1 << 0 -""" Allow floating of panes. """ -AUI_MGR_ALLOW_ACTIVE_PANE = 1 << 1 -""" If a pane becomes active, "highlight" it in the interface. """ -AUI_MGR_TRANSPARENT_DRAG = 1 << 2 -""" If the platform supports it, set transparency on a floating pane -while it is dragged by the user. """ -AUI_MGR_TRANSPARENT_HINT = 1 << 3 -""" If the platform supports it, show a transparent hint window when -the user is about to dock a floating pane. """ -AUI_MGR_VENETIAN_BLINDS_HINT = 1 << 4 -""" Show a "venetian blind" effect when the user is about to dock a -floating pane. """ -AUI_MGR_RECTANGLE_HINT = 1 << 5 -""" Show a rectangle hint effect when the user is about to dock a -floating pane. """ -AUI_MGR_HINT_FADE = 1 << 6 -""" If the platform supports it, the hint window will fade in and out. """ -AUI_MGR_NO_VENETIAN_BLINDS_FADE = 1 << 7 -""" Disables the "venetian blind" fade in and out. """ -AUI_MGR_LIVE_RESIZE = 1 << 8 -""" Live resize when the user drag a sash. """ -AUI_MGR_ANIMATE_FRAMES = 1 << 9 -""" Fade-out floating panes when they are closed (all platforms which support -frames transparency) and show a moving rectangle when they are docked -(Windows < Vista and GTK only). """ -AUI_MGR_AERO_DOCKING_GUIDES = 1 << 10 -""" Use the new Aero-style bitmaps as docking guides. """ -AUI_MGR_PREVIEW_MINIMIZED_PANES = 1 << 11 -""" Slide in and out minimized panes to preview them. """ -AUI_MGR_WHIDBEY_DOCKING_GUIDES = 1 << 12 -""" Use the new Whidbey-style bitmaps as docking guides. """ -AUI_MGR_SMOOTH_DOCKING = 1 << 13 -""" Performs a "smooth" docking of panes (a la PyQT). """ -AUI_MGR_USE_NATIVE_MINIFRAMES = 1 << 14 -""" Use miniframes with native caption bar as floating panes instead or custom -drawn caption bars (forced on wxMac). """ -AUI_MGR_AUTONB_NO_CAPTION = 1 << 15 -""" Panes that merge into an automatic notebook will not have the pane -caption visible. """ - - -AUI_MGR_DEFAULT = AUI_MGR_ALLOW_FLOATING | AUI_MGR_TRANSPARENT_HINT | \ - AUI_MGR_HINT_FADE | AUI_MGR_NO_VENETIAN_BLINDS_FADE -""" Default `AuiManager` style. """ - -# Panes Customization -AUI_DOCKART_SASH_SIZE = 0 -""" Customizes the sash size. """ -AUI_DOCKART_CAPTION_SIZE = 1 -""" Customizes the caption size. """ -AUI_DOCKART_GRIPPER_SIZE = 2 -""" Customizes the gripper size. """ -AUI_DOCKART_PANE_BORDER_SIZE = 3 -""" Customizes the pane border size. """ -AUI_DOCKART_PANE_BUTTON_SIZE = 4 -""" Customizes the pane button size. """ -AUI_DOCKART_BACKGROUND_COLOUR = 5 -""" Customizes the background colour. """ -AUI_DOCKART_BACKGROUND_GRADIENT_COLOUR = 6 -""" Customizes the background gradient colour. """ -AUI_DOCKART_SASH_COLOUR = 7 -""" Customizes the sash colour. """ -AUI_DOCKART_ACTIVE_CAPTION_COLOUR = 8 -""" Customizes the active caption colour. """ -AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR = 9 -""" Customizes the active caption gradient colour. """ -AUI_DOCKART_INACTIVE_CAPTION_COLOUR = 10 -""" Customizes the inactive caption colour. """ -AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR = 11 -""" Customizes the inactive gradient caption colour. """ -AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR = 12 -""" Customizes the active caption text colour. """ -AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR = 13 -""" Customizes the inactive caption text colour. """ -AUI_DOCKART_BORDER_COLOUR = 14 -""" Customizes the border colour. """ -AUI_DOCKART_GRIPPER_COLOUR = 15 -""" Customizes the gripper colour. """ -AUI_DOCKART_CAPTION_FONT = 16 -""" Customizes the caption font. """ -AUI_DOCKART_GRADIENT_TYPE = 17 -""" Customizes the gradient type (no gradient, vertical or horizontal). """ -AUI_DOCKART_DRAW_SASH_GRIP = 18 -""" Draw a sash grip on the sash. """ - -# Caption Gradient Type -AUI_GRADIENT_NONE = 0 -""" No gradient on the captions. """ -AUI_GRADIENT_VERTICAL = 1 -""" Vertical gradient on the captions. """ -AUI_GRADIENT_HORIZONTAL = 2 -""" Horizontal gradient on the captions. """ - -# Pane Button State -AUI_BUTTON_STATE_NORMAL = 0 -""" Normal button state. """ -AUI_BUTTON_STATE_HOVER = 1 << 1 -""" Hovered button state. """ -AUI_BUTTON_STATE_PRESSED = 1 << 2 -""" Pressed button state. """ -AUI_BUTTON_STATE_DISABLED = 1 << 3 -""" Disabled button state. """ -AUI_BUTTON_STATE_HIDDEN = 1 << 4 -""" Hidden button state. """ -AUI_BUTTON_STATE_CHECKED = 1 << 5 -""" Checked button state. """ - -# Pane minimize mode -AUI_MINIMIZE_POS_SMART = 0x01 -""" Minimizes the pane on the closest tool bar. """ -AUI_MINIMIZE_POS_TOP = 0x02 -""" Minimizes the pane on the top tool bar. """ -AUI_MINIMIZE_POS_LEFT = 0x03 -""" Minimizes the pane on its left tool bar. """ -AUI_MINIMIZE_POS_RIGHT = 0x04 -""" Minimizes the pane on its right tool bar. """ -AUI_MINIMIZE_POS_BOTTOM = 0x05 -""" Minimizes the pane on its bottom tool bar. """ -AUI_MINIMIZE_POS_MASK = 0x07 -""" Mask to filter the position flags. """ -AUI_MINIMIZE_CAPT_HIDE = 0 -""" Hides the caption of the minimized pane. """ -AUI_MINIMIZE_CAPT_SMART = 0x08 -""" Displays the caption in the best rotation (horz or clockwise). """ -AUI_MINIMIZE_CAPT_HORZ = 0x10 -""" Displays the caption horizontally. """ -AUI_MINIMIZE_CAPT_MASK = 0x18 -""" Mask to filter the caption flags. """ - -# Button kind -AUI_BUTTON_CLOSE = 101 -""" Shows a close button on the pane. """ -AUI_BUTTON_MAXIMIZE_RESTORE = 102 -""" Shows a maximize/restore button on the pane. """ -AUI_BUTTON_MINIMIZE = 103 -""" Shows a minimize button on the pane. """ -AUI_BUTTON_PIN = 104 -""" Shows a pin button on the pane. """ -AUI_BUTTON_OPTIONS = 105 -""" Shows an option button on the pane (not implemented). """ -AUI_BUTTON_WINDOWLIST = 106 -""" Shows a window list button on the pane (for AuiNotebook). """ -AUI_BUTTON_LEFT = 107 -""" Shows a left button on the pane (for AuiNotebook). """ -AUI_BUTTON_RIGHT = 108 -""" Shows a right button on the pane (for AuiNotebook). """ -AUI_BUTTON_UP = 109 -""" Shows an up button on the pane (not implemented). """ -AUI_BUTTON_DOWN = 110 -""" Shows a down button on the pane (not implemented). """ -AUI_BUTTON_CUSTOM1 = 201 -""" Shows a custom button on the pane. """ -AUI_BUTTON_CUSTOM2 = 202 -""" Shows a custom button on the pane. """ -AUI_BUTTON_CUSTOM3 = 203 -""" Shows a custom button on the pane. """ -AUI_BUTTON_CUSTOM4 = 204 -""" Shows a custom button on the pane. """ -AUI_BUTTON_CUSTOM5 = 205 -""" Shows a custom button on the pane. """ -AUI_BUTTON_CUSTOM6 = 206 -""" Shows a custom button on the pane. """ -AUI_BUTTON_CUSTOM7 = 207 -""" Shows a custom button on the pane. """ -AUI_BUTTON_CUSTOM8 = 208 -""" Shows a custom button on the pane. """ -AUI_BUTTON_CUSTOM9 = 209 -""" Shows a custom button on the pane. """ - -# Pane Insert Level -AUI_INSERT_PANE = 0 -""" Level for inserting a pane. """ -AUI_INSERT_ROW = 1 -""" Level for inserting a row. """ -AUI_INSERT_DOCK = 2 -""" Level for inserting a dock. """ - -# Action constants -actionNone = 0 -""" No current action. """ -actionResize = 1 -""" Resize action. """ -actionClickButton = 2 -""" Click on a pane button action. """ -actionClickCaption = 3 -""" Click on a pane caption action. """ -actionDragToolbarPane = 4 -""" Drag a floating toolbar action. """ -actionDragFloatingPane = 5 -""" Drag a floating pane action. """ - -# Drop/Float constants -auiInsertRowPixels = 10 -""" Number of pixels between rows. """ -auiNewRowPixels = 40 -""" Number of pixels for a new inserted row. """ -auiLayerInsertPixels = 40 -""" Number of pixels between layers. """ -auiLayerInsertOffset = 5 -""" Number of offset pixels between layers. """ -auiToolBarLayer = 10 -""" AUI layer for a toolbar. """ - -# some built in bitmaps - -if wx.Platform == "__WXMAC__": - - close_bits = "\xFF\xFF\xFF\xFF\x0F\xFE\x03\xF8\x01\xF0\x19\xF3\xB8\xE3\xF0" \ - "\xE1\xE0\xE0\xF0\xE1\xB8\xE3\x19\xF3\x01\xF0\x03\xF8\x0F\xFE\xFF\xFF" - """ Close button bitmap for a pane on wxMAC. """ - -elif wx.Platform == "__WXGTK__": - - close_bits = "\xff\xff\xff\xff\x07\xf0\xfb\xef\xdb\xed\x8b\xe8\x1b\xec\x3b\xee" \ - "\x1b\xec\x8b\xe8\xdb\xed\xfb\xef\x07\xf0\xff\xff\xff\xff\xff\xff" - """ Close button bitmap for a pane on wxGTK. """ - -else: - - close_bits = "\xff\xff\xff\xff\xff\xff\xff\xff\xcf\xf3\x9f\xf9\x3f\xfc\x7f\xfe" \ - "\x3f\xfc\x9f\xf9\xcf\xf3\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" - """ Close button bitmap for a pane on wxMSW. """ - -pin_bits = '\xff\xff\xff\xff\xff\xff\x1f\xfc\xdf\xfc\xdf\xfc\xdf\xfc\xdf\xfc' \ - '\xdf\xfc\x0f\xf8\x7f\xff\x7f\xff\x7f\xff\xff\xff\xff\xff\xff\xff' -""" Pin button bitmap for a pane. """ - -max_bits = '\xff\xff\xff\xff\xff\xff\x07\xf0\xf7\xf7\x07\xf0\xf7\xf7\xf7\xf7' \ - '\xf7\xf7\xf7\xf7\xf7\xf7\x07\xf0\xff\xff\xff\xff\xff\xff\xff\xff' -""" Maximize button bitmap for a pane. """ - -restore_bits = '\xff\xff\xff\xff\xff\xff\x1f\xf0\x1f\xf0\xdf\xf7\x07\xf4\x07\xf4' \ - '\xf7\xf5\xf7\xf1\xf7\xfd\xf7\xfd\x07\xfc\xff\xff\xff\xff\xff\xff' -""" Restore/maximize button bitmap for a pane. """ - -minimize_bits = '\xff\xff\xff\xff\xff\xff\x07\xf0\xf7\xf7\x07\xf0\xff\xff\xff\xff' \ - '\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' -""" Minimize button bitmap for a pane. """ - -restore_xpm = ["16 15 3 1", - " c None", - ". c #000000", - "+ c #FFFFFF", - " ", - " .......... ", - " .++++++++. ", - " .......... ", - " .++++++++. ", - " ..........+++. ", - " .++++++++.+++. ", - " ..........+++. ", - " .++++++++..... ", - " .++++++++. ", - " .++++++++. ", - " .++++++++. ", - " .++++++++. ", - " .......... ", - " "] -""" Restore/minimize button bitmap for a pane. """ - -#---------------------------------------------------------------------- - -down_focus_single = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAgCAIAAABhFeQrAAAAA3NCSVQICAjb4U/gAAACaUlE" - "QVRIib2WvWsUQRjGn5mdnWxyTaqz9q+QlLnGToSgWAYDNjbpNCAGDGIvaRPbNJGQyiAEbK+w" - "sAo2qexyEhbxsvt+jMXc3u3liPfhmWeXnWVm9vc+vO/M7prVzTb+gxyA7Ye/nXPWWmvtXKBb" - "B9YBcM5lWZam6by4QNcBsNamaeq9d87NmWutdc59+NgGoKIizCwsxMTMFI8oZmZilzomZiFm" - "FWERaXbv7eyueO+TJEHM79LSkvfeWnv2qftgex2ASGDmkrUkKUspiIuCy5IL4qKQgnghdQVx" - "ScKsxCKiaH8lIu99NOwAEFGsG4Dv5xeiQYOKBBYVUWJlFhIVVmIlEZGQJKVIYBbWoKqqwQN5" - "nqdpuri42OMys6rGOG/X78yW0bXWNyLqcyyAEEIIYcYK3aB5Lazb4o5fsPc3ToFaloxBwMle" - "6+9Pjfd7stda6HR85+dCPC86Y6ETcQEcHz32eZ7meZrnx0ePJnlk0vwenm70r/PkTgWdjjuV" - "rnPPfvxaa+3NcL3GMaub7XdPtNFoZFn24tmX1/trAOLuM6aaFQwQYExAMPWNaUw1FW+eHj5/" - "dbfZbDYajY33F7e1L4gUA5uo3fd8AWbQH70bjGqEyxLq3LoMYhKCgakCIWZoLLdkMRE43Iy0" - "tWi9QOP8xoIFAyBUjF7dgOizb9iMhLmByxIAHbAGKYigUPX3hqog47hSvfCHfYRaDcNg3IzO" - "7GmydRaGi37zMujrut/9l58nijROQ9yd3ZXLy8urq6vZWFmW9f+Yhrje++XlZR2keDpZa4f+" - "H/pKkiR+/f9dDsDWgQW6QHcuxKg/ZbVtCjjzINkAAAAASUVORK5CYII=") -""" VS2005 focused docking guide window down bitmap. """ - -#---------------------------------------------------------------------- -down_single = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAgCAIAAABhFeQrAAAAA3NCSVQICAjb4U/gAAACY0lE" - "QVRIib2WwWrUUBSG/3tzc5s2m0JhXPsU0u1s3Lkpui4W3PgAuhAFi2/QbesTVEphwCIU3Hbh" - "wk2LG1fujJQgtMk55x4Xd2aS6VAzM479JyQhufnOz3/uzcQMBgP8BzkAeZ4756y11tqlQIui" - "cACcc1mWpWm6ZK61Nk1T771zbilcxBxiAs659x/OAAQJIswsLMTEzBR/UczMxC51TMxCzEGE" - "RaR39WB3b9N7nyTJkLu2tua9t9ZefLx69GYbgIgyc82hJqlrqYiriuuaK+Kqkop4JXUVcU3C" - "HIhFJODsCxF57xu/RBT7BuDb958SNGgQUZYgEogDs5AE4UAcSEREk6QWUWbhoCGEENQDZVmm" - "abq6ujrkMnMIIdZ5t31vsUC3+l+JaMyxAFRVVRds0C1azsS6O273hH24cwq0UjIGipP9/t+f" - "6vZ7st9fKQpf/FqJ28+iEzoTF8Dx0RNflmlZpmV5fPR4lkdmzffwdGe8XyZ3Luh83Ll0k3vx" - "4/dWf3+B/Q2OGQwGGxsbeZ5nWfbi2efXB1sA4uozZjRKDaAwRqGmvTCNGQ3F26eHz1/d7/V6" - "eZ6fn5/f1bogCmhsonU+9AWY5nr0bjCtKS6LtrltGcQQ1MCMCiEm1MmtWUwETh6mjq1qw0Jd" - "fmPD1ADQEWPYNyD6HBs2U2Vu4bIoEBpWE0EE6ej68NaoSBdXRi/8SR/a6qE29830yKFmm2c6" - "2fTbp8FYN/0evPw0U6UuTXB39zYvLy+vr68XY2VZNv5imuB679fX10MT8Xyy1k58P4yVJEn8" - "9/93OQBFURRFsRTcWH8An5lwqISXsWUAAAAASUVORK5CYII=") -""" VS2005 unfocused docking guide window down bitmap. """ - -#---------------------------------------------------------------------- -left_focus_single = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAdCAIAAABE/PnQAAAAA3NCSVQICAjb4U/gAAACVElE" - "QVRIibWWvW8TQRDF3+7Ors8ShSsaSpo0dEgoFcINVChSBFRUkajpIKKgiPgP0pqGJiAhITqE" - "FIk2BQUVHT2VK+y7ndmhWN/5Ixcbh8tYWvtO8vvdm5mdPXPv+RmuMgjA670/RGSttdZ2q354" - "YgkAERVF4b3vHABMCIC11nsfQiCiqwJYa4noxbNvOw/6AJIk62ySJMLMwhI5MnPMnxzMzJHJ" - "E0dmicxJhEXk+uTO0fFuCME5h1yDxbh5+zEz93q+LGOv50WUmStOVZSqkjJyWXJVcRm5LKWM" - "3PNURq6iMKfIIpJw9n08Hg8Gg36/3wL4+eu3iHpykcWTS5pElCWJpMiJWaIk4RQ5RRERda4S" - "UWbhpCmllDQA0+k0pZQFVwF3bzEAZ5N3jgje+0COnPVknbUAdm5cW5/1/eGPxcuL2saoAczC" - "DQWAV0/fr1c/HxcBFNC8QGEMMu3NuyddAfIjG9QLjKJTB3NIHV050EZuoQI6+93q4P7B6TYA" - "A2gW1xlC61K0OXi492HZ6EbAnGFqEmBmhlYc7A9HutRq/wgA5plSwDT9tORgfzgCNsmv2QfQ" - "OvEwps7BooOPpwebxFsB83wazdWdl321BjOGWWejrciZ0+wBMwef76LPnx6trXFrivIfVOsl" - "P2V7FwH4MhpuCTBLX7mjckU628naTImlrdDdLDJ59OT+XDDU8SwyTX+Y2bC7hIPVA+fty6/b" - "SmwBODreHY/H0+n0P0WLomjegJYAIYTBYNAcp5cOa20IoQXgnMuvAh0GATg8scAEmHQrneMv" - "3LAo6X/e0vAAAAAASUVORK5CYII=") -""" VS2005 focused docking guide window left bitmap. """ - -#---------------------------------------------------------------------- -left_single = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAdCAIAAABE/PnQAAAAA3NCSVQICAjb4U/gAAACTklE" - "QVRIibWWPWsUURSG3/u5u8RiKxtLmzR2gqQSttFKhKBWqQL+BQXL4D9IGxsrBUGEFCIEbC0s" - "rOzshYHt3Jl7PizuzsduJhs3Ts7C3Z2BfZ95zzn33DGnp6e4zvAAdnZ2vPfWWmvtsOpFUXgA" - "3vvxeBxCuC6AtTaEEGP03g8LQE5RTo73/sXzr7sPJwCExTorLMxExMSJEhGl/MlBRJTIB0+J" - "iBORMBMz3/xz7+h4L8bonFsCunH77lMiGo1CWabRKDArEVUkVeKq4jJRWVJVUZmoLLlMNAq+" - "TFQlJpJEzCz49n0+n0+n08lk0gP4+es3swbvEnHwTlSYlViYJZEQcWJhkkSSmJnVuYpZiZhE" - "RUREI7BYLESkTVE37t8hAM5KcM57hBCid97Z4K2zFsDurRubk74/+9G9vKhtjBrAdG4oALw6" - "eLdZ/XxcBFBA8wKFMci012+fDQXIj2xQLzCKQR20kDqGcqCNXKcCuvzd6+DB4dk2AANoFtcl" - "QutS9Dl49Pj9qtFLAS3D1CTALA2tOdifnehKq/0jAGgzpYBp+mnFwf7sBLhMfsM+gNaJhzF1" - "DroOPpwdXibeC2jzaTRXty37eg2WDLPJRl+RM6fZA6YFn++iTx+fbKxxb4ryH1TrJT9lfxcB" - "+Hwy2xJgVr5yR+WKDLaTtZkSK1thuFlk8ujJ/dkxNPAsMk1/mOWwu4KD9QPnzcsv20psATg6" - "3pvP54vF4j9Fx+Nx8wa0AogxTqfT5ji9clhrY4w9AOdcfhUYMDyAoiiKohhWt4m/9Qss43IB" - "CBMAAAAASUVORK5CYII=") -""" VS2005 unfocused docking guide window left bitmap. """ - -#---------------------------------------------------------------------- -right_focus_single = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAdCAIAAABE/PnQAAAAA3NCSVQICAjb4U/gAAACWElE" - "QVRIibWWv2/TQBTHv3e+uyRbJwZWFv4AJNSRLjChSkhlYqrEzFZVDAwVC3PXsrAUISTExlKJ" - "tQMSWzcmFqaqQqT2+8VwtuMkbiBp+mzF0pPz/dzX7z373IMXp7jJCABebf8JIXjvvffrVd8/" - "9gFACGE4HMYY1w4AxgGA9z7GmFIKIdwUwHsfQth7/vXuoxEAFfWFV1ERZhYWYmJmykcOZmbi" - "EAMTsxCzirCI3BrfPzjcTCkVRYFcg27cubfDzINBLEsaDKKIMXPFWpFUlZTEZclVxSVxWUpJ" - "PIihJK5ImJVYRBSn387Pzzc2NkajUQ/g7McvEYuhIJYYCjUVMRYVUWJlFhIVVmIlERErikrE" - "mIXVVFXVEnB5eamqWXAW8Gb39uKHevbzNwARZVFirUSIlFkqEVUD8Pb71P1Lt83LZ+8BAA7O" - "AYABMAPcFfcvDXj97ikA5wxmHVVrf64LyA7Mau1so770uVjRQa1lzaKtSc2ZWAR4uHsyn2xq" - "YBnjbFp4zsRCBw6Ptz/M5GoHgLla15AfUV8F/gEwA/Bk66jPgXNwMNhkyf199F816DIaB5bx" - "yB2aO2qFLsp/+Xiy22YmczA1Cq4hLQlwsK56xwHgumLWln0pgPv8aWcmNdVF7TKujkWAL0db" - "88nagXWb0xYgVn4XWf0CymdzWQNgapJzWC7HCnPQF5M5aBhXzthqgMkcoF57Zxx6YvaDMzO3" - "148pwMHhJhFdXFwQ0XVEh8NhuwOaAqSUUkoxxvaLulp471NKPYC80ci7gXVFALB/7IExMF6j" - "bht/AXIQRaTUgkiHAAAAAElFTkSuQmCC") -""" VS2005 focused docking guide window right bitmap. """ - -#---------------------------------------------------------------------- -right_single = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAdCAIAAABE/PnQAAAAA3NCSVQICAjb4U/gAAACVElE" - "QVRIibWWv2sUQRTHvzM7M3dHmlQWtjb+AYKkTaOVCEKsrAL+CxaWwcY6bWysRAQRUtgEbC0E" - "u3RWNsJCCILZfb8sZvdu925zej/yveMWHnvvM9837+2OOz09xU0qANjZ2QkheO+999vNXpZl" - "ABBCGI/HMcabAnjvY4wppRDCdgHIJcrFCSG8eP7l7sMJABX1hVdREWYWFmJiZsqfLGZm4hAD" - "E7MQs4qwiNz6c//oeC+lVBRFA+jqzr0DZh6NYlXRaBRFjJlr1pqkrqUiriqua66Iq0oq4lEM" - "FXFNwqzEIqL4+u3i4mJ3d3cymQwAzn/8ErEYCmKJoVBTEWNRESVWZiFRYSVWEhGxoqhFjFlY" - "TVVVLQFXV1eqOitRV68Pby+v6fnP3wBElEWJtRYhUmapRVQNwJvvvftXbpuXz94BABycAwAD" - "YAa4a+5fGfDq7VMAzhnMOllt+rMpIDswa3JnG81lyMWaDppc1i7a2tCCiWWAB4dni8F2Dyxj" - "nPUTL5hY6sDh0eP3c7HGAWCuyWvIJRragX8AzAA82T8ZcuAcHAw2W/JwH/3XHnQZrQPLeOQO" - "zR21Rhflv3w4O5xGZnPQGwXXklYEOFg3e8cB4LrJbLrtKwHcp48Hc6FeF02Xcb2WAT6f7C8G" - "GwfWbU5bglj7WWTNAyh/28sWAL1JzrK8HWvMwZBmc9Ayrp2x9QCzOUCz9s44DGj+hTM3t5ur" - "Bzg63iOiy8tLItok6Xg8np6AeoCUUkopxjh9o64n731KaQCQDxr5NLAtBQBlWZZlucWkXf0F" - "imtJnvbT2psAAAAASUVORK5CYII=") -""" VS2005 unfocused docking guide window right bitmap. """ - -#---------------------------------------------------------------------- -tab_focus_single = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAdCAIAAADZ8fBYAAAAA3NCSVQICAjb4U/gAAAC10lE" - "QVRIidWWT0gUcRTH387+ZveXZgzsbmvSsmqEfzBJSYz+gUsHCYJgISPytCQKFhJdpIN0qIUO" - "ezIUaU/roQ5eEzp46ZT/DhG4haCXdSUPK+Wuzvze+02HgdFmFqMtD76Bx8yb3/v8vr/3Zn4z" - "np6ReTgCYwAwdqfEGFMURVGU/wIdfaswAGCMcc5VVf1fXIBdBgCKoqiq+nxkobn3BABIkgBA" - "hIiEJFAgorAOyxARBTKVoUAkgSiJkIhO73a/nLjGOd/nWkrPXbqLiH6/CgBEJiIaKA1BhkG6" - "QF1Hw0BdoK6TLtCvMl2gIQhRCiQiCfPLm5ubtbW1YNXXtuzadyJTZV4AkKYkMpEkkRQoEUmQ" - "JJQCpSAiMr1eg8hEJJSmlFJK0wdQLBYR0cl9laj7l6LGY5/tc2ejsrmdgeGJbG5nYHgym9uJ" - "x9KHeGuMNd7B8fSMzCfvyerq6rHHn2bmEgPDE09G+/9WaSqZmRofisfSiadnotHoozclp94K" - "oGWznNxn/e8q4LqznNwXmb4KuO6s4643lZyugOvOcj8PDyrgurOOe30r05tKZv7ALavXmszt" - "rXZZL7EjhTmuU8lpRxNSyemZuUEAmJlLOPzU+CAAuKFluO7OWpF4LO1OPsTcejOOTcRepqXR" - "tngs7Y6U4bbcqNrIF6bGh6yt0prAgm7kC6E2fSNfWF9b2d7e1jStvqGlbMSmeRsuP7zZZvp8" - "PvCoW1s/a2qq7vddD57y3b7VZfmNfGFxadUQBgqztbWps7Pdy04uLq0WSyVJnoMRgUY45NM0" - "bXZZ7OvtaA8vLOdeT85mP+4eXN35K/6W5nBjxFz5tv7+w8LWF3+oTW+IBpsavStf1+xIfTTY" - "cNbknDPGfqsD5/xCa6AuDFe791xtEJyHIhHedTGw17tnj49EeFdH8GAkEAhwzgF+7HMZY5qm" - "cc6tD6rDGGOMMUS075aN2Ho9R/R/9gsXZ7dKHM+ODQAAAABJRU5ErkJggg==") -""" VS2005 focused docking guide window center bitmap. """ - -#---------------------------------------------------------------------- -tab_single = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAdCAIAAADZ8fBYAAAAA3NCSVQICAjb4U/gAAAC1klE" - "QVRIidWVTWgTQRTHJ5vZZEyMLKSx1RbSImJbioeiCKIechLBU8CCtadAaaGIFC/iQTxowENO" - "hUohp/Tiocdce/Gk/TiIpTm0JCnmA+OaFJs2u/PerIcp27IbKsZ66Ft47P5n3m/evLc768lm" - "s+Q/GCWEBINBSqmiKIqinApU13VKCKGUMsZUVT1lrqIoqqq+frYyeP8cIUSgIIQgAgACcuAA" - "wOUlDQCAA1UpcADkAAIREPHiwa2383cYY0TWwa7AlRuPAMDvVwkhiBYAmCBMjqaJBgfDANME" - "g4NhoMHBr1KDg8kRQHBAREE+r1er1Z6enkOubbn8d0RLpV5CiLAEogUoEAUHAYAcBYLgIDgi" - "ouX1mogWAIKwhBBCWD5Cms0mADi57xKX/6Ws8dgX+97ZqFxpb3JmPlfam5x5nyvtxWPpE7yc" - "I+c7OJ5sNhsOh4PB4Kunn5aWE5Mz87MvJv4201QyszA3HY+lE88vRaPRYrHozLcDaNsoJ/fl" - "xIcOuO4oJ/dNZqwDrjvqrOebSi52wHVHud+HJx1w3VFnvb6d5ZtKZv7AbZuvXMztZbvkR+wI" - "oY7nVHLR0YRUcnFpeYoQsrSccPiFuSlCiBvahuvurFTisbQ7+ARz55txHCL2NmWOtsVjabfS" - "hjt0L1Cu1BfmpuVRKReQ0HKlHhkxypV6Ib/ZaDQ0TesfGGqr2DTv+Ph4IBDw+XzEo9Zqv0Kh" - "wOOxu10XfA8f3JS+XKmvrm2Z3ARuDQ9fGx297qXnV9e2mvv7Aj3HFQ5md8Snadru7u7Rua6q" - "6sp6aTNXzX08OL67q7f9Q4PdTP1ZKCn5Qq321R8ZMQaiXf19VuGbJ1/8IZX+aNdAnxWJRHp7" - "e7e3t4+4oVCo0Wjout5qtdx9YIwxxlqtlj3aVgmHw5qmbWxsHNWXUqppGmNM/lCd/aWUUgoA" - "9mhbhTFGKT3sm67ruq7v7Oy4cR3bb5uW079be13FAAAAAElFTkSuQmCC") -""" VS2005 unfocused docking guide window center bitmap. """ - -#---------------------------------------------------------------------- -up_focus_single = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAgCAIAAABhFeQrAAAAA3NCSVQICAjb4U/gAAACTUlE" - "QVRIic2WP28TMRjGH/85c1miqEF8CnbUgSFdukVRmZGQ+gW6Vgwd+hW60Yq1gMQMQzpHGZAg" - "C6JS+QIMmUju/L5+Ge6ulzoRTcMh5TmdZfv8/vT4Pcu26h2N8R9kAZwMfltrtdZa60agx5fa" - "ArDWpmmaJElTXGBmAWitkyRxzllrG+Zqra21bz+OAQQOzETExJ48EfniKURE5MkmljwRe6LA" - "TMz8ZPbs9GzXOWeMQZHfW33/NOufvALALESUU8g95zlnnrKM8pwyT1nGmadHic085Z6Jgidm" - "Dhh/mU6nnU6n1WrFXAA/fv7iIEECsxAH5uApELHnwBQ8Bc/MLMbkzELEFCSEEII4YD6fhxAK" - "Tsx9/tQDEIgqOzRggAQQQEEBguIFgKoNqDdfvy1yYq41emG4QKkSpDQAiNQfFQClpBoZcaK2" - "s0awEHzXVVyri1gxN7FaFuILu6qwtAyokqWWwEvcxNTTKsIK95Cqs4JJzV02vMJvHS/1cFFQ" - "UGV+K3tSzWlZq/5bOWGllIio0mzpX+pZSJXdVRmOuabcItRC+ZfKcn+pFRvN65fvNihj9Y7G" - "o9FoMplcX18f9M5lUx30zofD4WQyubm56R2Nm9oYY20B98XeRfPcAro+ei1uf/DBt9u+3c7b" - "7f7gfTPc/cOr7HE36+5k3Z28u5N1u/uHV/dG3X+gfb7YW8dgpC1YD1vBjfP7oEW6Lvf0bHc6" - "nc7n881YaZre3pjucJ1znU7n9qx+qLTWzrkVXGNMcav4d1kAx5camAGzRoiF/gCKPmudbgYP" - "HQAAAABJRU5ErkJggg==") -""" VS2005 focused docking guide window up bitmap. """ - -#---------------------------------------------------------------------- -up_single = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAgCAIAAABhFeQrAAAAA3NCSVQICAjb4U/gAAACTklE" - "QVRIic2WP4vUQBjGn/mTMUtgWS6yvb29XGGzzXXHwdWCcGBzH8BCweK+wnWyWKtot6DNge0V" - "gjYnNn4BA9vdJvO+81ok2ewmi7d3RtgnZEgm8/545skwiZrNZvgPsgCSJLHWaq211r1Asyyz" - "AKy1cRxHUdQzV2sdRZFzzlrbCxdlDmUC1to3Hy8BBA7MRMTEnjwR+fIoRUTkyUaWPBF7osBM" - "zDy+fnR2vu+cM8ZU3KV+fLo+fPUUALMQUUGh8FwUnHvKcyoKyj3lOeee7kU291R4JgqemDng" - "8ut8Ph+NRoPBoM0F8PPXbw4SJDALcWAOngIRew5MwVPwzMxiTMEsRExBQgghiAMWi0UIoclh" - "VY8fegACUVWHBgwQAQIoKEBQngBQ3wPq9bfv7XzX7o1eGS5QqgIpDQAizUMFQCmpR3bf26qc" - "NYKV4nVX7aumaavNjayWlfrSriotdQF1WKoD7nAj00yrLCvdQ+rOGiYNt2t4g9+mXprhoqCg" - "qnxre1LPqatN762asFJKRFRltvIvzSykTndTwm2uqbYItdL+5aLbX2nDRvPiyds7tC2p2WyW" - "pmmSJHEcP3/25cPFSXfQNjqeTE9fPhiPx0mSXF1d9bMxdrUD3OPJtH9uCd0evRX38Oi9Hw79" - "cFgMh4dH7/rhHpxc5PfTPN3L070i3cvT9ODk4saqmz9on6eTbQy2tAPrYSe47XxvtUi35Z6d" - "78/n88VicTdWHMfLP6Y1rnNuNBotv9W3ldbaObeBa4wp/yr+XRZAlmVZlvWCW+oP2FUt8NYb" - "g5wAAAAASUVORK5CYII=") -""" VS2005 unfocused docking guide window up bitmap. """ - -#---------------------------------------------------------------------- -down = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAgCAIAAABhFeQrAAAAA3NCSVQICAjb4U/gAAACFUlE" - "QVRIidWVPWvbUBSG3+tv8KKpnYtH/4DuJtCti2nntBm7depQWih0zT9w/AtSQsDQ0JIfkKFD" - "wRC61Iu3uBgRiKXz1eFalizb8QfxkFdCurofz3l1zhVyg8EAe1BhH9BHyC3NWkTU/XYFQEVF" - "mFlYiImZyR9ezMzEpXKJiVmIWUVYRJ7cPT/uHizhFgqF6+93Lz8fAhAxZo5ZY5I4log4ijiO" - "OSKOIomIq+VSRByTMCuxiCiufo3H4yAI8txisQjgz98bUVNTEWNRESVWZiFRYSVWEhGxYjEW" - "MWZhNVVVtQoQhuESrtfXw6e7JbTd+k1E6dv3+/3dQPeo3+8/3n22Si+OLgFLn52D4aLTun/V" - "er8XnVZ1NKqM/lX9eTNaC92IC+D87HUlDMthWA7D87NXmyzZNL+nl0ez60Nyt4Jux91Kee71" - "8Lbd6uxwzXFcr9drNpv+4f2bn59O2gDMAMC5ZJY5wOCcwZxlV7tkKr68PX338Vmj0cBev7f8" - "d0GkSG0i0576Alza7707LGqBy2JZblYOPgnm4JJA8Blay41ZnAfO3xbumWjTQOv8+oKZA2AJ" - "Y1o3wPucGXYLYVZwWQzQlJWmwIMs6Z8OJUHWcUU1aWZ9WKaGlo67xZlTbbbPbL7oq7fBTHm/" - "Jx9+bBRpnea4x92D4XA4mUx2Y9VqteVcAEEQ1Ov13bhZ5fP7IFB4v/v41f8HFQ1ap0nfm7YA" - "AAAASUVORK5CYII=") -""" VS2005 unfocused docking guide window down bitmap. """ - -#---------------------------------------------------------------------- -down_focus = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAgCAIAAABhFeQrAAAAA3NCSVQICAjb4U/gAAACaUlE" - "QVRIib2WvWsUQRjGn5mdnWxyTaqz9q+QlLnGToSgWAYDNjbpNCAGDGIvaRPbNJGQyiAEbK+w" - "sAo2qexyEhbxsvt+jMXc3u3liPfhmWeXnWVm9vc+vO/M7prVzTb+gxyA7Ye/nXPWWmvtXKBb" - "B9YBcM5lWZam6by4QNcBsNamaeq9d87NmWutdc59+NgGoKIizCwsxMTMFI8oZmZilzomZiFm" - "FWERaXbv7eyueO+TJEHM79LSkvfeWnv2qftgex2ASGDmkrUkKUspiIuCy5IL4qKQgnghdQVx" - "ScKsxCKiaH8lIu99NOwAEFGsG4Dv5xeiQYOKBBYVUWJlFhIVVmIlEZGQJKVIYBbWoKqqwQN5" - "nqdpuri42OMys6rGOG/X78yW0bXWNyLqcyyAEEIIYcYK3aB5Lazb4o5fsPc3ToFaloxBwMle" - "6+9Pjfd7stda6HR85+dCPC86Y6ETcQEcHz32eZ7meZrnx0ePJnlk0vwenm70r/PkTgWdjjuV" - "rnPPfvxaa+3NcL3GMaub7XdPtNFoZFn24tmX1/trAOLuM6aaFQwQYExAMPWNaUw1FW+eHj5/" - "dbfZbDYajY33F7e1L4gUA5uo3fd8AWbQH70bjGqEyxLq3LoMYhKCgakCIWZoLLdkMRE43Iy0" - "tWi9QOP8xoIFAyBUjF7dgOizb9iMhLmByxIAHbAGKYigUPX3hqog47hSvfCHfYRaDcNg3IzO" - "7GmydRaGi37zMujrut/9l58nijROQ9yd3ZXLy8urq6vZWFmW9f+Yhrje++XlZR2keDpZa4f+" - "H/pKkiR+/f9dDsDWgQW6QHcuxKg/ZbVtCjjzINkAAAAASUVORK5CYII=") -""" VS2005 focused docking guide window down bitmap. """ - -#---------------------------------------------------------------------- -left = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAdCAIAAABE/PnQAAAAA3NCSVQICAjb4U/gAAACMElE" - "QVRIib2WPYsTURSG3zv3ThKJRSqblDYLwU6wFMKCViIEtbKQ/QdWgrXt/oO4hZWCIEIKUfYH" - "WFgIATuraewHM3PPh8XNZCaTSWI2oydwMx/kfeY959wzMbPZDC3FaDTavOi23Wgron8n/Z8A" - "rnry/NmXk/vXAAhLZCNhYSYiJvbkiciHTwgiIk8uduSJ2BMJMzHzjd93zi9OmwEAbt5+TETd" - "bpxlvtuNmZWIcpLcc55z5inLKM8p85RlnHnqxi7zlHsmEk/MLPj6LUmS4XDYDPjx8xezxs56" - "4thZUWFWYmEWT0LEnoVJPIlnZlZrc2YlYhIVERHtAIvFYquDu7cIgI0kttY5xHHccdbZKHaR" - "jSIAJ8Pru5M+GX+vnm4rslEDmMoFBYCXT9/uVt+MbQAFNCxQGINAe/XmSVuA8MgGxQKjaNVB" - "CSmiLQe6kqtUQJfHjQ7unV0eAjCABnFdIrQoRZODBw/frRvdCygZpiABZmmo5mAynupaq/0l" - "ACgzpYBZ9dOag8l4CuyT37EPoEXiYUyRg6qD95dn+8QbAWU+jYbqlmWv12DJMLtsNBU5cFZ7" - "wJTgzS76+OHRzho3pij8QLVYwlM2dxGAT9PxgQCz9hU6KlSktZ2sqymxthXam0UmjJ7QnxVD" - "Lc8is+oPsxx2V3BQf+G8fvH5UIkDAOcXp0mSVF94V4ter5emab/frwMADAaDcOOYSNO00+mE" - "4zrgePWaiAMwn8+PF932//MPv0Uk8OspzrYAAAAASUVORK5CYII=") -""" VS2005 unfocused docking guide window left bitmap. """ - -#---------------------------------------------------------------------- -left_focus = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAdCAIAAABE/PnQAAAAA3NCSVQICAjb4U/gAAACVElE" - "QVRIibWWvW8TQRDF3+7Ors8ShSsaSpo0dEgoFcINVChSBFRUkajpIKKgiPgP0pqGJiAhITqE" - "FIk2BQUVHT2VK+y7ndmhWN/5Ixcbh8tYWvtO8vvdm5mdPXPv+RmuMgjA670/RGSttdZ2q354" - "YgkAERVF4b3vHABMCIC11nsfQiCiqwJYa4noxbNvOw/6AJIk62ySJMLMwhI5MnPMnxzMzJHJ" - "E0dmicxJhEXk+uTO0fFuCME5h1yDxbh5+zEz93q+LGOv50WUmStOVZSqkjJyWXJVcRm5LKWM" - "3PNURq6iMKfIIpJw9n08Hg8Gg36/3wL4+eu3iHpykcWTS5pElCWJpMiJWaIk4RQ5RRERda4S" - "UWbhpCmllDQA0+k0pZQFVwF3bzEAZ5N3jgje+0COnPVknbUAdm5cW5/1/eGPxcuL2saoAczC" - "DQWAV0/fr1c/HxcBFNC8QGEMMu3NuyddAfIjG9QLjKJTB3NIHV050EZuoQI6+93q4P7B6TYA" - "A2gW1xlC61K0OXi492HZ6EbAnGFqEmBmhlYc7A9HutRq/wgA5plSwDT9tORgfzgCNsmv2QfQ" - "OvEwps7BooOPpwebxFsB83wazdWdl321BjOGWWejrciZ0+wBMwef76LPnx6trXFrivIfVOsl" - "P2V7FwH4MhpuCTBLX7mjckU628naTImlrdDdLDJ59OT+XDDU8SwyTX+Y2bC7hIPVA+fty6/b" - "SmwBODreHY/H0+n0P0WLomjegJYAIYTBYNAcp5cOa20IoQXgnMuvAh0GATg8scAEmHQrneMv" - "3LAo6X/e0vAAAAAASUVORK5CYII=") -""" VS2005 focused docking guide window left bitmap. """ - -#---------------------------------------------------------------------- -right = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAdCAIAAABE/PnQAAAAA3NCSVQICAjb4U/gAAACMklE" - "QVRIibWWvY7TUBCFz83vojSuKNiShgdAol8hQYWQkJaKAuUNtqWmoeANFgoqhJAQHRLaB6BA" - "orC0HWnSUEURK2LPmRmKayeO4wTysydWbI+c+e7xzDgOo9EIK0rTdDW4m0Ij4FBK07R1fdmj" - "rh3QqZ6cPf965+ENAKbWardMTZWkUoVCUuIniiSFnW6HQqqQpkpVvfnn3uu395sBAG7fPSXZ" - "73ezTPr9rqqTzGm5aJ5rJswy5jkzYZZpJux3O5kwFyVNqKqGb9/H4/Hx8XEz4PLnL1XvdtpC" - "7Xba5qbqVFM1oZEqakoTmqiqerudqzqpNDczM+8Bs9lsrYNXw1ub7+nl+DcAVaOa0HJVESM1" - "VzVzAG9+LF2/dZFfPHsPAAgIAQAcgDsQ1ly/NeDlu6cAQnC4V7L6/GtfQHTgXuSONopdk4sd" - "HRS5vFy0l6EVE5sAD4YXq8GyBh4xwZcTr5jY6CDg0eMPtVjhAPBQ5HXEW9RUgX8A3AE8OTlv" - "chACAhy+WHJzH/1XDaqM0oFHPGKHxo7aoYviTz5eDOeRxRwsjUIoSVsCAryaveIACNVkPi/7" - "VoDw+dNpLbTURfNlrNcmwJfzk9Vg4cCrzekbEDs/i7x4AMWt3B0AsDTJUR7LscMcNGkxByVj" - "7YztBljMAYq1V8ahQfU/nNrc7q/6e9FkMplOpyKyT9Kjo6MkSQaDQZqmdQdJkiRJsk92AFdX" - "V71eLx7XAQfRYDCYH68FHOr19C8Ad0k9S0aHzwAAAABJRU5ErkJggg==") -""" VS2005 unfocused docking guide window right bitmap. """ - -#---------------------------------------------------------------------- -right_focus = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAdCAIAAABE/PnQAAAAA3NCSVQICAjb4U/gAAACWElE" - "QVRIibWWv2/TQBTHv3e+uyRbJwZWFv4AJNSRLjChSkhlYqrEzFZVDAwVC3PXsrAUISTExlKJ" - "tQMSWzcmFqaqQqT2+8VwtuMkbiBp+mzF0pPz/dzX7z373IMXp7jJCABebf8JIXjvvffrVd8/" - "9gFACGE4HMYY1w4AxgGA9z7GmFIKIdwUwHsfQth7/vXuoxEAFfWFV1ERZhYWYmJmykcOZmbi" - "EAMTsxCzirCI3BrfPzjcTCkVRYFcg27cubfDzINBLEsaDKKIMXPFWpFUlZTEZclVxSVxWUpJ" - "PIihJK5ImJVYRBSn387Pzzc2NkajUQ/g7McvEYuhIJYYCjUVMRYVUWJlFhIVVmIlERErikrE" - "mIXVVFXVEnB5eamqWXAW8Gb39uKHevbzNwARZVFirUSIlFkqEVUD8Pb71P1Lt83LZ+8BAA7O" - "AYABMAPcFfcvDXj97ikA5wxmHVVrf64LyA7Mau1so770uVjRQa1lzaKtSc2ZWAR4uHsyn2xq" - "YBnjbFp4zsRCBw6Ptz/M5GoHgLla15AfUV8F/gEwA/Bk66jPgXNwMNhkyf199F816DIaB5bx" - "yB2aO2qFLsp/+Xiy22YmczA1Cq4hLQlwsK56xwHgumLWln0pgPv8aWcmNdVF7TKujkWAL0db" - "88nagXWb0xYgVn4XWf0CymdzWQNgapJzWC7HCnPQF5M5aBhXzthqgMkcoF57Zxx6YvaDMzO3" - "148pwMHhJhFdXFwQ0XVEh8NhuwOaAqSUUkoxxvaLulp471NKPYC80ci7gXVFALB/7IExMF6j" - "bht/AXIQRaTUgkiHAAAAAElFTkSuQmCC") -""" VS2005 focused docking guide window right bitmap. """ - -#---------------------------------------------------------------------- -tab = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAdCAIAAADZ8fBYAAAAA3NCSVQICAjb4U/gAAACq0lE" - "QVRIidWWTWgTQRTHJ+3ETEugERrtF6QhFhKsIlgQRITm5LkBvdiDhBZKc5DiRXryoAEPPRUi" - "pTnVi4cee5NePAitFtFoVxSyheYDa02KCd3deW/Gw2Cy7MZaIz307TK7/Gfeb9587Nvx6LpO" - "TsA6TgJ6glyqHgcHB4/ub0ZvdRFCBApCCCIAICAHDgBcXcoAADhQLwUOgBxAIAIinju89iRz" - "gzHW5Pb09BBCImO3AcDn8xJCECUAWCAsjpaFJgfTBMsCk4NposnB56UmB4sjgOCAiIJsbJXL" - "5b6+PsYYtQev5b8hSi/tJIQIKRAloEAUHAQAchQIgoPgiIiys9NClAAIQgohhJBnCKnX6wDQ" - "jFfZ0+TA/8xpIv6+8e5cN61Qm05ltEJtOvVMK9QS8ewRpWqj2js4nsb+nbv3cnU9OZ3KzD2c" - "/NdIF9IrS4sziXg2+aA/FAr5/X5nvG1AW3o5ufOTL9rgur2c3Mcrd9rgur1Oe7wL6edtcN1e" - "7v1wtw2u2+u0z2978S6kV/7CbRmv6sxdquVSH7HTR/9tE+PLUsqp2cz27k/7PTWbkcezifHl" - "tbW1XC6n6zp1dONeWaUk4tnjTwtx5F81KEcSaQxzdT1p1xPxrFtpwY3d7C6WKkuLMypVqg4U" - "tFiqBEfNYqmi57er1WogEBgOx1oqDVoz/77e2Onu6hq7emGg/6w9imKp8ubt149a/mI0rGqV" - "8u7DlyuXRuzKp8/5yzG/yr9NrmEYm1uFba2svTq0c0eu+2LR88z7Qy905PW9vZwvOGqGQ73D" - "Q1Lf9eR3vitlONQbHpLBYHBwcJAx5rGfd6rV6v7+vmEY7nVgjDHGDMNo1LZUIpGIc34ppYFA" - "gDGmfqgOo5RSSgGgUdtSUSUANLmqWp0q/mTK82hFcX4Bm24GMv+uL+EAAAAASUVORK5CYII=") -""" VS2005 unfocused docking guide window center bitmap. """ - -#---------------------------------------------------------------------- -tab_focus = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAdCAIAAADZ8fBYAAAAA3NCSVQICAjb4U/gAAAC10lE" - "QVRIidWWT0gUcRTH387+ZveXZgzsbmvSsmqEfzBJSYz+gUsHCYJgISPytCQKFhJdpIN0qIUO" - "ezIUaU/roQ5eEzp46ZT/DhG4haCXdSUPK+Wuzvze+02HgdFmFqMtD76Bx8yb3/v8vr/3Zn4z" - "np6ReTgCYwAwdqfEGFMURVGU/wIdfaswAGCMcc5VVf1fXIBdBgCKoqiq+nxkobn3BABIkgBA" - "hIiEJFAgorAOyxARBTKVoUAkgSiJkIhO73a/nLjGOd/nWkrPXbqLiH6/CgBEJiIaKA1BhkG6" - "QF1Hw0BdoK6TLtCvMl2gIQhRCiQiCfPLm5ubtbW1YNXXtuzadyJTZV4AkKYkMpEkkRQoEUmQ" - "JJQCpSAiMr1eg8hEJJSmlFJK0wdQLBYR0cl9laj7l6LGY5/tc2ejsrmdgeGJbG5nYHgym9uJ" - "x9KHeGuMNd7B8fSMzCfvyerq6rHHn2bmEgPDE09G+/9WaSqZmRofisfSiadnotHoozclp94K" - "oGWznNxn/e8q4LqznNwXmb4KuO6s4643lZyugOvOcj8PDyrgurOOe30r05tKZv7ALavXmszt" - "rXZZL7EjhTmuU8lpRxNSyemZuUEAmJlLOPzU+CAAuKFluO7OWpF4LO1OPsTcejOOTcRepqXR" - "tngs7Y6U4bbcqNrIF6bGh6yt0prAgm7kC6E2fSNfWF9b2d7e1jStvqGlbMSmeRsuP7zZZvp8" - "PvCoW1s/a2qq7vddD57y3b7VZfmNfGFxadUQBgqztbWps7Pdy04uLq0WSyVJnoMRgUY45NM0" - "bXZZ7OvtaA8vLOdeT85mP+4eXN35K/6W5nBjxFz5tv7+w8LWF3+oTW+IBpsavStf1+xIfTTY" - "cNbknDPGfqsD5/xCa6AuDFe791xtEJyHIhHedTGw17tnj49EeFdH8GAkEAhwzgF+7HMZY5qm" - "cc6tD6rDGGOMMUS075aN2Ho9R/R/9gsXZ7dKHM+ODQAAAABJRU5ErkJggg==") -""" VS2005 focused docking guide window center bitmap. """ - -#---------------------------------------------------------------------- -up = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAgCAIAAABhFeQrAAAAA3NCSVQICAjb4U/gAAACHUlE" - "QVRIidWWP4vUQBjGn8mfcyGQYiM2W8mWsRcLm22uWw6uFpQt7WwVLPwKVsp+gFMsAwqynY2F" - "oLAgNu4HsEiz3E7mfee1yN9Lcueu7oo+IcPMZN4fz7yZzEQlSYIDyAMQx/F+ocvl0tkvsdKh" - "uF6z8eLsAwDLlpmImNiQISKTX7mIiAx5vkeGiA2RZSZmvnF++9nzO0EQ9HC/vj2fPr0PgFmI" - "KCObGc4y1oa0piwjbUhr1oau+Z42lBkmsoaY2eLjpzRN+7kAvn3/wVasWGYhtszWkCViw5bJ" - "GrKGmVlcN2MWIiYr1lpr5QjYbDb9eQBw95YBIBBVdDiAC/iAAAoKEOQ3AJRtQL38/OXS/ALw" - "XKcxXKBUAVIOAIjUDxUApaQcecV7A3DkuYJG8EVX7VpdtNXm+p4jjfjcrsotdQFlslQH3OH6" - "bj2tPCx3Dyk7S5jU3K7hHr91vNTDRUFBFfkt7Uk5p6763lsxYaWUiKjCbOFf6llImd2+DLe5" - "ruM0UlA5uazS7S/Usz88vnf2G2VLKkmSap989OD9m8WsO2gbnU7mD5/cHI/H+C/3yR24p5P5" - "/rk5dHv0VtzpyWsThiYMszCcnrzaD/d4ttDXIx0NdTTMoqGOouPZ4pdR7e+iq3fzyTYGWzrY" - "etj7zwOAOI7/yjmPHRfpFVKr1apqrNfrNE2bx+pOGgwGo9Eor1/wGwRB9QPwh/oH9oed9BPW" - "YyQlBOJt4AAAAABJRU5ErkJggg==") -""" VS2005 unfocused docking guide window up bitmap. """ -#---------------------------------------------------------------------- -up_focus = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAgCAIAAABhFeQrAAAAA3NCSVQICAjb4U/gAAACTUlE" - "QVRIic2WP28TMRjGH/85c1miqEF8CnbUgSFdukVRmZGQ+gW6Vgwd+hW60Yq1gMQMQzpHGZAg" - "C6JS+QIMmUju/L5+Ge6ulzoRTcMh5TmdZfv8/vT4Pcu26h2N8R9kAZwMfltrtdZa60agx5fa" - "ArDWpmmaJElTXGBmAWitkyRxzllrG+Zqra21bz+OAQQOzETExJ48EfniKURE5MkmljwRe6LA" - "TMz8ZPbs9GzXOWeMQZHfW33/NOufvALALESUU8g95zlnnrKM8pwyT1nGmadHic085Z6Jgidm" - "Dhh/mU6nnU6n1WrFXAA/fv7iIEECsxAH5uApELHnwBQ8Bc/MLMbkzELEFCSEEII4YD6fhxAK" - "Tsx9/tQDEIgqOzRggAQQQEEBguIFgKoNqDdfvy1yYq41emG4QKkSpDQAiNQfFQClpBoZcaK2" - "s0awEHzXVVyri1gxN7FaFuILu6qwtAyokqWWwEvcxNTTKsIK95Cqs4JJzV02vMJvHS/1cFFQ" - "UGV+K3tSzWlZq/5bOWGllIio0mzpX+pZSJXdVRmOuabcItRC+ZfKcn+pFRvN65fvNihj9Y7G" - "o9FoMplcX18f9M5lUx30zofD4WQyubm56R2Nm9oYY20B98XeRfPcAro+ei1uf/DBt9u+3c7b" - "7f7gfTPc/cOr7HE36+5k3Z28u5N1u/uHV/dG3X+gfb7YW8dgpC1YD1vBjfP7oEW6Lvf0bHc6" - "nc7n881YaZre3pjucJ1znU7n9qx+qLTWzrkVXGNMcav4d1kAx5camAGzRoiF/gCKPmudbgYP" - "HQAAAABJRU5ErkJggg==") -""" VS2005 focused docking guide window up bitmap. """ - -#---------------------------------------------------------------------- -aero_dock_pane = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAGcAAABlCAMAAABnVw3AAAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFAAAAb3WKdHqPdnyRd3+deYGge4OifISifoallZaWgIy1g463hZC5hZG6iJO8o6Sk" - "pKSkpKWlpaampqenqKmpqaqqqqurq6ysrKysra6urq+vr7CwsLGxsbKysrOzs7S0tLS0tLW1" - "tba2tre3t7i4uLm5uru7vLy8vL29vr6+iZfLjJrNjpzPjpzQkZ7PkJ/SlKHSkaHek6Pgk6Th" - "labjmKjlnqzhnqzjoa/npbPov8DAwMDAwMHBwsLCwsPDw8TExMXFxsbGycnJycrKysvLzMzM" - "zM3Nzc7Ozs/Pz9DQ0NDQ0NHR0dLS0tPT09TU1NTU1tbW1tfX0tTY19jY1tjd2NjY2dnZ2dra" - "2tvb29zc29zf3Nzc3N3d3d7e3t/fxs7szNPt0NXo0dfu1djk09js2tzk3d/k3d/m2Nzv3N/r" - "1Nr02N713OH13OL23+X43+X54ODg4eHh4eLi4+Pj4uPm4uPn4+Tk5OTk5OXl5ubm5+fn4eLo" - "4uTs5eXp5efv5+jo6Ojo6enp6urq6+vr6Onv7Ozs7O3t7e7u7u/v4Ob55Oj16Ov37e/26+/9" - "7/D28PDw8fHx8vLy8/Pz8/P09PT09fX19vb29vf38vT89ff9+Pj4+Pj5+vr6+vr7+/v8/Pz8" - "/f39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAsPpcmgAAAQB0Uk5T////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn" - "4iUAAAf+SURBVGhD7Zr7d9tEGoa9UKBZCiapneBQN3bUQlgo13DbhXBrnRQnS0LJNhDbUO7s" - "ErCtZWWZm2Rj2YHdbWQsCSQL2/yjZkaypBlpdKH14XA4vL8kkuebx3PR6HtnHBtHkfxyZoGs" - "zMtR4sfjWJRi0mJRHZGlFhej1BCNs1XyocDbpa0ooEjtSfcDOHp6apyFAMzop4XfF2f0K7Vn" - "qpyhr0bT5AwHvhpOkzPQ/TVNjt73lT6c4jzQNV/1p8npq77SBlNsj6b4Sr1Ozmtr99xpvQpm" - "6LKvquyMVezOe9Ze81uDfNbRHLUtiPaqNi8KvrqqztvlRGGbypFJRM7mMoOtnPNHDV8JisOB" - "QczyJolE4qy/MMAX6Pl23VdNGeeMBi+sE0AEzsYl92tgXqj5ipNcnNHo0oYX5OVsnfe8beab" - "VVQcelHveTij895XrJdD6SGc4b+HCIglcHTK0yAPJ4dPAYOJtUd/78b3dAdE4owYz6zzcM4Q" - "3tEop/v18ePHv+7aICJndMbdIDdn93Iwp/vh7VAf2iAy5/KuC+TmPN0J5HQ+eNDUB51Ji8ic" - "zjMhnAwpIbT7TfjXU4+ZeuqfbRNE5miZEE5qGNSe2g//s/RDLYgzSoVwiKlammMmvVTjLE0w" - "NH+UJmV37peFe3yInM3NZp0liz/azk+NM0ptt3tkdXZSxGQ1vD3EDOpiep6s9EVSeW+y5e03" - "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" - "XFekjMjBOHUAAAAASUVORK5CYII=") - -#---------------------------------------------------------------------- -aero_dock_pane_denied = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAGcAAABlCAYAAABQif3yAAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "ABh0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjM2qefiJQAAELhJREFUeF7tnfmPHNURx81v" - "hEsCIQQCxCnu60d+AH5BCCGBAAkEP/AHABKKkEhCCErCHcA4WGAIYJwYbOMrGHzgE9vYxvje" - "9drYa+99etd7zHov766PSn3avFFvu3v6dU9Pz2Q9K5Vmtt9VVd9X76zqOWtSCf4NDw9LfX39" - "pMbGxklHR0YKxuHvzj570tVXXz3ptttuO6tgjUykioeGhuTbRYukrr5eRkZG5OTJkwUj6qcd" - "2ptIOiyYLFV79khDQ0PBAPEDm/Zot2BCTZSKFy9eLGNjY6mCc+zYMaHdiaLDgsmxYOHCVIHB" - "kvij3YIJNVEqLoNTwkgWAxysp2w5Fp2iDI6FkoqVxYBz4sQJSYPM6q1sORaIoyRAOX78eCpE" - "W+VhzQIYsgAOwLC8TYvK4EQAB1DY66RBtIX1lIc1C4BQEgobHR1NhegAZXAsgDHDGgrj3CsN" - "ohMwjJYtxwIglITCjh49mgrRAc5YcGpqa2Xjxo2yZs0aWaiKR/m5aNonn0hLS4vodUEq1NTc" - "LO3t7UK7YbzBP3IgD3JZ9LXSzLJj505Zvny57Nu3T7p7eqS/v9/qzGzBggVO3h4tkwb19fU5" - "wyft2lxPGN6QC/mQszQR8OGqqqpKlv3wg7S2tloJ61UISjpy5IgcPnw4FaIDMITaguPlFzmR" - "F7lLGqRdu3bJ1q1bnTHcphf65UFJvb29cujQoVSoq6tLuHmNCw4yIC9yI39JAlRRUSH7q6tj" - "g5I9RlFw6M1tbW2pUEdHh3D7mg84hnfkRw8lBRC3iNu3b88bGGenruDQm5t1oo5KKDpqGSx0" - "cHAwEXDgHz2U1K0qEyMbx7hDmbtcXHDYSDa3tDsbyigAsVJLEhz0gD5KwnpYrcSd/IPmnKiW" - "MzZ2TOoaWuWPr051PvnfFqCkwUEm9FESq7jlK1YkYjHuOScKOAMDA9LRmZG/vj07S/zPcxuA" - "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" - "VvwtWIicAAAAAElFTkSuQmCC") - -#---------------------------------------------------------------------- -aero_dock_pane_bottom = PyEmbeddedImage( - "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") - -#---------------------------------------------------------------------- -aero_dock_pane_center = PyEmbeddedImage( - "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" - "AAAASUVORK5CYII=") - -#---------------------------------------------------------------------- -aero_dock_pane_left = PyEmbeddedImage( - "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") - -#---------------------------------------------------------------------- -aero_dock_pane_right = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAGcAAABlCAYAAABQif3yAAAALHRFWHRDcmVhdGlvbiBUaW1l" - "AG1lciAyNSBtYXIgMjAwOSAxNzoyMTozMiArMDEwMExUiZ4AAAAHdElNRQfZAxkQJBxqm5sb" - "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAD6VJREFUeNrtXVlsVNcZ" - "/mc89oztGWyDd8xgjDEGgx02BSVEkKRK8kCWkkWpIjVKX6pIbdVK6UP7UFWV2r60ah8aRbw0" - "SdUsDSFEJAW60SQCSlIMMXYwqwEb23gBY7zNfnu+O3PG1zN3PHebe2+V+dBhPHfuPcv/nfOf" - "/z/bdZANMTs7K/T19dG1a9doLhDIWTrFHg81NjbSkiVLnvT7/QetLrftMTMzI3xw4IBwpa9P" - "CAQCQiwWy1lA/EgH6fX39z9vddlT4bA6A6k4290t+LxeWrlypWlpXr9+naamp6l940ZbycNp" - "dQZSce3qVVq+fLmpaTY0NIjp2g22IycYCpHL5TI1TaSHdO0G25GTxzzy5DAIgmB1FmSRJ8fG" - "MFe5q4BZtdnhsJWBtgC2JAfEmKlq7ErQ154cpFNQUGB1kWXxtScHrcauBoEtyQHsKjAzYUty" - "zO5z7FoR8uTYGDkn59Lly8LN4WEKBoN0584dyiby0dFRMUSjUVME4HA6qdDlEtPc9/77i2YP" - "Nl15eTm53W6qraujNc3NOTXzckLO3r17W7ds3do7xgocDoVo3fr1VFRYSF6vN+uz+/fvp7Ky" - "MgqHw7ksdxKw1DweD1VXVdHTe/ZkvX96elrM28jICB0+fFioqq6mrVu25IQkw8k5e/asMHDj" - "BtXW1NDmTZs0xQGVZlbL4ekpBa9gFRUV1NraSkNDQ/TXQ4eEFQ0N1N7ebihJhpJz+vRpYW5u" - "jh595BFyOrWPDIEY09SaTlO6vr6eamtrqbOzUyz/5s2bDSPIsLG1M2fOCMUlJbRt2zZdxAAQ" - "ViwWMyWgEug1PlBelBvlhxyMkqkh5GD2MhKJ0NqWFkMyxYWmNqD/UPuMkZYhyg85QB5GxGcI" - "OYOsj7nnnnsMKaBWYPY0FI6pnkU12mSHHCAPI6CbnFOdncLGjRstHZ+qra2ja/3D9Ie9+8RP" - "fLcKkAPkAbnojUs3OWNjY2KnaBVgNd2emKY33/mUPCWV4ie+47pVgDwgF73QRc758+eF1U1N" - "lgkBBIyMB+iN9zqpxFeTDPiO61YSBLlAPnri0EXOTeaIVTHnzQr4fD4aHInQx58Mk8dbnRZw" - "Hb/jPitQyeSCUQc90OXnTE9NUXFxsekFLy0tpZGJIursnSJP8bKM93X2BqljrZfqK72iZ29q" - "HplZfffuXV1x6CIHy4kKCwtNLTQQCATIX1dOyyo8We8tZrdM3p40PY+Qi97lVrrIgT9i9BRv" - "kdst+h9w7BC/HPD7xO2biizEydnMow3IO/eNkK7RyJR/pbDdlMGqxkYaYbq6vq5OdOgW80OU" - "FB4EZFqkyAc9BwcHqdHE5b9KYTtyNmzYQAc+/FAcxseYVVFRUc7SwugyBi57z5+nbz71lNVF" - "T4Mh5BjtZT/15JMYAqFjx45RIBjMWeE9TJWt8PvF9Iwsg1Gq3nYth6OdedkIX2fkV3zmAEa1" - "Qt0tJz/fnw6j1Foylp6eHkHtNj94wGpHCGAdrWR6fv369SaJSj+Onfyc/nwuSsMzua2E9V4n" - "fbvNRZvaN4ozriI52HbX0dFBy+vrVVlHGNwDOWpaTog5ZoPMQurq6qInHn887XdYUN09PWLc" - "MHVzvVQWZvaypUtFK1EOT7z6BQmt99HO7QKtLnEQxkM8LEuQErwslyPeN6jpH+AAwPOKMLHB" - "TQ2xzzn2eXVOoH+cdJCz9wS9+52N5NCzzQ8CrKys1CQUbPXD8EZbW9uC68eOHxfjbF69WveM" - "qhKgMly6dEn8O5Wgz06cpN9O3ke/3CkQ6nGBM0GGGBzxz8S9aqqQwAP7LyqALIEisfi1MIv0" - "R0cF+nHF5+S0YpsfIG71YwRJgfEvrEFoYyoPy48wBJLrUFJSQmvWrKGx8fG0PL55LkYNDzio" - "KBav7blGlCXiYv+t2+Wg17vD5LRimx+ANEPMh+EGBQ9WrPdHC40mRiOkYZypmRqmw8w0d5BW" - "tdshpp03pW0My5xQsXbSQp/AaoNczrDBlZjkE8GR8rtDQ96FDAGIJf7QRY4eH2cxK0xUbzbZ" - "0ISxVfQFUZadAvQ9zrgRIPZBQtw4EBwaDAIhToKQSAN/w4JzSMSZJEeLkAWNzy2IQ/q8tBVZ" - "4NjKpRkTJMERF17SOEg0GbXVSBDmW0osEZ/4mYiY58LFM6Vl7kFgzyhtPeh0k50+axVyLYPH" - "o3ceRA2yrfiMst/CLDhZltysyZQwW3oO9q+QUGgJwtQQlFSTQjz+aMKkht/DpJQkySkVilqo" - "Ieb6UIgCIWfW54xojWrLwNOVFWRC5cC/qWY6bHxgjsoLHfO1XVjYHykJgpAeeFwRYV6BJMnR" - "FBQ8C2LOX5mk46fv0u270QUCSU1b7poZIVO6QDRCooNYVOCgm7eidPDoLbp4bowqipwLCNIT" - "opLACQR09Tmc4kzPulyFNDo+RZ9+PkTOwop0MmSEozkvOrBYuhBYKBYnCMM1k9MR2ndokL5f" - "WUgrl1dQ/4wQ78hVpCdtcYgXrQWf4Vg8njS1piUstkDc4XBS/41ReuO9/1IoMt+HKFGFMUlf" - "ZnbrSYUoPCbJmGSMIBiK0s9/c4R6Lw5QvTu+3jqmMuAf+hve+vB3RIjFW0+qWtOyQp8/l1pQ" - "eP+3bt2h19/657xpQly/ZlaL3BAwc5dBagtKU2tCvEZHZWyUn/3qLRoaHqOlzFJQo8aSVlqK" - "SuNGgWBUy0kVJKyfC5eu0u9efVtiGQvEu13pc6lpW9FyMuWFXwtHE2otQ+N6+Ye/pt4vvyQP" - "65OiMsKWC0lVxtVZQnWGovHAK4LY52AYP6RhjRUGKWdmZtLUQqO/nn7w8vP02h//llZTseaM" - "L1Xi3zmQB8SFkWKzzGkYLEgP6QZk5rL+NCbQskCYCdFFHc70nuW13/+EXJW1dHFS+WYvTlKY" - "NZ0gK2aAfZlhhsdkSCDGMX3E2oyfk6N1J5l0j4sUU1NTVLmsgl564Rv0l4PdC36TqsRU8BqL" - "OM0iJ1v/Fw2z8jDBBZCdlJHIX/z0Baqvq6JPRqOqhm+4+gqLxMTDLEtjJhonJCZtOVr3YEYT" - "m5zkBIm5Hn9DLb343DY68PeBpGWH+7EeTaoSOfjffPOUGZDr8xaAkYNaHYxS0rZ1FxXQK688" - "Rn5mrX08EBGvOVWYa5wcUZXF4nGLJLGoMGcUjkrI0SqMWIaWwzE0NCjujN55bx2d7g3Hna2U" - "liNrvpq4J1QK2XIwSc2wjiEUi48IlHld9PDDTTTlLaN3+kLkYqzwCTil4EYG4kQfE2QXoNow" - "8uBMmNRAsuVoGltbrMYlMDExQfVVS2g2WEzeYgcFZ8ML/By5lmPmopFUQyQNCR9nbE6g8ion" - "3dvhI1ruo5OjEXE4xykda1OITA4o0gHRUam1lmtghrO5IcaIGU2eL5BphMFKLJaXG7Mxevtm" - "hIpW+ah7wpxWbcrSKKioycnJjM8n/45fMKXg2fIih5tzMTo2IhDTbFTsyv2UhuUrPjNNGVie" - "FxvAEnKSQsgwtmYJbKBWU2F5y0mFGvHweSE9s6ZYGxdmpr0dTyt08UKaDdk1BCpqLt/4hEWQ" - "8Ju0IsL6Q6yh8y1ZIp++09wF5UiLVxOXmxUu204yIyHdTSa3ZVFpNUE8WNt2/MSJzH0Vu4eX" - "ySlXAROzoGWMmCaZXeEVRTEqZY/7ipymEORmTcVX6KQpVpxK5na4GletEo+nwt55PsakFBh9" - "RlBDKoiBULFpqSrDalElqgqVCWe44fOhBx9MyzevBD09PeLCQb/fn/Y88v6vo0eprk7+UIk9" - "K2bos54CanggSm7mlPiYheZlAVPVHla9mRypEOlocEL58I2HWeWIy+2Kr4/zMVJ8/yZxzbQL" - "b77Y/8EHgkvDTjJsbFrCap0abx4qaGh4mHp7e2nHjh0LfsMid+h/CC5bPnAPVowi32iBcn0G" - "8jc+Pk7bt2+X3fUNB3l2dlasLHLYtqmD2vpO0rtfbadV9wq0tsRB5YwJH9YSMDLcWDPtAEHq" - "VJ9IDPsMYo00I2iafWKSuI9d6P6CqHXyJG3t2DCvRbq6uoT+gQHZkdlMwC6DivJycYxNKXAo" - "3jLWYlrWrJH9/caNG+L5Bi4FHbSHCRyEYhxPrvUijkJGMkbP5eAtLaXqmpqMLRhAi/zPmW46" - "NFhC48HcKrfaUic93+qkbe1t4omIuiwBHLu4a+fOjIXXg5CCkwqLLNhmrwRozdAoh48coWef" - "eUazjG1nSnPYVfBmIr9W2sawbcu5fPmyuC1DywytUsDoQH/T3NxsdXFlYUtysIEKh8pt2bIl" - "p+cQ8F12SG/H/fdbXew02I4c7DLDqbpmvFAPxOPEEDioSHdNBgvSKtiuz4EqM/twPezsk9vZ" - "ZjV0tRy+ON3IN2lglELJSVQB5rDNBLKnWcw8xRLP4tYs0jPykHEuD717WnWR49Y56KgH/cMB" - "6vxqiqZmMo9O+EoLqH2tl9qaS0zLF4jhy63cOvtLXeR4fT7RAYWXbvaCjJbGYqJYiI58NpDx" - "nl1bV1BLU3ZijJ7HATlYzwdHVA90kYMj8e9MTtLy0lLDyVEisJamMnIVRGjfx11pvz27u4Oa" - "VpYpisfIKRM+oHrr9m2qrq7WF5eeh1tbWx14wwcyY2QB1SylbVq5jF56bgvNTd1MBnzHdSXL" - "eo0EP9sNViDOcIN89MSn21qrqa2l0bExMUNGEaRGaCBgaYWXXvzWLgrM3hI/8V3pNIZRBEkn" - "/+A71TCtohe6ycHrSa5cuSJmzMjjUNQsRkeSjf46+t53nxU/8d2oLSBqyOFTFxcvXDDktS2G" - "OKE4aAjzM+vWrRO9br0vb8i2UFEOuL+2plK19ajXDeATgyAGhtGXXV1pE3taYYgTivfG4Dhh" - "nDqFiSuj+yCl0LpqVSu4KkOZMdt66fJl8chio96jY9gIAd4bA0vl3LlzYg3iJOGa2hUyZm2c" - "0rJmgpeF9y+YYUVZ0WKwlsHI9+cYOraGjOHNUxhIbGlpEU1tqBl+yq3S02zNbnU8zWxnAHEH" - "E8Tw6XGshbjA+hioMlu/eQrgGTx16pRw6eJFcV0CzmRDQZQ4Zby1mQUucD57me1e7D2C440p" - "+uHhYbF8u3fvzkltynkVlb7tcOLOnaz3o9CPPfqo6S/UO/jRR4qcxor/97cdSqG2AFiXgMPw" - "gjk8slgKkIPOHMTome/PBWw3nwOYubMt/25qldBqSWlNK0+OCmhxQrUiT45KWLXt0G6w3TR1" - "HvPIk2Nj5MmxMfLk2Bh5cmwMW5Jjl5NxrYbtyJFug8w1pFsg9S5jygVs5+fo2QapFgteqNfY" - "aHXR02BL/YFtkOtaW015oR520WGC8Ok9e2wnC9tliEPLNki1QKvxr1hBHR0dtpTD/wDriTgZ" - "SBhbDwAAAABJRU5ErkJggg==") - -#---------------------------------------------------------------------- -aero_dock_pane_top = PyEmbeddedImage( - "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") - -#---------------------------------------------------------------------- -aero_down = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB8AAAAgCAYAAADqgqNBAAAALHRFWHRDcmVhdGlvbiBUaW1l" - "AG1lciAyNSBtYXIgMjAwOSAxNzo1MTo0MyArMDEwMMndnrAAAAAHdElNRQfZAxkQNALaVrQp" - "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAAhJJREFUeNrtl01v2kAQ" - "ht81FgECjUQUyeKjBrfi0EOJktxzg0uOSaWe0lNP/Wk99lBy7A+oSiO1ORE+BChSTjGfBuPs" - "rATCNSkmyHtpX2ll2czOs+OdWTMMXIPBwKnVaqjX6xiORghK0UgEuVwOhmEgFosx1u/3ncrV" - "FYrFItKpFMLhcGBwy7LQ7nRQrVZRLpXAfl5fO4l4HLquBwb9U41GA2avB6V+e4t0Oi0NTMpk" - "MiCuOuavQlXVtRNGFs+NobPWLhphiO783YZ4gut3tc3OEN9/9fDQt5+0ebEbwttCHG9eR335" - "9A0v5LhDx0LlW+tJm6OTLAr59WDHcTaDiwXk96AqNj5/+eH57fzsEIa+t4k7KMur8TMMPYkP" - "744xMO8Wg+7puZ/5HrhfMI3ZbIb9ZByX708xHt6LK93Tc78+XHu+alXrlNdT+PTxgpepBtu2" - "fc8nu1AotB18Op1C0w7EdRMxxrwJtyn8uXOW9ezIt5ErctlwT+SUrTKkKIo7cvrUTSYTKXDK" - "dEo6V+RULrLkipxeuSy4p9QILmvP5yfhAi4z4VbCZZXaMkfZws/W+g//R+Hz4046fIe3R3S6" - "0YEftChIOtuJR1zRLvHiQ4r3afRxCbLeCRzhzWK73Rb/gNRXvGP8WqmILkLTtEAbRQqu0+3i" - "980NyuUyxGabpila5GarhVGALTJF/TKbFS1yIpFgj6VqglrJraorAAAAAElFTkSuQmCC") - -#---------------------------------------------------------------------- -aero_down_focus = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB8AAAAgCAYAAADqgqNBAAAALHRFWHRDcmVhdGlvbiBUaW1l" - "AG1lciAyNSBtYXIgMjAwOSAxNzo1NDo1OSArMDEwMEcuCiQAAAAHdElNRQfZAxkQNxVyqGIt" - "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAABENJREFUeNrtV02IHEUU" - "/qq6529nFnezLtGNEEk0O5NZI4GoQaLxoCJ4NgjBgAe9K/5c9SToQbx6UaJgQLyJXgIRDUkk" - "t+iS1YDgwSWHMGOyO7Mz0z/l97qqZ3vGnd0ZYb1oDY9XXT39vve+eu9VtwJHo9H4+ufrK8+f" - "XQ6xuh5jt8ZCReNM3Ue9uvjl3NzcKUXgH06fvX7C1B7H08cNDpQUSvxjXlGofWqPWo8JYCiR" - "CCchdZe6Q71OudE2uPy9gv7tEj57qXpeXbh4yXzQfAzvnTQoGwWPKL4WMM4JrERgZdwhDgh/" - "sRExCMURLhjOu1rjrW8M3tz3I/QnPwW4/4RCPrIPjRpaWad2Er2Nl+JELoox+xwguP6tDYOD" - "RYW4sz1wnjzeaW3nnh2VKQXDvYpH/FUYWShpLBPXH4fGPCNaudHC+ctNNG6HI/+35y4fTx6b" - "wZGlaYTRznb91BszQmR0aKhWrUDo+fSrX0YaO/XsImqHp9HK+GcyOq2jOM6CG0kGByhabmo7" - "ly1kHqJNg/X6PF7xAnz48Xd/A37t1adwqDqP9cAM2jIZ+0NbkVSQgAUuI6VE0lLpZ2xs9Z2e" - "waHFBbz7xjNYa/7eF7mWdbkfG/QlGpqL/SDeZEDbyPlQbKx2YuhRMocTt367F+PevTN45+0X" - "0F5bTbRcy3r/WQzZyNplJIO0x7YMPIp2ks2XpM4zJXQr9FCvHcBH77+OBw7ux83OYJmmVKcM" - "JlE7SbekD57SnaUs21iGu5s8vLoBzNy3P9HDI7vnm83GYqg0w7MJF2QiV8YhO52oLep2Y0Q5" - "DQA6VgO332IvNNnIaSSIbB/3XaR9qmN3PUF/jV3kUZrA8WbCqeFSs3tiqEXY043tUHG6O2rr" - "yEcNM1QtiV1hwLW9NNtt5KH1Ktl7bR9Mki6lHtv37K0iz+5zWr6h29KByM81DPaS9z0Fhemc" - "QpnHWdGzbTWn7enmTQCenmI9onepW1xYC4Amy1Hx9wVtnUzBO4x8nTcKSicLXpKuPCA8m7GT" - "gKeUC3iX4NKaNwjeZka3erbWgyDajLwb2PY5xasC1xl8QnNKtSRiPCG4ZHaPtrpOpDIEQ4KJ" - "ogztkuotulrmYpEbnReqo836NhOCJ22UKD2JPpLorbRDY50bAA8t9V1Kj1T3tHt9cm8xySEz" - "IXjax/sMOIxkDIDDlQV2Pl7HAd9KUtvZMe574a6M/8H/q+D63/Mii+Pfzc+jMmugwka+2w4U" - "WdjlnMY054Lrv/xQDheuedj3RIQSi7/C7lLJASV2mIJnDxb/H/T2gC2xyN5e4PM5HpF5vqnM" - "c71M0LlvFc4c9eEfXTq8Ur96pfr58nHUHjV4cEpjhqAVgvHDgocNHYDteOOCy6nGMwT8KEGL" - "rP5JadCjX/mu98dFoBpfwbGHl2z3bDab5uq1ZZxbiXGztXufyPeUNV6sajxypI7Z2Vn1F7X+" - "m7ZM/KBNAAAAAElFTkSuQmCC") - -#---------------------------------------------------------------------- -aero_down_focus_single = aero_down_focus - -#---------------------------------------------------------------------- -aero_down_single = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB8AAAAgCAYAAADqgqNBAAAALHRFWHRDcmVhdGlvbiBUaW1l" - "AG1lciAyNSBtYXIgMjAwOSAxNzo1MTo0MyArMDEwMMndnrAAAAAHdElNRQfZAxkQNALaVrQp" - "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAAhJJREFUeNrtl01v2kAQ" - "ht81FgECjUQUyeKjBrfi0EOJktxzg0uOSaWe0lNP/Wk99lBy7A+oSiO1ORE+BChSTjGfBuPs" - "rATCNSkmyHtpX2ll2czOs+OdWTMMXIPBwKnVaqjX6xiORghK0UgEuVwOhmEgFosx1u/3ncrV" - "FYrFItKpFMLhcGBwy7LQ7nRQrVZRLpXAfl5fO4l4HLquBwb9U41GA2avB6V+e4t0Oi0NTMpk" - "MiCuOuavQlXVtRNGFs+NobPWLhphiO783YZ4gut3tc3OEN9/9fDQt5+0ebEbwttCHG9eR335" - "9A0v5LhDx0LlW+tJm6OTLAr59WDHcTaDiwXk96AqNj5/+eH57fzsEIa+t4k7KMur8TMMPYkP" - "744xMO8Wg+7puZ/5HrhfMI3ZbIb9ZByX708xHt6LK93Tc78+XHu+alXrlNdT+PTxgpepBtu2" - "fc8nu1AotB18Op1C0w7EdRMxxrwJtyn8uXOW9ezIt5ErctlwT+SUrTKkKIo7cvrUTSYTKXDK" - "dEo6V+RULrLkipxeuSy4p9QILmvP5yfhAi4z4VbCZZXaMkfZws/W+g//R+Hz4046fIe3R3S6" - "0YEftChIOtuJR1zRLvHiQ4r3afRxCbLeCRzhzWK73Rb/gNRXvGP8WqmILkLTtEAbRQqu0+3i" - "980NyuUyxGabpila5GarhVGALTJF/TKbFS1yIpFgj6VqglrJraorAAAAAElFTkSuQmCC") - -#---------------------------------------------------------------------- -aero_left = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAYAAACGVs+MAAAALHRFWHRDcmVhdGlvbiBUaW1l" - "AG1lciAyNSBtYXIgMjAwOSAxNzo0NDo0MCArMDEwMN+SkKkAAAAHdElNRQfZAxkQMBKjjWFJ" - "AAAACXBIWXMAAAsRAAALEQF/ZF+RAAAABGdBTUEAALGPC/xhBQAAAkJJREFUeNrtV02P0lAU" - "PS2lUEIlkxlHpCAEZ89Ol27M8A/czMK4duO/caeJiSZu3SgTN25M3DhBFkMmDhQJEK0apnwM" - "0wK1t+Z1YOqyr2w8yWuT95qcc9+97/UeAS6m06nTarWg6zrOZzPwhJJMolQqoVwuI5VKCcJk" - "MnFqh4eoVCrQcjnIssxVgGVZ6PX7qNfrqO7vQ/jSaDhqOo1isciV+Co6nQ5G4zFEvd2GpmmR" - "khPy+TyIW7xwt0SSpMgFECdxi5EzX8HGBDiOs1kBDH7ymaKoIAjCpQAiXy6XXAlFUfR4aBA5" - "EyBGET2R630LM+tvxpmQNQG8BpE3T8/w8cjEb3MREMe1BuLxOL4bY3z4NIAob/nzq1x+DYQt" - "IBaLodM18PpNA0p6Fwn5kpzqjXZmTUCYRUiR//x1hucv3yOl3lhbY4Gyd+g7QJGffG3jxau3" - "SCg7gXUWLH3nC6BfJI2wUC4V8OTxAZ4+qwXWiGexWPgp8J40EeYwTRM72xk8OrgfEMC+CRzD" - "sEUYhoFi4ToePriDuBTzBdD20zqrOWl1Mmz0ej1kMhncu3sTn5u2XwORHEOG4XAIbfcazm0F" - "aUXExdQO3oS8MXZbrz1t6ZL/gG3ba2uRtEKUYirMf2Hj/cB/AZ4A1hxsREDCdUKrVyNvULD0" - "HyBO4vackXsokXNtGR0R3t0RkSddf0iX1Hw+h3TbNYnvajXPKGSzWe7ekILsDwY4bjZRrVbh" - "JX80Gnnu+Fu3ixlnd0zR3yoUPHesqqrwB18A5ik1mQXQAAAAAElFTkSuQmCC") - -#---------------------------------------------------------------------- -aero_left_focus = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAYAAACGVs+MAAAALHRFWHRDcmVhdGlvbiBUaW1l" - "AG1lciAyNSBtYXIgMjAwOSAxNzo0NjozNCArMDEwMCXtbZ4AAAAHdElNRQfZAxkQLw561jOY" - "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAABAVJREFUeNrtV02IHEUY" - "fVXTO70/M+yOExNd4oIRkgljDIiyQZR4FD0rQlDw6E1RDwkoIqiHXLzlKK4Iwb2peFDJHgxx" - "dS+LcTMhhw0qJkvG7Jjsz8xOd1f5qqu6p9eNMB2Y9WLBm6+nf+p79X2vvqoSYFtdXf3ql8bl" - "52aWQlxbVxhkmyxJvFz3UK8dmq1Wqy8IOv/+xEzjSV17AsePaTw0KjDCF4cFUKQtEB6vJSz6" - "bWYYERFqoEvbpW3TXm1rfDsvIBsX8OlLte/E3PkL+vTqNN4/rlGCQEE6hzGEta5TkYOATsCf" - "SBtCGqGy9wJ2+vo5jbcqP0J+fDHA/qcEisqyHnSL6MTjz+GnBYxv+SdDso/x1rvgPBudvb6A" - "8Z0nrQNpXsJIZaxBNt/a/c8bJf0vME3pDAGlbG4ieikYLUgrPOV6MULU4i5EqK0j7XyYazMz" - "RGYkXsImhbAvpIJ0Q8/jHM55MmLl+out6hFMCUR8OyCksiMX0kYj7gV26CInCZVxbvofKQhs" - "0Jq6IPkkISKTFKQRcB9plWGtt+ujH8QRcBgfEmj+3sYe1hVTY0J3PyUQhYiLhHkQa8Hlalvo" - "7hITRYErl5r44txNrNyMUGQkEpKZFLBUKiu2AjKhduKLLXKKkB9MjQn89kcLs18vo+Dvi++b" - "gQZRTwtecjMk3UiaHAlb97VlGidfO2306dy8N+krNK5cx+kz51GamMKo77TB3Ea6Nw1lEoFA" - "WSKR00SaBpU/Dff4EteuN/HOB5/dUZyh01hKwITEpMDAEAl0EpV/6KIPDDPHlxYX8eprH94x" - "Oqb/bmT7TFMw09SodgJUWJ/HKZoSpWqmjU9BDMWrI1dJt0L20w7Wj+LMRyfxxtuf7Hi2fFvh" - "V+45vuTYp9IUBMAaZ8IGmW0SbaKjLLZULzr9ovFXhMn778V7p07sIGD62wyxvQ6ABDZC+6BD" - "bEUWXYdA5UOH33yzAhw++ADeffMZ+MVCSsD013YzIUMgIgHFkWt+TFBJW6TYpQ2IxOaB6efz" - "qwHWS+N4/tkDGC95lgCfbdJXkNUA1E7RKbcoZStknqacKBeaIer7q5jurGGC+8Em05Msfr0I" - "DLgttRRGDpQxe4Ob3s3tQ/F2g4BJ7Q90fivYuaP4z3dE/xOQye9uMjG+ksrg7RkRGKMwy0W5" - "KyR8yr7M+r5GPRrf3itHhjC3WODhJILPyVv27FowSgy7tWAo51pgmqkBoVtlhyPEffmePX+U" - "6bg8h/iM6D16pH6jvjC/9+zSMTw4rXGIZ8MJeivTMS/hmzOiMCTypSl2Trulbeldp71NIsu8" - "cfEnoHZrHo8dfdjuMVqtll74eQlnLyusbAz2gHbfmMSLNYnHH6mjUqmIvwGdqbciWIcx6wAA" - "AABJRU5ErkJggg==") - -#---------------------------------------------------------------------- -aero_left_focus_single = aero_left_focus - -#---------------------------------------------------------------------- -aero_left_single = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAYAAACGVs+MAAAALHRFWHRDcmVhdGlvbiBUaW1l" - "AG1lciAyNSBtYXIgMjAwOSAxNzo0NDo0MCArMDEwMN+SkKkAAAAHdElNRQfZAxkQMBKjjWFJ" - "AAAACXBIWXMAAAsRAAALEQF/ZF+RAAAABGdBTUEAALGPC/xhBQAAAkJJREFUeNrtV02P0lAU" - "PS2lUEIlkxlHpCAEZ89Ol27M8A/czMK4duO/caeJiSZu3SgTN25M3DhBFkMmDhQJEK0apnwM" - "0wK1t+Z1YOqyr2w8yWuT95qcc9+97/UeAS6m06nTarWg6zrOZzPwhJJMolQqoVwuI5VKCcJk" - "MnFqh4eoVCrQcjnIssxVgGVZ6PX7qNfrqO7vQ/jSaDhqOo1isciV+Co6nQ5G4zFEvd2GpmmR" - "khPy+TyIW7xwt0SSpMgFECdxi5EzX8HGBDiOs1kBDH7ymaKoIAjCpQAiXy6XXAlFUfR4aBA5" - "EyBGET2R630LM+tvxpmQNQG8BpE3T8/w8cjEb3MREMe1BuLxOL4bY3z4NIAob/nzq1x+DYQt" - "IBaLodM18PpNA0p6Fwn5kpzqjXZmTUCYRUiR//x1hucv3yOl3lhbY4Gyd+g7QJGffG3jxau3" - "SCg7gXUWLH3nC6BfJI2wUC4V8OTxAZ4+qwXWiGexWPgp8J40EeYwTRM72xk8OrgfEMC+CRzD" - "sEUYhoFi4ToePriDuBTzBdD20zqrOWl1Mmz0ej1kMhncu3sTn5u2XwORHEOG4XAIbfcazm0F" - "aUXExdQO3oS8MXZbrz1t6ZL/gG3ba2uRtEKUYirMf2Hj/cB/AZ4A1hxsREDCdUKrVyNvULD0" - "HyBO4vackXsokXNtGR0R3t0RkSddf0iX1Hw+h3TbNYnvajXPKGSzWe7ekILsDwY4bjZRrVbh" - "JX80Gnnu+Fu3ixlnd0zR3yoUPHesqqrwB18A5ik1mQXQAAAAAElFTkSuQmCC") - -#---------------------------------------------------------------------- -aero_right = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAYAAACGVs+MAAAALHRFWHRDcmVhdGlvbiBUaW1l" - "AG1lciAyNSBtYXIgMjAwOSAxNzo0NToxOCArMDEwMEtfu5QAAAAHdElNRQfZAxkQLyM/CW/t" - "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAAkpJREFUeNrtVz2PEkEY" - "fnbZQ+AgGD+R5YSAxVkRLfwF5vgH11xlbeNPsbE2Ftf4C+RiY2OijeGu8GIusEjgiJ4Ej689" - "YHedd8zgsBgt3Fkan+TNZnY3eZ55v2ZeDQzj8dir1+uwLAsT24ZKxGMxFAoFFItFJBIJTRuN" - "Rl714ADlchlmNotoNKpUwHQ6RbvTQa1WQ2VnB9rh0ZGXSiaRz+eVEvvRbDYxGA6hW40GTNMM" - "lZyQy+VA3PoFc4lhGKELIE7i1kNn9mFtAjzPW68AgUXwhaKwoGnaLwFE7rru4gOZWKsiFwJ0" - "/+7tqQ6rw7JTVxcd4hOchvyCVPXOHbz9cA57soHtUhqO4yjxgMBSDogPo4mDN+/OcCVt4Ob1" - "JGazmTJvLEIgu4Uwmzt48fI9mq2vPBzyP/9qlF9LZeh/KeP5/mucffuOSCTC/wnCBOcfPSDj" - "6bN9fDppBOYJucJ4DtARSfbzKI6vCHjyeA+X05sYstMrCJA3RZVxAZTpwvx4tPcQ166m0ev1" - "Ak2+lTIkctk1G0YEu7sPeBV0u91AyQmCyxALEiBUbcYjuH/vFnsC7XY7cHK5yS01Iqr3ZELH" - "3VIc5g0X/X4/cHKx4d+ehiTgYvwFd0w3sIT7G1auQiRCZefzY+33gf8CuAD5eAxdwCXWfqkH" - "qLyAyKDNUismTuLmkxErSmTZWEbZr/puSOQxNh9Sg5vP5zBKbEh8Va3yQSGTySifDWmTndNT" - "fDw+RqVSAQ/+YDDg0/HnVgu24umYdn97a4tPx6lUSvsBjEDOU65zEi4AAAAASUVORK5CYII=") - -#---------------------------------------------------------------------- -aero_right_focus = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAYAAACGVs+MAAAALHRFWHRDcmVhdGlvbiBUaW1l" - "AG1lciAyNSBtYXIgMjAwOSAxNzo0ODo0NiArMDEwMKZ+RR0AAAAHdElNRQfZAxkQMQU5RdXP" - "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAA/ZJREFUeNrtV09oVEcY" - "/83sy27UfZhtNLWxKNaDK6sNlJZIabHgpdB7KYiCR28W7EEPIkLbgz1481hIaSt4a6UUWkyh" - "Imm9hKbpSg7pIUVjotnGJG5235uZft+bmc1bk8A+NTn1W743b98bvt9vvn9vRoBkbm7uxp/V" - "ux8Mjce4t6ixkdJflDhZCVApH7je29v7oSDwX48PVd8x5bdx9IjB/q0CW2hitwDyNOZIA7qX" - "sNqp8DIUaWyAJo1NGus0/l03+GlEQFZv46sT5Z/F8K3b5vLcID49alCEQE46wESFHZ1RkYGA" - "8UoXZZiQQazts4iMfnzT4JPSb5BfjkV49V2BvLasN1oUgQR0OfieAGPLh+SSl8nfZhPA097p" - "KwgwdpawbogEnpFOjazpeBv3P6uXzDrKok2KgNY2NopQcpwL0iaedlY4EY14hiQ0Fsg4DL7n" - "yhCplQSeTUuFndBKSLf0LOBw4H7F2tlLRr1CsEVA0eyIVNLLAi19K9VhnWvHOOc7UllI6BQ4" - "21euHLkvSHrjiUgfAp7I9d9H/n44VUdPl1hhbdrzoxM1ZrV6W7FfmyegYiRNIp8TmH6k8N3N" - "R5j4axalvGwj8TyqUupJrhDgdqktCZb5xRjXf5jEvw9q2EutudXNMgKyPT96jVgV2kNgX1Jc" - "Ur2w0VS4+MWPqE5Mob+giAS9z6j84/jrVC7ERrcW0+aByJXi03Lhs69x7/4sXqLszOIBg7Xd" - "7xPRpD3ALklCsE6nOX3mc1RHR9FNOaLWMLiWxs5e7O4jF+amsuoXm5Th0KxB73JEEwMMyNXF" - "dvXKOQQ7dmFiXnVchp5IRC5oENgy/VmiZJ+n7zKtA9/T2ve0+kAELNDLZY1VH/1L54+j/5Wd" - "+GVGZWrF3tVRAm71CWEsKQuq0x4AEWB2DdV6gkI+h7Nn38ee3SXcmIptvDJ0Ik8gcbu2thMi" - "ZIr3HJFqI6CIgKaJtvNtLwY4duw1LBS349vJJgJC9puULASiBNwkMW/QAw4Dd1jpynGFgKvR" - "Wfo+9+yUGBwIgd0hRmbipDXL9LehQ1mvCTEOL0alq8DLP080vpmOkd8XYqzWecI9j6zakEzX" - "NW49iFGPs6TcCySw2fI/Aemvm8mEsXLuPtixRWAblURI3/7NIFGgwg+7JBYoxxk7OHW4C8Oj" - "OTqcKBSoaEMq0iIpb8u6iSbNRRedkHLP0Ih8K+6mimZbhcCeP0ICDoeRnBGDNw5XZip3Rvqu" - "jR/BvkGDA7QB6SG0kPeGBFjgM6JgEtnClIDT2OAzIZFYpPExEZmkB2O/A+X5Ebw5cMjuM2u1" - "mrnzxziu3dWYXtrYA9qubRIflSXeer2CUqkk/gNN/sDRnOMoBAAAAABJRU5ErkJggg==") - -#---------------------------------------------------------------------- -aero_right_focus_single = aero_right_focus - -#---------------------------------------------------------------------- -aero_right_single = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAYAAACGVs+MAAAALHRFWHRDcmVhdGlvbiBUaW1l" - "AG1lciAyNSBtYXIgMjAwOSAxNzo0NToxOCArMDEwMEtfu5QAAAAHdElNRQfZAxkQLyM/CW/t" - "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAAkpJREFUeNrtVz2PEkEY" - "fnbZQ+AgGD+R5YSAxVkRLfwF5vgH11xlbeNPsbE2Ftf4C+RiY2OijeGu8GIusEjgiJ4Ej689" - "YHedd8zgsBgt3Fkan+TNZnY3eZ55v2ZeDQzj8dir1+uwLAsT24ZKxGMxFAoFFItFJBIJTRuN" - "Rl714ADlchlmNotoNKpUwHQ6RbvTQa1WQ2VnB9rh0ZGXSiaRz+eVEvvRbDYxGA6hW40GTNMM" - "lZyQy+VA3PoFc4lhGKELIE7i1kNn9mFtAjzPW68AgUXwhaKwoGnaLwFE7rru4gOZWKsiFwJ0" - "/+7tqQ6rw7JTVxcd4hOchvyCVPXOHbz9cA57soHtUhqO4yjxgMBSDogPo4mDN+/OcCVt4Ob1" - "JGazmTJvLEIgu4Uwmzt48fI9mq2vPBzyP/9qlF9LZeh/KeP5/mucffuOSCTC/wnCBOcfPSDj" - "6bN9fDppBOYJucJ4DtARSfbzKI6vCHjyeA+X05sYstMrCJA3RZVxAZTpwvx4tPcQ166m0ev1" - "Ak2+lTIkctk1G0YEu7sPeBV0u91AyQmCyxALEiBUbcYjuH/vFnsC7XY7cHK5yS01Iqr3ZELH" - "3VIc5g0X/X4/cHKx4d+ehiTgYvwFd0w3sIT7G1auQiRCZefzY+33gf8CuAD5eAxdwCXWfqkH" - "qLyAyKDNUismTuLmkxErSmTZWEbZr/puSOQxNh9Sg5vP5zBKbEh8Va3yQSGTySifDWmTndNT" - "fDw+RqVSAQ/+YDDg0/HnVgu24umYdn97a4tPx6lUSvsBjEDOU65zEi4AAAAASUVORK5CYII=") - -#---------------------------------------------------------------------- -aero_tab = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAMAAACxiD++AAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFq6ysra6urq+vr7CwsLGxsbKysrOzs7S0tLS0tLW1tba2tre3t7i4uLm5uru7vL29" - "v8DAwMDAwsPDxMXFxsbGycrKzc3Nzc7Ozs/P09TU19fX2dnZ2tra29vb3Nzc3N3d3t7e4ODg" - "4uLi4+Pj4+Tk5OTk5OXl5ubm5+fn6Ojo6enp6+vr7Ozs7e3t7e7u7+/v8fHx8vLy8/Pz9PT0" - "9fX19vb29vf3+Pj4+fn5+vr6+/v7/Pz8/f39/v7+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAA0PbvAwAAABh0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjM2" - "qefiJQAAAP9JREFUOE+t0tlSwjAUgOFjZQuxuOBSFURSSOyq0qYNEd//tUzCaIeLk9743Zyb" - "f5LOSUH3AC3vyEWIuIw06KvHRmGqKIJ3+u1RzaD0BpL+S3DwfIO5oqAHDxPk1LOpr9oGe0/h" - "ArXHmSCjLbpIpSobyBa3o5DSWqJaF+xqlPykEE/LHFWmU2AkS1GZCdYkFajkjZhAxCghCLwS" - "zlCcE1j1BpOeE176gqU/mMBy3F0Rb/mpZENh0QWxyJNTfD6HRXfFthgNndFgcJzDa2aCv0WZ" - "tUj7blLdP9nZ6PCZATtPft+qjELt/vAm/HCzCNYmuA2O5xqzmzOwAuIG0AfGfgDFvqY+8bKe" - "lgAAAABJRU5ErkJggg==") - -#---------------------------------------------------------------------- -aero_tab_focus = PyEmbeddedImage( - "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") - -#---------------------------------------------------------------------- -aero_tab_focus_single = aero_tab_focus - -#---------------------------------------------------------------------- -aero_tab_single = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAMAAACxiD++AAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFq6ysra6urq+vr7CwsLGxsbKysrOzs7S0tLS0tLW1tba2tre3t7i4uLm5uru7vL29" - "v8DAwMDAwsPDxMXFxsbGycrKzc3Nzc7Ozs/P09TU19fX2dnZ2tra29vb3Nzc3N3d3t7e4ODg" - "4uLi4+Pj4+Tk5OTk5OXl5ubm5+fn6Ojo6enp6+vr7Ozs7e3t7e7u7+/v8fHx8vLy8/Pz9PT0" - "9fX19vb29vf3+Pj4+fn5+vr6+/v7/Pz8/f39/v7+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAA0PbvAwAAABh0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjM2" - "qefiJQAAAP9JREFUOE+t0tlSwjAUgOFjZQuxuOBSFURSSOyq0qYNEd//tUzCaIeLk9743Zyb" - "f5LOSUH3AC3vyEWIuIw06KvHRmGqKIJ3+u1RzaD0BpL+S3DwfIO5oqAHDxPk1LOpr9oGe0/h" - "ArXHmSCjLbpIpSobyBa3o5DSWqJaF+xqlPykEE/LHFWmU2AkS1GZCdYkFajkjZhAxCghCLwS" - "zlCcE1j1BpOeE176gqU/mMBy3F0Rb/mpZENh0QWxyJNTfD6HRXfFthgNndFgcJzDa2aCv0WZ" - "tUj7blLdP9nZ6PCZATtPft+qjELt/vAm/HCzCNYmuA2O5xqzmzOwAuIG0AfGfgDFvqY+8bKe" - "lgAAAABJRU5ErkJggg==") - -#---------------------------------------------------------------------- -aero_up = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB8AAAAgCAYAAADqgqNBAAAALHRFWHRDcmVhdGlvbiBUaW1l" - "AG1lciAyNSBtYXIgMjAwOSAxNzo1MToxNCArMDEwMESarloAAAAHdElNRQfZAxkQMyBAd2MK" - "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAAh9JREFUeNrFl0tv2kAU" - "hY+NBXbAElS0QTwColKX4Q+gbvmDXXXVriq160olq7b7Rk2zICsejWyUqkmQgEIMxvWxZAti" - "0eCoHo40ssZj+5vrO3fmXgmuut2u4zb0+33MZjPEJU3TUKvVUK/X2SRlOp067ZMTNBoNNJtN" - "JJPJ2OCWZcEwTXw/OwO50o/zc0fPZFCtVmOD3tdgMMB4MoHc7/VQKpWEgalyuQxy5Tv3VyiK" - "IhROHrmyUOo97QXuOM7+4L4CZ/uziVuSJG3CCRYFX5+AcDg5iURiP3Ba7bOE+3xde/H5huWi" - "4SHLV6uVEKAsy5uW86hbLBZC4FzpoVCzbVsI3OcFcP5yUfBQqBEuyufkhFb7Y+BMubheHguX" - "fXiURjH7sSw7yIKivh/Ao4g+KxQK6A1MvHr9wbuyv35a7arI8Gw2i+ubCd6++4KUlveu7PN+" - "rPBcLoer33d48/4bDvTDoLHP+xyPop0zR13XYfxaov3VhJZ5Fhr/+NlE62UFh090jMfj/wdP" - "p9O4uk3itDNB6iC/9bnTjoXjFxmUnu42AQ/+0GKZz+c4KuaQz6kPflBTJYxuRrtZnnJjlbsb" - "N/xtsc7x2+thkIH8S6M/9tbdkkbyGxwn1yuX3OBDsVj0Dpc4j1aCVVWFYRhYLpdQnrsV46d2" - "26siGK9xFoo0zhwO0bm4QKvVgudsd3F4JfLPy0vPv3GJVh9VKl6J7EaP9Be4+2JJRD7+lAAA" - "AABJRU5ErkJggg==") - -#---------------------------------------------------------------------- -aero_up_focus = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB8AAAAgCAYAAADqgqNBAAAALHRFWHRDcmVhdGlvbiBUaW1l" - "AG1lciAyNSBtYXIgMjAwOSAxNzo1NTo1MyArMDEwMAycPlQAAAAHdElNRQfZAxkQOBMcU9vX" - "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAABFhJREFUeNq1V82LHEUU" - "/1VNz863yWyUyCSaEPzYuGtkwY8QYwLiQfTgwYsgBPMXeDJXvYmo+Qc8KEFIULyJHhQWNcSE" - "3KLrLgqLoMYVkplIdmZ2PrrL36uqnulOsu50YB68ed3V3fV771fvvZpSoDSbzS9/Xll9+czy" - "EFc3IkxLGlWNE/MBjj17RBljPlQE/uH1MytHzcEjeOGwwYGSQokvzigqbUCbo9UTAhhqKMqL" - "IW2PdpN2g/pbx+DH7xX02gWcPblwWi2dv2Debz2Dd48bVIxCjiiBFjBeE1iJwumkIg4If5ER" - "NRiKIxxgtOhpjVNfGby15xL0xz8NsP+owkzoPpqmiBP5MEL9RUBw9bWuwe6iwvRWOi2C0yhp" - "CO6kSzkVCWJvzBYqopBtScwdruM8sHj+wkYuiWGMBxTrHxrvQdZcMCat0S33qcgFbMBBTau0" - "y3CL6K0yfmxCibzDoYkz3pdelGbA0U53Ir4RqfHLmq9FcHVmSy1D+GbEphnNF5cdLFYuAR65" - "MsgJqNcwMZkFzxB5THXcbGzUXk1iGS240BGmPEw3lqwlkcyfcbNxGHbOKEW7W/M4cpVYb7Em" - "I+0pQM/qIHIq8w1NMnLyMwhdHw98pCOqI39/NwnnGY2tMKwwLjUL7tbE0Iqyp1Ot5/HqqOwJ" - "FyYot/MKA5EZMTOOfOi8smuv3Yc26RLdRWeMPLnOoU++oV/SVOTnmuzv5H22oFDLK1S4nRVZ" - "DTN0JK/d7pbLAB7vYn2i92jbHLg5AFp9KV6Fs5zreAy+ycg3+KDADiMDOZuuCibnMjYLeEy5" - "gPcIvsmQuwTvMKPbfWNrfTAIx5H36FWHDpR5V+A4g7c0x1RLIkYZwSWz+5yr57UbOgwJJgwT" - "tEuqt+lqhYNFLvSMUB2O69tkBB/adm1IuwBL9E47ZMA6lwIfOup71D6p7mv/98m3VvHC3AIu" - "tzuYI//2zG27WJy8cW1bBjyGFQ8+al5RQs02Ksvxyr4Ae9t/WqvV9t8k548l858JYeOlhsLy" - "yhrePHXaWrnPUg13DX5oNsDf/9zAO+99jnKtYa3cy/hUwRd3Bbj5xzre/uAb1Or7Rir3Mi7P" - "s8jEbz+yI4fm79fxyRdrqO588LbnH322hjdezePRvbP4pRVONOdE4PtrGr2rHXx7qWup3krk" - "+bGwjYceqNCB4bbzOnD9//yv86Tx/IEKGrvL205YLSssXds68iROcC+PRxXmf5WNfCsHpEF8" - "xwlLE/DUve7a6Z2kyO8reY0arwU3OPl4HktXctjzHCenw1V2l2oeKLF2Cjm3scQNZzjByUKO" - "WvfwoDdgSyyytxf4fZ5b5Az/qdxHnyoE3fW1wonFAMHiwmOr85cvzn26fBgHnzZ4uKyxk6BV" - "gvFgwc2GDsB1vEnEdjj+cA8BDyVo0+Eb1CbZ+5Unxr/OA3PRRTz5xILrnq1Wy1y+soxzqxHW" - "29M7ON1f0XhtTuOpQ/Oo1+vqPxxtdiUOpmR7AAAAAElFTkSuQmCC") - -#---------------------------------------------------------------------- -aero_up_focus_single = aero_up_focus - -#---------------------------------------------------------------------- -aero_up_single = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB8AAAAgCAYAAADqgqNBAAAALHRFWHRDcmVhdGlvbiBUaW1l" - "AG1lciAyNSBtYXIgMjAwOSAxNzo1MToxNCArMDEwMESarloAAAAHdElNRQfZAxkQMyBAd2MK" - "AAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAAh9JREFUeNrFl0tv2kAU" - "hY+NBXbAElS0QTwColKX4Q+gbvmDXXXVriq160olq7b7Rk2zICsejWyUqkmQgEIMxvWxZAti" - "0eCoHo40ssZj+5vrO3fmXgmuut2u4zb0+33MZjPEJU3TUKvVUK/X2SRlOp067ZMTNBoNNJtN" - "JJPJ2OCWZcEwTXw/OwO50o/zc0fPZFCtVmOD3tdgMMB4MoHc7/VQKpWEgalyuQxy5Tv3VyiK" - "IhROHrmyUOo97QXuOM7+4L4CZ/uziVuSJG3CCRYFX5+AcDg5iURiP3Ba7bOE+3xde/H5huWi" - "4SHLV6uVEKAsy5uW86hbLBZC4FzpoVCzbVsI3OcFcP5yUfBQqBEuyufkhFb7Y+BMubheHguX" - "fXiURjH7sSw7yIKivh/Ao4g+KxQK6A1MvHr9wbuyv35a7arI8Gw2i+ubCd6++4KUlveu7PN+" - "rPBcLoer33d48/4bDvTDoLHP+xyPop0zR13XYfxaov3VhJZ5Fhr/+NlE62UFh090jMfj/wdP" - "p9O4uk3itDNB6iC/9bnTjoXjFxmUnu42AQ/+0GKZz+c4KuaQz6kPflBTJYxuRrtZnnJjlbsb" - "N/xtsc7x2+thkIH8S6M/9tbdkkbyGxwn1yuX3OBDsVj0Dpc4j1aCVVWFYRhYLpdQnrsV46d2" - "26siGK9xFoo0zhwO0bm4QKvVgudsd3F4JfLPy0vPv3GJVh9VKl6J7EaP9Be4+2JJRD7+lAAA" - "AABJRU5ErkJggg==") - -#---------------------------------------------------------------------- -aero_denied = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAADxklEQVQ4jbWUzWuUVxTGn3Pe" - "+955k8nMJE5m0vqRZCaUYomG0uJGjDR0UXBRUj+6Kqg7kSy6SBf5A7ropiB07aK4qIsWIYsu" - "ioXBQoRKqWhJ1eq0sWqSmWQyk8y8H/e+p4t8oJ2YuPHA2dzD+fHwnHMuiQheR/BroQJQOxWv" - "Z7N9cRB8nAA+dIEBAIiAvwPgJ04kro1Vq/Mv66XtrCgVi9osLEx1K/V57+HD6a5Dh8B9fSDH" - "ga1WsXr7Niq3btVrUfS1yue/HH34MNwV/HM+n1HN5vd7+/vHsmfPQu3bt60i8+wZli5fxr/l" - "8nXT2fnJBwsLK8/XX/B4ZnhYqWbzyv5icaz34kXwnj2IrYUoBXge4HkQpRBbC85kkL1wAfuH" - "hsZUs3llZnhYvRQclMvnsqnUidTp04DWoEwGnE6DEwmQ44AcB5xIgNNpUCYDaI3UqVPIplIn" - "gnL53LbgmULB9YCp9LFjcHM5KM8D+z6o0QD+l9RogH0fyvPg5nLIHD8OD5iaKRTcTd6W/KhS" - "OZJOJgc7R0ag4ngd8gqhAHSOjMArlQbrlcoRAL+8oJhFjiaLRWhmrN29ixYzfNdF6LqIXBdG" - "a1itEWsNaA24LoQZ5s4duAC6hobAIkfbFDOQ78jlQPU6zNIS3jh/Hqz1jmolDFE7eRIqk4GX" - "zYKBfDtYJGDfB9VqkNXVV7IBAOT+fYjrrs9DJGgDE/Ns+OABkExCBQHmL10CM4OMAVkLAkAb" - "3hEAIgJZC7YW9OgRwnodzDy7xds8kF97et70iMrFfF6T1gAzEEWAMburBvBwcTH0RQbfX15+" - "Cjw3vIOl0tMgiq7VVlbA9Tq4VgOvrYGDYNes1esIoujawVLpaZtiAPitu/sta8yt/o6OVI/a" - "8X/aimVj8E+r1XCUeu/dWu3+tmAA+D2dHvetvdqtlDrgOEgQbQsMRDBnLWrGGM9xzozU6z88" - "X28D29VV/LF370d+HH/bFOntIkKGCJuLFwJYEcGqCDqJKh7zZ+88efKj09WFHcFbtuTzOW61" - "vghEPo1EDtiNdweASzSnib6Tjo6vum/eXCwUCm39dO/ePUxMTDizs7Oq0WjoMAy1tVbHceyK" - "iJsFOs4wv32AqF8AzMXx3FWRP5cAn4hCZo6YOdRah8lkMhwYGDCTk5NGzc/PY21tDcYYiuOY" - "RIQ30gGgKiL4xpi/AJSxvsIWAIjIAaBEJBYRx1rLxhhqtVqoVqu0rRXT09N048YNPH78mKrV" - "KjWbTfi+TwDgeZ4kEgn09vZKX1+fjI6OYnx8vA3yHxWIwp50Lj49AAAAAElFTkSuQmCC") - -#---------------------------------------------------------------------- -auinotebook_preview = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0" - "RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJXSURBVHjahFJRSBNxGP/d/+52" - "W66ildPKJB9EMSwjFSNoUkS+GYg9pi9R9tJeopcgC3yKYvRUMHA+VBJUmpQPQSySKINqEGSB" - "Np3aNjs3N8+7285d/7sxa9yw3/G777v/932/+76PP6PrOgw8D876dYImWJAEZPpW8l89nYea" - "i8KGgMHRYPitvgkCw0G9qaNXD4x80Qs1BknRnzaBEfX1e+G758PQaEgvnP8VULA5lCS8/T7T" - "NUQK4ApO4j/1l3s6N/zA8MiGTxiGgUGowGwkhqkfc5Bl1SKwlM6i90y75dzsoKX9fNPLF2Mt" - "sZVGuMt3YPDpK7jsDnj7uiEIfH6ClAjF5rAKHD1xcW99a927C5e6hP3luwCGwONpRjwm4tqA" - "H7du9pmJDG9HrsSeSE3dvmdnz512tFZVQaGjaCyBjedRubscxzva8PrNJzNR0xmsKsQq4KzY" - "fqDW7UY8o4KjxRzLmpYlBLUNNZj48BVRMQlWA7I5yTqCvcyuq+s0qmkQiC1/QeiTo1ajNpWS" - "oMoMVJVyXbZ2sDj9S5sMh2l7CjJUJGswq0HNZBCNLmEhPA0xsQpJUSHJJUZILCbuxuZF7fv8" - "ApbTaaysrSEpSVgURdy//RDJxAp2RvzgMgkQzbpEziVEbgQfBeuXPY1dqcMS4W08cnIWY0Pj" - "iIXjuNI2A0dsDmXyT3yUTtESZ5EAU3CuDvhD7ydDB1mWg6zQWelSj2ydwbE9v1Fd4TQZmHLj" - "yTfBzP88PsgUCZTCne4qFycID7Zt4TuqK50TFaTmZMP1x5l/c/4IMABbKBvEcRELXgAAAABJ" - "RU5ErkJggg==") - -#---------------------------------------------------------------------- -whidbey_down = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACsAAAAeCAMAAACCNBfsAAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFAAAAaHWVZ3egZ3e1cYCncYa0dpC4cYXGcpDBc5fWd6Dld6Pwi5OzgJbUkJjQkqHC" - "hafggqfwh7Dwk6Xgl7fwoKjWp7fXsbbWoLfnoLjwpMLwscHnsMfxtdD0wMHg5eTo5/D49/f3" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAverH2wAAAQB0Uk5T////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn" - "4iUAAAF4SURBVDhPbZTpYoIwEITRGqAQ1ChqOFrx/R8y3SObq8yvsHwZhglaOdH7HZbJIp1W" - "YW7t7w68LOcwDaxd5+lhC3q18zwOMhTWIjtZ+3wGfFmWFYZjgJl9vWC/1x30AI2zzExzIcqz" - "a2RxC2Ak2n4zJmEx1TgaY8R7AtHsdgMS1IivJRZHyN5lA6PMEgwZ2JVYs23bxwuWG3PGdF3X" - "ImvtBO/KqAl38ytgO+WqMz1SDDz7KXaCbatU5YYARt+SbUHg61zT9/iMHsQZKHBI9A1S6njk" - "fpuCRTjmJVQBymfxlfuCc5IX0cMhnhvCMYO8KCdCV0L9GbMz8Fhqous1ugbWw/32k2oDtFUn" - "do2sz1ywqWvCElz6pq4pS3CRVxooMvjqsI2+v5LwXCVrljfrGclhqH2v5e+Nr6VnYltgBct7" - "iDDExm+grvm0ouL/QwrjN1CHXvczYAz0xF5Pp9w168zfAhjeH9gSle8hnWutldL6H7rHOq2P" - "agd1f/M7VhKuYPh3AAAAAElFTkSuQmCC") - -#---------------------------------------------------------------------- -whidbey_down_single = whidbey_down - -#---------------------------------------------------------------------- -whidbey_down_focus = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACsAAAAeCAMAAACCNBfsAAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFAAAAECBXFC9vECiQBS2oIDKMIDigC0CVJUqQIkewJFKlJlayMEiwMlSiK2G0JFTR" - "LmnSKGHmKHDoInDwMGjgNnDgNXLwSFeKQFizR2OkUGagcHiYZ3egcHilUHjRQXLwR4DwU4Pw" - "YIfTcYXGcIjVc5fWZpHxcJj3d6PwgJbUkJjAkJjQkqHChafggqfwh7Dgh7Dwl7fwoKjAqLDI" - "sLDIl8D4pMLw4Of35/D4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAQS37pgAAAQB0Uk5T////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn" - "4iUAAAGeSURBVDhPfdOLUsIwEAVQCCixFSggVfBFQWpVjKJo+f8fi3ezSZq2jDsDhHB62Wyh" - "o319Vctg9V2tO34p5H0bHw5D4Xe9FULK5bKhb6UcDs/cprNdMYiprhee30khaStx2NpudwCb" - "JHG8WAhbEkU0cZgtUge0iYrjCEUuilheOWysS2U9GpluGJJ1mKyg1LHZn6NYNNYUCWuozSjr" - "FVxnLGQUjZPJlLJKCk7piar0Nk2zS90RAhINVDZN5yUeNZuhbjq6BzmZomYoICr/Yr5mtcry" - "fL2mfnvjSd2anvkSsqBZUazN2XS/YVNLrc2Qut3yHAj/10OWFwVRtrpPvZo5cL+28A7fnxfv" - "G6Ps74GwsfXCsXKkMnWWko39DKukAbjUygKfskFqYLnnKvcHdQT9sA0EPdgD1ts9Vr2G/fpp" - "pDMeAg3gWe2fgn9V9d+0yW5edCylQurnwJejZ/7VPJpZ7V+C1PBsFrPFXAul6rSRi2S2uFmq" - "kdrK1frcWOq1kXrC6osHulnq963Wa3Nm9kOySrVpq1/yr5vNbtdK1foPGIxy6qmqIg0AAAAA" - "SUVORK5CYII=") - -#---------------------------------------------------------------------- -whidbey_down_focus_single = whidbey_down_focus - -#---------------------------------------------------------------------- -whidbey_dock_pane = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAF0AAABdCAMAAADwr5rxAAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFAAAAaHWVcHiYZ3egZ3e1cHilcYCncYa0dpC4ZobHcYXGcpDBc5fWcZjgd6Dld6Pw" - "i5Ozl6e3q62xgIjQgpXEgJbUkJjAkJjQgJjggKDXkqHCk6TWhafggqfwh7Dwk6Xgk7Tkl7fw" - "oKjAoKjWqLDIp7fXsLDIsbbWoLfnoLjwsLjjl8D4pMLwscHnsMfxtdD0wMHg6tTN4Njk5eTo" - "4Of35/D48Ofh9/f3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAA1jVbdgAAAQB0Uk5T////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn" - "4iUAAAdFSURBVGhDtZpxe6I4EMbtbQVXrHJuaY8KWq/XW3Sr196u8v0/GTfzThICRIh9nssf" - "u4rw42UyM5kJHVVXjDQah/EV51ejK05+SKMwjK/BX0Gfzu9ms2kY3PgL8qd/nc/vCB+GN/54" - "b/p0sVjMaRA+9Mb70hku9GvUe9IBV3TC+9rejy5wTfdX70VneJ7LHRaLu7uIPNPL9j50hp+a" - "w9NzPOhQfvrHHqeZn/phOmzeofvZfpA+zTFa2rNsFk2GPWeIruB5y+5En00mg1E7QNfw/CSP" - "oEaZ51kWDavvpxu4phOWB+hJMqi+l17DFb0sBa+eJB3KOX30xLIFeAQXvKYTvtf2PfTVbrtd" - "6xsonrKMoafhJAwu5/vL9NWO6Rp/iZ5OJsFlfI/2onh7oxvQYKOsaeALjTV944fK2DFn489o" - "ryqmA69NDrtjWPSwZyHs9RlWr+h5Qzt9UdqzPvhATTBMn/Uu4QOxut9r24vFdzSUvUh+lk37" - "6wMXfVNf8sF0mdrt9nGF8YbB3ppNl/WpK8eNHPTNxuCXHx/a9q+vZz3exZvW6+m5NPhi58B3" - "6Yfj2zYRHcuSgOI5Bi0fDgeiT/nT8oxTi2K3U1dZz9ChH5gu+GXJ9HNRvP/dgoOfyEGox/Tn" - "nVlo04kNm34DHPRfv7psxuujywqm4rBo41t0Vs4uvl4/PXHUNLj7/f6VRvte5RJTjxBo4Zv0" - "A3sDxw2d+EeTcnzd4qnIdR43zZ/EbSUjNfEN+oHppFsiEZOmxn5/ZJOBvt1uNivrNyvk2nib" - "fmA6W0W0Z6FGkL0sNvLYt0L/aKeLtnqLTvCD2FzRNR53VelSZ8l1IfhfdqqDbRaWcWo6nWZs" - "zrk1SZLVvww40oBeZTG9oDwbOm6pDy8svKHzA9Y2Z3oUgU5WOSIXdOjAv/Nv1hLJ5aZRr+lQ" - "XhNYevSEZye6ZJo2PZNpd9ANXtFFuYtOM0p50UnP4Dm2VeQZavVCZ6cqudziCOL/szSKYkh7" - "hReu62UJv/MyS8+HM2AZuUwNgwcdTlVSkasrrppOgSL0Rg2ME9l6uD8/cqmWd643T0Y90xEO" - "azku48RzCu0vau1z0lNEhJu++Epkoks4dOhjPPaL+Hl+gf4upmlplzaIPGdUIbewXls7OTvo" - "xktbdK6auNyAWz266fOHaoQ4ZKNpOl940vRXHQN99BU9XMkzqylo3+7u0nTEdkHkKzoKRUNH" - "tccxeoEOwxs6XQqK0GdRNFoVKkqEDo+8lk4Syq2UsDWd2ubxKHtm5dzVid1Fe5bOjCx4kUt7" - "mohf8QPCMg3ttGERjp4z1Yk27O5HV15r6MbuVF1S2xbHo+pRNblNf88SaN9sVIpyaSfDYhnU" - "dEQK7A54ELO/f6VJqC2joknF4bmfPgadw4UtY+hmo4Vj9ZanWNtd07PsRfmDuYqTgc43nAei" - "e8TEu4OuWh7kGcb70kViKfR7phdvVA808gw34thHkBzJ+EZHSquH5NfzN5p1ZU+S/kM3fZxE" - "owBnCF2lWFAivcWi8jvUYydDBujAZ0JX7XD5Q0yTMT0EnVf6emHh9FC3anptgu3nc5ueppC2" - "0nfT//OdqRcOA5HeoVsbFGZdFbxFJ3/7C3ShyTPoz/C4PwHnhau+rLmxVdcEwNunRdEYNcFK" - "8Wv6jO4cBL8DfuC1xbqssbVi1TOMN6chHoSu1Ws6ByLZBfDzObEX8yRqNvd2LaZsLzt3k8lY" - "1g8aDw+Ukc3gfatAzMJjapTnOdEb2yqNOtLgSdwkMHBWGEIxxmQS/iYTqvAyGSmN9rZEswZW" - "eJkaC0Af4/ieBrPHY6kWWniCh+0NoVb9DjzbPLhZNhH07f4+CIK4heYbT0V7d0ui3XvcSvLk" - "QEbXROPnz859zFGOLGptZhRDru2UTt9EeB3ISj31TQ784fBIRwVeVTQtrq2gbs93G0Vfvtg9" - "3/Ft92KqdXWfI1cpVCspOOMnjg3QLr0aRwpOxuGOj+i7orD6JarnqVugEE2sfnXs2khx0CsD" - "r6rv33U3w/3MZvNCQ/dP3EI+1c2pa5fGRbfa2e/SApohXbw6RmFk0a2rzMd+ujRclAI0XnYh" - "pBRH1ujfhuil6yZX6LTEmlEnl158H91uFVVtr+t7ne0o9iKXSdSxHjpvLJieqLmXar5xaPfs" - "Ll2mP8IMWqRzTy/PSTplzIvqe7Qndit3gc4581Paq4p23lHpYP+dH6K5lyoZSce1U3+vz0xb" - "dMZLgcD/AB5aode9Qb+/S5VmtEsDUNMH334MxKqpcxw+4/HWbIAuNSbXgc3RLIo+4zNyjeBR" - "ZdbjRKuFKec+F03qqrpCtuieb/uGLGNXyDbdR7mugXsezlUhn06D3iJED+2qvkcDpCpUvzdl" - "nnTVnSg6vavxfT/spb1Wz9qpnPN7Q+mrXTsmF1I+78j0PHpq13jOLR7v966mV6jS0BX0vAJq" - "OZ+3dlLP8UnDH+7nkUpRHMf/399CVFUcf7nu7zj+A8yummsi9EdGAAAAAElFTkSuQmCC") - -#---------------------------------------------------------------------- -whidbey_dock_pane_bottom = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAF0AAABdCAMAAADwr5rxAAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFAAAAECBXFC9vECiQBS2oIDKMIDigC0CVJUqQIkewJFKlJlayMEiwMlSiK2G0JFTR" - "LmnSKGHmKHDoInDwMGjgNnDgNXLwSFeKQFizR2OkUGagaHWVcHiYZ3egZ3e1cHilUHjRQXLw" - "cYCncYa0dpC4R4DwU4PwZobHYIfTcYXGcIjVcpDBc5fWZpHxcZjgcJj3d6Dld6Pwi5Ozl6e3" - "q62xgIjQgpXEgJbUkJjAkJjQgJjggKDXkqHCk6TWhafggqfwh7Dgh7Dwk6Xgk7Tkl7fwoKjA" - "oKjWqLDIp7fXsLDIsbbWoLfnoLjwsLjjl8D4pMLwscHnsMfxtdD0wMHg6tTN4Njk5eTo4Of3" - "5/D48Ofh9/f3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAaHenigAAAQB0Uk5T////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn" - "4iUAAAejSURBVGhDpZkLe9o2FIYpTVeWrG3Srmy9stk0LTPJMKMhmYM9KOuSERqydAX8//+H" - "dy6SLF+QRXeepwtg+9XnT+fotlqyRQRey+1vcX9S2+Lm08Bz3f42+C3ond5xt9txnRf2guzp" - "b3u9Y8C77gt7vDW94/t+DwLwrjXelo5wpm+j3pJOcEEHvK33dnSGS7q9eis6wqOIW/D942MP" - "MtPKexs6wlfZsMwcCzopX/2jx6prp76aTp4X6HbeV9I7EUVOexh2vXZ15lTRBTzK+Q70brtd" - "WbUVdAmPVvwKIuIoCkOvWr2ZruCSDlgMog+HleqN9BQu6HHMePEmQdWYY6IPNS+IB3DGSzrg" - "jd4b6KOr6XQsGxA84YyiB27bdTaP95vpoyukS/wmetBuO5vxBu2z2fU1NACBpowh6AvEGL7h" - "S4WYmN3W12hPEqQTXlpOvlNodNcwERpzBtULepTRDl+E9tAEr1gTVNO7xim8olbnc+k9O34F" - "IfwC+WHYMa8PyuiT9JHPSOeunU7PRhTXFJitYWeQ3joqaaiEPpko/ODzZ+n9xcVaxi1n03jc" - "WccKP7sqwRfpi5vr6ZB1DGIAcuYoNH9YLIDewU+DNd06m11diae0dyjQF0hn/CBG+no2u73M" - "wYk/5B9JPXV/VOiFPB3Y5Ol7ghN9uSyyES9/HSRkFZZFHp+jo3JM8fH4/ByrJsOdz+cXEPm2" - "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") - -#---------------------------------------------------------------------- -whidbey_dock_pane_center = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAF0AAABdCAMAAADwr5rxAAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFAAAAGDeAJUqQIEOkIkewJFKlJlayMlSiMle1K2G0LmnSNnDgR2OkQ2O1UGagUHCo" - "VXSzaHWVZ3egZ3e1cHilQ2TAQHDAQnLSVnfFQXfgcYCncYa0dpC4VYTTRIDjVYbgZobHYIfT" - "ZpPXcYXGcpDBc5fWYIjgYZHgcZjgd6Dld6Pwi5Ozq62xgIjQgJbUkJjAkJjQgJjggKDXkqHC" - "k6TWlrDXhafggqfwh7Dwk6Xgk7Tkl7fwoKjWqLDIp7fXsLDIsbbWoLfnoLjwsLjjpMLwscHn" - "sMfxtdD0wMHg6tTN4Njk5eTo4Of35/D48Ofh9/f3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAXehG6QAAAQB0Uk5T////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn" - "4iUAAAdqSURBVGhDtZoNW9pIEMc5emrB651VUDRUpEkqb5d6SBOUXq9Q8dprke//aXLzsrvZ" - "hGWz+NzN87RCzP74M5mZzGyspDvYOGh4wx3OTys7nPx+HHjecBf8DnS/3wtD37t47S7InX7V" - "7/cA73mv3fHOdH8wGPTBAO85413pCGf6Luod6QQXdMC7+t6NznBJd1fvREd4kvAnDAa9XgCR" - "6eR7FzrCV3lzjBwHOilf/a3bKnRTX04nn2/Q3XxfSvcTsoL2OA6DdnnklNEFPCn4Hehhu12a" - "tSV0CU9W/BWErZMkjoNy9Xa6gks6YNGIHkWl6q30DC7o6zXjxTcZl9UcGz3SfEE8gDNe0gFv" - "9b2FPlnMZlP5AYInPKPoY6/tXWyv99vpkwXSJX4bfdxuX2zHW7TP5w8P8AFg6JQpGL0Bm8I7" - "/FIxBmbYeI72NEU64aXLye9kGt2z3AitMYPqBT3JaYc3Qntsg5f0BOX00HoLL8nVL1+k79nj" - "CzDhL5Afx769PzDR77Il35DOl3Y2u5mQPZBhtMb+KDt1YvggA/3uTuFH375J33/69CTtK0fT" - "dOo/rRV+vjDgN+nLx4dZxDpGawBy5Cg0v1guge7jq9ETnTqfLxZilfYdNuhLpDN+tEb603z+" - "9a8CnPgRHyT1dPmTjatQpAObfPo7wYn+48cmG/Hy6CglV2FaFPEFOirHEJ9Ob28xazRuFIYt" - "sjjOf9p6RJeeUqCAz9OXGA2YN3DiHzrjw4du66zT6VyCNZvNdzk+hy1XpDw+R18iHXRzJtJF" - "Y4uvrrpdgBP98vJds9vNfqmlXBGv05dIR6+w9tiThLet62tkn50h+xzs8GVL/lIvF0X1Gh3g" - "S/a5oEt8+PYtws/AFP2wxfgfeqkj3ww052R0OE35HGtrFEWTfxBwDUZ6NauDnSq6LNNM1/CK" - "jl8w8znSg4DoEcDZG0U64b9indBukdhuKvWSTsqVV+iOH9zSBe0C3Eiv/3yFJxjoCi/orNxE" - "73YBbqbXiS5vAJn+TD3TMajW2G5hBuHPeBwEQ1wbtjrklfuCoePrtVDgsV3QujWFJzoF1Rqa" - "XNlxafSOoOO1zeye6TWkf8KvvBa3d+w3V8r3SKd0mPJxthVeU9Q+adno9Rco3kwfXAEZ6JwO" - "G/QG6nKhg+cL2nkMgsippFRbUK+uHYKd6G/edDoUiPcmz9TrB3jSjZnef59WqLag0yQd262V" - "pLfedC5L6RMImzXEPK1EjTS+9XrjcQX9Qpkv6NQoKnqzc8lZZNOu6LBUo4dBUJnMRV1hOkXk" - "rnRIqPWMW9iMDmNzoxLfo3Kc6tjvrD0eh1Qhm5BI27XX9qt06YnOSzW673mV+1hMojm/P4+u" - "/A7dJYxtw2ElvRFDbj7e44i0d09F9TL5vba/f6Rrp0yhq0rwiyHG+xVc4swzIpugijnQq0TH" - "dEHPKLraaMFcPcEAkn6X9Dj+CAs/NM/PMedVzMhyg3Vg/6A6xhpsoIuRh+oM4rfSD/P0Q3qP" - "dQbolEzzB+gHcnUGB3HaR+AaifjcRAp3j3iCS3svqV5J7Z37jL63R9IFXZRYogRyi0XUd1JP" - "OxlsRCc8weuQTmwd/gGH9gUd7/SyjcCF+vaQvDeR7/t9nT4mZZNXzC8asKsBnrBB1zYo1H2V" - "8RodEvnPrfRaDei/ERwb8GxZfmMr6wkIr58WBA3qCU5Pi7qJXf2V4Eu8X2rLclsrWj+DeHUa" - "5QPTnwr0GhjQCQ4tQ+bzJImC/HCv92LC97xz1243qMKjvXpVq0n9NchQpRx/6SvlRM9tq+T6" - "SIUPcfdFwZ8mk9oLVMxksJ+OKEnZfAywOB6DFbcl8j2wwPOlydbDq/DgYG8P/6Funa3wAPeK" - "G0KF/p3w6POL16McHfQfHR1Uq9W9XwIKRM2GpB7gG1sSxdnjhIsnJjJNTWDfvxdo2lG8Y8Bo" - "E0IOmbZTNuYmwMtEFuphbjLgl8sbOMrwNPXMG1mbM99JEBwf6zPf48Pi47zAf8QuJUK6GCm9" - "sG3YAN2kp41AwME5OPEBfTGfa/Mq9PmPcBAmQ21ebZg2Ugz0VMHT9PNn3odAgyn57iPYjBta" - "bKz922w4Ne3SmOjaOPuZR0BlPMWLY5BGGl1bpV7a6TxwQXmQeN6F4FacqoZ9G8JKl0Mu0++0" - "75AVFyveRtdHRdHby/5eVjvIvcDkEnHMQseNBTUT5fdS1TtMbcvu0nb6TW6SM+7pJQlIh4K+" - "Vb1Fe6SPclvoAdiztKcp7LxTp0P77+jp/F4qVySZ10b91pjxC3TEczeF/xHc01Jv8wPs8c5d" - "mtLOA0BGL336UZKrqs8xxIzDU7MSOveY2AfmLd8UPSdmeA3jqcvMbAV3C9XOPS+bxKqsQ9bo" - "jk/7yjyjd8g63UW57IEtX87UIa9WpdHCRAftor+nAYhbl//0OZ+cTgQdntW4Ph920p6pR+XQ" - "zrk9oXT0jApMbKRcnpHJ6+ioXcY91haH53s701Pq0mgOtTwCKgSfs3ZQj/kJ5g53i0ihaDgc" - "/n9/C5Gmw+Hxbn/H8S+cD8xcYY4GnAAAAABJRU5ErkJggg==") - -#---------------------------------------------------------------------- -whidbey_dock_pane_left = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAF0AAABdCAMAAADwr5rxAAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFAAAAECBXFC9vECiQBS2oIDKMIDigC0CVJUqQIkewJFKlJlayMEiwMlSiK2G0JFTR" - "LmnSKGHmKHDoInDwMGjgNnDgNXLwSFeKQFizR2OkUGagaHWVcHiYZ3egZ3e1cHilUHjRQXLw" - "cYCncYa0dpC4R4DwU4PwZobHYIfTcYXGcIjVcpDBc5fWZpHxcZjgcJj3d6Dld6Pwi5Ozl6e3" - "q62xgIjQgpXEgJbUkJjAkJjQgKDXkqHCk6TWhafggqfwh7Dgh7Dwk6Xgk7Tkl7fwoKjAoKjW" - "qLDIp7fXsLDIsbbWoLfnoLjwsLjjl8D4pMLwscHnsMfxtdD0wMHg6tTN4Njk5eTo4Of35/D4" - "8Ofh9/f3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAA+wCLtAAAAQB0Uk5T////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn" - "4iUAAAeDSURBVGhDtZr/f9JGGMdprZPJnHSKm9OKI4DG0K5kWAptGIw5FGqpdQL5//+Q7Ply" - "d7kkR3L4ms8PWmjyzifP3T33PM+1FO1gQ6/u+DtcH5V2uPh86DmOvwt+B7p7etLpuE7jmb0g" - "e/qr09MTwDvOM3u8Nd3tdrunYIB3rPG2dIQzfRf1lnSCCzrgbX1vR2e4pNurt6IjfDTiJ3S7" - "JycezEwr39vQEb5OmuXMsaCT8vUn3dYdO/XFdPJ5hm7n+0K6OyJLaQ+CjtcsnjlFdAEfpfwO" - "9E6zWbhqC+gSPlrzKwgLR6Mg8IrV59MVXNIBi0b0fr9QfS49hgt6GDJevMmwKObk0fuaL4gH" - "cMZLOuBzfZ9Dv1xMp2P5AMETnlH0odN0Gtvj/Xb65QLpEr+NPmw2G9vxOdrn8+treAAYOmUM" - "Rh/AxvAJXyrAidmpf432KEI64aXLye9kGt3J2Qhz5wyqF/RRQjt8ENqDPHhBTlBM7+Ru4QVr" - "9epK+p49vgAT/gL5QeDm5wcm+n58y2ek89BOp4NLsmsynK2B24svvTQ8yEC/s6/wvc+fpe9n" - "s420W55N47G7CRV+vjDgs/Q7D+/fE/heCECeOQrNPyyXQHfxp96GNM/ni0U/oz5DP3iIdML3" - "QqRv5vPb9yk48fv8Jamn4R9lRiFNPzg8rCJ+j+BEX62ybMTLb3sRuQqXRRqfogP88BDo9/b2" - "LnDVJLhXV1czsPSzwh4NPS2BFD5JP3j0E1j1YeUeqE9SbmZTmikwdQaT5K942nJESuIT9INH" - "TK9WAL+n46+ubm54HqJNJpcaX1tyabxOBzjR0fWofl8ilkudTXHs7Vz+Ug8XafUaHeFEl+ol" - "frlcgmy5pjhKjueMX+mhjnzT1ZwT0w8eVcHwCfg/eqdc/hsBN2BMVNGeMH8pOj1Q7jNdDa/o" - "oDxDr/+LMw/gpDtDJ/wt/k7bIjHdVOolHd2SpFcrv9K7A50jTZoe0FrdGOgKL+jkcyMdRhTi" - "opEe0MzRvcLvEKtnOsJXutXQ7yRtRrNwHG9LIaVltO9xLCDPhPw1m8ITnZSv4M1XT9BqtRXS" - "f8ZbYaEwPZEDfxJ0ws/QaaHY3jHfXCv1SP+OmCl65elTvPWd2PuM9KGznd59BWSgf0/wtPYK" - "wYHO+/YW+i27JqWdyyCYOaXo5csamK79SW1V/fE+rVRc/DRXUnTMmjDduMCLBmb66XlUOm+3" - "k3T0vaLPbOiX8HIhjizmgOh3Kt9OTobDknt8nKCvVjiq1Qprp2wvRzs5XtEBr9E7npem07Tc" - "lQ4SwimnsDEdyuZ66WLUPW63flN+B+3o90qZtctlbvL7sO/58gXJMwnt0LBwgD46Pm614lHd" - "ge6l6MrvkF1C2eb7pWhwDeqBv/qorSapfTIRIcqkHRxL2yAODmqnzJ5GleANH+f7ACLDcbtt" - "pG/y6XWi44JL0FWjBddqf4r4BL1WuV8+Eo5XmjAYyHiDUcY7q+Mltwa6KHkozvTRNxl62Uhn" - "B4RMP8NL5teQDyTiDBbi1EfgGAnqf1+vtSBZk47fvA107R9l0RcMPc9rULBgOsVIESk92WIR" - "8R0KMJ45HCNrSC8/x3sDpotyOPzIrgmQ7hAd9lxtY8HwEJdqcm96MwXntFtM5m21Un5PvkE2" - "1DD0FPyfDdgsPUPXGhRqX33TpXmp6LhrM13ydDrNONrTl7hxyX01qVz6HX3v/onqdfqDB/8Q" - "XvBjegdmeqPxB8GXuLdo9ERrRctnoFWi06uVB/uYEyj1ko4LEfxC8M2mr2/mfS9Z3Ou5mBvg" - "qmo9Qbc/flyt3uX7N5vz875m2LdqsFvQXKV8NAJ6oq2SyCNJfatFdA2OCh1STNZsOs95QAWe" - "B2YIlm5LJHNgUk/0JBwwvn8Ghux6nSJjGg9wJ90QSuXvLvqG4b0kAj6dnTUaDT+Fxge7rD3b" - "kkjXHp0O8GHW38Xag/lfvmSeo77FlQWlTQfWkKmdkqmbmE5RQqiHusmAXy4H8C3DowiGxdQK" - "ytZ8r1+320dcvXHNd3O9eKeydfGcGywJIFcScMQ3DQ1QQ736uv2DLA1B/Rzpi/lcq5cgn4dq" - "AZZoX6tX66ZGioEe/RLXnR8+yGoG65nJ5B2YrJ+whLyILzV1aUz0+I7oA1RLXCuxcRUvvoNl" - "pNG1u9SP+XQuuCAESDp3ITiZp+CS34bIpcsil+mwxSqLg0suPo+ul4q08bCJ9J2kQ0bnmVwi" - "vsuhY2NBJkupXqrqrGLCmNNd2k4fkBtk5Db29FA7Rsyt6nO0w1Ye2xY6xsyv0g67FZ90cP+d" - "8oxEL5XTuSOxro36c+eMm6IjnhME/IfgTh68oKf3IqmdC4CYXnj6UbBWER97Rg0Day/qYOs5" - "gXngST08wXB2UKi8mB4xvps+96C0oPDMqcAz8ELs+/SJ0P90ZsP4DN1GuYVnhPpvdlYm1FMB" - "LTJUu5MyO+3S94IOZzW258PFo0ozVc571A7pnN0Jpa12oR5Phq3OyOTasdQu8RhbLM73dqZH" - "L1A3VQU5R0CpBW+tHdTj+gSzh+/0txC+73+7v4WIIt8/2u3vOP4D32mBB1S/lsMAAAAASUVO" - "RK5CYII=") - -#---------------------------------------------------------------------- -whidbey_dock_pane_right = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAF0AAABdCAMAAADwr5rxAAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFAAAAECBXFC9vECiQBS2oIDKMIDigC0CVJUqQIkewJFKlJlayMEiwMlSiK2G0JFTR" - "LmnSKGHmKHDoInDwMGjgNnDgNXLwSFeKQFizR2OkUGagaHWVcHiYZ3egZ3e1cHilUHjRQXLw" - "cYCncYa0dpC4R4DwU4PwZobHYIfTcYXGcIjVcpDBc5fWZpHxcZjgcJj3d6Dld6Pwi5Ozl6e3" - "q62xgIjQgpXEgJbUkJjAkJjQgJjggKDXkqHCk6TWhafggqfwh7Dgh7Dwk6Xgk7Tkl7fwoKjA" - "oKjWqLDIp7fXsLDIsbbWoLfnoLjwsLjjl8D4pMLwscHnsMfxtdD0wMHg6tTN4Njk5eTo4Of3" - "5/D48Ofh9/f3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAaHenigAAAQB0Uk5T////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn" - "4iUAAAe+SURBVGhDtZr/W9pWFMYtW1en67RzunWdpUvQlgWdMCoyJFkotbaRCrMryP//f2Tn" - "yz25N19ILn2enV8Qkn7y5s2555570414jRh4dbezxvnxxhonXww81+2sg1+D3jw7bbWarvPM" - "XpA9/eXZ2SngXfeZPd6a3my322cQgHet8bZ0hDN9HfWWdIIrOuBtvbejM1zo9uqt6AgPAr5C" - "u3166kFmWnlvQ0f4Ih2WmWNBJ+WLf8xYtOzUV9PJ8xzdzvtKejOgyGj3/ZbXqM6cKrqCBxnf" - "gd5qNCpHbQVd4MGCb0HFMgh836tWX05P4EIHLAbRe71K9aV0DVf05ZLx6k4GVTWnjN4zvCAe" - "wBkvdMCXel9CH96Mx6FcQPGUMwl94DZcZ3W9X00f3iBd8Kvog0bDWY0v0R5Ft7dwAQg0JYSg" - "LxAhfMOb8jExW/Uv0R7HSCe8WE6+Uxh0t2QiLM0ZVK/oQUo7fFHa/TJ4RU9QTW+VTuEVY3Uy" - "Ee/Z8RsI5RfI9/1meX9QRB/pf/IJ6fxox+P+kOKWArPVb3b1qT8XXKiAPhol+O6nT+L99fW9" - "xB1nUxg275cJ/rvjV3l8nj6d3Y57fGJ3CUDOnATNf0ynQG/iX917OjU6Pn6Vx+foU6QzvrtE" - "+n0U3b3PwInf4x9JfbR/cHzSzj3iLB3Y5OlrghN9Ps+zES+/duO7h/tMz+IzdFSOKR6Gl5c4" - "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" - "AABJRU5ErkJggg==") - -#---------------------------------------------------------------------- -whidbey_dock_pane_top = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAF0AAABdCAMAAADwr5rxAAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFAAAAECBXFC9vECiQBS2oIDKMIDigC0CVJUqQIkewJFKlJlayMEiwMlSiK2G0JFTR" - "LmnSKGHmKHDoInDwMGjgNnDgNXLwSFeKQFizR2OkUGagaHWVcHiYZ3egZ3e1cHilUHjRQXLw" - "cYCncYa0dpC4R4DwU4PwZobHYIfTcYXGcIjVcpDBc5fWZpHxcZjgcJj3d6Dld6Pwi5Ozl6e3" - "q62xgIjQgpXEgJbUkJjAkJjQgJjggKDXkqHCk6TWhafggqfwh7Dgh7Dwk6Xgk7Tkl7fwoKjA" - "oKjWqLDIp7fXsLDIsbbWoLfnoLjwsLjjl8D4pMLwscHnsMfxtdD0wMHg6tTN4Njk5eTo4Of3" - "5/D48Ofh9/f3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAaHenigAAAQB0Uk5T////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn" - "4iUAAAe1SURBVGhDpZkNexJHEMcxrTVNao3G0PoSaXmJ4l1soBhCCUdBmkaPCDFWCN//e1z/" - "M7O7t/fC3aHzPMqFu/3t/2ZnZmeTUrCBnZ83m2cbPB+UNni4NxweHx/9tsGIDei92bBF9B+L" - "44vTu6T8AFb+oTC+ML07gfIjppe/L4ovSofy1nGjIfT9oviC9O6kBZ83flf0ovhi9NccLY2y" - "sv39gvhC9NeT4R/HR5q+Xwa9GL4IvQmvLBcRK4gvQG/+DZcvP8JG2hYF1efTSflxY2HIdLHY" - "gxVwTi696VGCptLz8Xl0Ud4oR90u2vOXNodOyjlYFjoa+VPT89Rn010ol+xXdP1Bq/oI9jA7" - "azPprguX23T4R7QbejY+i/6q1YJXpLYwlZ0foz/4LqOkZdBfvaJgaZQzPbP3IAu/nv7rEYxi" - "g+xgIfVrgX+44FV99HAP7J2dra216jO0/3RULkfpPAP9p+lg37u3Hp65r/oHByE9GvDy/e4u" - "2Bnw7F3bD+kQbGbS1w/y4Dk9wd29vcePtc5dtp9/1rOQ8jt3MjfBnFwlPLtgd2dnG7YD291V" - "88Et2fBU7eNQz2fgiU3kLWVPnhBflHfCRwcpb5GifTw2+M5n4Mkf21vbh7fanvzCPoLy25XB" - "+9MUfJI+v55NuqKjswLw7v3729vPDVounj6ld6Grzi0/6vvTqRplvUOCPie64Dsrot9u3X//" - "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" - "gg==") - -#---------------------------------------------------------------------- -whidbey_left = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB4AAAArCAMAAABYWciOAAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFAAAAaHWVZ3egZ3e1cHilcYCncYa0dpC4ZobHcYXGcpDBc5fWd6Dld6Pwi5OzgIjQ" - "gJbUkJjQgJjggKDXkqHCk6TWhafggqfwh7Dwk6Xgk7Tkl7fwoKjWqLDIoLfnpMLwscHnsMfx" - "tdD04Njk5/D49/f3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAQ3JLMwAAAQB0Uk5T////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn" - "4iUAAAF4SURBVDhPfdTbdoIwEAVQL6htAi0tElBaoVb+/xPTM5M7wc6LLvc6GTIJbnRel/DT" - "ZkUvwXOefsahdqGMJ2LvSwaO4P7d5BdMWejQ9+dzzhOiY4/quu4z44kYSebudbH4REwLm7Q6" - "Jr2hk+lrGR4e7Rb17ZRSdV23v55vxL4vsRCBOesXRrquBbZm0yb7jIHD/EDNKPpUjRBvbmOU" - "Heb7/f6g/aISJhz6R8J4MJvmbM6FGSrPmRaM09i0YZ4zDdHxTN8909I8RMtzyu3NztgwbyxK" - "qytlq6pK0qqROC/0vipGzx0v7ll/MAY2Y1G1SWv9UpXlCvNlpiPZlyjX2w4VJ/rlZk7+D3Oe" - "DsoXwqoNV5HzKHtidJlUC3eXifuXZcxNE91U4xFLIb6jm8oeWIKLcFPN/jxLKY/HhM3+TUl5" - "OhU48eQN9Y6VTwe6D+kLbJ0W3m5X3m926ntgXb7+eg/z2ZzJhcuusN4Lsds9/WfSuhBes94U" - "C6r/AM3yZVcU56/qAAAAAElFTkSuQmCC") - -#---------------------------------------------------------------------- -whidbey_left_single = whidbey_left - -#---------------------------------------------------------------------- -whidbey_left_focus = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB4AAAArCAMAAABYWciOAAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFAAAAECBXFC9vECiQBS2oIDKMIDigC0CVJUqQIkewJFKlJlayMEiwMlSiK2G0JFTR" - "LmnSKGHmKHDoInDwMGjgNnDgNXLwSFeKQFizR2OkUGagcHiYZ3egcHilUHjRQXLwR4DwU4Pw" - "YIfTcYXGcIjVc5fWZpHxcJj3d6PwgJbUkJjAkJjQkqHChafggqfwh7Dgh7Dwl7fwoKjAqLDI" - "sLDIl8D4pMLw4Of35/D4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAQS37pgAAAQB0Uk5T////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn" - "4iUAAAGNSURBVDhPfdRrW8IgFAdwLyuXZLIUy67D6dK0pd3w+38xOuewAYOMN3ue/fbnwHZG" - "R8ej5251Yu33nMfcHw8H1iNOxsiNh5xkGUfvmqIBg2YZ8KBrvM3J5BoGH7NBnW9xMjHMGTjl" - "fQYlxvKYh/V5jErc5MEdJxMOAx/BKxZI0w/LkI340aZx5jZzdmdrU92TjKr8IbB2szHKqv1+" - "r2Y4hFDINzWf082A2Xxu+II0TDNU4KcnAcNPz4TiV0P6pp1XKduM9R0XZdlipXBpnNXpgGl3" - "Hu+qdSnzZ1sb0libpab2rqrKMs/d0tqstz+QhwfUt/dabFrrbYXzy1OsNwf0Fgs2TB+ad77B" - "6SNOba9B/uV49D6ZqIvX3bJp1m++mEBO710rLg8wv8wNmVZj6ZdrxeWatmcZW9FjXbxj3ufR" - "6NPr8wLyHnM28vtc6+INX08+w9LTKednwS9I+TwnJg3+UMoTGw3/7wKndxqyXq3gAdg9ZaO0" - "1oab8yo+mRYLKe1p9se5tpCX/7G+dUfhL8vucupsrDz0AAAAAElFTkSuQmCC") - -#---------------------------------------------------------------------- -whidbey_left_focus_single = whidbey_left_focus - -#---------------------------------------------------------------------- -whidbey_right = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB4AAAArCAMAAABYWciOAAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFAAAAaHWVcHilcYCncYa0dpC4ZobHcYXGcpDBc5fWcZjgd6Dld6Pwi5OzgJbUkJjA" - "kJjQgKDXk6TWhafggqfwh7Dwl7fwp7fXoLfnoLjwsLjjpMLwscHntdD0wMHg4Of35/D49/f3" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAWZqHkAAAAQB0Uk5T////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn" - "4iUAAAFySURBVDhPddPbeoIwDABglDqoFDcVGBVw8P4PyXJoQ0sxN+L3m0NDzVaJx/YoT5k8" - "9fbAhfve2luS77kfhq5rir077pkTZ34Ng7Vt2yRO/ELuUPeOTIWxdOrA3Fc46p/9AVobsgnm" - "Z0b1xRsTeLa+EV1f+jCBQ+8DlnzgsDBX2fLxYFR8WeYtxJF/u65tF95KM0/TNEv+ZzZfkElL" - "TbKhuDEVnJ/4Z1+cufpmfsBwC47newNV1fV6v8cMTqMx67Jkhs0s3YIRsNbqHDCePczWhVIx" - "S28NoVRdRyxrMaR5zZPjdcDJha+opxOf+33ACthtrR/glkY7LzmXs5npjbn3VqqcFHmE2i0E" - "934+fd9PjKXdvylbR7yn/q7FuVB8HOF9uMJUOsjF3retb9PcysuFZ+aA0QrJJXYzC6/Fk+IO" - "Eee628IOquJcx5wP6nYV9cYvGpYBKucNRqNHpfW+r9+580uS63vjD855vvXcF4fvB7r+A9+i" - "Xf4K/oDaAAAAAElFTkSuQmCC") - -#---------------------------------------------------------------------- -whidbey_right_single = whidbey_right - -#---------------------------------------------------------------------- -whidbey_right_focus = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAAB4AAAArCAMAAABYWciOAAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFAAAAECBXFC9vECiQBS2oIDKMIDigC0CVJUqQIkewJFKlJlayMEiwMlSiK2G0JFTR" - "LmnSKGHmKHDoInDwMGjgNnDgNXLwSFeKQFizR2OkUGagcHiYZ3egcHilUHjRQXLwR4DwU4Pw" - "YIfTcYXGcIjVc5fWZpHxcJj3d6PwgJbUkJjAkJjQkqHChafggqfwh7Dgh7Dwl7fwoKjAqLDI" - "sLDIl8D4pMLw4Of35/D4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAQS37pgAAAQB0Uk5T////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn" - "4iUAAAGXSURBVDhPdZTZVoNADEDpaC2CFSqC1hVaxWoVqdv0/39szDIraF7gcHuTTCankbJx" - "6V7tW2TfTprVmDvcNKsxt7ismnbzOPQ1npaMh5zxNMdo4Afr0CfMNK8Bv4UcMdBzwshDHzBS" - "wlWN6QM/UmKecu68hBj40ed8nmrOuN28u/qR+op9XNfANw+mf8asow31ge8Mh9au4zhlRIF+" - "1z2zjwcTiKWL/f6p2zFHHMdJWkpty77/lpCffcQ3IwzHY5+GitkDG8fTddv/MB2v+9n6dlVJ" - "aBxq9/Dk/l+95IDgu8b3eD0GJ1ibTmYwzqFt12wTLn07xKc51XW16XqaF20D1jPVtRHf3XHn" - "Sxyqm1ovC5r+MZ97OcJEj/TULuA+B3ZRFIdm5njd/o1JaSgmvzK7Bh8LXAt8kku1/8KaAr61" - "u+ZsQ1X0Aauks1tsKdhCzGb4gzMKr66uTTzLFwuNnctjmUycb3t2m6om7JPtu3qZyE+yBURI" - "+UogvwAM5QfUYOw/ybIhtVghPuBUXrg/LiHG1NmwcSNXqV+4tHLqnJPo+QAAAABJRU5ErkJg" - "gg==") - -#---------------------------------------------------------------------- -whidbey_right_focus_single = whidbey_right_focus - -#---------------------------------------------------------------------- -whidbey_up = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACsAAAAeCAMAAACCNBfsAAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFAAAAaHWVcHilcYCncYa0dpC4ZobHcYXGcpDBc5fWcZjgd6Dld6Pwi5OzgJbUkJjA" - "kJjQgKDXk6TWhafggqfwh7Dwl7fwp7fXoLfnoLjwsLjjpMLwscHntdD0wMHg4Of35/D49/f3" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAWZqHkAAAAQB0Uk5T////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn" - "4iUAAAFmSURBVDhPhdTtdoMgDAZgW3GKWjsL2i/X2vu/SJaEBBXcWf6Jz3l5i9bMpdNXR3Xa" - "Wc/StXNfKXXawaktm1rrUuWHJCWxX01TA1bqkODYlm3bNjCAVYwji9TbneStJcoWcNR5Yz0V" - "mySvLVJrvW/buq7g7NadVxbpvJ3taSyWUuef9cx6kxwsdU3sprPY0tJEucboqginwZapjfqC" - "1UUhT9BboXb28Twfa42pQjLZQMUCwiHbdZKMdqFsPx+PeZee3w2w3WpXugvUY7GAsXPmLvdx" - "HITzXe4QbK8Klbvsckcr+C/bF0WeZ+52ez6Bw+D2AwxdwAxwhRsaPDp9hA4OLWGpSn1pVlZh" - "X8Cg2dpNLlxwrgFKFpP/sRqZf26Ph3T2Te8w3AyijSlJ8fuA1v/Acfy+0Dxp8DyZig2dr9fw" - "WXj5ExoGnxpy5TSi78c0gRUacvE0XjvfsGnqwuryH3q/d6hz07L6CxOEXf5LAPv7AAAAAElF" - "TkSuQmCC") - -#---------------------------------------------------------------------- -whidbey_up_single = whidbey_up - -#---------------------------------------------------------------------- -whidbey_up_focus = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAACsAAAAeCAMAAACCNBfsAAAAAXNSR0IArs4c6QAAAARnQU1B" - "AACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA" - "AwBQTFRFAAAAECBXFC9vECiQBS2oIDKMIDigC0CVJUqQIkewJFKlJlayMEiwMlSiK2G0JFTR" - "LmnSKGHmKHDoInDwMGjgNnDgNXLwSFeKQFizR2OkUGagcHiYZ3egcHilUHjRQXLwR4DwU4Pw" - "YIfTcYXGcIjVc5fWZpHxcJj3d6PwgJbUkJjAkJjQkqHChafggqfwh7Dgh7Dwl7fwoKjAqLDI" - "sLDIl8D4pMLw4Of35/D4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAQS37pgAAAQB0Uk5T////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////////////////////////////////////////////////////////" - "////////////////////AFP3ByUAAAAYdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My4zNqnn" - "4iUAAAGTSURBVDhPfdQNV4IwFAZgpEyCVBRZaR8OUcI0yrLw//8xuvfuy22e7jkKZz68uxtg" - "0Pm135fl24XxwB/bNU1VFS/+D77d/TY12lsPe3aLqTkUu3Gxa7cHSC3IsmsHOxZS64pzYTMH" - "23Z7qKFXvpTWwZZd0w5wJivLbHxu14fmtSqUzRhYC5/ZEuY/tVbZ2NjyA1o9/UB9qmrtZG0x" - "teKtdnjSplCmDWXLd7xZF63G0opUzux2Ra5eoLCYShvQqv2io7IymewGUsV9lVYdcG1TqAnd" - "QbSbDbR6bqETkastYbCruob5xTNAhpp27PgK7WqFG8DZvz2kY8DBQwGF68XKW/HUtPCBE1rb" - "dJKCjOMwDLq7gjHbkscvZUEOBiGtLc+NtTdYjCcJyFDsQ2cshOnr1PlYUmH7aTqbqYyEajRS" - "12Bqr6f2V2CaLInjCCqGShJ5NTRAVOQSRokulDWfozap2gLGmaMwetIv7/yeulGpxnb94TCK" - "Hp23fLHAedSgeS/C4fHo/y89R5qqfhF9+xJGvszoH5Xccuo6pVT3AAAAAElFTkSuQmCC") - -#---------------------------------------------------------------------- -whidbey_up_focus_single = whidbey_up_focus - -#---------------------------------------------------------------------- - -whidbey_denied = aero_denied - -#---------------------------------------------------------------------- - -# ------------------------ # -# - AuiToolBar Constants - # -# ------------------------ # - -ITEM_CONTROL = wx.ITEM_MAX -""" The item in the AuiToolBar is a control. """ -ITEM_LABEL = ITEM_CONTROL + 1 -""" The item in the AuiToolBar is a text label. """ -ITEM_SPACER = ITEM_CONTROL + 2 -""" The item in the AuiToolBar is a spacer. """ -ITEM_SEPARATOR = wx.ITEM_SEPARATOR -""" The item in the AuiToolBar is a separator. """ -ITEM_CHECK = wx.ITEM_CHECK -""" The item in the AuiToolBar is a toolbar check item. """ -ITEM_NORMAL = wx.ITEM_NORMAL -""" The item in the AuiToolBar is a standard toolbar item. """ -ITEM_RADIO = wx.ITEM_RADIO -""" The item in the AuiToolBar is a toolbar radio item. """ -ID_RESTORE_FRAME = wx.ID_HIGHEST + 10000 -""" Identifier for restoring a minimized pane. """ - -BUTTON_DROPDOWN_WIDTH = 10 -""" Width of the drop-down button in AuiToolBar. """ - -DISABLED_TEXT_GREY_HUE = 153.0 -""" Hue text colour for the disabled text in AuiToolBar. """ -DISABLED_TEXT_COLOUR = wx.Colour(DISABLED_TEXT_GREY_HUE, - DISABLED_TEXT_GREY_HUE, - DISABLED_TEXT_GREY_HUE) -""" Text colour for the disabled text in AuiToolBar. """ - -AUI_TB_TEXT = 1 << 0 -""" Shows the text in the toolbar buttons; by default only icons are shown. """ -AUI_TB_NO_TOOLTIPS = 1 << 1 -""" Don't show tooltips on `AuiToolBar` items. """ -AUI_TB_NO_AUTORESIZE = 1 << 2 -""" Do not auto-resize the `AuiToolBar`. """ -AUI_TB_GRIPPER = 1 << 3 -""" Shows a gripper on the `AuiToolBar`. """ -AUI_TB_OVERFLOW = 1 << 4 -""" The `AuiToolBar` can contain overflow items. """ -AUI_TB_VERTICAL = 1 << 5 -""" The `AuiToolBar` is vertical. """ -AUI_TB_HORZ_LAYOUT = 1 << 6 -""" Shows the text and the icons alongside, not vertically stacked. -This style must be used with ``AUI_TB_TEXT``. """ -AUI_TB_PLAIN_BACKGROUND = 1 << 7 -""" Don't draw a gradient background on the toolbar. """ -AUI_TB_CLOCKWISE = 1 << 8 -AUI_TB_COUNTERCLOCKWISE = 1 << 9 - -AUI_TB_HORZ_TEXT = AUI_TB_HORZ_LAYOUT | AUI_TB_TEXT -""" Combination of ``AUI_TB_HORZ_LAYOUT`` and ``AUI_TB_TEXT``. """ -AUI_TB_VERT_TEXT = AUI_TB_VERTICAL | AUI_TB_CLOCKWISE | AUI_TB_TEXT - -AUI_TB_DEFAULT_STYLE = 0 -""" `AuiToolBar` default style. """ - -# AuiToolBar settings -AUI_TBART_SEPARATOR_SIZE = 0 -""" Separator size in AuiToolBar. """ -AUI_TBART_GRIPPER_SIZE = 1 -""" Gripper size in AuiToolBar. """ -AUI_TBART_OVERFLOW_SIZE = 2 -""" Overflow button size in AuiToolBar. """ - -# AuiToolBar text orientation -AUI_TBTOOL_TEXT_LEFT = 0 # unused/unimplemented -""" Text in AuiToolBar items is aligned left. """ -AUI_TBTOOL_TEXT_RIGHT = 1 -""" Text in AuiToolBar items is aligned right. """ -AUI_TBTOOL_TEXT_TOP = 2 # unused/unimplemented -""" Text in AuiToolBar items is aligned top. """ -AUI_TBTOOL_TEXT_BOTTOM = 3 -""" Text in AuiToolBar items is aligned bottom. """ - -# AuiToolBar tool orientation -AUI_TBTOOL_HORIZONTAL = 0 # standard -AUI_TBTOOL_VERT_CLOCKWISE = 1 # rotation of 90 on the right -AUI_TBTOOL_VERT_COUNTERCLOCKWISE = 2 # rotation of 90 on the left - - -# --------------------- # -# - AuiMDI* Constants - # -# --------------------- # - -wxWINDOWCLOSE = 4001 -""" Identifier for the AuiMDI "close window" menu. """ -wxWINDOWCLOSEALL = 4002 -""" Identifier for the AuiMDI "close all windows" menu. """ -wxWINDOWNEXT = 4003 -""" Identifier for the AuiMDI "next window" menu. """ -wxWINDOWPREV = 4004 -""" Identifier for the AuiMDI "previous window" menu. """ - -# ----------------------------- # -# - AuiDockingGuide Constants - # -# ----------------------------- # - -colourTargetBorder = wx.Colour(180, 180, 180) -colourTargetShade = wx.Colour(206, 206, 206) -colourTargetBackground = wx.Colour(224, 224, 224) -colourIconBorder = wx.Colour(82, 65, 156) -colourIconBackground = wx.Colour(255, 255, 255) -colourIconDockingPart1 = wx.Colour(215, 228, 243) -colourIconDockingPart2 = wx.Colour(180, 201, 225) -colourIconShadow = wx.Colour(198, 198, 198) -colourIconArrow = wx.Colour(77, 79, 170) -colourHintBackground = wx.Colour(0, 64, 255) -guideSizeX, guideSizeY = 29, 32 -aeroguideSizeX, aeroguideSizeY = 31, 32 -whidbeySizeX, whidbeySizeY = 43, 30 - -# ------------------------------- # -# - AuiSwitcherDialog Constants - # -# ------------------------------- # - -SWITCHER_TEXT_MARGIN_X = 4 -SWITCHER_TEXT_MARGIN_Y = 1 diff --git a/agw/aui/aui_switcherdialog.py b/agw/aui/aui_switcherdialog.py deleted file mode 100644 index 552cb84..0000000 --- a/agw/aui/aui_switcherdialog.py +++ /dev/null @@ -1,1216 +0,0 @@ -""" -Description -=========== - -The idea of `SwitcherDialog` is to make it easier to implement keyboard -navigation in AUI and other applications that have multiple panes and -tabs. - -A key combination with a modifier (such as ``Ctrl`` + ``Tab``) shows the -dialog, and the user holds down the modifier whilst navigating with -``Tab`` and arrow keys before releasing the modifier to dismiss the dialog -and activate the selected pane. - -The switcher dialog is a multi-column menu with no scrolling, implemented -by the `MultiColumnListCtrl` class. You can have headings for your items -for logical grouping, and you can force a column break if you need to. - -The modifier used for invoking and dismissing the dialog can be customised, -as can the colours, number of rows, and the key used for cycling through -the items. So you can use different keys on different platforms if -required (especially since ``Ctrl`` + ``Tab`` is reserved on some platforms). - -Items are shown as names and optional 16x16 images. - - -Base Functionalities -==================== - -To use the dialog, you set up the items in a `SwitcherItems` object, -before passing this to the `SwitcherDialog` instance. - -Call L{SwitcherItems.AddItem} and optionally L{SwitcherItems.AddGroup} to add items and headings. These -functions take a label (to be displayed to the user), an identifying name, -an integer id, and a bitmap. The name and id are purely for application-defined -identification. You may also set a description to be displayed when each -item is selected; and you can set a window pointer for convenience when -activating the desired window after the dialog returns. - -Have created the dialog, you call `ShowModal()`, and if the return value is -``wx.ID_OK``, retrieve the selection from the dialog and activate the pane. - -The sample code below shows a generic method of finding panes and notebook -tabs within the current L{AuiManager}, and using the pane name or notebook -tab position to display the pane. - -The only other code to add is a menu item with the desired accelerator, -whose modifier matches the one you pass to L{SwitcherDialog.SetModifierKey} -(the default being ``wx.WXK_CONTROL``). - - -Usage -===== - -Menu item:: - - if wx.Platform == "__WXMAC__": - switcherAccel = "Alt+Tab" - elif wx.Platform == "__WXGTK__": - switcherAccel = "Ctrl+/" - else: - switcherAccel = "Ctrl+Tab" - - view_menu.Append(ID_SwitchPane, _("S&witch Window...") + "\t" + switcherAccel) - - -Event handler:: - - def OnSwitchPane(self, event): - - items = SwitcherItems() - items.SetRowCount(12) - - # Add the main windows and toolbars, in two separate columns - # We'll use the item 'id' to store the notebook selection, or -1 if not a page - - for k in xrange(2): - if k == 0: - items.AddGroup(_("Main Windows"), "mainwindows") - else: - items.AddGroup(_("Toolbars"), "toolbars").BreakColumn() - - for pane in self._mgr.GetAllPanes(): - name = pane.name - caption = pane.caption - - toolbar = isinstance(info.window, wx.ToolBar) or isinstance(info.window, aui.AuiToolBar) - if caption and (toolBar and k == 1) or (not toolBar and k == 0): - items.AddItem(caption, name, -1).SetWindow(pane.window) - - # Now add the wxAuiNotebook pages - - items.AddGroup(_("Notebook Pages"), "pages").BreakColumn() - - for pane in self._mgr.GetAllPanes(): - nb = pane.window - if isinstance(nb, aui.AuiNotebook): - for j in xrange(nb.GetPageCount()): - - name = nb.GetPageText(j) - win = nb.GetPage(j) - - items.AddItem(name, name, j, nb.GetPageBitmap(j)).SetWindow(win) - - # Select the focused window - - idx = items.GetIndexForFocus() - if idx != wx.NOT_FOUND: - items.SetSelection(idx) - - if wx.Platform == "__WXMAC__": - items.SetBackgroundColour(wx.WHITE) - - # Show the switcher dialog - - dlg = SwitcherDialog(items, wx.GetApp().GetTopWindow()) - - # In GTK+ we can't use Ctrl+Tab; we use Ctrl+/ instead and tell the switcher - # to treat / in the same was as tab (i.e. cycle through the names) - - if wx.Platform == "__WXGTK__": - dlg.SetExtraNavigationKey(wxT('/')) - - if wx.Platform == "__WXMAC__": - dlg.SetBackgroundColour(wx.WHITE) - dlg.SetModifierKey(wx.WXK_ALT) - - ans = dlg.ShowModal() - - if ans == wx.ID_OK and dlg.GetSelection() != -1: - item = items.GetItem(dlg.GetSelection()) - - if item.GetId() == -1: - info = self._mgr.GetPane(item.GetName()) - info.Show() - self._mgr.Update() - info.window.SetFocus() - - else: - nb = item.GetWindow().GetParent() - win = item.GetWindow(); - if isinstance(nb, aui.AuiNotebook): - nb.SetSelection(item.GetId()) - win.SetFocus() - - -""" - -import wx - -import auibook -from aui_utilities import FindFocusDescendant -from aui_constants import SWITCHER_TEXT_MARGIN_X, SWITCHER_TEXT_MARGIN_Y - - -# Define a translation function -_ = wx.GetTranslation - - -class SwitcherItem(object): - """ An object containing information about one item. """ - - def __init__(self, item=None): - """ Default class constructor. """ - - self._id = 0 - self._isGroup = False - self._breakColumn = False - self._rowPos = 0 - self._colPos = 0 - self._window = None - self._description = "" - - self._textColour = wx.NullColour - self._bitmap = wx.NullBitmap - self._font = wx.NullFont - - if item: - self.Copy(item) - - - def Copy(self, item): - """ - Copy operator between 2 L{SwitcherItem} instances. - - :param `item`: another instance of L{SwitcherItem}. - """ - - self._id = item._id - self._name = item._name - self._title = item._title - self._isGroup = item._isGroup - self._breakColumn = item._breakColumn - self._rect = item._rect - self._font = item._font - self._textColour = item._textColour - self._bitmap = item._bitmap - self._description = item._description - self._rowPos = item._rowPos - self._colPos = item._colPos - self._window = item._window - - - def SetTitle(self, title): - - self._title = title - return self - - - def GetTitle(self): - - return self._title - - - def SetName(self, name): - - self._name = name - return self - - - def GetName(self): - - return self._name - - - def SetDescription(self, descr): - - self._description = descr - return self - - - def GetDescription(self): - - return self._description - - - def SetId(self, id): - - self._id = id - return self - - - def GetId(self): - - return self._id - - - def SetIsGroup(self, isGroup): - - self._isGroup = isGroup - return self - - - def GetIsGroup(self): - - return self._isGroup - - - def BreakColumn(self, breakCol=True): - - self._breakColumn = breakCol - return self - - - def GetBreakColumn(self): - - return self._breakColumn - - - def SetRect(self, rect): - - self._rect = rect - return self - - - def GetRect(self): - - return self._rect - - - def SetTextColour(self, colour): - - self._textColour = colour - return self - - - def GetTextColour(self): - - return self._textColour - - - def SetFont(self, font): - - self._font = font - return self - - - def GetFont(self): - - return self._font - - - def SetBitmap(self, bitmap): - - self._bitmap = bitmap - return self - - - def GetBitmap(self): - - return self._bitmap - - - def SetRowPos(self, pos): - - self._rowPos = pos - return self - - - def GetRowPos(self): - - return self._rowPos - - - def SetColPos(self, pos): - - self._colPos = pos - return self - - - def GetColPos(self): - - return self._colPos - - - def SetWindow(self, win): - - self._window = win - return self - - - def GetWindow(self): - - return self._window - - -class SwitcherItems(object): - """ An object containing switcher items. """ - - def __init__(self, items=None): - """ Default class constructor. """ - - self._selection = -1 - self._rowCount = 10 - self._columnCount = 0 - - self._backgroundColour = wx.NullColour - self._textColour = wx.NullColour - self._selectionColour = wx.NullColour - self._selectionOutlineColour = wx.NullColour - self._itemFont = wx.NullFont - - self._items = [] - - if wx.Platform == "__WXMSW__": - # If on Windows XP/Vista, use more appropriate colours - self.SetSelectionOutlineColour(wx.Colour(49, 106, 197)) - self.SetSelectionColour(wx.Colour(193, 210, 238)) - - if items: - self.Copy(items) - - - def Copy(self, items): - """ - Copy operator between 2 L{SwitcherItems}. - - :param `items`: another instance of L{SwitcherItems}. - """ - - self.Clear() - - for item in items._items: - self._items.append(item) - - self._selection = items._selection - self._rowCount = items._rowCount - self._columnCount = items._columnCount - - self._backgroundColour = items._backgroundColour - self._textColour = items._textColour - self._selectionColour = items._selectionColour - self._selectionOutlineColour = items._selectionOutlineColour - self._itemFont = items._itemFont - - - def AddItem(self, titleOrItem, name=None, id=0, bitmap=wx.NullBitmap): - - if isinstance(titleOrItem, SwitcherItem): - self._items.append(titleOrItem) - return self._items[-1] - - item = SwitcherItem() - item.SetTitle(titleOrItem) - item.SetName(name) - item.SetId(id) - item.SetBitmap(bitmap) - - self._items.append(item) - return self._items[-1] - - - def AddGroup(self, title, name, id=0, bitmap=wx.NullBitmap): - - item = self.AddItem(title, name, id, bitmap) - item.SetIsGroup(True) - - return item - - - def Clear(self): - - self._items = [] - - - def FindItemByName(self, name): - - for i in xrange(len(self._items)): - if self._items[i].GetName() == name: - return i - - return wx.NOT_FOUND - - - def FindItemById(self, id): - - for i in xrange(len(self._items)): - if self._items[i].GetId() == id: - return i - - return wx.NOT_FOUND - - - def SetSelection(self, sel): - - self._selection = sel - - - def SetSelectionByName(self, name): - - idx = self.FindItemByName(name) - if idx != wx.NOT_FOUND: - self.SetSelection(idx) - - - def GetSelection(self): - - return self._selection - - - def GetItem(self, i): - - return self._items[i] - - - def GetItemCount(self): - - return len(self._items) - - - def SetRowCount(self, rows): - - self._rowCount = rows - - - def GetRowCount(self): - - return self._rowCount - - - def SetColumnCount(self, cols): - - self._columnCount = cols - - - def GetColumnCount(self): - - return self._columnCount - - - def SetBackgroundColour(self, colour): - - self._backgroundColour = colour - - - def GetBackgroundColour(self): - - return self._backgroundColour - - - def SetTextColour(self, colour): - - self._textColour = colour - - - def GetTextColour(self): - - return self._textColour - - - def SetSelectionColour(self, colour): - - self._selectionColour = colour - - - def GetSelectionColour(self): - - return self._selectionColour - - - def SetSelectionOutlineColour(self, colour): - - self._selectionOutlineColour = colour - - - def GetSelectionOutlineColour(self): - - return self._selectionOutlineColour - - - def SetItemFont(self, font): - - self._itemFont = font - - - def GetItemFont(self): - - return self._itemFont - - - def PaintItems(self, dc, win): - - backgroundColour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE) - standardTextColour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT) - selectionColour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT) - selectionOutlineColour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT) - standardFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) - groupFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) - groupFont.SetWeight(wx.BOLD) - - if self.GetBackgroundColour().IsOk(): - backgroundColour = self.GetBackgroundColour() - - if self.GetTextColour().IsOk(): - standardTextColour = self.GetTextColour() - - if self.GetSelectionColour().IsOk(): - selectionColour = self.GetSelectionColour() - - if self.GetSelectionOutlineColour().IsOk(): - selectionOutlineColour = self.GetSelectionOutlineColour() - - if self.GetItemFont().IsOk(): - - standardFont = self.GetItemFont() - groupFont = wx.Font(standardFont.GetPointSize(), standardFont.GetFamily(), standardFont.GetStyle(), - wx.BOLD, standardFont.GetUnderlined(), standardFont.GetFaceName()) - - textMarginX = SWITCHER_TEXT_MARGIN_X - - dc.SetLogicalFunction(wx.COPY) - dc.SetBrush(wx.Brush(backgroundColour)) - dc.SetPen(wx.TRANSPARENT_PEN) - dc.DrawRectangleRect(win.GetClientRect()) - dc.SetBackgroundMode(wx.TRANSPARENT) - - for i in xrange(len(self._items)): - item = self._items[i] - if i == self._selection: - dc.SetPen(wx.Pen(selectionOutlineColour)) - dc.SetBrush(wx.Brush(selectionColour)) - dc.DrawRectangleRect(item.GetRect()) - - clippingRect = wx.Rect(*item.GetRect()) - clippingRect.Deflate(1, 1) - - dc.SetClippingRect(clippingRect) - - if item.GetTextColour().IsOk(): - dc.SetTextForeground(item.GetTextColour()) - else: - dc.SetTextForeground(standardTextColour) - - if item.GetFont().IsOk(): - dc.SetFont(item.GetFont()) - else: - if item.GetIsGroup(): - dc.SetFont(groupFont) - else: - dc.SetFont(standardFont) - - w, h = dc.GetTextExtent(item.GetTitle()) - x = item.GetRect().x - - x += textMarginX - - if not item.GetIsGroup(): - if item.GetBitmap().IsOk() and item.GetBitmap().GetWidth() <= 16 \ - and item.GetBitmap().GetHeight() <= 16: - x -= textMarginX - dc.DrawBitmap(item.GetBitmap(), x, item.GetRect().y + \ - (item.GetRect().height - item.GetBitmap().GetHeight())/2, - True) - x += 16 + textMarginX - #x += textMarginX - - y = item.GetRect().y + (item.GetRect().height - h)/2 - dc.DrawText(item.GetTitle(), x, y) - dc.DestroyClippingRegion() - - - def CalculateItemSize(self, dc): - - # Start off allowing for an icon - sz = wx.Size(150, 16) - standardFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) - groupFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) - groupFont.SetWeight(wx.BOLD) - - textMarginX = SWITCHER_TEXT_MARGIN_X - textMarginY = SWITCHER_TEXT_MARGIN_Y - maxWidth = 300 - maxHeight = 40 - - if self.GetItemFont().IsOk(): - standardFont = self.GetItemFont() - - for item in self._items: - if item.GetFont().IsOk(): - dc.SetFont(item.GetFont()) - else: - if item.GetIsGroup(): - dc.SetFont(groupFont) - else: - dc.SetFont(standardFont) - - w, h = dc.GetTextExtent(item.GetTitle()) - w += 16 + 2*textMarginX - - if w > sz.x: - sz.x = min(w, maxWidth) - if h > sz.y: - sz.y = min(h, maxHeight) - - if sz == wx.Size(16, 16): - sz = wx.Size(100, 25) - else: - sz.x += textMarginX*2 - sz.y += textMarginY*2 - - return sz - - - def GetIndexForFocus(self): - - for i, item in enumerate(self._items): - if item.GetWindow(): - - if FindFocusDescendant(item.GetWindow()): - return i - - return wx.NOT_FOUND - - -class MultiColumnListCtrl(wx.PyControl): - """ A control for displaying several columns (not scrollable). """ - - def __init__(self, parent, aui_manager, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, - style=0, validator=wx.DefaultValidator, name="MultiColumnListCtrl"): - - wx.PyControl.__init__(self, parent, id, pos, size, style, validator, name) - - self._overallSize = wx.Size(200, 100) - self._modifierKey = wx.WXK_CONTROL - self._extraNavigationKey = 0 - self._aui_manager = aui_manager - - self.SetInitialSize(size) - self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) - - self.Bind(wx.EVT_PAINT, self.OnPaint) - self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) - self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvent) - self.Bind(wx.EVT_CHAR, self.OnChar) - self.Bind(wx.EVT_KEY_DOWN, self.OnKey) - self.Bind(wx.EVT_KEY_UP, self.OnKey) - - - def __del__(self): - - self._aui_manager.HideHint() - - - def DoGetBestSize(self): - - return self._overallSize - - - def OnEraseBackground(self, event): - - pass - - - def OnPaint(self, event): - - dc = wx.AutoBufferedPaintDC(self) - rect = self.GetClientRect() - - if self._items.GetColumnCount() == 0: - self.CalculateLayout(dc) - - if self._items.GetColumnCount() == 0: - return - - self._items.PaintItems(dc, self) - - - def OnMouseEvent(self, event): - - if event.LeftDown(): - self.SetFocus() - - - def OnChar(self, event): - - event.Skip() - - - def OnKey(self, event): - - if event.GetEventType() == wx.wxEVT_KEY_UP: - if event.GetKeyCode() == self.GetModifierKey(): - topLevel = wx.GetTopLevelParent(self) - closeEvent = wx.CloseEvent(wx.wxEVT_CLOSE_WINDOW, topLevel.GetId()) - closeEvent.SetEventObject(topLevel) - closeEvent.SetCanVeto(False) - - topLevel.GetEventHandler().ProcessEvent(closeEvent) - return - - event.Skip() - return - - keyCode = event.GetKeyCode() - - if keyCode in [wx.WXK_ESCAPE, wx.WXK_RETURN]: - if keyCode == wx.WXK_ESCAPE: - self._items.SetSelection(-1) - - topLevel = wx.GetTopLevelParent(self) - closeEvent = wx.CloseEvent(wx.wxEVT_CLOSE_WINDOW, topLevel.GetId()) - closeEvent.SetEventObject(topLevel) - closeEvent.SetCanVeto(False) - - topLevel.GetEventHandler().ProcessEvent(closeEvent) - return - - elif keyCode in [wx.WXK_TAB, self.GetExtraNavigationKey()]: - if event.ShiftDown(): - - self._items.SetSelection(self._items.GetSelection() - 1) - if self._items.GetSelection() < 0: - self._items.SetSelection(self._items.GetItemCount() - 1) - - self.AdvanceToNextSelectableItem(-1) - - else: - - self._items.SetSelection(self._items.GetSelection() + 1) - if self._items.GetSelection() >= self._items.GetItemCount(): - self._items.SetSelection(0) - - self.AdvanceToNextSelectableItem(1) - - self.GenerateSelectionEvent() - self.Refresh() - - elif keyCode in [wx.WXK_DOWN, wx.WXK_NUMPAD_DOWN]: - self._items.SetSelection(self._items.GetSelection() + 1) - if self._items.GetSelection() >= self._items.GetItemCount(): - self._items.SetSelection(0) - - self.AdvanceToNextSelectableItem(1) - self.GenerateSelectionEvent() - self.Refresh() - - elif keyCode in [wx.WXK_UP, wx.WXK_NUMPAD_UP]: - self._items.SetSelection(self._items.GetSelection() - 1) - if self._items.GetSelection() < 0: - self._items.SetSelection(self._items.GetItemCount() - 1) - - self.AdvanceToNextSelectableItem(-1) - self.GenerateSelectionEvent() - self.Refresh() - - elif keyCode in [wx.WXK_HOME, wx.WXK_NUMPAD_HOME]: - self._items.SetSelection(0) - self.AdvanceToNextSelectableItem(1) - self.GenerateSelectionEvent() - self.Refresh() - - elif keyCode in [wx.WXK_END, wx.WXK_NUMPAD_END]: - self._items.SetSelection(self._items.GetItemCount() - 1) - self.AdvanceToNextSelectableItem(-1) - self.GenerateSelectionEvent() - self.Refresh() - - elif keyCode in [wx.WXK_LEFT, wx.WXK_NUMPAD_LEFT]: - item = self._items.GetItem(self._items.GetSelection()) - - row = item.GetRowPos() - newCol = item.GetColPos() - 1 - if newCol < 0: - newCol = self._items.GetColumnCount() - 1 - - # Find the first item from the end whose row matches and whose column is equal or lower - for i in xrange(self._items.GetItemCount()-1, -1, -1): - item2 = self._items.GetItem(i) - if item2.GetColPos() == newCol and item2.GetRowPos() <= row: - self._items.SetSelection(i) - break - - self.AdvanceToNextSelectableItem(-1) - self.GenerateSelectionEvent() - self.Refresh() - - elif keyCode in [wx.WXK_RIGHT, wx.WXK_NUMPAD_RIGHT]: - item = self._items.GetItem(self._items.GetSelection()) - - row = item.GetRowPos() - newCol = item.GetColPos() + 1 - if newCol >= self._items.GetColumnCount(): - newCol = 0 - - # Find the first item from the end whose row matches and whose column is equal or lower - for i in xrange(self._items.GetItemCount()-1, -1, -1): - item2 = self._items.GetItem(i) - if item2.GetColPos() == newCol and item2.GetRowPos() <= row: - self._items.SetSelection(i) - break - - self.AdvanceToNextSelectableItem(1) - self.GenerateSelectionEvent() - self.Refresh() - - else: - event.Skip() - - - def AdvanceToNextSelectableItem(self, direction): - - if self._items.GetItemCount() < 2: - return - - if self._items.GetSelection() == -1: - self._items.SetSelection(0) - - oldSel = self._items.GetSelection() - - while 1: - - if self._items.GetItem(self._items.GetSelection()).GetIsGroup(): - - self._items.SetSelection(self._items.GetSelection() + direction) - if self._items.GetSelection() == -1: - self._items.SetSelection(self._items.GetItemCount()-1) - elif self._items.GetSelection() == self._items.GetItemCount(): - self._items.SetSelection(0) - if self._items.GetSelection() == oldSel: - break - - else: - break - - self.SetTransparency() - selection = self._items.GetItem(self._items.GetSelection()).GetWindow() - pane = self._aui_manager.GetPane(selection) - - if not pane.IsOk(): - if isinstance(selection.GetParent(), auibook.AuiNotebook): - self.SetTransparency(selection) - self._aui_manager.ShowHint(selection.GetScreenRect()) - wx.CallAfter(self.SetFocus) - self.SetFocus() - return - else: - self._aui_manager.HideHint() - return - if not pane.IsShown(): - self._aui_manager.HideHint() - return - - self.SetTransparency(selection) - self._aui_manager.ShowHint(selection.GetScreenRect()) - # NOTE: this is odd but it is the only way for the focus to - # work correctly on wxMac... - wx.CallAfter(self.SetFocus) - self.SetFocus() - - - def SetTransparency(self, selection=None): - - if not self.GetParent().CanSetTransparent(): - return - - if selection is not None: - intersects = False - if selection.GetScreenRect().Intersects(self.GetParent().GetScreenRect()): - intersects = True - self.GetParent().SetTransparent(200) - return - - self.GetParent().SetTransparent(255) - - - def GenerateSelectionEvent(self): - - event = wx.CommandEvent(wx.wxEVT_COMMAND_LISTBOX_SELECTED, self.GetId()) - event.SetEventObject(self) - event.SetInt(self._items.GetSelection()) - self.GetEventHandler().ProcessEvent(event) - - - def CalculateLayout(self, dc=None): - - if dc is None: - dc = wx.ClientDC(self) - - if self._items.GetSelection() == -1: - self._items.SetSelection(0) - - columnCount = 1 - - # Spacing between edge of window or between columns - xMargin = 4 - yMargin = 4 - - # Inter-row spacing - rowSpacing = 2 - - itemSize = self._items.CalculateItemSize(dc) - self._overallSize = wx.Size(350, 200) - - currentRow = 0 - x = xMargin - y = yMargin - - breaking = False - i = 0 - - while 1: - - oldOverallSize = self._overallSize - item = self._items.GetItem(i) - - item.SetRect(wx.Rect(x, y, itemSize.x, itemSize.y)) - item.SetColPos(columnCount-1) - item.SetRowPos(currentRow) - - if item.GetRect().GetBottom() > self._overallSize.y: - self._overallSize.y = item.GetRect().GetBottom() + yMargin - - if item.GetRect().GetRight() > self._overallSize.x: - self._overallSize.x = item.GetRect().GetRight() + xMargin - - currentRow += 1 - - y += rowSpacing + itemSize.y - stopBreaking = breaking - - if currentRow > self._items.GetRowCount() or (item.GetBreakColumn() and not breaking and currentRow != 1): - currentRow = 0 - columnCount += 1 - x += xMargin + itemSize.x - y = yMargin - - # Make sure we don't orphan a group - if item.GetIsGroup() or (item.GetBreakColumn() and not breaking): - self._overallSize = oldOverallSize - - if item.GetBreakColumn(): - breaking = True - - # Repeat the last item, in the next column - i -= 1 - - if stopBreaking: - breaking = False - - i += 1 - - if i >= self._items.GetItemCount(): - break - - self._items.SetColumnCount(columnCount) - self.InvalidateBestSize() - - - def SetItems(self, items): - - self._items = items - - - def GetItems(self): - - return self._items - - - def SetExtraNavigationKey(self, keyCode): - """ - Set an extra key that can be used to cycle through items, - in case not using the ``Ctrl`` + ``Tab`` combination. - """ - - self._extraNavigationKey = keyCode - - - def GetExtraNavigationKey(self): - - return self._extraNavigationKey - - - def SetModifierKey(self, modifierKey): - """ - Set the modifier used to invoke the dialog, and therefore to test for - release. - """ - - self._modifierKey = modifierKey - - - def GetModifierKey(self): - - return self._modifierKey - - - -class SwitcherDialog(wx.Dialog): - """ - SwitcherDialog shows a L{MultiColumnListCtrl} with a list of panes - and tabs for the user to choose. ``Ctrl`` + ``Tab`` cycles through them. - """ - - def __init__(self, items, parent, aui_manager, id=wx.ID_ANY, title=_("Pane Switcher"), pos=wx.DefaultPosition, - size=wx.DefaultSize, style=wx.STAY_ON_TOP|wx.DIALOG_NO_PARENT|wx.BORDER_SIMPLE): - """ Default class constructor. """ - - self._switcherBorderStyle = (style & wx.BORDER_MASK) - if self._switcherBorderStyle == wx.BORDER_NONE: - self._switcherBorderStyle = wx.BORDER_SIMPLE - - style &= wx.BORDER_MASK - style |= wx.BORDER_NONE - - wx.Dialog.__init__(self, parent, id, title, pos, size, style) - - self._listCtrl = MultiColumnListCtrl(self, aui_manager, - style=wx.WANTS_CHARS|wx.NO_BORDER) - self._listCtrl.SetItems(items) - self._listCtrl.CalculateLayout() - - self._descriptionCtrl = wx.html.HtmlWindow(self, size=(-1, 100), style=wx.BORDER_NONE) - self._descriptionCtrl.SetBackgroundColour(self.GetBackgroundColour()) - - if wx.Platform == "__WXGTK__": - fontSize = 11 - self._descriptionCtrl.SetStandardFonts(fontSize) - - sizer = wx.BoxSizer(wx.VERTICAL) - self.SetSizer(sizer) - sizer.Add(self._listCtrl, 1, wx.ALL|wx.EXPAND, 10) - sizer.Add(self._descriptionCtrl, 0, wx.ALL|wx.EXPAND, 10) - sizer.SetSizeHints(self) - - self._listCtrl.SetFocus() - - self.Centre(wx.BOTH) - - if self._listCtrl.GetItems().GetSelection() == -1: - self._listCtrl.GetItems().SetSelection(0) - - self._listCtrl.AdvanceToNextSelectableItem(1) - - self.ShowDescription(self._listCtrl.GetItems().GetSelection()) - - self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) - self.Bind(wx.EVT_ACTIVATE, self.OnActivate) - self.Bind(wx.EVT_LISTBOX, self.OnSelectItem) - self.Bind(wx.EVT_PAINT, self.OnPaint) - - # Attributes - self._closing = False - if wx.Platform == "__WXMSW__": - self._borderColour = wx.Colour(49, 106, 197) - else: - self._borderColour = wx.BLACK - - self._aui_manager = aui_manager - - - def OnCloseWindow(self, event): - - if self._closing: - return - - if self.IsModal(): - self._closing = True - - if self.GetSelection() == -1: - self.EndModal(wx.ID_CANCEL) - else: - self.EndModal(wx.ID_OK) - - self._aui_manager.HideHint() - - - def GetSelection(self): - - return self._listCtrl.GetItems().GetSelection() - - - def OnActivate(self, event): - - if not event.GetActive(): - if not self._closing: - self._closing = True - self.EndModal(wx.ID_CANCEL) - - - def OnPaint(self, event): - - dc = wx.PaintDC(self) - - if self._switcherBorderStyle == wx.BORDER_SIMPLE: - - dc.SetPen(wx.Pen(self._borderColour)) - dc.SetBrush(wx.TRANSPARENT_BRUSH) - - rect = self.GetClientRect() - dc.DrawRectangleRect(rect) - - # Draw border around the HTML control - rect = wx.Rect(*self._descriptionCtrl.GetRect()) - rect.Inflate(1, 1) - dc.DrawRectangleRect(rect) - - - def OnSelectItem(self, event): - - self.ShowDescription(event.GetSelection()) - - -# Convert a colour to a 6-digit hex string - def ColourToHexString(self, col): - - hx = '%02x%02x%02x' % tuple([int(c) for c in col]) - return hx - - - def ShowDescription(self, i): - - item = self._listCtrl.GetItems().GetItem(i) - colour = self._listCtrl.GetItems().GetBackgroundColour() - - if not colour.IsOk(): - colour = self.GetBackgroundColour() - - backgroundColourHex = self.ColourToHexString(colour) - html = _("") + item.GetTitle() + _("") - - if item.GetDescription(): - html += _("

") - html += item.GetDescription() - - html += _("") - self._descriptionCtrl.SetPage(html) - - - def SetExtraNavigationKey(self, keyCode): - - self._extraNavigationKey = keyCode - if self._listCtrl: - self._listCtrl.SetExtraNavigationKey(keyCode) - - - def GetExtraNavigationKey(self): - - return self._extraNavigationKey - - - def SetModifierKey(self, modifierKey): - - self._modifierKey = modifierKey - if self._listCtrl: - self._listCtrl.SetModifierKey(modifierKey) - - - def GetModifierKey(self): - - return self._modifierKey - - - def SetBorderColour(self, colour): - - self._borderColour = colour - - \ No newline at end of file diff --git a/agw/aui/aui_utilities.py b/agw/aui/aui_utilities.py deleted file mode 100644 index d6c701a..0000000 --- a/agw/aui/aui_utilities.py +++ /dev/null @@ -1,678 +0,0 @@ -""" -This module contains some common functions used by wxPython-AUI to -manipulate colours, bitmaps, text, gradient shadings and custom -dragging images for AuiNotebook tabs. -""" - -__author__ = "Andrea Gavana " -__date__ = "31 March 2009" - - -import wx - -from aui_constants import * - - -if wx.Platform == "__WXMAC__": - import Carbon.Appearance - - -def BlendColour(fg, bg, alpha): - """ - Blends the two colour component `fg` and `bg` into one colour component, adding - an optional alpha channel. - - :param `fg`: the first colour component; - :param `bg`: the second colour component; - :param `alpha`: an optional transparency value. - """ - - result = bg + (alpha*(fg - bg)) - - if result < 0.0: - result = 0.0 - if result > 255: - result = 255 - - return result - - -def StepColour(c, ialpha): - """ - Darken/lighten the input colour `c`. - - :param `c`: a colour to darken/lighten; - :param `ialpha`: a transparency value. - """ - - if ialpha == 100: - return c - - r, g, b = c.Red(), c.Green(), c.Blue() - - # ialpha is 0..200 where 0 is completely black - # and 200 is completely white and 100 is the same - # convert that to normal alpha 0.0 - 1.0 - ialpha = min(ialpha, 200) - ialpha = max(ialpha, 0) - alpha = (ialpha - 100.0)/100.0 - - if ialpha > 100: - - # blend with white - bg = 255 - alpha = 1.0 - alpha # 0 = transparent fg 1 = opaque fg - - else: - - # blend with black - bg = 0 - alpha = 1.0 + alpha # 0 = transparent fg 1 = opaque fg - - r = BlendColour(r, bg, alpha) - g = BlendColour(g, bg, alpha) - b = BlendColour(b, bg, alpha) - - return wx.Colour(r, g, b) - - -def LightContrastColour(c): - """ - Creates a new, lighter colour based on the input colour `c`. - - :param `c`: the input colour to analyze. - """ - - amount = 120 - - # if the colour is especially dark, then - # make the contrast even lighter - if c.Red() < 128 and c.Green() < 128 and c.Blue() < 128: - amount = 160 - - return StepColour(c, amount) - - -def ChopText(dc, text, max_size): - """ - Chops the input `text` if its size does not fit in `max_size`, by cutting the - text and adding ellipsis at the end. - - :param `dc`: a `wx.DC` device context; - :param `text`: the text to chop; - :param `max_size`: the maximum size in which the text should fit. - """ - - # first check if the text fits with no problems - x, y, dummy = dc.GetMultiLineTextExtent(text) - - if x <= max_size: - return text - - textLen = len(text) - last_good_length = 0 - - for i in xrange(textLen, -1, -1): - s = text[0:i] - s += "..." - - x, y = dc.GetTextExtent(s) - last_good_length = i - - if x < max_size: - break - - ret = text[0:last_good_length] + "..." - return ret - - -def BitmapFromBits(bits, w, h, colour): - """ - BitmapFromBits() is a utility function that creates a - masked bitmap from raw bits (XBM format). - - :param `bits`: a string containing the raw bits of the bitmap; - :param `w`: the bitmap width; - :param `h`: the bitmap height; - :param `colour`: the colour which will replace all white pixels in the - raw bitmap. - """ - - img = wx.BitmapFromBits(bits, w, h).ConvertToImage() - img.Replace(0, 0, 0, 123, 123, 123) - img.Replace(255, 255, 255, colour.Red(), colour.Green(), colour.Blue()) - img.SetMaskColour(123, 123, 123) - return wx.BitmapFromImage(img) - - -def IndentPressedBitmap(rect, button_state): - """ - Indents the input rectangle `rect` based on the value of `button_state`. - - :param `rect`: an instance of wx.Rect; - :param `button_state`: an L{AuiNotebook} button state. - """ - - if button_state == AUI_BUTTON_STATE_PRESSED: - rect.x += 1 - rect.y += 1 - - return rect - - -def GetBaseColour(): - """ - Returns the face shading colour on push buttons/backgrounds, mimicking as closely - as possible the platform UI colours. - """ - - if wx.Platform == "__WXMAC__": - - if hasattr(wx, 'MacThemeColour'): - base_colour = wx.MacThemeColour(Carbon.Appearance.kThemeBrushToolbarBackground) - else: - brush = wx.Brush(wx.BLACK) - brush.MacSetTheme(Carbon.Appearance.kThemeBrushToolbarBackground) - base_colour = brush.GetColour() - - else: - - base_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE) - - # the base_colour is too pale to use as our base colour, - # so darken it a bit - if ((255-base_colour.Red()) + - (255-base_colour.Green()) + - (255-base_colour.Blue()) < 60): - - base_colour = StepColour(base_colour, 92) - - return base_colour - - -def MakeDisabledBitmap(bitmap): - """ - Convert the given image (in place) to a grayed-out version, - appropriate for a 'disabled' appearance. - - :param `bitmap`: the bitmap to gray-out. - """ - - anImage = bitmap.ConvertToImage() - factor = 0.7 # 0 < f < 1. Higher Is Grayer - - if anImage.HasMask(): - maskColour = (anImage.GetMaskRed(), anImage.GetMaskGreen(), anImage.GetMaskBlue()) - else: - maskColour = None - - data = map(ord, list(anImage.GetData())) - - for i in range(0, len(data), 3): - - pixel = (data[i], data[i+1], data[i+2]) - pixel = MakeGray(pixel, factor, maskColour) - - for x in range(3): - data[i+x] = pixel[x] - - anImage.SetData(''.join(map(chr, data))) - - return anImage.ConvertToBitmap() - - -def MakeGray(rgbTuple, factor, maskColour): - """ - Make a pixel grayed-out. If the pixel matches the `maskColour`, it won't be - changed. - - :param `rgbTuple`: a tuple representing a pixel colour; - :param `factor`: a graying-out factor; - :param `maskColour`: a colour mask. - """ - - if rgbTuple != maskColour: - r, g, b = rgbTuple - return map(lambda x: int((230 - x) * factor) + x, (r, g, b)) - else: - return rgbTuple - - -def Clip(a, b, c): - """ - Clips the value in `a` based on the extremes `b` and `c`. - - :param `a`: the value to analyze; - :param `b`: a minimum value; - :param `c`: a maximum value. - """ - - return ((a < b and [b]) or [(a > c and [c] or [a])[0]])[0] - - -def LightColour(colour, percent): - """ - Brighten input `colour` by `percent`. - - :param `colour`: the colour to be brightened; - :param `percent`: brightening percentage. - """ - - end_colour = wx.WHITE - - rd = end_colour.Red() - colour.Red() - gd = end_colour.Green() - colour.Green() - bd = end_colour.Blue() - colour.Blue() - - high = 100 - - # We take the percent way of the colour from colour -. white - i = percent - r = colour.Red() + ((i*rd*100)/high)/100 - g = colour.Green() + ((i*gd*100)/high)/100 - b = colour.Blue() + ((i*bd*100)/high)/100 - return wx.Colour(r, g, b) - - -def PaneCreateStippleBitmap(): - """ - Creates a stipple bitmap to be used in a `wx.Brush`. - This is used to draw sash resize hints. - """ - - data = [0, 0, 0, 192, 192, 192, 192, 192, 192, 0, 0, 0] - img = wx.EmptyImage(2, 2) - counter = 0 - - for ii in xrange(2): - for jj in xrange(2): - img.SetRGB(ii, jj, data[counter], data[counter+1], data[counter+2]) - counter = counter + 3 - - return img.ConvertToBitmap() - - -def DrawMACCloseButton(colour, backColour=None): - """ - Draws the wxMAC tab close button using `wx.GraphicsContext`. - - :param `colour`: the colour to use to draw the circle; - :param `backColour`: the optional background colour for the circle. - """ - - bmp = wx.EmptyBitmapRGBA(16, 16) - dc = wx.MemoryDC() - dc.SelectObject(bmp) - - gc = wx.GraphicsContext.Create(dc) - gc.SetBrush(wx.Brush(colour)) - path = gc.CreatePath() - path.AddCircle(6.5, 7, 6.5) - path.CloseSubpath() - gc.FillPath(path) - - path = gc.CreatePath() - if backColour is not None: - pen = wx.Pen(backColour, 2) - else: - pen = wx.Pen("white", 2) - - pen.SetCap(wx.CAP_BUTT) - pen.SetJoin(wx.JOIN_BEVEL) - gc.SetPen(pen) - path.MoveToPoint(3.5, 4) - path.AddLineToPoint(9.5, 10) - path.MoveToPoint(3.5, 10) - path.AddLineToPoint(9.5, 4) - path.CloseSubpath() - gc.DrawPath(path) - - dc.SelectObject(wx.NullBitmap) - return bmp - - -def DarkenBitmap(bmp, caption_colour, new_colour): - """ - Darkens the input bitmap on wxMAC using the input colour. - - :param `bmp`: the bitmap to be manipulated; - :param `caption_colour`: the colour of the pane caption; - :param `new_colour`: the colour used to darken the bitmap. - """ - - image = bmp.ConvertToImage() - red = caption_colour.Red()/float(new_colour.Red()) - green = caption_colour.Green()/float(new_colour.Green()) - blue = caption_colour.Blue()/float(new_colour.Blue()) - image = image.AdjustChannels(red, green, blue) - return image.ConvertToBitmap() - - -def DrawGradientRectangle(dc, rect, start_colour, end_colour, direction, offset=0, length=0): - """ - Draws a gradient-shaded rectangle. - - :param `dc`: a `wx.DC` device context; - :param `rect`: the rectangle in which to draw the gradient; - :param `start_colour`: the first colour of the gradient; - :param `end_colour`: the second colour of the gradient; - :param `direction`: the gradient direction (horizontal or vertical). - """ - - if direction == AUI_GRADIENT_VERTICAL: - dc.GradientFillLinear(rect, start_colour, end_colour, wx.SOUTH) - else: - dc.GradientFillLinear(rect, start_colour, end_colour, wx.EAST) - - -def FindFocusDescendant(ancestor): - """ - Find a window with the focus, that is also a descendant of the given window. - This is used to determine the window to initially send commands to. - - :param `ancestor`: the window to check for ancestry. - """ - - # Process events starting with the window with the focus, if any. - focusWin = wx.Window.FindFocus() - win = focusWin - - # Check if this is a descendant of this frame. - # If not, win will be set to NULL. - while win: - if win == ancestor: - break - else: - win = win.GetParent() - - if win is None: - focusWin = None - - return focusWin - - -def GetLabelSize(dc, label, vertical): - """ - Returns the L{AuiToolBar} item label size. - - :param `label`: the toolbar tool label; - :param `vertical`: whether the toolbar tool orientation is vertical or not. - """ - - text_width = text_height = 0 - - # get the text height - dummy, text_height = dc.GetTextExtent("ABCDHgj") - # get the text width - if label.strip(): - text_width, dummy = dc.GetTextExtent(label) - - if vertical: - tmp = text_height - text_height = text_width - text_width = tmp - - return wx.Size(text_width, text_height) - - -#--------------------------------------------------------------------------- -# TabDragImage implementation -# This class handles the creation of a custom image when dragging -# AuiNotebook tabs -#--------------------------------------------------------------------------- - -class TabDragImage(wx.DragImage): - """ - This class handles the creation of a custom image in case of drag and - drop of a notebook tab. - """ - - def __init__(self, notebook, page, button_state, tabArt): - """ - Default class constructor. - - For internal use: do not call it in your code! - - :param `notebook`: an instance of L{AuiNotebook}; - :param `page`: the dragged L{AuiNotebook} page; - :param `button_state`: the state of the close button on the tab; - :param `tabArt`: an instance of L{AuiDefaultTabArt} or one of its derivations. - """ - - self._backgroundColour = wx.NamedColour("pink") - self._bitmap = self.CreateBitmap(notebook, page, button_state, tabArt) - wx.DragImage.__init__(self, self._bitmap) - - - def CreateBitmap(self, notebook, page, button_state, tabArt): - """ - Actually creates the drag and drop bitmap. - - :param `notebook`: an instance of L{AuiNotebook}; - :param `page`: the dragged L{AuiNotebook} page; - :param `button_state`: the state of the close button on the tab; - :param `tabArt`: an instance of L{AuiDefaultTabArt} or one of its derivations. - """ - - control = page.control - memory = wx.MemoryDC(wx.EmptyBitmap(1, 1)) - - tab_size, x_extent = tabArt.GetTabSize(memory, notebook, page.caption, page.bitmap, page.active, - button_state, control) - - tab_width, tab_height = tab_size - rect = wx.Rect(0, 0, tab_width, tab_height) - - bitmap = wx.EmptyBitmap(tab_width+1, tab_height+1) - memory.SelectObject(bitmap) - - if wx.Platform == "__WXMAC__": - memory.SetBackground(wx.TRANSPARENT_BRUSH) - else: - memory.SetBackground(wx.Brush(self._backgroundColour)) - - memory.SetBackgroundMode(wx.TRANSPARENT) - memory.Clear() - - paint_control = wx.Platform != "__WXMAC__" - tabArt.DrawTab(memory, notebook, page, rect, button_state, paint_control=paint_control) - - memory.SetBrush(wx.TRANSPARENT_BRUSH) - memory.SetPen(wx.BLACK_PEN) - memory.DrawRoundedRectangle(0, 0, tab_width+1, tab_height+1, 2) - - memory.SelectObject(wx.NullBitmap) - - # Gtk and Windows unfortunatly don't do so well with transparent - # drawing so this hack corrects the image to have a transparent - # background. - if wx.Platform != '__WXMAC__': - timg = bitmap.ConvertToImage() - if not timg.HasAlpha(): - timg.InitAlpha() - for y in xrange(timg.GetHeight()): - for x in xrange(timg.GetWidth()): - pix = wx.Colour(timg.GetRed(x, y), - timg.GetGreen(x, y), - timg.GetBlue(x, y)) - if pix == self._backgroundColour: - timg.SetAlpha(x, y, 0) - bitmap = timg.ConvertToBitmap() - return bitmap - - -def GetDockingImage(direction, useAero, center): - """ - Returns the correct name of the docking bitmap depending on the input parameters. - - :param `useAero`: whether L{AuiManager} is using Aero-style or Whidbey-style docking - images or not; - :param `center`: whether we are looking for the center diamond-shaped bitmap or not. - """ - - suffix = (center and [""] or ["_single"])[0] - prefix = "" - if useAero == 2: - # Whidbey docking guides - prefix = "whidbey_" - elif useAero == 1: - # Aero docking style - prefix = "aero_" - - if direction == wx.TOP: - bmp_unfocus = eval("%sup%s"%(prefix, suffix)).GetBitmap() - bmp_focus = eval("%sup_focus%s"%(prefix, suffix)).GetBitmap() - elif direction == wx.BOTTOM: - bmp_unfocus = eval("%sdown%s"%(prefix, suffix)).GetBitmap() - bmp_focus = eval("%sdown_focus%s"%(prefix, suffix)).GetBitmap() - elif direction == wx.LEFT: - bmp_unfocus = eval("%sleft%s"%(prefix, suffix)).GetBitmap() - bmp_focus = eval("%sleft_focus%s"%(prefix, suffix)).GetBitmap() - elif direction == wx.RIGHT: - bmp_unfocus = eval("%sright%s"%(prefix, suffix)).GetBitmap() - bmp_focus = eval("%sright_focus%s"%(prefix, suffix)).GetBitmap() - else: - bmp_unfocus = eval("%stab%s"%(prefix, suffix)).GetBitmap() - bmp_focus = eval("%stab_focus%s"%(prefix, suffix)).GetBitmap() - - return bmp_unfocus, bmp_focus - - -def TakeScreenShot(rect): - """ - Takes a screenshot of the screen at given position and size (rect). - - :param `rect`: the screen rectangle for which we want to take a screenshot. - """ - - # Create a DC for the whole screen area - dcScreen = wx.ScreenDC() - - # Create a Bitmap that will later on hold the screenshot image - # Note that the Bitmap must have a size big enough to hold the screenshot - # -1 means using the current default colour depth - bmp = wx.EmptyBitmap(rect.width, rect.height) - - # Create a memory DC that will be used for actually taking the screenshot - memDC = wx.MemoryDC() - - # Tell the memory DC to use our Bitmap - # all drawing action on the memory DC will go to the Bitmap now - memDC.SelectObject(bmp) - - # Blit (in this case copy) the actual screen on the memory DC - # and thus the Bitmap - memDC.Blit( 0, # Copy to this X coordinate - 0, # Copy to this Y coordinate - rect.width, # Copy this width - rect.height, # Copy this height - dcScreen, # From where do we copy? - rect.x, # What's the X offset in the original DC? - rect.y # What's the Y offset in the original DC? - ) - - # Select the Bitmap out of the memory DC by selecting a new - # uninitialized Bitmap - memDC.SelectObject(wx.NullBitmap) - - return bmp - - -def RescaleScreenShot(bmp, thumbnail_size=200): - """ - Rescales a bitmap to be 300 pixels wide (or tall) at maximum. - - :param `bmp`: the bitmap to rescale; - :param `thumbnail_size`: the maximum size of every page thumbnail. - """ - - bmpW, bmpH = bmp.GetWidth(), bmp.GetHeight() - img = bmp.ConvertToImage() - - newW, newH = bmpW, bmpH - - if bmpW > bmpH: - if bmpW > thumbnail_size: - ratio = bmpW/float(thumbnail_size) - newW, newH = int(bmpW/ratio), int(bmpH/ratio) - img.Rescale(newW, newH, wx.IMAGE_QUALITY_HIGH) - else: - if bmpH > thumbnail_size: - ratio = bmpH/float(thumbnail_size) - newW, newH = int(bmpW/ratio), int(bmpH/ratio) - img.Rescale(newW, newH, wx.IMAGE_QUALITY_HIGH) - - newBmp = img.ConvertToBitmap() - otherBmp = wx.EmptyBitmap(newW+5, newH+5) - - memDC = wx.MemoryDC() - memDC.SelectObject(otherBmp) - memDC.SetBackground(wx.WHITE_BRUSH) - memDC.Clear() - - memDC.SetPen(wx.TRANSPARENT_PEN) - - pos = 0 - for i in xrange(5, 0, -1): - brush = wx.Brush(wx.Colour(50*i, 50*i, 50*i)) - memDC.SetBrush(brush) - memDC.DrawRoundedRectangle(0, 0, newW+5-pos, newH+5-pos, 2) - pos += 1 - - memDC.DrawBitmap(newBmp, 0, 0, True) - - # Select the Bitmap out of the memory DC by selecting a new - # uninitialized Bitmap - memDC.SelectObject(wx.NullBitmap) - - return otherBmp - - -def GetSlidingPoints(rect, size, direction): - """ - Returns the point at which the sliding in and out of a minimized pane begins. - - :param `rect`: the L{AuiToolBar} tool screen rectangle; - :param `size`: the pane window size; - :param `direction`: the pane docking direction. - """ - - if direction == AUI_DOCK_LEFT: - startX, startY = rect.x + rect.width + 2, rect.y - elif direction == AUI_DOCK_TOP: - startX, startY = rect.x, rect.y + rect.height + 2 - elif direction == AUI_DOCK_RIGHT: - startX, startY = rect.x - size.x - 2, rect.y - elif direction == AUI_DOCK_BOTTOM: - startX, startY = rect.x, rect.y - size.y - 2 - else: - raise Exception("How did we get here?") - - caption_height = wx.SystemSettings.GetMetric(wx.SYS_CAPTION_Y) - frame_border_x = wx.SystemSettings.GetMetric(wx.SYS_FRAMESIZE_X) - frame_border_y = wx.SystemSettings.GetMetric(wx.SYS_FRAMESIZE_Y) - - stopX = size.x + caption_height + frame_border_x - stopY = size.x + frame_border_y - - return startX, startY, stopX, stopY - - -def CopyAttributes(newArt, oldArt): - """ - Copies pens, brushes, colours and fonts from the old tab art to the new one. - - :param `newArt`: the new instance of L{AuiDefaultTabArt}; - :param `oldArt`: the old instance of L{AuiDefaultTabArt}. - """ - - attrs = dir(oldArt) - - for attr in attrs: - if attr.startswith("_") and (attr.endswith("_colour") or attr.endswith("_font") or \ - attr.endswith("_font") or attr.endswith("_brush") or \ - attr.endswith("Pen") or attr.endswith("_pen")): - setattr(newArt, attr, getattr(oldArt, attr)) - - return newArt - diff --git a/agw/aui/auibar.py b/agw/aui/auibar.py deleted file mode 100644 index 4d348b7..0000000 --- a/agw/aui/auibar.py +++ /dev/null @@ -1,3926 +0,0 @@ -""" -auibar contains an implementation of L{AuiToolBar}, which is a completely owner-drawn -toolbar perfectly integrated with the AUI layout system. This allows drag and drop of -toolbars, docking/floating behaviour and the possibility to define "overflow" items -in the toolbar itself. - -The default theme that is used is L{AuiDefaultToolBarArt}, which provides a modern, -glossy look and feel. The theme can be changed by calling L{AuiToolBar.SetArtProvider}. -""" - -__author__ = "Andrea Gavana " -__date__ = "31 March 2009" - - -import wx -import types - -from aui_utilities import BitmapFromBits, StepColour, GetLabelSize -from aui_utilities import GetBaseColour, MakeDisabledBitmap - -import framemanager -from aui_constants import * - -# wxPython version string -_VERSION_STRING = wx.VERSION_STRING - -# AuiToolBar events -wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN = wx.NewEventType() -wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK = wx.NewEventType() -wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK = wx.NewEventType() -wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK = wx.NewEventType() -wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG = wx.NewEventType() - -EVT_AUITOOLBAR_TOOL_DROPDOWN = wx.PyEventBinder(wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN, 1) -""" A dropdown `AuiToolBarItem` is being shown. """ -EVT_AUITOOLBAR_OVERFLOW_CLICK = wx.PyEventBinder(wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK, 1) -""" The user left-clicked on the overflow button in `AuiToolBar`. """ -EVT_AUITOOLBAR_RIGHT_CLICK = wx.PyEventBinder(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, 1) -""" Fires an event when the user right-clicks on a `AuiToolBarItem`. """ -EVT_AUITOOLBAR_MIDDLE_CLICK = wx.PyEventBinder(wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK, 1) -""" Fires an event when the user middle-clicks on a `AuiToolBarItem`. """ -EVT_AUITOOLBAR_BEGIN_DRAG = wx.PyEventBinder(wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG, 1) -""" A drag operation involving a toolbar item has started. """ - -# ---------------------------------------------------------------------- - -class CommandToolBarEvent(wx.PyCommandEvent): - """ A specialized command event class for events sent by L{AuiToolBar}. """ - - def __init__(self, command_type, win_id): - """ - Default class constructor. - - :param `command_type`: the event kind or an instance of `wx.PyCommandEvent`. - :param `win_id`: the window identification number. - """ - - if type(command_type) == types.IntType: - wx.PyCommandEvent.__init__(self, command_type, win_id) - else: - wx.PyCommandEvent.__init__(self, command_type.GetEventType(), command_type.GetId()) - - self.is_dropdown_clicked = False - self.click_pt = wx.Point(-1, -1) - self.rect = wx.Rect(-1, -1, 0, 0) - self.tool_id = -1 - - - def IsDropDownClicked(self): - """ Returns whether the drop down menu has been clicked. """ - - return self.is_dropdown_clicked - - - def SetDropDownClicked(self, c): - """ - Sets whether the drop down menu has been clicked. - - :param `c`: ``True`` to set the drop down as clicked, ``False`` otherwise. - """ - - self.is_dropdown_clicked = c - - - def GetClickPoint(self): - """ Returns the point where the user clicked with the mouse. """ - - return self.click_pt - - - def SetClickPoint(self, p): - """ - Sets the clicking point. - - :param `p`: a `wx.Point` object. - """ - - self.click_pt = p - - - def GetItemRect(self): - """ Returns the L{AuiToolBarItem} rectangle. """ - - return self.rect - - - def SetItemRect(self, r): - """ - Sets the L{AuiToolBarItem} rectangle. - - :param `r`: an instance of `wx.Rect`. - """ - - self.rect = r - - - def GetToolId(self): - """ Returns the L{AuiToolBarItem} identifier. """ - - return self.tool_id - - - def SetToolId(self, id): - """ - Sets the L{AuiToolBarItem} identifier. - - :param `id`: the toolbar item identifier. - """ - - self.tool_id = id - - -# ---------------------------------------------------------------------- - -class AuiToolBarEvent(CommandToolBarEvent): - """ A specialized command event class for events sent by L{AuiToolBar}. """ - - def __init__(self, command_type=None, win_id=0): - """ - Default class constructor. - - :param `command_type`: the event kind or an instance of `wx.PyCommandEvent`. - :param `win_id`: the window identification number. - """ - - CommandToolBarEvent.__init__(self, command_type, win_id) - - if type(command_type) == types.IntType: - self.notify = wx.NotifyEvent(command_type, win_id) - else: - self.notify = wx.NotifyEvent(command_type.GetEventType(), command_type.GetId()) - - - def GetNotifyEvent(self): - """ Returns the actual `wx.NotifyEvent`. """ - - return self.notify - - - def IsAllowed(self): - """ Returns whether the event is allowed or not. """ - - return self.notify.IsAllowed() - - - def Veto(self): - """ - Prevents the change announced by this event from happening. - - It is in general a good idea to notify the user about the reasons for - vetoing the change because otherwise the applications behaviour (which - just refuses to do what the user wants) might be quite surprising. - """ - - self.notify.Veto() - - - def Allow(self): - """ - This is the opposite of L{Veto}: it explicitly allows the event to be - processed. For most events it is not necessary to call this method as the - events are allowed anyhow but some are forbidden by default (this will - be mentioned in the corresponding event description). - """ - - self.notify.Allow() - - -# ---------------------------------------------------------------------- - -class ToolbarCommandCapture(wx.PyEvtHandler): - """ A class to handle the dropdown window menu. """ - - def __init__(self): - """ Default class constructor. """ - - wx.PyEvtHandler.__init__(self) - self._last_id = 0 - - - def GetCommandId(self): - """ Returns the event command identifier. """ - - return self._last_id - - - def ProcessEvent(self, event): - """ - Processes an event, searching event tables and calling zero or more suitable - event handler function(s). - - :param `event`: the event to process. - - :note: Normally, your application would not call this function: it is called - in the wxPython implementation to dispatch incoming user interface events - to the framework (and application). - However, you might need to call it if implementing new functionality (such as - a new control) where you define new event types, as opposed to allowing the - user to override functions. - - An instance where you might actually override the L{ProcessEvent} function is where - you want to direct event processing to event handlers not normally noticed by - wxPython. For example, in the document/view architecture, documents and views - are potential event handlers. When an event reaches a frame, L{ProcessEvent} will - need to be called on the associated document and view in case event handler - functions are associated with these objects. - - The normal order of event table searching is as follows: - - 1. If the object is disabled (via a call to `SetEvtHandlerEnabled`) the function - skips to step (6). - 2. If the object is a `wx.Window`, L{ProcessEvent} is recursively called on the window's - `wx.Validator`. If this returns ``True``, the function exits. - 3. wxWidgets `SearchEventTable` is called for this event handler. If this fails, the - base class table is tried, and so on until no more tables exist or an appropriate - function was found, in which case the function exits. - 4. The search is applied down the entire chain of event handlers (usually the chain - has a length of one). If this succeeds, the function exits. - 5. If the object is a `wx.Window` and the event is a `wx.CommandEvent`, L{ProcessEvent} is - recursively applied to the parent window's event handler. If this returns ``True``, - the function exits. - 6. Finally, L{ProcessEvent} is called on the `wx.App` object. - """ - - if event.GetEventType() == wx.wxEVT_COMMAND_MENU_SELECTED: - self._last_id = event.GetId() - return True - - if self.GetNextHandler(): - return self.GetNextHandler().ProcessEvent(event) - - return False - - -# ---------------------------------------------------------------------- - -class AuiToolBarItem(object): - """ - AuiToolBarItem is a toolbar element. - - It has a unique id (except for the separators which always have id = -1), the - style (telling whether it is a normal button, separator or a control), the - state (toggled or not, enabled or not) and short and long help strings. The - default implementations use the short help string for the tooltip text which - is popped up when the mouse pointer enters the tool and the long help string - for the applications status bar. - """ - - def __init__(self, item=None): - """ - Default class constructor. - - :param `item`: another instance of L{AuiToolBarItem}. - """ - - if item: - self.Assign(item) - return - - self.window = None - self.clockwisebmp = wx.NullBitmap - self.counterclockwisebmp = wx.NullBitmap - self.clockwisedisbmp = wx.NullBitmap - self.counterclockwisedisbmp = wx.NullBitmap - self.sizer_item = None - self.spacer_pixels = 0 - self.id = 0 - self.kind = ITEM_NORMAL - self.state = 0 # normal, enabled - self.proportion = 0 - self.active = True - self.dropdown = True - self.sticky = True - self.user_data = 0 - - self.label = "" - self.bitmap = wx.NullBitmap - self.disabled_bitmap = wx.NullBitmap - self.hover_bitmap = wx.NullBitmap - self.short_help = "" - self.long_help = "" - self.min_size = wx.Size(-1, -1) - self.alignment = wx.ALIGN_CENTER - self.orientation = AUI_TBTOOL_HORIZONTAL - - - def Assign(self, c): - """ - Assigns the properties of the L{AuiToolBarItem} `c` to `self`. - - :param `c`: another instance of L{AuiToolBarItem}. - """ - - self.window = c.window - self.label = c.label - self.bitmap = c.bitmap - self.disabled_bitmap = c.disabled_bitmap - self.hover_bitmap = c.hover_bitmap - self.short_help = c.short_help - self.long_help = c.long_help - self.sizer_item = c.sizer_item - self.min_size = c.min_size - self.spacer_pixels = c.spacer_pixels - self.id = c.id - self.kind = c.kind - self.state = c.state - self.proportion = c.proportion - self.active = c.active - self.dropdown = c.dropdown - self.sticky = c.sticky - self.user_data = c.user_data - self.alignment = c.alignment - self.orientation = c.orientation - - - def SetWindow(self, w): - """ - Assigns a window to the toolbar item. - - :param `w`: an instance of `wx.Window`. - """ - - self.window = w - - - def GetWindow(self): - """ Returns window associated to the toolbar item. """ - - return self.window - - - def SetId(self, new_id): - """ - Sets the toolbar item identifier. - - :param `new_id`: the new tool id. - """ - - self.id = new_id - - - def GetId(self): - """ Returns the toolbar item identifier. """ - - return self.id - - - def SetKind(self, new_kind): - """ - Sets the L{AuiToolBarItem} kind. - - :param `new_kind`: can be one of the following items: - - ======================== ============================= - Item Kind Description - ======================== ============================= - ``ITEM_CONTROL`` The item in the `AuiToolBar` is a control - ``ITEM_LABEL`` The item in the `AuiToolBar` is a text label - ``ITEM_SPACER`` The item in the `AuiToolBar` is a spacer - ``ITEM_SEPARATOR`` The item in the `AuiToolBar` is a separator - ``ITEM_CHECK`` The item in the `AuiToolBar` is a toolbar check item - ``ITEM_NORMAL`` The item in the `AuiToolBar` is a standard toolbar item - ``ITEM_RADIO`` The item in the `AuiToolBar` is a toolbar radio item - ======================== ============================= - """ - - self.kind = new_kind - - - def GetKind(self): - """ Returns the toolbar item kind. See L{SetKind} for more details. """ - - return self.kind - - - def SetState(self, new_state): - """ - Sets the toolbar item state. - - :param `new_state`: can be one of the following states: - - ============================================ ====================================== - Button State Constant Description - ============================================ ====================================== - ``AUI_BUTTON_STATE_NORMAL`` Normal button state - ``AUI_BUTTON_STATE_HOVER`` Hovered button state - ``AUI_BUTTON_STATE_PRESSED`` Pressed button state - ``AUI_BUTTON_STATE_DISABLED`` Disabled button state - ``AUI_BUTTON_STATE_HIDDEN`` Hidden button state - ``AUI_BUTTON_STATE_CHECKED`` Checked button state - ============================================ ====================================== - - """ - - self.state = new_state - - - def GetState(self): - """ - Returns the toolbar item state. See L{SetState} for more details. - - :see: L{SetState} - """ - - return self.state - - - def SetSizerItem(self, s): - """ - Associates a sizer item to this toolbar item. - - :param `s`: an instance of `wx.SizerItem`. - """ - - self.sizer_item = s - - - def GetSizerItem(self): - """ Returns the associated sizer item. """ - - return self.sizer_item - - - def SetLabel(self, s): - """ - Sets the toolbar item label. - - :param `s`: a string specifying the toolbar item label. - """ - - self.label = s - - - def GetLabel(self): - """ Returns the toolbar item label. """ - - return self.label - - - def SetBitmap(self, bmp): - """ - Sets the toolbar item bitmap. - - :param `bmp`: an instance of `wx.Bitmap`. - """ - - self.bitmap = bmp - - - def GetBitmap(self): - """ Returns the toolbar item bitmap. """ - - return self.GetRotatedBitmap(False) - - - def SetDisabledBitmap(self, bmp): - """ - Sets the toolbar item disabled bitmap. - - :param `bmp`: an instance of `wx.Bitmap`. - """ - - self.disabled_bitmap = bmp - - - def GetDisabledBitmap(self): - """ Returns the toolbar item disabled bitmap. """ - - return self.GetRotatedBitmap(True) - - - def SetHoverBitmap(self, bmp): - """ - Sets the toolbar item hover bitmap. - - :param `bmp`: an instance of `wx.Bitmap`. - """ - - self.hover_bitmap = bmp - - - def SetOrientation(self, a): - """ - Sets the toolbar tool orientation. - - :param `a`: one of ``AUI_TBTOOL_HORIZONTAL``, ``AUI_TBTOOL_VERT_CLOCKWISE`` or - ``AUI_TBTOOL_VERT_COUNTERCLOCKWISE``. - """ - - self.orientation = a - - - def GetOrientation(self): - """ Returns the toolbar tool orientation. """ - - return self.orientation - - - def GetHoverBitmap(self): - """ Returns the toolbar item hover bitmap. """ - - return self.hover_bitmap - - - def GetRotatedBitmap(self, disabled): - """ - Returns the correct bitmap depending on the tool orientation. - - :param `disabled`: whether to return the disabled bitmap or not. - """ - - bitmap_to_rotate = (disabled and [self.disabled_bitmap] or [self.bitmap])[0] - if not bitmap_to_rotate.IsOk() or self.orientation == AUI_TBTOOL_HORIZONTAL: - return bitmap_to_rotate - - rotated_bitmap = wx.NullBitmap - clockwise = True - if self.orientation == AUI_TBTOOL_VERT_CLOCKWISE: - rotated_bitmap = (disabled and [self.clockwisedisbmp] or [self.clockwisebmp])[0] - - elif self.orientation == AUI_TBTOOL_VERT_COUNTERCLOCKWISE: - rotated_bitmap = (disabled and [self.counterclockwisedisbmp] or [self.counterclockwisebmp])[0] - clockwise = False - - if not rotated_bitmap.IsOk(): - rotated_bitmap = wx.BitmapFromImage(bitmap_to_rotate.ConvertToImage().Rotate90(clockwise)) - - return rotated_bitmap - - - def SetShortHelp(self, s): - """ - Sets the short help string for the L{AuiToolBarItem}, to be displayed in a - `wx.ToolTip` when the mouse hover over the toolbar item. - - :param `s`: the tool short help string. - """ - - self.short_help = s - - - def GetShortHelp(self): - """ Returns the short help string for the L{AuiToolBarItem}. """ - - return self.short_help - - - def SetLongHelp(self, s): - """ - Sets the long help string for the toolbar item. This string is shown in the - statusbar (if any) of the parent frame when the mouse pointer is inside the - tool. - - :param `s`: the tool long help string. - """ - - self.long_help = s - - - def GetLongHelp(self): - """ Returns the long help string for the L{AuiToolBarItem}. """ - - return self.long_help - - - def SetMinSize(self, s): - """ - Sets the toolbar item minimum size. - - :param `s`: an instance of `wx.Size`. - """ - - self.min_size = wx.Size(*s) - - - def GetMinSize(self): - """ Returns the toolbar item minimum size. """ - - return self.min_size - - - def SetSpacerPixels(self, s): - """ - Sets the number of pixels for a toolbar item with kind = ``ITEM_SEPARATOR``. - - :param `s`: number of pixels. - """ - - self.spacer_pixels = s - - - def GetSpacerPixels(self): - """ Returns the number of pixels for a toolbar item with kind = ``ITEM_SEPARATOR``. """ - - return self.spacer_pixels - - - def SetProportion(self, p): - """ - Sets the L{AuiToolBarItem} proportion in the toolbar. - - :param `p`: the item proportion. - """ - - self.proportion = p - - - def GetProportion(self): - """ Returns the L{AuiToolBarItem} proportion in the toolbar. """ - - return self.proportion - - - def SetActive(self, b): - """ - Activates/deactivates the toolbar item. - - :param `b`: ``True`` to activate the item, ``False`` to deactivate it. - """ - - self.active = b - - - def IsActive(self): - """ Returns whether the toolbar item is active or not. """ - - return self.active - - - def SetHasDropDown(self, b): - """ - Sets whether the toolbar item has an associated dropdown menu. - - :param `b`: ``True`` to set a dropdown menu, ``False`` otherwise. - """ - - self.dropdown = b - - - def HasDropDown(self): - """ Returns whether the toolbar item has an associated dropdown menu or not. """ - - return self.dropdown - - - def SetSticky(self, b): - """ - Sets whether the toolbar item is sticky (permanent highlight after mouse enter) - or not. - - :param `b`: ``True`` to set the item as sticky, ``False`` otherwise. - """ - - self.sticky = b - - - def IsSticky(self): - """ Returns whether the toolbar item has a sticky behaviour or not. """ - - return self.sticky - - - def SetUserData(self, l): - """ - Associates some kind of user data to the toolbar item. - - :param `l`: a Python object. - - :note: The user data can be any Python object. - """ - - self.user_data = l - - - def GetUserData(self): - """ Returns the associated user data. """ - - return self.user_data - - - def SetAlignment(self, l): - """ - Sets the toolbar item alignment. - - :param `l`: the item alignment, which can be one of the available `wx.Sizer` - alignments. - """ - - self.alignment = l - - - def GetAlignment(self): - """ Returns the toolbar item alignment. """ - - return self.alignment - - -# ---------------------------------------------------------------------- - -class AuiDefaultToolBarArt(object): - """ - Toolbar art provider code - a tab provider provides all drawing functionality to - the L{AuiToolBar}. This allows the L{AuiToolBar} to have a plugable look-and-feel. - - By default, a L{AuiToolBar} uses an instance of this class called L{AuiDefaultToolBarArt} - which provides bitmap art and a colour scheme that is adapted to the major platforms' - look. You can either derive from that class to alter its behaviour or write a - completely new tab art class. Call L{AuiToolBar.SetArtProvider} to make use this - new tab art. - """ - - def __init__(self): - """ Default class constructor. """ - - self._base_colour = GetBaseColour() - - self._agwFlags = 0 - self._text_orientation = AUI_TBTOOL_TEXT_BOTTOM - self._highlight_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT) - - self._separator_size = 7 - self._orientation = AUI_TBTOOL_HORIZONTAL - self._gripper_size = 7 - self._overflow_size = 16 - - darker1_colour = StepColour(self._base_colour, 85) - darker2_colour = StepColour(self._base_colour, 75) - darker3_colour = StepColour(self._base_colour, 60) - darker4_colour = StepColour(self._base_colour, 50) - darker5_colour = StepColour(self._base_colour, 40) - - self._gripper_pen1 = wx.Pen(darker5_colour) - self._gripper_pen2 = wx.Pen(darker3_colour) - self._gripper_pen3 = wx.WHITE_PEN - - button_dropdown_bits = "\xe0\xf1\xfb" - overflow_bits = "\x80\xff\x80\xc1\xe3\xf7" - - self._button_dropdown_bmp = BitmapFromBits(button_dropdown_bits, 5, 3, wx.BLACK) - self._disabled_button_dropdown_bmp = BitmapFromBits(button_dropdown_bits, 5, 3, - wx.Colour(128, 128, 128)) - self._overflow_bmp = BitmapFromBits(overflow_bits, 7, 6, wx.BLACK) - self._disabled_overflow_bmp = BitmapFromBits(overflow_bits, 7, 6, wx.Colour(128, 128, 128)) - - self._font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) - - - def Clone(self): - """ Clones the L{AuiToolBar} art. """ - - return AuiDefaultToolBarArt() - - - def SetAGWFlags(self, agwFlags): - """ - Sets the toolbar art flags. - - :param `agwFlags`: a combination of the following values: - - ==================================== ================================== - Flag name Description - ==================================== ================================== - ``AUI_TB_TEXT`` Shows the text in the toolbar buttons; by default only icons are shown - ``AUI_TB_NO_TOOLTIPS`` Don't show tooltips on `AuiToolBar` items - ``AUI_TB_NO_AUTORESIZE`` Do not auto-resize the `AuiToolBar` - ``AUI_TB_GRIPPER`` Shows a gripper on the `AuiToolBar` - ``AUI_TB_OVERFLOW`` The `AuiToolBar` can contain overflow items - ``AUI_TB_VERTICAL`` The `AuiToolBar` is vertical - ``AUI_TB_HORZ_LAYOUT`` Shows the text and the icons alongside, not vertically stacked. This style must be used with ``AUI_TB_TEXT`` - ``AUI_TB_PLAIN_BACKGROUND`` Don't draw a gradient background on the toolbar - ``AUI_TB_HORZ_TEXT`` Combination of ``AUI_TB_HORZ_LAYOUT`` and ``AUI_TB_TEXT`` - ==================================== ================================== - - """ - - self._agwFlags = agwFlags - - - def GetAGWFlags(self): - """ - Returns the L{AuiDefaultToolBarArt} flags. See L{SetAGWFlags} for more - details. - - :see: L{SetAGWFlags} - """ - - return self._agwFlags - - - def SetFont(self, font): - """ - Sets the L{AuiDefaultToolBarArt} font. - - :param `font`: a `wx.Font` object. - """ - - self._font = font - - - def SetTextOrientation(self, orientation): - """ - Sets the text orientation. - - :param `orientation`: can be one of the following constants: - - ==================================== ================================== - Orientation Switches Description - ==================================== ================================== - ``AUI_TBTOOL_TEXT_LEFT`` Text in `AuiToolBar` items is aligned left - ``AUI_TBTOOL_TEXT_RIGHT`` Text in `AuiToolBar` items is aligned right - ``AUI_TBTOOL_TEXT_TOP`` Text in `AuiToolBar` items is aligned top - ``AUI_TBTOOL_TEXT_BOTTOM`` Text in `AuiToolBar` items is aligned bottom - ==================================== ================================== - - """ - - self._text_orientation = orientation - - - def GetFont(self): - """ Returns the L{AuiDefaultToolBarArt} font. """ - - return self._font - - - def GetTextOrientation(self): - """ - Returns the L{AuiDefaultToolBarArt} text orientation. See - L{SetTextOrientation} for more details. - - :see: L{SetTextOrientation} - """ - - return self._text_orientation - - - def SetOrientation(self, orientation): - """ - Sets the toolbar tool orientation. - - :param `orientation`: one of ``AUI_TBTOOL_HORIZONTAL``, ``AUI_TBTOOL_VERT_CLOCKWISE`` or - ``AUI_TBTOOL_VERT_COUNTERCLOCKWISE``. - """ - - self._orientation = orientation - - - def GetOrientation(self): - """ Returns the toolbar orientation. """ - - return self._orientation - - - def DrawBackground(self, dc, wnd, _rect, horizontal=True): - """ - Draws a toolbar background with a gradient shading. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` derived window; - :param `_rect`: the L{AuiToolBar} rectangle; - :param `horizontal`: ``True`` if the toolbar is horizontal, ``False`` if it is vertical. - """ - - rect = wx.Rect(*_rect) - - start_colour = StepColour(self._base_colour, 180) - end_colour = StepColour(self._base_colour, 85) - reflex_colour = StepColour(self._base_colour, 95) - - dc.GradientFillLinear(rect, start_colour, end_colour, - (horizontal and [wx.SOUTH] or [wx.EAST])[0]) - - left = rect.GetLeft() - right = rect.GetRight() - top = rect.GetTop() - bottom = rect.GetBottom() - - dc.SetPen(wx.Pen(reflex_colour)) - if horizontal: - dc.DrawLine(left, bottom, right+1, bottom) - else: - dc.DrawLine(right, top, right, bottom+1) - - - def DrawPlainBackground(self, dc, wnd, _rect): - """ - Draws a toolbar background with a plain colour. - - This method contrasts with the default behaviour of the L{AuiToolBar} that - draws a background gradient and this break the window design when putting - it within a control that has margin between the borders and the toolbar - (example: put L{AuiToolBar} within a `wx.StaticBoxSizer` that has a plain background). - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` derived window; - :param `_rect`: the L{AuiToolBar} rectangle. - """ - - rect = wx.Rect(*_rect) - rect.height += 1 - - dc.SetBrush(wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE))) - dc.DrawRectangle(rect.x - 1, rect.y - 1, rect.width + 2, rect.height + 1) - - - def DrawLabel(self, dc, wnd, item, rect): - """ - Draws a toolbar item label. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` derived window; - :param `item`: an instance of L{AuiToolBarItem}; - :param `rect`: the L{AuiToolBarItem} rectangle. - """ - - dc.SetFont(self._font) - dc.SetTextForeground(wx.BLACK) - orient = item.GetOrientation() - - horizontal = orient == AUI_TBTOOL_HORIZONTAL - # we only care about the text height here since the text - # will get cropped based on the width of the item - label_size = GetLabelSize(dc, item.GetLabel(), not horizontal) - text_width = label_size.GetWidth() - text_height = label_size.GetHeight() - - if orient == AUI_TBTOOL_HORIZONTAL: - text_x = rect.x - text_y = rect.y + (rect.height-text_height)/2 - dc.DrawText(item.GetLabel(), text_x, text_y) - - elif orient == AUI_TBTOOL_VERT_CLOCKWISE: - text_x = rect.x + (rect.width+text_width)/2 - text_y = rect.y - dc.DrawRotatedText(item.GetLabel(), text_x, text_y, 270) - - elif AUI_TBTOOL_VERT_COUNTERCLOCKWISE: - text_x = rect.x + (rect.width-text_width)/2 - text_y = rect.y + text_height - dc.DrawRotatedText(item.GetLabel(), text_x, text_y, 90) - - - def DrawButton(self, dc, wnd, item, rect): - """ - Draws a toolbar item button. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` derived window; - :param `item`: an instance of L{AuiToolBarItem}; - :param `rect`: the L{AuiToolBarItem} rectangle. - """ - - bmp_rect, text_rect = self.GetToolsPosition(dc, item, rect) - - if not item.GetState() & AUI_BUTTON_STATE_DISABLED: - - if item.GetState() & AUI_BUTTON_STATE_PRESSED: - - dc.SetPen(wx.Pen(self._highlight_colour)) - dc.SetBrush(wx.Brush(StepColour(self._highlight_colour, 150))) - dc.DrawRectangleRect(rect) - - elif item.GetState() & AUI_BUTTON_STATE_HOVER or item.IsSticky(): - - dc.SetPen(wx.Pen(self._highlight_colour)) - dc.SetBrush(wx.Brush(StepColour(self._highlight_colour, 170))) - - # draw an even lighter background for checked item hovers (since - # the hover background is the same colour as the check background) - if item.GetState() & AUI_BUTTON_STATE_CHECKED: - dc.SetBrush(wx.Brush(StepColour(self._highlight_colour, 180))) - - dc.DrawRectangleRect(rect) - - elif item.GetState() & AUI_BUTTON_STATE_CHECKED: - - # it's important to put this code in an else statment after the - # hover, otherwise hovers won't draw properly for checked items - dc.SetPen(wx.Pen(self._highlight_colour)) - dc.SetBrush(wx.Brush(StepColour(self._highlight_colour, 170))) - dc.DrawRectangleRect(rect) - - if item.GetState() & AUI_BUTTON_STATE_DISABLED: - bmp = item.GetDisabledBitmap() - else: - bmp = item.GetBitmap() - - if bmp.IsOk(): - dc.DrawBitmap(bmp, bmp_rect.x, bmp_rect.y, True) - - # set the item's text colour based on if it is disabled - dc.SetTextForeground(wx.BLACK) - if item.GetState() & AUI_BUTTON_STATE_DISABLED: - dc.SetTextForeground(DISABLED_TEXT_COLOUR) - - if self._agwFlags & AUI_TB_TEXT and item.GetLabel() != "": - self.DrawLabel(dc, wnd, item, text_rect) - - - def DrawDropDownButton(self, dc, wnd, item, rect): - """ - Draws a toolbar dropdown button. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` derived window; - :param `item`: an instance of L{AuiToolBarItem}; - :param `rect`: the L{AuiToolBarItem} rectangle. - """ - - dropbmp_x = dropbmp_y = 0 - - button_rect = wx.Rect(rect.x, rect.y, rect.width-BUTTON_DROPDOWN_WIDTH, rect.height) - dropdown_rect = wx.Rect(rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1, rect.y, BUTTON_DROPDOWN_WIDTH+1, rect.height) - - horizontal = item.GetOrientation() == AUI_TBTOOL_HORIZONTAL - - if horizontal: - button_rect = wx.Rect(rect.x, rect.y, rect.width-BUTTON_DROPDOWN_WIDTH, rect.height) - dropdown_rect = wx.Rect(rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1, rect.y, BUTTON_DROPDOWN_WIDTH+1, rect.height) - else: - button_rect = wx.Rect(rect.x, rect.y, rect.width, rect.height-BUTTON_DROPDOWN_WIDTH) - dropdown_rect = wx.Rect(rect.x, rect.y+rect.height-BUTTON_DROPDOWN_WIDTH-1, rect.width, BUTTON_DROPDOWN_WIDTH+1) - - dropbmp_width = self._button_dropdown_bmp.GetWidth() - dropbmp_height = self._button_dropdown_bmp.GetHeight() - if not horizontal: - tmp = dropbmp_width - dropbmp_width = dropbmp_height - dropbmp_height = tmp - - dropbmp_x = dropdown_rect.x + (dropdown_rect.width/2) - dropbmp_width/2 - dropbmp_y = dropdown_rect.y + (dropdown_rect.height/2) - dropbmp_height/2 - - bmp_rect, text_rect = self.GetToolsPosition(dc, item, button_rect) - - if item.GetState() & AUI_BUTTON_STATE_PRESSED: - - dc.SetPen(wx.Pen(self._highlight_colour)) - dc.SetBrush(wx.Brush(StepColour(self._highlight_colour, 140))) - dc.DrawRectangleRect(button_rect) - dc.DrawRectangleRect(dropdown_rect) - - elif item.GetState() & AUI_BUTTON_STATE_HOVER or item.IsSticky(): - - dc.SetPen(wx.Pen(self._highlight_colour)) - dc.SetBrush(wx.Brush(StepColour(self._highlight_colour, 170))) - dc.DrawRectangleRect(button_rect) - dc.DrawRectangleRect(dropdown_rect) - - elif item.GetState() & AUI_BUTTON_STATE_CHECKED: - # it's important to put this code in an else statment after the - # hover, otherwise hovers won't draw properly for checked items - dc.SetPen(wx.Pen(self._highlight_colour)) - dc.SetBrush(wx.Brush(StepColour(self._highlight_colour, 170))) - dc.DrawRectangle(button_rect) - dc.DrawRectangle(dropdown_rect) - - if item.GetState() & AUI_BUTTON_STATE_DISABLED: - - bmp = item.GetDisabledBitmap() - dropbmp = self._disabled_button_dropdown_bmp - - else: - - bmp = item.GetBitmap() - dropbmp = self._button_dropdown_bmp - - if not bmp.IsOk(): - return - - dc.DrawBitmap(bmp, bmp_rect.x, bmp_rect.y, True) - if horizontal: - dc.DrawBitmap(dropbmp, dropbmp_x, dropbmp_y, True) - else: - dc.DrawBitmap(wx.BitmapFromImage(dropbmp.ConvertToImage().Rotate90(item.GetOrientation() == AUI_TBTOOL_VERT_CLOCKWISE)), - dropbmp_x, dropbmp_y, True) - - # set the item's text colour based on if it is disabled - dc.SetTextForeground(wx.BLACK) - if item.GetState() & AUI_BUTTON_STATE_DISABLED: - dc.SetTextForeground(DISABLED_TEXT_COLOUR) - - if self._agwFlags & AUI_TB_TEXT and item.GetLabel() != "": - self.DrawLabel(dc, wnd, item, text_rect) - - - def DrawControlLabel(self, dc, wnd, item, rect): - """ - Draws a label for a toolbar control. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` derived window; - :param `item`: an instance of L{AuiToolBarItem}; - :param `rect`: the L{AuiToolBarItem} rectangle. - """ - - label_size = GetLabelSize(dc, item.GetLabel(), item.GetOrientation() != AUI_TBTOOL_HORIZONTAL) - text_height = label_size.GetHeight() - text_width = label_size.GetWidth() - - dc.SetFont(self._font) - - if self._agwFlags & AUI_TB_TEXT: - - tx, text_height = dc.GetTextExtent("ABCDHgj") - - text_width, ty = dc.GetTextExtent(item.GetLabel()) - - # don't draw the label if it is wider than the item width - if text_width > rect.width: - return - - # set the label's text colour - dc.SetTextForeground(wx.BLACK) - - text_x = rect.x + (rect.width/2) - (text_width/2) + 1 - text_y = rect.y + rect.height - text_height - 1 - - if self._agwFlags & AUI_TB_TEXT and item.GetLabel() != "": - dc.DrawText(item.GetLabel(), text_x, text_y) - - - def GetLabelSize(self, dc, wnd, item): - """ - Returns the label size for a toolbar item. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` derived window; - :param `item`: an instance of L{AuiToolBarItem}. - """ - - dc.SetFont(self._font) - label_size = GetLabelSize(dc, item.GetLabel(), self._orientation != AUI_TBTOOL_HORIZONTAL) - - return wx.Size(item.GetMinSize().GetWidth(), label_size.GetHeight()) - - - def GetToolSize(self, dc, wnd, item): - """ - Returns the toolbar item size. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` derived window; - :param `item`: an instance of L{AuiToolBarItem}. - """ - - if not item.GetBitmap().IsOk() and not self._agwFlags & AUI_TB_TEXT: - return wx.Size(16, 16) - - width = item.GetBitmap().GetWidth() - height = item.GetBitmap().GetHeight() - - if self._agwFlags & AUI_TB_TEXT: - - dc.SetFont(self._font) - label_size = GetLabelSize(dc, item.GetLabel(), self.GetOrientation() != AUI_TBTOOL_HORIZONTAL) - padding = 6 - - if self._text_orientation == AUI_TBTOOL_TEXT_BOTTOM: - - if self.GetOrientation() != AUI_TBTOOL_HORIZONTAL: - height += 3 # space between top border and bitmap - height += 3 # space between bitmap and text - padding = 0 - - height += label_size.GetHeight() - - if item.GetLabel() != "": - width = max(width, label_size.GetWidth()+padding) - - elif self._text_orientation == AUI_TBTOOL_TEXT_RIGHT and item.GetLabel() != "": - - if self.GetOrientation() == AUI_TBTOOL_HORIZONTAL: - - width += 3 # space between left border and bitmap - width += 3 # space between bitmap and text - padding = 0 - - width += label_size.GetWidth() - height = max(height, label_size.GetHeight()+padding) - - # if the tool has a dropdown button, add it to the width - if item.HasDropDown(): - if item.GetOrientation() == AUI_TBTOOL_HORIZONTAL: - width += BUTTON_DROPDOWN_WIDTH+4 - else: - height += BUTTON_DROPDOWN_WIDTH+4 - - return wx.Size(width, height) - - - def DrawSeparator(self, dc, wnd, _rect): - """ - Draws a toolbar separator. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` derived window; - :param `_rect`: the L{AuiToolBarItem} rectangle. - """ - - horizontal = True - if self._agwFlags & AUI_TB_VERTICAL: - horizontal = False - - rect = wx.Rect(*_rect) - - if horizontal: - - rect.x += (rect.width/2) - rect.width = 1 - new_height = (rect.height*3)/4 - rect.y += (rect.height/2) - (new_height/2) - rect.height = new_height - - else: - - rect.y += (rect.height/2) - rect.height = 1 - new_width = (rect.width*3)/4 - rect.x += (rect.width/2) - (new_width/2) - rect.width = new_width - - start_colour = StepColour(self._base_colour, 80) - end_colour = StepColour(self._base_colour, 80) - dc.GradientFillLinear(rect, start_colour, end_colour, (horizontal and [wx.SOUTH] or [wx.EAST])[0]) - - - def DrawGripper(self, dc, wnd, rect): - """ - Draws the toolbar gripper. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` derived window; - :param `rect`: the L{AuiToolBar} rectangle. - """ - - i = 0 - while 1: - - if self._agwFlags & AUI_TB_VERTICAL: - - x = rect.x + (i*4) + 4 - y = rect.y + 3 - if x > rect.GetWidth() - 4: - break - - else: - - x = rect.x + 3 - y = rect.y + (i*4) + 4 - if y > rect.GetHeight() - 4: - break - - dc.SetPen(self._gripper_pen1) - dc.DrawPoint(x, y) - dc.SetPen(self._gripper_pen2) - dc.DrawPoint(x, y+1) - dc.DrawPoint(x+1, y) - dc.SetPen(self._gripper_pen3) - dc.DrawPoint(x+2, y+1) - dc.DrawPoint(x+2, y+2) - dc.DrawPoint(x+1, y+2) - - i += 1 - - - def DrawOverflowButton(self, dc, wnd, rect, state): - """ - Draws the overflow button for the L{AuiToolBar}. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` derived window; - :param `rect`: the L{AuiToolBar} rectangle; - :param `state`: the overflow button state. - """ - - if state & AUI_BUTTON_STATE_HOVER or state & AUI_BUTTON_STATE_PRESSED: - - cli_rect = wnd.GetClientRect() - light_gray_bg = StepColour(self._highlight_colour, 170) - - if self._agwFlags & AUI_TB_VERTICAL: - - dc.SetPen(wx.Pen(self._highlight_colour)) - dc.DrawLine(rect.x, rect.y, rect.x+rect.width, rect.y) - dc.SetPen(wx.Pen(light_gray_bg)) - dc.SetBrush(wx.Brush(light_gray_bg)) - dc.DrawRectangle(rect.x, rect.y+1, rect.width, rect.height) - - else: - - dc.SetPen(wx.Pen(self._highlight_colour)) - dc.DrawLine(rect.x, rect.y, rect.x, rect.y+rect.height) - dc.SetPen(wx.Pen(light_gray_bg)) - dc.SetBrush(wx.Brush(light_gray_bg)) - dc.DrawRectangle(rect.x+1, rect.y, rect.width, rect.height) - - x = rect.x + 1 + (rect.width-self._overflow_bmp.GetWidth())/2 - y = rect.y + 1 + (rect.height-self._overflow_bmp.GetHeight())/2 - dc.DrawBitmap(self._overflow_bmp, x, y, True) - - - def GetElementSize(self, element_id): - """ - Returns the size of a UI element in the L{AuiToolBar}. - - :param `element_id`: can be one of the following: - - ==================================== ================================== - Element Identifier Description - ==================================== ================================== - ``AUI_TBART_SEPARATOR_SIZE`` Separator size in `AuiToolBar` - ``AUI_TBART_GRIPPER_SIZE`` Gripper size in `AuiToolBar` - ``AUI_TBART_OVERFLOW_SIZE`` Overflow button size in `AuiToolBar` - ==================================== ================================== - """ - - if element_id == AUI_TBART_SEPARATOR_SIZE: - return self._separator_size - elif element_id == AUI_TBART_GRIPPER_SIZE: - return self._gripper_size - elif element_id == AUI_TBART_OVERFLOW_SIZE: - return self._overflow_size - - return 0 - - - def SetElementSize(self, element_id, size): - """ - Sets the size of a UI element in the L{AuiToolBar}. - - :param `element_id`: can be one of the following: - - ==================================== ================================== - Element Identifier Description - ==================================== ================================== - ``AUI_TBART_SEPARATOR_SIZE`` Separator size in `AuiToolBar` - ``AUI_TBART_GRIPPER_SIZE`` Gripper size in `AuiToolBar` - ``AUI_TBART_OVERFLOW_SIZE`` Overflow button size in `AuiToolBar` - ==================================== ================================== - - :param `size`: the new size of the UI element. - """ - - if element_id == AUI_TBART_SEPARATOR_SIZE: - self._separator_size = size - elif element_id == AUI_TBART_GRIPPER_SIZE: - self._gripper_size = size - elif element_id == AUI_TBART_OVERFLOW_SIZE: - self._overflow_size = size - - - def ShowDropDown(self, wnd, items): - """ - Shows the drop down window menu for overflow items. - - :param `wnd`: an instance of `wx.Window`; - :param `items`: the overflow toolbar items (a Python list). - """ - - menuPopup = wx.Menu() - items_added = 0 - - for item in items: - - if item.GetKind() not in [ITEM_SEPARATOR, ITEM_SPACER, ITEM_CONTROL]: - - text = item.GetShortHelp() - if text == "": - text = item.GetLabel() - if text == "": - text = " " - - kind = item.GetKind() - m = wx.MenuItem(menuPopup, item.GetId(), text, item.GetShortHelp(), kind) - orientation = item.GetOrientation() - item.SetOrientation(AUI_TBTOOL_HORIZONTAL) - - if kind not in [ITEM_CHECK, ITEM_RADIO]: - m.SetBitmap(item.GetBitmap()) - - item.SetOrientation(orientation) - - menuPopup.AppendItem(m) - if kind in [ITEM_CHECK, ITEM_RADIO]: - state = (item.state & AUI_BUTTON_STATE_CHECKED and [True] or [False])[0] - m.Check(state) - - items_added += 1 - - else: - - if items_added > 0 and item.GetKind() == ITEM_SEPARATOR: - menuPopup.AppendSeparator() - - # find out where to put the popup menu of window items - pt = wx.GetMousePosition() - pt = wnd.ScreenToClient(pt) - - # find out the screen coordinate at the bottom of the tab ctrl - cli_rect = wnd.GetClientRect() - pt.y = cli_rect.y + cli_rect.height - - cc = ToolbarCommandCapture() - wnd.PushEventHandler(cc) - - # Adjustments to get slightly better menu placement - if wx.Platform == "__WXMAC__": - pt.y += 5 - pt.x -= 5 - - wnd.PopupMenu(menuPopup, pt) - command = cc.GetCommandId() - wnd.PopEventHandler(True) - - return command - - - def GetToolsPosition(self, dc, item, rect): - """ - Returns the bitmap and text rectangles for a toolbar item. - - :param `dc`: a `wx.DC` device context; - :param `item`: an instance of L{AuiToolBarItem}; - :param `rect`: the tool rect. - """ - - text_width = text_height = 0 - horizontal = self._orientation == AUI_TBTOOL_HORIZONTAL - text_bottom = self._text_orientation == AUI_TBTOOL_TEXT_BOTTOM - text_right = self._text_orientation == AUI_TBTOOL_TEXT_RIGHT - bmp_width = item.GetBitmap().GetWidth() - bmp_height = item.GetBitmap().GetHeight() - - if self._agwFlags & AUI_TB_TEXT: - dc.SetFont(self._font) - label_size = GetLabelSize(dc, item.GetLabel(), not horizontal) - text_height = label_size.GetHeight() - text_width = label_size.GetWidth() - - bmp_x = bmp_y = text_x = text_y = 0 - - if horizontal and text_bottom: - bmp_x = rect.x + (rect.width/2) - (bmp_width/2) - bmp_y = rect.y + 3 - text_x = rect.x + (rect.width/2) - (text_width/2) - text_y = rect.y + ((bmp_y - rect.y) * 2) + bmp_height - - elif horizontal and text_right: - bmp_x = rect.x + 3 - bmp_y = rect.y + (rect.height/2) - (bmp_height / 2) - text_x = rect.x + ((bmp_x - rect.x) * 2) + bmp_width - text_y = rect.y + (rect.height/2) - (text_height/2) - - elif not horizontal and text_bottom: - bmp_x = rect.x + (rect.width / 2) - (bmp_width / 2) - bmp_y = rect.y + 3 - text_x = rect.x + (rect.width / 2) - (text_width / 2) - text_y = rect.y + ((bmp_y - rect.y) * 2) + bmp_height - - bmp_rect = wx.Rect(bmp_x, bmp_y, bmp_width, bmp_height) - text_rect = wx.Rect(text_x, text_y, text_width, text_height) - - return bmp_rect, text_rect - - -class AuiToolBar(wx.PyControl): - """ - AuiToolBar is a completely owner-drawn toolbar perfectly integrated with the - AUI layout system. This allows drag and drop of toolbars, docking/floating - behaviour and the possibility to define "overflow" items in the toolbar itself. - - The default theme that is used is L{AuiDefaultToolBarArt}, which provides a modern, - glossy look and feel. The theme can be changed by calling L{AuiToolBar.SetArtProvider}. - """ - - def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, - size=wx.DefaultSize, style=0, agwStyle=AUI_TB_DEFAULT_STYLE): - """ - Default class constructor. - - :param `parent`: the L{AuiToolBar} parent; - :param `id`: an identifier for the control: a value of -1 is taken to mean a default; - :param `pos`: the control position. A value of (-1, -1) indicates a default position, - chosen by either the windowing system or wxPython, depending on platform; - :param `size`: the control size. A value of (-1, -1) indicates a default size, - chosen by either the windowing system or wxPython, depending on platform; - :param `style`: the control window style; - :param `agwStyle`: the AGW-specific window style. This can be a combination of the - following bits: - - ==================================== ================================== - Flag name Description - ==================================== ================================== - ``AUI_TB_TEXT`` Shows the text in the toolbar buttons; by default only icons are shown - ``AUI_TB_NO_TOOLTIPS`` Don't show tooltips on `AuiToolBar` items - ``AUI_TB_NO_AUTORESIZE`` Do not auto-resize the `AuiToolBar` - ``AUI_TB_GRIPPER`` Shows a gripper on the `AuiToolBar` - ``AUI_TB_OVERFLOW`` The `AuiToolBar` can contain overflow items - ``AUI_TB_VERTICAL`` The `AuiToolBar` is vertical - ``AUI_TB_HORZ_LAYOUT`` Shows the text and the icons alongside, not vertically stacked. This style must be used with ``AUI_TB_TEXT`` - ``AUI_TB_PLAIN_BACKGROUND`` Don't draw a gradient background on the toolbar - ``AUI_TB_HORZ_TEXT`` Combination of ``AUI_TB_HORZ_LAYOUT`` and ``AUI_TB_TEXT`` - ==================================== ================================== - - The default value for `agwStyle` is: ``AUI_TB_DEFAULT_STYLE`` = 0 - - """ - - wx.PyControl.__init__(self, parent, id, pos, size, style|wx.BORDER_NONE) - - self._sizer = wx.BoxSizer(wx.HORIZONTAL) - self.SetSizer(self._sizer) - self._button_width = -1 - self._button_height = -1 - self._sizer_element_count = 0 - self._action_pos = wx.Point(-1, -1) - self._action_item = None - self._tip_item = None - self._art = AuiDefaultToolBarArt() - self._tool_packing = 2 - self._tool_border_padding = 3 - self._tool_text_orientation = AUI_TBTOOL_TEXT_BOTTOM - self._tool_orientation = AUI_TBTOOL_HORIZONTAL - self._tool_alignment = wx.EXPAND - self._gripper_sizer_item = None - self._overflow_sizer_item = None - self._dragging = False - - self._agwStyle = self._originalStyle = agwStyle - - self._gripper_visible = (self._agwStyle & AUI_TB_GRIPPER and [True] or [False])[0] - self._overflow_visible = (self._agwStyle & AUI_TB_OVERFLOW and [True] or [False])[0] - self._overflow_state = 0 - self._custom_overflow_prepend = [] - self._custom_overflow_append = [] - - self._items = [] - - self.SetMargins(5, 5, 2, 2) - self.SetFont(wx.NORMAL_FONT) - self._art.SetAGWFlags(self._agwStyle) - self.SetExtraStyle(wx.WS_EX_PROCESS_IDLE) - - if agwStyle & AUI_TB_HORZ_LAYOUT: - self.SetToolTextOrientation(AUI_TBTOOL_TEXT_RIGHT) - elif agwStyle & AUI_TB_VERTICAL: - if agwStyle & AUI_TB_CLOCKWISE: - self.SetToolOrientation(AUI_TBTOOL_VERT_CLOCKWISE) - elif agwStyle & AUI_TB_COUNTERCLOCKWISE: - self.SetToolOrientation(AUI_TBTOOL_VERT_COUNTERCLOCKWISE) - - self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) - - self.Bind(wx.EVT_SIZE, self.OnSize) - self.Bind(wx.EVT_IDLE, self.OnIdle) - self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) - self.Bind(wx.EVT_PAINT, self.OnPaint) - self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) - self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown) - self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) - self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown) - self.Bind(wx.EVT_RIGHT_DCLICK, self.OnRightDown) - self.Bind(wx.EVT_RIGHT_UP, self.OnRightUp) - self.Bind(wx.EVT_MIDDLE_DOWN, self.OnMiddleDown) - self.Bind(wx.EVT_MIDDLE_DCLICK, self.OnMiddleDown) - self.Bind(wx.EVT_MIDDLE_UP, self.OnMiddleUp) - self.Bind(wx.EVT_MOTION, self.OnMotion) - self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow) - self.Bind(wx.EVT_SET_CURSOR, self.OnSetCursor) - - - def SetWindowStyleFlag(self, style): - """ - Sets the style of the window. - - :param `style`: the new window style. - - :note: Please note that some styles cannot be changed after the window - creation and that `Refresh` might need to be be called after changing the - others for the change to take place immediately. - - :note: Overridden from `wx.PyControl`. - """ - - wx.PyControl.SetWindowStyleFlag(self, style|wx.BORDER_NONE) - - - def SetAGWWindowStyleFlag(self, agwStyle): - """ - Sets the AGW-specific style of the window. - - :param `agwStyle`: the new window style. This can be a combination of the - following bits: - - ==================================== ================================== - Flag name Description - ==================================== ================================== - ``AUI_TB_TEXT`` Shows the text in the toolbar buttons; by default only icons are shown - ``AUI_TB_NO_TOOLTIPS`` Don't show tooltips on `AuiToolBar` items - ``AUI_TB_NO_AUTORESIZE`` Do not auto-resize the `AuiToolBar` - ``AUI_TB_GRIPPER`` Shows a gripper on the `AuiToolBar` - ``AUI_TB_OVERFLOW`` The `AuiToolBar` can contain overflow items - ``AUI_TB_VERTICAL`` The `AuiToolBar` is vertical - ``AUI_TB_HORZ_LAYOUT`` Shows the text and the icons alongside, not vertically stacked. This style must be used with ``AUI_TB_TEXT`` - ``AUI_TB_PLAIN_BACKGROUND`` Don't draw a gradient background on the toolbar - ``AUI_TB_HORZ_TEXT`` Combination of ``AUI_TB_HORZ_LAYOUT`` and ``AUI_TB_TEXT`` - ==================================== ================================== - - :note: Please note that some styles cannot be changed after the window - creation and that `Refresh` might need to be be called after changing the - others for the change to take place immediately. - """ - - self._agwStyle = self._originalStyle = agwStyle - - if self._art: - self._art.SetAGWFlags(self._agwStyle) - - if agwStyle & AUI_TB_GRIPPER: - self._gripper_visible = True - else: - self._gripper_visible = False - - if agwStyle & AUI_TB_OVERFLOW: - self._overflow_visible = True - else: - self._overflow_visible = False - - if agwStyle & AUI_TB_HORZ_LAYOUT: - self.SetToolTextOrientation(AUI_TBTOOL_TEXT_RIGHT) - else: - self.SetToolTextOrientation(AUI_TBTOOL_TEXT_BOTTOM) - - if agwStyle & AUI_TB_VERTICAL: - if agwStyle & AUI_TB_CLOCKWISE: - self.SetToolOrientation(AUI_TBTOOL_VERT_CLOCKWISE) - elif agwStyle & AUI_TB_COUNTERCLOCKWISE: - self.SetToolOrientation(AUI_TBTOOL_VERT_COUNTERCLOCKWISE) - - - def GetAGWWindowStyleFlag(self): - """ - Returns the AGW-specific window style flag. - - :see: L{SetAGWWindowStyleFlag} for an explanation of various AGW-specific style. - """ - - return self._agwStyle - - - def SetArtProvider(self, art): - """ - Instructs L{AuiToolBar} to use art provider specified by parameter `art` - for all drawing calls. This allows plugable look-and-feel features. - - :param `art`: an art provider. - - :note: The previous art provider object, if any, will be deleted by L{AuiToolBar}. - """ - - del self._art - self._art = art - - if self._art: - self._art.SetAGWFlags(self._agwStyle) - self._art.SetTextOrientation(self._tool_text_orientation) - self._art.SetOrientation(self._tool_orientation) - - - def GetArtProvider(self): - """ Returns the current art provider being used. """ - - return self._art - - - def AddSimpleTool(self, tool_id, label, bitmap, short_help_string="", kind=ITEM_NORMAL): - """ - Adds a tool to the toolbar. This is the simplest method you can use to - ass an item to the L{AuiToolBar}. - - :param `tool_id`: an integer by which the tool may be identified in subsequent operations; - :param `label`: the toolbar tool label; - :param `bitmap`: the primary tool bitmap; - :param `short_help_string`: this string is used for the tools tooltip; - :param `kind`: the item kind. Can be one of the following: - - ======================== ============================= - Item Kind Description - ======================== ============================= - ``ITEM_CONTROL`` The item in the `AuiToolBar` is a control - ``ITEM_LABEL`` The item in the `AuiToolBar` is a text label - ``ITEM_SPACER`` The item in the `AuiToolBar` is a spacer - ``ITEM_SEPARATOR`` The item in the `AuiToolBar` is a separator - ``ITEM_CHECK`` The item in the `AuiToolBar` is a toolbar check item - ``ITEM_NORMAL`` The item in the `AuiToolBar` is a standard toolbar item - ``ITEM_RADIO`` The item in the `AuiToolBar` is a toolbar radio item - ======================== ============================= - """ - - return self.AddTool(tool_id, label, bitmap, wx.NullBitmap, kind, short_help_string, "", None) - - - def AddToggleTool(self, tool_id, bitmap, disabled_bitmap, toggle=False, client_data=None, short_help_string="", long_help_string=""): - """ - Adds a toggle tool to the toolbar. - - :param `tool_id`: an integer by which the tool may be identified in subsequent operations; - :param `bitmap`: the primary tool bitmap; - :param `disabled_bitmap`: the bitmap to use when the tool is disabled. If it is equal to - `wx.NullBitmap`, the disabled bitmap is automatically generated by greing the normal one; - :param `client_data`: whatever Python object to associate with the toolbar item; - :param `short_help_string`: this string is used for the tools tooltip; - :param `long_help_string`: this string is shown in the statusbar (if any) of the parent - frame when the mouse pointer is inside the tool. - """ - - kind = (toggle and [ITEM_CHECK] or [ITEM_NORMAL])[0] - return self.AddTool(tool_id, "", bitmap, disabled_bitmap, kind, short_help_string, long_help_string, client_data) - - - def AddTool(self, tool_id, label, bitmap, disabled_bitmap, kind, short_help_string, long_help_string, client_data): - """ - Adds a tool to the toolbar. This is the full feature version of L{AddTool}. - - :param `tool_id`: an integer by which the tool may be identified in subsequent operations; - :param `label`: the toolbar tool label; - :param `bitmap`: the primary tool bitmap; - :param `disabled_bitmap`: the bitmap to use when the tool is disabled. If it is equal to - `wx.NullBitmap`, the disabled bitmap is automatically generated by greing the normal one; - :param `kind`: the item kind. Can be one of the following: - - ======================== ============================= - Item Kind Description - ======================== ============================= - ``ITEM_CONTROL`` The item in the `AuiToolBar` is a control - ``ITEM_LABEL`` The item in the `AuiToolBar` is a text label - ``ITEM_SPACER`` The item in the `AuiToolBar` is a spacer - ``ITEM_SEPARATOR`` The item in the `AuiToolBar` is a separator - ``ITEM_CHECK`` The item in the `AuiToolBar` is a toolbar check item - ``ITEM_NORMAL`` The item in the `AuiToolBar` is a standard toolbar item - ``ITEM_RADIO`` The item in the `AuiToolBar` is a toolbar radio item - ======================== ============================= - - :param `short_help_string`: this string is used for the tools tooltip; - :param `long_help_string`: this string is shown in the statusbar (if any) of the parent - frame when the mouse pointer is inside the tool. - :param `client_data`: whatever Python object to associate with the toolbar item. - """ - - item = AuiToolBarItem() - item.window = None - item.label = label - item.bitmap = bitmap - item.disabled_bitmap = disabled_bitmap - item.short_help = short_help_string - item.long_help = long_help_string - item.active = True - item.dropdown = False - item.spacer_pixels = 0 - - if tool_id == wx.ID_ANY: - tool_id = wx.NewId() - - item.id = tool_id - item.state = 0 - item.proportion = 0 - item.kind = kind - item.sizer_item = None - item.min_size = wx.Size(-1, -1) - item.user_data = 0 - item.sticky = False - item.orientation = self._tool_orientation - - if not item.disabled_bitmap.IsOk(): - # no disabled bitmap specified, we need to make one - if item.bitmap.IsOk(): - item.disabled_bitmap = MakeDisabledBitmap(item.bitmap) - - self._items.append(item) - return self._items[-1] - - - def AddCheckTool(self, tool_id, label, bitmap, disabled_bitmap, short_help_string="", long_help_string="", client_data=None): - """ - Adds a new check (or toggle) tool to the L{AuiToolBar}. - - :see: L{AddTool}. - """ - - return self.AddTool(tool_id, label, bitmap, disabled_bitmap, ITEM_CHECK, short_help_string, long_help_string, client_data) - - - def AddRadioTool(self, tool_id, label, bitmap, disabled_bitmap, short_help_string="", long_help_string="", client_data=None): - """ - Adds a new radio tool to the toolbar. - - Consecutive radio tools form a radio group such that exactly one button - in the group is pressed at any moment, in other words whenever a button - in the group is pressed the previously pressed button is automatically - released. You should avoid having the radio groups of only one element - as it would be impossible for the user to use such button. - - :note: By default, the first button in the radio group is initially pressed, - the others are not. - - :see: L{AddTool}. - """ - - return self.AddTool(tool_id, label, bitmap, disabled_bitmap, ITEM_RADIO, short_help_string, long_help_string, client_data) - - - def AddControl(self, control, label=""): - """ - Adds any control to the toolbar, typically e.g. a combobox. - - :param `control`: the control to be added; - :param `label`: the label which appears if the control goes into the - overflow items in the toolbar. - """ - - item = AuiToolBarItem() - item.window = control - item.label = label - item.bitmap = wx.NullBitmap - item.disabled_bitmap = wx.NullBitmap - item.active = True - item.dropdown = False - item.spacer_pixels = 0 - item.id = control.GetId() - item.state = 0 - item.proportion = 0 - item.kind = ITEM_CONTROL - item.sizer_item = None - item.min_size = control.GetEffectiveMinSize() - item.user_data = 0 - item.sticky = False - item.orientation = self._tool_orientation - - self._items.append(item) - return self._items[-1] - - - def AddLabel(self, tool_id, label="", width=0): - """ - Adds a label tool to the L{AuiToolBar}. - - :param `tool_id`: an integer by which the tool may be identified in subsequent operations; - :param `label`: the toolbar tool label; - :param `width`: the tool width. - """ - - min_size = wx.Size(-1, -1) - - if width != -1: - min_size.x = width - - item = AuiToolBarItem() - item.window = None - item.label = label - item.bitmap = wx.NullBitmap - item.disabled_bitmap = wx.NullBitmap - item.active = True - item.dropdown = False - item.spacer_pixels = 0 - - if tool_id == wx.ID_ANY: - tool_id = wx.NewId() - - item.id = tool_id - item.state = 0 - item.proportion = 0 - item.kind = ITEM_LABEL - item.sizer_item = None - item.min_size = min_size - item.user_data = 0 - item.sticky = False - item.orientation = self._tool_orientation - - self._items.append(item) - return self._items[-1] - - - def AddSeparator(self): - """ Adds a separator for spacing groups of tools. """ - - item = AuiToolBarItem() - item.window = None - item.label = "" - item.bitmap = wx.NullBitmap - item.disabled_bitmap = wx.NullBitmap - item.active = True - item.dropdown = False - item.id = -1 - item.state = 0 - item.proportion = 0 - item.kind = ITEM_SEPARATOR - item.sizer_item = None - item.min_size = wx.Size(-1, -1) - item.user_data = 0 - item.sticky = False - item.orientation = self._tool_orientation - - self._items.append(item) - return self._items[-1] - - - def AddSpacer(self, pixels): - """ - Adds a spacer for spacing groups of tools. - - :param `pixels`: the width of the spacer. - """ - - item = AuiToolBarItem() - item.window = None - item.label = "" - item.bitmap = wx.NullBitmap - item.disabled_bitmap = wx.NullBitmap - item.active = True - item.dropdown = False - item.spacer_pixels = pixels - item.id = -1 - item.state = 0 - item.proportion = 0 - item.kind = ITEM_SPACER - item.sizer_item = None - item.min_size = wx.Size(-1, -1) - item.user_data = 0 - item.sticky = False - item.orientation = self._tool_orientation - - self._items.append(item) - return self._items[-1] - - - def AddStretchSpacer(self, proportion=1): - """ - Adds a stretchable spacer for spacing groups of tools. - - :param `proportion`: the stretchable spacer proportion. - """ - - item = AuiToolBarItem() - item.window = None - item.label = "" - item.bitmap = wx.NullBitmap - item.disabled_bitmap = wx.NullBitmap - item.active = True - item.dropdown = False - item.spacer_pixels = 0 - item.id = -1 - item.state = 0 - item.proportion = proportion - item.kind = ITEM_SPACER - item.sizer_item = None - item.min_size = wx.Size(-1, -1) - item.user_data = 0 - item.sticky = False - item.orientation = self._tool_orientation - - self._items.append(item) - return self._items[-1] - - - def Clear(self): - """ Deletes all the tools in the L{AuiToolBar}. """ - - self._items = [] - self._sizer_element_count = 0 - - - def ClearTools(self): - """ Deletes all the tools in the L{AuiToolBar}. """ - - self.Clear() - - - def DeleteTool(self, tool_id): - """ - Removes the specified tool from the toolbar and deletes it. - - :param `tool_id`: the L{AuiToolBarItem} identifier. - - :returns: ``True`` if the tool was deleted, ``False`` otherwise. - - :note: Note that it is unnecessary to call L{Realize} for the change to - take place, it will happen immediately. - """ - - idx = self.GetToolIndex(tool_id) - - if idx >= 0 and idx < len(self._items): - self._items.pop(idx) - self.Realize() - return True - - return False - - - def DeleteToolByPos(self, pos): - """ - This function behaves like L{DeleteTool} but it deletes the tool at the - specified position and not the one with the given id. - - :param `pos`: the tool position. - - :see: L{DeleteTool} - """ - - if pos >= 0 and pos < len(self._items): - - self._items.pop(pos) - self.Realize() - return True - - return False - - - def FindControl(self, id): - """ - Returns a pointer to the control identified by `id` or ``None`` if no corresponding - control is found. - - :param `id`: the control identifier. - """ - - wnd = self.FindWindow(id) - return wnd - - - def FindTool(self, tool_id): - """ - Finds a tool for the given tool id. - - :param `tool_id`: the L{AuiToolBarItem} identifier. - """ - - for item in self._items: - if item.id == tool_id: - return item - - return None - - - def FindToolForPosition(self, x, y): - """ - Finds a tool for the given mouse position. - - :param `x`: mouse `x` position; - :param `y`: mouse `y` position. - - :returns: a pointer to a L{AuiToolBarItem} if a tool is found, or ``None`` otherwise. - """ - - for i, item in enumerate(self._items): - if not item.sizer_item: - continue - - rect = item.sizer_item.GetRect() - if rect.Contains((x,y)): - - # if the item doesn't fit on the toolbar, return None - if not self.GetToolFitsByIndex(i): - return None - - return item - - return None - - - def FindToolForPositionWithPacking(self, x, y): - """ - Finds a tool for the given mouse position, taking into account also the - tool packing. - - :param `x`: mouse `x` position; - :param `y`: mouse `y` position. - - :returns: a pointer to a L{AuiToolBarItem} if a tool is found, or ``None`` otherwise. - """ - - count = len(self._items) - - for i, item in enumerate(self._items): - if not item.sizer_item: - continue - - rect = item.sizer_item.GetRect() - - # apply tool packing - if i+1 < count: - rect.width += self._tool_packing - - if rect.Contains((x,y)): - - # if the item doesn't fit on the toolbar, return None - if not self.GetToolFitsByIndex(i): - return None - - return item - - return None - - - def FindToolByIndex(self, pos): - """ - Finds a tool for the given tool position in the L{AuiToolBar}. - - :param `pos`: the tool position in the toolbar. - - :returns: a pointer to a L{AuiToolBarItem} if a tool is found, or ``None`` otherwise. - """ - - if pos < 0 or pos >= len(self._items): - return None - - return self._items[pos] - - - def SetToolBitmapSize(self, size): - """ - Sets the default size of each tool bitmap. The default bitmap size is - 16 by 15 pixels. - - :param `size`: the size of the bitmaps in the toolbar. - - :note: This should be called to tell the toolbar what the tool bitmap - size is. Call it before you add tools. - - :note: Note that this is the size of the bitmap you pass to L{AddTool}, - and not the eventual size of the tool button. - - :todo: Add `wx.ToolBar` compatibility, actually implementing this method. - """ - - # TODO: wx.ToolBar compatibility - pass - - - def GetToolBitmapSize(self): - """ - Returns the size of bitmap that the toolbar expects to have. The default - bitmap size is 16 by 15 pixels. - - :note: Note that this is the size of the bitmap you pass to L{AddTool}, - and not the eventual size of the tool button. - - :todo: Add `wx.ToolBar` compatibility, actually implementing this method. - """ - - # TODO: wx.ToolBar compatibility - return wx.Size(16, 15) - - - def SetToolProportion(self, tool_id, proportion): - """ - Sets the tool proportion in the toolbar. - - :param `tool_id`: the L{AuiToolBarItem} identifier; - :param `proportion`: the tool proportion in the toolbar. - """ - - item = self.FindTool(tool_id) - if not item: - return - - item.proportion = proportion - - - def GetToolProportion(self, tool_id): - """ - Returns the tool proportion in the toolbar. - - :param `tool_id`: the L{AuiToolBarItem} identifier. - """ - - item = self.FindTool(tool_id) - if not item: - return - - return item.proportion - - - def SetToolSeparation(self, separation): - """ - Sets the separator size for the toolbar. - - :param `separation`: the separator size in pixels. - """ - - if self._art: - self._art.SetElementSize(AUI_TBART_SEPARATOR_SIZE, separation) - - - def GetToolSeparation(self): - """ Returns the separator size for the toolbar, in pixels. """ - - if self._art: - return self._art.GetElementSize(AUI_TBART_SEPARATOR_SIZE) - - return 5 - - - def SetToolDropDown(self, tool_id, dropdown): - """ - Assigns a drop down window menu to the toolbar item. - - :param `tool_id`: the L{AuiToolBarItem} identifier; - :param `dropdown`: whether to assign a drop down menu or not. - """ - - item = self.FindTool(tool_id) - if not item: - return - - item.dropdown = dropdown - - - def GetToolDropDown(self, tool_id): - """ - Returns whether the toolbar item identified by `tool_id` has an associated - drop down window menu or not. - - :param `tool_id`: the L{AuiToolBarItem} identifier. - """ - - item = self.FindTool(tool_id) - if not item: - return - - return item.dropdown - - - def SetToolSticky(self, tool_id, sticky): - """ - Sets the toolbar item as sticky or non-sticky. - - :param `tool_id`: the L{AuiToolBarItem} identifier; - :param `sticky`: whether the tool should be sticky or not. - """ - - # ignore separators - if tool_id == -1: - return - - item = self.FindTool(tool_id) - if not item: - return - - if item.sticky == sticky: - return - - item.sticky = sticky - - self.Refresh(False) - self.Update() - - - def GetToolSticky(self, tool_id): - """ - Returns whether the toolbar item identified by `tool_id` has a sticky - behaviour or not. - - :param `tool_id`: the L{AuiToolBarItem} identifier. - """ - - item = self.FindTool(tool_id) - if not item: - return - - return item.sticky - - - def SetToolBorderPadding(self, padding): - """ - Sets the padding between the tool border and the label. - - :param `padding`: the padding in pixels. - """ - - self._tool_border_padding = padding - - - def GetToolBorderPadding(self): - """ Returns the padding between the tool border and the label, in pixels. """ - - return self._tool_border_padding - - - def SetToolTextOrientation(self, orientation): - """ - Sets the label orientation for the toolbar items. - - :param `orientation`: the L{AuiToolBarItem} label orientation. - """ - - self._tool_text_orientation = orientation - - if self._art: - self._art.SetTextOrientation(orientation) - - - def GetToolTextOrientation(self): - """ Returns the label orientation for the toolbar items. """ - - return self._tool_text_orientation - - - def SetToolOrientation(self, orientation): - """ - Sets the tool orientation for the toolbar items. - - :param `orientation`: the L{AuiToolBarItem} orientation. - """ - - self._tool_orientation = orientation - if self._art: - self._art.SetOrientation(orientation) - - - def GetToolOrientation(self): - """ Returns the orientation for the toolbar items. """ - - return self._tool_orientation - - - def SetToolPacking(self, packing): - """ - Sets the value used for spacing tools. The default value is 1 pixel. - - :param `packing`: the value for packing. - """ - - self._tool_packing = packing - - - def GetToolPacking(self): - """ Returns the value used for spacing tools. The default value is 1 pixel. """ - - return self._tool_packing - - - def SetOrientation(self, orientation): - """ - Sets the toolbar orientation. - - :param `orientation`: either ``wx.VERTICAL`` or ``wx.HORIZONTAL``. - - :note: This can be temporarily overridden by L{AuiManager} when floating and - docking a L{AuiToolBar}. - """ - - pass - - - def SetMargins(self, left=-1, right=-1, top=-1, bottom=-1): - """ - Set the values to be used as margins for the toolbar. - - :param `left`: the left toolbar margin; - :param `right`: the right toolbar margin; - :param `top`: the top toolbar margin; - :param `bottom`: the bottom toolbar margin. - """ - - if left != -1: - self._left_padding = left - if right != -1: - self._right_padding = right - if top != -1: - self._top_padding = top - if bottom != -1: - self._bottom_padding = bottom - - - def SetMarginsSize(self, size): - """ - Set the values to be used as margins for the toolbar. - - :param `size`: the margin size (an instance of `wx.Size`). - """ - - self.SetMargins(size.x, size.x, size.y, size.y) - - - def SetMarginsXY(self, x, y): - """ - Set the values to be used as margins for the toolbar. - - :param `x`: left margin, right margin and inter-tool separation value; - :param `y`: top margin, bottom margin and inter-tool separation value. - """ - - self.SetMargins(x, x, y, y) - - - def GetGripperVisible(self): - """ Returns whether the toolbar gripper is visible or not. """ - - return self._gripper_visible - - - def SetGripperVisible(self, visible): - """ - Sets whether the toolbar gripper is visible or not. - - :param `visible`: ``True`` for a visible gripper, ``False`` otherwise. - """ - - self._gripper_visible = visible - if visible: - self._agwStyle |= AUI_TB_GRIPPER - else: - self._agwStyle &= ~AUI_TB_GRIPPER - - self.Realize() - self.Refresh(False) - - - def GetOverflowVisible(self): - """ Returns whether the overflow button is visible or not. """ - - return self._overflow_visible - - - def SetOverflowVisible(self, visible): - """ - Sets whether the overflow button is visible or not. - - :param `visible`: ``True`` for a visible overflow button, ``False`` otherwise. - """ - - self._overflow_visible = visible - if visible: - self._agwStyle |= AUI_TB_OVERFLOW - else: - self._agwStyle &= ~AUI_TB_OVERFLOW - - self.Refresh(False) - - - def SetFont(self, font): - """ - Sets the L{AuiToolBar} font. - - :param `font`: a `wx.Font` object. - - :note: Overridden from `wx.PyControl`. - """ - - res = wx.PyControl.SetFont(self, font) - - if self._art: - self._art.SetFont(font) - - return res - - - def SetHoverItem(self, pitem): - """ - Sets a toolbar item to be currently hovered by the mouse. - - :param `pitem`: an instance of L{AuiToolBarItem}. - """ - - former_hover = None - - for item in self._items: - - if item.state & AUI_BUTTON_STATE_HOVER: - former_hover = item - - item.state &= ~AUI_BUTTON_STATE_HOVER - - if pitem: - pitem.state |= AUI_BUTTON_STATE_HOVER - - if former_hover != pitem: - self.Refresh(False) - self.Update() - - - def SetPressedItem(self, pitem): - """ - Sets a toolbar item to be currently in a "pressed" state. - - :param `pitem`: an instance of L{AuiToolBarItem}. - """ - - former_item = None - - for item in self._items: - - if item.state & AUI_BUTTON_STATE_PRESSED: - former_item = item - - item.state &= ~AUI_BUTTON_STATE_PRESSED - - if pitem: - pitem.state &= ~AUI_BUTTON_STATE_HOVER - pitem.state |= AUI_BUTTON_STATE_PRESSED - - if former_item != pitem: - self.Refresh(False) - self.Update() - - - def RefreshOverflowState(self): - """ Refreshes the overflow button. """ - - if not self._overflow_sizer_item: - self._overflow_state = 0 - return - - overflow_state = 0 - overflow_rect = self.GetOverflowRect() - - # find out the mouse's current position - pt = wx.GetMousePosition() - pt = self.ScreenToClient(pt) - - # find out if the mouse cursor is inside the dropdown rectangle - if overflow_rect.Contains((pt.x, pt.y)): - - if _VERSION_STRING < "2.9": - leftDown = wx.GetMouseState().LeftDown() - else: - leftDown = wx.GetMouseState().LeftIsDown() - - if leftDown: - overflow_state = AUI_BUTTON_STATE_PRESSED - else: - overflow_state = AUI_BUTTON_STATE_HOVER - - if overflow_state != self._overflow_state: - self._overflow_state = overflow_state - self.Refresh(False) - self.Update() - - self._overflow_state = overflow_state - - - def ToggleTool(self, tool_id, state): - """ - Toggles a tool on or off. This does not cause any event to get emitted. - - :param `tool_id`: tool in question. - :param `state`: if ``True``, toggles the tool on, otherwise toggles it off. - - :note: This only applies to a tool that has been specified as a toggle tool. - """ - - tool = self.FindTool(tool_id) - - if tool: - if tool.kind not in [ITEM_CHECK, ITEM_RADIO]: - return - - if tool.kind == ITEM_RADIO: - idx = self.GetToolIndex(tool_id) - if idx >= 0 and idx < len(self._items): - for i in xrange(idx, len(self._items)): - tool = self.FindToolByIndex(i) - if tool.kind != ITEM_RADIO: - break - tool.state &= ~AUI_BUTTON_STATE_CHECKED - - for i in xrange(idx, -1, -1): - tool = self.FindToolByIndex(i) - if tool.kind != ITEM_RADIO: - break - tool.state &= ~AUI_BUTTON_STATE_CHECKED - - tool = self.FindTool(tool_id) - tool.state |= AUI_BUTTON_STATE_CHECKED - else: - if state == True: - tool.state |= AUI_BUTTON_STATE_CHECKED - else: - tool.state &= ~AUI_BUTTON_STATE_CHECKED - - - def GetToolToggled(self, tool_id): - """ - Returns whether a tool is toggled or not. - - :param `tool_id`: the toolbar item identifier. - - :note: This only applies to a tool that has been specified as a toggle tool. - """ - - tool = self.FindTool(tool_id) - - if tool: - if tool.kind not in [ITEM_CHECK, ITEM_RADIO]: - return False - - return (tool.state & AUI_BUTTON_STATE_CHECKED and [True] or [False])[0] - - return False - - - def EnableTool(self, tool_id, state): - """ - Enables or disables the tool. - - :param `tool_id`: identifier for the tool to enable or disable. - :param `state`: if ``True``, enables the tool, otherwise disables it. - """ - - tool = self.FindTool(tool_id) - - if tool: - - if state == True: - tool.state &= ~AUI_BUTTON_STATE_DISABLED - else: - tool.state |= AUI_BUTTON_STATE_DISABLED - - - def GetToolEnabled(self, tool_id): - """ - Returns whether the tool identified by `tool_id` is enabled or not. - - :param `tool_id`: the tool identifier. - """ - - tool = self.FindTool(tool_id) - - if tool: - return (tool.state & AUI_BUTTON_STATE_DISABLED and [False] or [True])[0] - - return False - - - def GetToolLabel(self, tool_id): - """ - Returns the tool label for the tool identified by `tool_id`. - - :param `tool_id`: the tool identifier. - """ - - tool = self.FindTool(tool_id) - if not tool: - return "" - - return tool.label - - - def SetToolLabel(self, tool_id, label): - """ - Sets the tool label for the tool identified by `tool_id`. - - :param `tool_id`: the tool identifier; - :param `label`: the new toolbar item label. - """ - - tool = self.FindTool(tool_id) - if tool: - tool.label = label - - - def GetToolBitmap(self, tool_id): - """ - Returns the tool bitmap for the tool identified by `tool_id`. - - :param `tool_id`: the tool identifier. - """ - - tool = self.FindTool(tool_id) - if not tool: - return wx.NullBitmap - - return tool.bitmap - - - def SetToolBitmap(self, tool_id, bitmap): - """ - Sets the tool bitmap for the tool identified by `tool_id`. - - :param `tool_id`: the tool identifier; - :param `bitmap`: the new bitmap for the toolbar item (an instance of `wx.Bitmap`). - """ - - tool = self.FindTool(tool_id) - if tool: - tool.bitmap = bitmap - - - def SetToolNormalBitmap(self, tool_id, bitmap): - """ - Sets the tool bitmap for the tool identified by `tool_id`. - - :param `tool_id`: the tool identifier; - :param `bitmap`: the new bitmap for the toolbar item (an instance of `wx.Bitmap`). - """ - - self.SetToolBitmap(tool_id, bitmap) - - - def SetToolDisabledBitmap(self, tool_id, bitmap): - """ - Sets the tool disabled bitmap for the tool identified by `tool_id`. - - :param `tool_id`: the tool identifier; - :param `bitmap`: the new disabled bitmap for the toolbar item (an instance of `wx.Bitmap`). - """ - - tool = self.FindTool(tool_id) - if tool: - tool.disabled_bitmap = bitmap - - - def GetToolShortHelp(self, tool_id): - """ - Returns the short help for the given tool. - - :param `tool_id`: the tool identifier. - """ - - tool = self.FindTool(tool_id) - if not tool: - return "" - - return tool.short_help - - - def SetToolShortHelp(self, tool_id, help_string): - """ - Sets the short help for the given tool. - - :param `tool_id`: the tool identifier; - :param `help_string`: the string for the short help. - """ - - tool = self.FindTool(tool_id) - if tool: - tool.short_help = help_string - - - def GetToolLongHelp(self, tool_id): - """ - Returns the long help for the given tool. - - :param `tool_id`: the tool identifier. - """ - - tool = self.FindTool(tool_id) - if not tool: - return "" - - return tool.long_help - - - def SetToolAlignment(self, alignment=wx.EXPAND): - """ - This sets the alignment for all of the tools within the - toolbar (only has an effect when the toolbar is expanded). - - :param `alignment`: `wx.Sizer` alignment value - (``wx.ALIGN_CENTER_HORIZONTAL`` or ``wx.ALIGN_CENTER_VERTICAL``). - """ - - self._tool_alignment = alignment - - - - def SetToolLongHelp(self, tool_id, help_string): - """ - Sets the long help for the given tool. - - :param `tool_id`: the tool identifier; - :param `help_string`: the string for the long help. - """ - - tool = self.FindTool(tool_id) - if tool: - tool.long_help = help_string - - - def SetCustomOverflowItems(self, prepend, append): - """ - Sets the two lists `prepend` and `append` as custom overflow items. - - :param `prepend`: a list of L{AuiToolBarItem} to be prepended; - :param `append`: a list of L{AuiToolBarItem} to be appended. - """ - - self._custom_overflow_prepend = prepend - self._custom_overflow_append = append - - - def GetToolCount(self): - """ Returns the number of tools in the L{AuiToolBar}. """ - - return len(self._items) - - - def GetToolIndex(self, tool_id): - """ - Returns the position of the tool in the toolbar given its identifier. - - :param `tool_id`: the toolbar item identifier. - """ - - # this will prevent us from returning the index of the - # first separator in the toolbar since its id is equal to -1 - if tool_id == -1: - return wx.NOT_FOUND - - for i, item in enumerate(self._items): - if item.id == tool_id: - return i - - return wx.NOT_FOUND - - - def GetToolPos(self, tool_id): - """ - Returns the position of the tool in the toolbar given its identifier. - - :param `tool_id`: the toolbar item identifier. - """ - - return self.GetToolIndex(tool_id) - - - def GetToolFitsByIndex(self, tool_id): - """ - Returns whether the tool identified by `tool_id` fits into the toolbar or not. - - :param `tool_id`: the toolbar item identifier. - """ - - if tool_id < 0 or tool_id >= len(self._items): - return False - - if not self._items[tool_id].sizer_item: - return False - - cli_w, cli_h = self.GetClientSize() - rect = self._items[tool_id].sizer_item.GetRect() - - if self._agwStyle & AUI_TB_VERTICAL: - # take the dropdown size into account - if self._overflow_visible: - cli_h -= self._overflow_sizer_item.GetSize().y - - if rect.y+rect.height < cli_h: - return True - - else: - - # take the dropdown size into account - if self._overflow_visible: - cli_w -= self._overflow_sizer_item.GetSize().x - - if rect.x+rect.width < cli_w: - return True - - return False - - - def GetToolFits(self, tool_id): - """ - Returns whether the tool identified by `tool_id` fits into the toolbar or not. - - :param `tool_id`: the toolbar item identifier. - """ - - return self.GetToolFitsByIndex(self.GetToolIndex(tool_id)) - - - def GetToolRect(self, tool_id): - """ - Returns the toolbar item rectangle - - :param `tool_id`: the toolbar item identifier. - """ - - tool = self.FindTool(tool_id) - if tool and tool.sizer_item: - return tool.sizer_item.GetRect() - - return wx.Rect() - - - def GetToolBarFits(self): - """ Returns whether the L{AuiToolBar} size fits in a specified size. """ - - if len(self._items) == 0: - # empty toolbar always 'fits' - return True - - # entire toolbar content fits if the last tool fits - return self.GetToolFitsByIndex(len(self._items) - 1) - - - def Realize(self): - """ Realizes the toolbar. This function should be called after you have added tools. """ - - dc = wx.ClientDC(self) - - if not dc.IsOk(): - return False - - horizontal = True - if self._agwStyle & AUI_TB_VERTICAL: - horizontal = False - - # create the new sizer to add toolbar elements to - sizer = wx.BoxSizer((horizontal and [wx.HORIZONTAL] or [wx.VERTICAL])[0]) - - # add gripper area - separator_size = self._art.GetElementSize(AUI_TBART_SEPARATOR_SIZE) - gripper_size = self._art.GetElementSize(AUI_TBART_GRIPPER_SIZE) - - if gripper_size > 0 and self._gripper_visible: - if horizontal: - self._gripper_sizer_item = sizer.Add((gripper_size, 1), 0, wx.EXPAND) - else: - self._gripper_sizer_item = sizer.Add((1, gripper_size), 0, wx.EXPAND) - else: - self._gripper_sizer_item = None - - # add "left" padding - if self._left_padding > 0: - if horizontal: - sizer.Add((self._left_padding, 1)) - else: - sizer.Add((1, self._left_padding)) - - count = len(self._items) - for i, item in enumerate(self._items): - - sizer_item = None - kind = item.kind - - if kind == ITEM_LABEL: - - size = self._art.GetLabelSize(dc, self, item) - sizer_item = sizer.Add((size.x + (self._tool_border_padding*2), - size.y + (self._tool_border_padding*2)), - item.proportion, - item.alignment) - if i+1 < count: - sizer.AddSpacer(self._tool_packing) - - - elif kind in [ITEM_CHECK, ITEM_NORMAL, ITEM_RADIO]: - - size = self._art.GetToolSize(dc, self, item) - sizer_item = sizer.Add((size.x + (self._tool_border_padding*2), - size.y + (self._tool_border_padding*2)), - 0, - item.alignment) - # add tool packing - if i+1 < count: - sizer.AddSpacer(self._tool_packing) - - elif kind == ITEM_SEPARATOR: - - if horizontal: - sizer_item = sizer.Add((separator_size, 1), 0, wx.EXPAND) - else: - sizer_item = sizer.Add((1, separator_size), 0, wx.EXPAND) - - # add tool packing - if i+1 < count: - sizer.AddSpacer(self._tool_packing) - - elif kind == ITEM_SPACER: - - if item.proportion > 0: - sizer_item = sizer.AddStretchSpacer(item.proportion) - else: - sizer_item = sizer.Add((item.spacer_pixels, 1)) - - elif kind == ITEM_CONTROL: - - vert_sizer = wx.BoxSizer(wx.VERTICAL) - vert_sizer.AddStretchSpacer(1) - ctrl_sizer_item = vert_sizer.Add(item.window, 0, wx.EXPAND) - vert_sizer.AddStretchSpacer(1) - - if self._agwStyle & AUI_TB_TEXT and \ - self._tool_text_orientation == AUI_TBTOOL_TEXT_BOTTOM and \ - item.GetLabel() != "": - - s = self.GetLabelSize(item.GetLabel()) - vert_sizer.Add((1, s.y)) - - sizer_item = sizer.Add(vert_sizer, item.proportion, wx.EXPAND) - min_size = item.min_size - - # proportional items will disappear from the toolbar if - # their min width is not set to something really small - if item.proportion != 0: - min_size.x = 1 - - if min_size.IsFullySpecified(): - sizer.SetItemMinSize(vert_sizer, min_size) - vert_sizer.SetItemMinSize(item.window, min_size) - - # add tool packing - if i+1 < count: - sizer.AddSpacer(self._tool_packing) - - item.sizer_item = sizer_item - - - # add "right" padding - if self._right_padding > 0: - if horizontal: - sizer.Add((self._right_padding, 1)) - else: - sizer.Add((1, self._right_padding)) - - # add drop down area - self._overflow_sizer_item = None - - if self._agwStyle & AUI_TB_OVERFLOW: - - overflow_size = self._art.GetElementSize(AUI_TBART_OVERFLOW_SIZE) - if overflow_size > 0 and self._overflow_visible: - - if horizontal: - self._overflow_sizer_item = sizer.Add((overflow_size, 1), 0, wx.EXPAND) - else: - self._overflow_sizer_item = sizer.Add((1, overflow_size), 0, wx.EXPAND) - - else: - - self._overflow_sizer_item = None - - # the outside sizer helps us apply the "top" and "bottom" padding - outside_sizer = wx.BoxSizer((horizontal and [wx.VERTICAL] or [wx.HORIZONTAL])[0]) - - # add "top" padding - if self._top_padding > 0: - - if horizontal: - outside_sizer.Add((1, self._top_padding)) - else: - outside_sizer.Add((self._top_padding, 1)) - - # add the sizer that contains all of the toolbar elements - outside_sizer.Add(sizer, 1, self._tool_alignment) - - # add "bottom" padding - if self._bottom_padding > 0: - - if horizontal: - outside_sizer.Add((1, self._bottom_padding)) - else: - outside_sizer.Add((self._bottom_padding, 1)) - - del self._sizer # remove old sizer - self._sizer = outside_sizer - self.SetSizer(outside_sizer) - - # calculate the rock-bottom minimum size - for item in self._items: - - if item.sizer_item and item.proportion > 0 and item.min_size.IsFullySpecified(): - item.sizer_item.SetMinSize((0, 0)) - - self._absolute_min_size = self._sizer.GetMinSize() - - # reset the min sizes to what they were - for item in self._items: - - if item.sizer_item and item.proportion > 0 and item.min_size.IsFullySpecified(): - item.sizer_item.SetMinSize(item.min_size) - - # set control size - size = self._sizer.GetMinSize() - self.SetMinSize(size) - self._minWidth = size.x - self._minHeight = size.y - - if self._agwStyle & AUI_TB_NO_AUTORESIZE == 0: - - cur_size = self.GetClientSize() - new_size = self.GetMinSize() - - if new_size != cur_size: - - self.SetClientSize(new_size) - - else: - - self._sizer.SetDimension(0, 0, cur_size.x, cur_size.y) - - else: - - cur_size = self.GetClientSize() - self._sizer.SetDimension(0, 0, cur_size.x, cur_size.y) - - self.Refresh(False) - return True - - - def GetOverflowState(self): - """ Returns the state of the overflow button. """ - - return self._overflow_state - - - def GetOverflowRect(self): - """ Returns the rectangle of the overflow button. """ - - cli_rect = wx.RectPS(wx.Point(0, 0), self.GetClientSize()) - overflow_rect = wx.Rect(*self._overflow_sizer_item.GetRect()) - overflow_size = self._art.GetElementSize(AUI_TBART_OVERFLOW_SIZE) - - if self._agwStyle & AUI_TB_VERTICAL: - - overflow_rect.y = cli_rect.height - overflow_size - overflow_rect.x = 0 - overflow_rect.width = cli_rect.width - overflow_rect.height = overflow_size - - else: - - overflow_rect.x = cli_rect.width - overflow_size - overflow_rect.y = 0 - overflow_rect.width = overflow_size - overflow_rect.height = cli_rect.height - - return overflow_rect - - - def GetLabelSize(self, label): - """ - Returns the standard size of a toolbar item. - - :param `label`: a test label. - """ - - dc = wx.ClientDC(self) - dc.SetFont(self._font) - - return GetLabelSize(dc, label, self._tool_orientation != AUI_TBTOOL_HORIZONTAL) - - - def GetAuiManager(self): - """ Returns the L{AuiManager} which manages the toolbar. """ - - try: - return self._auiManager - except AttributeError: - return False - - - def SetAuiManager(self, auiManager): - """ Sets the L{AuiManager} which manages the toolbar. """ - - self._auiManager = auiManager - - - def DoIdleUpdate(self): - """ Updates the toolbar during idle times. """ - - handler = self.GetEventHandler() - if not handler: - return - - need_refresh = False - - for item in self._items: - - if item.id == -1: - continue - - evt = wx.UpdateUIEvent(item.id) - evt.SetEventObject(self) - - if handler.ProcessEvent(evt): - - if evt.GetSetEnabled(): - - if item.window: - is_enabled = item.window.IsEnabled() - else: - is_enabled = (item.state & AUI_BUTTON_STATE_DISABLED and [False] or [True])[0] - - new_enabled = evt.GetEnabled() - if new_enabled != is_enabled: - - if item.window: - item.window.Enable(new_enabled) - else: - if new_enabled: - item.state &= ~AUI_BUTTON_STATE_DISABLED - else: - item.state |= AUI_BUTTON_STATE_DISABLED - - need_refresh = True - - if evt.GetSetChecked(): - - # make sure we aren't checking an item that can't be - if item.kind != ITEM_CHECK and item.kind != ITEM_RADIO: - continue - - is_checked = (item.state & AUI_BUTTON_STATE_CHECKED and [True] or [False])[0] - new_checked = evt.GetChecked() - - if new_checked != is_checked: - - if new_checked: - item.state |= AUI_BUTTON_STATE_CHECKED - else: - item.state &= ~AUI_BUTTON_STATE_CHECKED - - need_refresh = True - - if need_refresh: - self.Refresh(False) - - - def OnSize(self, event): - """ - Handles the ``wx.EVT_SIZE`` event for L{AuiToolBar}. - - :param `event`: a `wx.SizeEvent` event to be processed. - """ - - x, y = self.GetClientSize() - realize = False - - if x > y: - self.SetOrientation(wx.HORIZONTAL) - else: - self.SetOrientation(wx.VERTICAL) - - if (x >= y and self._absolute_min_size.x > x) or (y > x and self._absolute_min_size.y > y): - - # hide all flexible items - for item in self._items: - if item.sizer_item and item.proportion > 0 and item.sizer_item.IsShown(): - item.sizer_item.Show(False) - item.sizer_item.SetProportion(0) - - if self._originalStyle & AUI_TB_OVERFLOW: - if not self.GetOverflowVisible(): - self.SetOverflowVisible(True) - realize = True - - else: - - if self._originalStyle & AUI_TB_OVERFLOW and not self._custom_overflow_append and \ - not self._custom_overflow_prepend: - if self.GetOverflowVisible(): - self.SetOverflowVisible(False) - realize = True - - # show all flexible items - for item in self._items: - if item.sizer_item and item.proportion > 0 and not item.sizer_item.IsShown(): - item.sizer_item.Show(True) - item.sizer_item.SetProportion(item.proportion) - - self._sizer.SetDimension(0, 0, x, y) - - if realize: - self.Realize() - else: - self.Refresh(False) - - self.Update() - - - def DoSetSize(self, x, y, width, height, sizeFlags=wx.SIZE_AUTO): - """ - Sets the position and size of the window in pixels. The `sizeFlags` - parameter indicates the interpretation of the other params if they are - equal to -1. - - :param `x`: the window `x` position; - :param `y`: the window `y` position; - :param `width`: the window width; - :param `height`: the window height; - :param `sizeFlags`: may have one of this bit set: - - =================================== ====================================== - Size Flags Description - =================================== ====================================== - ``wx.SIZE_AUTO`` A -1 indicates that a class-specific default should be used. - ``wx.SIZE_AUTO_WIDTH`` A -1 indicates that a class-specific default should be used for the width. - ``wx.SIZE_AUTO_HEIGHT`` A -1 indicates that a class-specific default should be used for the height. - ``wx.SIZE_USE_EXISTING`` Existing dimensions should be used if -1 values are supplied. - ``wx.SIZE_ALLOW_MINUS_ONE`` Allow dimensions of -1 and less to be interpreted as real dimensions, not default values. - ``wx.SIZE_FORCE`` Normally, if the position and the size of the window are already the same as the parameters of this function, nothing is done. but with this flag a window resize may be forced even in this case (supported in wx 2.6.2 and later and only implemented for MSW and ignored elsewhere currently) - =================================== ====================================== - - :note: Overridden from `wx.PyControl`. - """ - - parent_size = self.GetParent().GetClientSize() - if x + width > parent_size.x: - width = max(0, parent_size.x - x) - if y + height > parent_size.y: - height = max(0, parent_size.y - y) - - wx.PyControl.DoSetSize(self, x, y, width, height, sizeFlags) - - - def OnIdle(self, event): - """ - Handles the ``wx.EVT_IDLE`` event for L{AuiToolBar}. - - :param `event`: a `wx.IdleEvent` event to be processed. - """ - - self.DoIdleUpdate() - event.Skip() - - - def DoGetBestSize(self): - """ - Gets the size which best suits the window: for a control, it would be the - minimal size which doesn't truncate the control, for a panel - the same - size as it would have after a call to `Fit()`. - - :note: Overridden from `wx.PyControl`. - """ - - return self._absolute_min_size - - - def OnPaint(self, event): - """ - Handles the ``wx.EVT_PAINT`` event for L{AuiToolBar}. - - :param `event`: a `wx.PaintEvent` event to be processed. - """ - - dc = wx.AutoBufferedPaintDC(self) - cli_rect = wx.RectPS(wx.Point(0, 0), self.GetClientSize()) - - horizontal = True - if self._agwStyle & AUI_TB_VERTICAL: - horizontal = False - - if self._agwStyle & AUI_TB_PLAIN_BACKGROUND: - self._art.DrawPlainBackground(dc, self, cli_rect) - else: - self._art.DrawBackground(dc, self, cli_rect, horizontal) - - gripper_size = self._art.GetElementSize(AUI_TBART_GRIPPER_SIZE) - dropdown_size = self._art.GetElementSize(AUI_TBART_OVERFLOW_SIZE) - - # paint the gripper - if gripper_size > 0 and self._gripper_sizer_item: - gripper_rect = wx.Rect(*self._gripper_sizer_item.GetRect()) - if horizontal: - gripper_rect.width = gripper_size - else: - gripper_rect.height = gripper_size - - self._art.DrawGripper(dc, self, gripper_rect) - - # calculated how far we can draw items - if horizontal: - last_extent = cli_rect.width - else: - last_extent = cli_rect.height - - if self._overflow_visible: - last_extent -= dropdown_size - - # paint each individual tool - for item in self._items: - - if not item.sizer_item: - continue - - item_rect = wx.Rect(*item.sizer_item.GetRect()) - - if (horizontal and item_rect.x + item_rect.width >= last_extent) or \ - (not horizontal and item_rect.y + item_rect.height >= last_extent): - - break - - if item.kind == ITEM_SEPARATOR: - # draw a separator - self._art.DrawSeparator(dc, self, item_rect) - - elif item.kind == ITEM_LABEL: - # draw a text label only - self._art.DrawLabel(dc, self, item, item_rect) - - elif item.kind == ITEM_NORMAL: - # draw a regular button or dropdown button - if not item.dropdown: - self._art.DrawButton(dc, self, item, item_rect) - else: - self._art.DrawDropDownButton(dc, self, item, item_rect) - - elif item.kind == ITEM_CHECK: - # draw a regular toggle button or a dropdown one - if not item.dropdown: - self._art.DrawButton(dc, self, item, item_rect) - else: - self._art.DrawDropDownButton(dc, self, item, item_rect) - - elif item.kind == ITEM_RADIO: - # draw a toggle button - self._art.DrawButton(dc, self, item, item_rect) - - elif item.kind == ITEM_CONTROL: - # draw the control's label - self._art.DrawControlLabel(dc, self, item, item_rect) - - # fire a signal to see if the item wants to be custom-rendered - self.OnCustomRender(dc, item, item_rect) - - # paint the overflow button - if dropdown_size > 0 and self._overflow_sizer_item: - dropdown_rect = self.GetOverflowRect() - self._art.DrawOverflowButton(dc, self, dropdown_rect, self._overflow_state) - - - def OnEraseBackground(self, event): - """ - Handles the ``wx.EVT_ERASE_BACKGROUND`` event for L{AuiToolBar}. - - :param `event`: a `wx.EraseEvent` event to be processed. - - :note: This is intentionally empty, to reduce flicker. - """ - - pass - - - def OnLeftDown(self, event): - """ - Handles the ``wx.EVT_LEFT_DOWN`` event for L{AuiToolBar}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - cli_rect = wx.RectPS(wx.Point(0, 0), self.GetClientSize()) - self.StopPreviewTimer() - - if self._gripper_sizer_item: - - gripper_rect = wx.Rect(*self._gripper_sizer_item.GetRect()) - if gripper_rect.Contains(event.GetPosition()): - - # find aui manager - manager = self.GetAuiManager() - if not manager: - return - - x_drag_offset = event.GetX() - gripper_rect.GetX() - y_drag_offset = event.GetY() - gripper_rect.GetY() - - clientPt = wx.Point(*event.GetPosition()) - screenPt = self.ClientToScreen(clientPt) - managedWindow = manager.GetManagedWindow() - managerClientPt = managedWindow.ScreenToClient(screenPt) - - # gripper was clicked - manager.OnGripperClicked(self, managerClientPt, wx.Point(x_drag_offset, y_drag_offset)) - return - - if self._overflow_sizer_item: - overflow_rect = self.GetOverflowRect() - - if self._art and self._overflow_visible and overflow_rect.Contains(event.GetPosition()): - - e = AuiToolBarEvent(wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK, -1) - e.SetEventObject(self) - e.SetToolId(-1) - e.SetClickPoint(event.GetPosition()) - processed = self.ProcessEvent(e) - - if processed: - self.DoIdleUpdate() - else: - overflow_items = [] - - # add custom overflow prepend items, if any - count = len(self._custom_overflow_prepend) - for i in xrange(count): - overflow_items.append(self._custom_overflow_prepend[i]) - - # only show items that don't fit in the dropdown - count = len(self._items) - for i in xrange(count): - - if not self.GetToolFitsByIndex(i): - overflow_items.append(self._items[i]) - - # add custom overflow append items, if any - count = len(self._custom_overflow_append) - for i in xrange(count): - overflow_items.append(self._custom_overflow_append[i]) - - res = self._art.ShowDropDown(self, overflow_items) - self._overflow_state = 0 - self.Refresh(False) - if res != -1: - e = wx.CommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, res) - e.SetEventObject(self) - if not self.GetParent().ProcessEvent(e): - tool = self.FindTool(res) - if tool: - state = (tool.state & AUI_BUTTON_STATE_CHECKED and [True] or [False])[0] - self.ToggleTool(res, not state) - - return - - self._dragging = False - self._action_pos = wx.Point(*event.GetPosition()) - self._action_item = self.FindToolForPosition(*event.GetPosition()) - - if self._action_item: - - if self._action_item.state & AUI_BUTTON_STATE_DISABLED: - - self._action_pos = wx.Point(-1, -1) - self._action_item = None - return - - self.SetPressedItem(self._action_item) - - # fire the tool dropdown event - e = AuiToolBarEvent(wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN, self._action_item.id) - e.SetEventObject(self) - e.SetToolId(self._action_item.id) - e.SetDropDownClicked(False) - - mouse_x, mouse_y = event.GetX(), event.GetY() - rect = wx.Rect(*self._action_item.sizer_item.GetRect()) - - if self._action_item.dropdown: - if (self._action_item.orientation == AUI_TBTOOL_HORIZONTAL and \ - mouse_x >= (rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1) and \ - mouse_x < (rect.x+rect.width)) or \ - (self._action_item.orientation != AUI_TBTOOL_HORIZONTAL and \ - mouse_y >= (rect.y+rect.height-BUTTON_DROPDOWN_WIDTH-1) and \ - mouse_y < (rect.y+rect.height)): - - e.SetDropDownClicked(True) - - e.SetClickPoint(event.GetPosition()) - e.SetItemRect(rect) - self.ProcessEvent(e) - self.DoIdleUpdate() - - - def OnLeftUp(self, event): - """ - Handles the ``wx.EVT_LEFT_UP`` event for L{AuiToolBar}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - self.SetPressedItem(None) - - hit_item = self.FindToolForPosition(*event.GetPosition()) - - if hit_item and not hit_item.state & AUI_BUTTON_STATE_DISABLED: - self.SetHoverItem(hit_item) - - if self._dragging: - # reset drag and drop member variables - self._dragging = False - self._action_pos = wx.Point(-1, -1) - self._action_item = None - - else: - - if self._action_item and hit_item == self._action_item: - self.SetToolTipString("") - - if hit_item.kind in [ITEM_CHECK, ITEM_RADIO]: - toggle = not (self._action_item.state & AUI_BUTTON_STATE_CHECKED) - self.ToggleTool(self._action_item.id, toggle) - - # repaint immediately - self.Refresh(False) - self.Update() - - e = wx.CommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, self._action_item.id) - e.SetEventObject(self) - e.SetInt(toggle) - self._action_pos = wx.Point(-1, -1) - self._action_item = None - - self.ProcessEvent(e) - self.DoIdleUpdate() - - else: - - if self._action_item.id == ID_RESTORE_FRAME: - # find aui manager - manager = self.GetAuiManager() - - if not manager: - return - - pane = manager.GetPane(self) - e = framemanager.AuiManagerEvent(framemanager.wxEVT_AUI_PANE_MIN_RESTORE) - - e.SetManager(manager) - e.SetPane(pane) - - manager.ProcessEvent(e) - self.DoIdleUpdate() - - else: - - e = wx.CommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, self._action_item.id) - e.SetEventObject(self) - self.ProcessEvent(e) - self.DoIdleUpdate() - - # reset drag and drop member variables - self._dragging = False - self._action_pos = wx.Point(-1, -1) - self._action_item = None - - - def OnRightDown(self, event): - """ - Handles the ``wx.EVT_RIGHT_DOWN`` event for L{AuiToolBar}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - cli_rect = wx.RectPS(wx.Point(0, 0), self.GetClientSize()) - - if self._gripper_sizer_item: - gripper_rect = self._gripper_sizer_item.GetRect() - if gripper_rect.Contains(event.GetPosition()): - return - - if self._overflow_sizer_item: - - dropdown_size = self._art.GetElementSize(AUI_TBART_OVERFLOW_SIZE) - if dropdown_size > 0 and event.m_x > cli_rect.width - dropdown_size and \ - event.m_y >= 0 and event.m_y < cli_rect.height and self._art: - return - - self._action_pos = wx.Point(*event.GetPosition()) - self._action_item = self.FindToolForPosition(*event.GetPosition()) - - if self._action_item: - if self._action_item.state & AUI_BUTTON_STATE_DISABLED: - - self._action_pos = wx.Point(-1, -1) - self._action_item = None - return - - - def OnRightUp(self, event): - """ - Handles the ``wx.EVT_RIGHT_UP`` event for L{AuiToolBar}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - hit_item = self.FindToolForPosition(*event.GetPosition()) - - if self._action_item and hit_item == self._action_item: - - e = AuiToolBarEvent(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, self._action_item.id) - e.SetEventObject(self) - e.SetToolId(self._action_item.id) - e.SetClickPoint(self._action_pos) - self.ProcessEvent(e) - self.DoIdleUpdate() - - else: - - # right-clicked on the invalid area of the toolbar - e = AuiToolBarEvent(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, -1) - e.SetEventObject(self) - e.SetToolId(-1) - e.SetClickPoint(self._action_pos) - self.ProcessEvent(e) - self.DoIdleUpdate() - - # reset member variables - self._action_pos = wx.Point(-1, -1) - self._action_item = None - - - def OnMiddleDown(self, event): - """ - Handles the ``wx.EVT_MIDDLE_DOWN`` event for L{AuiToolBar}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - cli_rect = wx.RectPS(wx.Point(0, 0), self.GetClientSize()) - - if self._gripper_sizer_item: - - gripper_rect = self._gripper_sizer_item.GetRect() - if gripper_rect.Contains(event.GetPosition()): - return - - if self._overflow_sizer_item: - - dropdown_size = self._art.GetElementSize(AUI_TBART_OVERFLOW_SIZE) - if dropdown_size > 0 and event.m_x > cli_rect.width - dropdown_size and \ - event.m_y >= 0 and event.m_y < cli_rect.height and self._art: - return - - self._action_pos = wx.Point(*event.GetPosition()) - self._action_item = self.FindToolForPosition(*event.GetPosition()) - - if self._action_item: - if self._action_item.state & AUI_BUTTON_STATE_DISABLED: - - self._action_pos = wx.Point(-1, -1) - self._action_item = None - return - - - def OnMiddleUp(self, event): - """ - Handles the ``wx.EVT_MIDDLE_UP`` event for L{AuiToolBar}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - hit_item = self.FindToolForPosition(*event.GetPosition()) - - if self._action_item and hit_item == self._action_item: - if hit_item.kind == ITEM_NORMAL: - - e = AuiToolBarEvent(wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK, self._action_item.id) - e.SetEventObject(self) - e.SetToolId(self._action_item.id) - e.SetClickPoint(self._action_pos) - self.ProcessEvent(e) - self.DoIdleUpdate() - - # reset member variables - self._action_pos = wx.Point(-1, -1) - self._action_item = None - - - def OnMotion(self, event): - """ - Handles the ``wx.EVT_MOTION`` event for L{AuiToolBar}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - # start a drag event - if not self._dragging and self._action_item != None and self._action_pos != wx.Point(-1, -1) and \ - abs(event.m_x - self._action_pos.x) + abs(event.m_y - self._action_pos.y) > 5: - - self.SetToolTipString("") - self._dragging = True - - e = AuiToolBarEvent(wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG, self.GetId()) - e.SetEventObject(self) - e.SetToolId(self._action_item.id) - self.ProcessEvent(e) - self.DoIdleUpdate() - return - - hit_item = self.FindToolForPosition(*event.GetPosition()) - - if hit_item: - if not hit_item.state & AUI_BUTTON_STATE_DISABLED: - self.SetHoverItem(hit_item) - else: - self.SetHoverItem(None) - - else: - # no hit item, remove any hit item - self.SetHoverItem(hit_item) - - # figure out tooltips - packing_hit_item = self.FindToolForPositionWithPacking(*event.GetPosition()) - - if packing_hit_item: - - if packing_hit_item != self._tip_item: - self._tip_item = packing_hit_item - - if packing_hit_item.short_help != "": - self.StartPreviewTimer() - self.SetToolTipString(packing_hit_item.short_help) - else: - self.SetToolTipString("") - self.StopPreviewTimer() - - else: - - self.SetToolTipString("") - self._tip_item = None - self.StopPreviewTimer() - - # if we've pressed down an item and we're hovering - # over it, make sure it's state is set to pressed - if self._action_item: - - if self._action_item == hit_item: - self.SetPressedItem(self._action_item) - else: - self.SetPressedItem(None) - - # figure out the dropdown button state (are we hovering or pressing it?) - self.RefreshOverflowState() - - - def OnLeaveWindow(self, event): - """ - Handles the ``wx.EVT_LEAVE_WINDOW`` event for L{AuiToolBar}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - self.RefreshOverflowState() - self.SetHoverItem(None) - self.SetPressedItem(None) - - self._tip_item = None - self.StopPreviewTimer() - - - def OnSetCursor(self, event): - """ - Handles the ``wx.EVT_SET_CURSOR`` event for L{AuiToolBar}. - - :param `event`: a `wx.SetCursorEvent` event to be processed. - """ - - cursor = wx.NullCursor - - if self._gripper_sizer_item: - - gripper_rect = self._gripper_sizer_item.GetRect() - if gripper_rect.Contains((event.GetX(), event.GetY())): - cursor = wx.StockCursor(wx.CURSOR_SIZING) - - event.SetCursor(cursor) - - - def OnCustomRender(self, dc, item, rect): - """ - Handles custom render for single L{AuiToolBar} items. - - :param `dc`: a `wx.DC` device context; - :param `item`: an instance of L{AuiToolBarItem}; - :param `rect`: the toolbar item rect. - - :note: This method must be overridden to provide custom rendering of items. - """ - - pass - - - def IsPaneMinimized(self): - """ Returns whether this L{AuiToolBar} contains a minimized pane tool. """ - - manager = self.GetAuiManager() - if not manager: - return False - - if manager.GetAGWFlags() & AUI_MGR_PREVIEW_MINIMIZED_PANES == 0: - # No previews here - return False - - self_name = manager.GetPane(self).name - - if not self_name.endswith("_min"): - # Wrong tool name - return False - - return self_name[0:-4] - - - def StartPreviewTimer(self): - """ Starts a timer in L{AuiManager} to slide-in/slide-out the minimized pane. """ - - self_name = self.IsPaneMinimized() - if not self_name: - return - - manager = self.GetAuiManager() - manager.StartPreviewTimer(self) - - - def StopPreviewTimer(self): - """ Stops a timer in L{AuiManager} to slide-in/slide-out the minimized pane. """ - - self_name = self.IsPaneMinimized() - if not self_name: - return - - manager = self.GetAuiManager() - manager.StopPreviewTimer() - diff --git a/agw/aui/auibook.py b/agw/aui/auibook.py deleted file mode 100644 index abae4a3..0000000 --- a/agw/aui/auibook.py +++ /dev/null @@ -1,5736 +0,0 @@ -""" -auibook contains a notebook control which implements many features common in -applications with dockable panes. Specifically, L{AuiNotebook} implements functionality -which allows the user to rearrange tab order via drag-and-drop, split the tab window -into many different splitter configurations, and toggle through different themes to -customize the control's look and feel. - -An effort has been made to try to maintain an API as similar to that of `wx.Notebook`. - -The default theme that is used is L{AuiDefaultTabArt}, which provides a modern, glossy -look and feel. The theme can be changed by calling L{AuiNotebook.SetArtProvider}. -""" - -__author__ = "Andrea Gavana " -__date__ = "31 March 2009" - - -import wx -import types -import datetime - -from wx.lib.expando import ExpandoTextCtrl - -import framemanager -import tabart as TA - -from aui_utilities import LightColour, MakeDisabledBitmap, TabDragImage -from aui_utilities import TakeScreenShot, RescaleScreenShot - -from aui_constants import * - -# AuiNotebook events -wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_BUTTON = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_END_DRAG = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_TAB_DCLICK = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_BG_MIDDLE_DOWN = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_BG_MIDDLE_UP = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_BG_RIGHT_DOWN = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_BG_RIGHT_UP = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK = wx.NewEventType() - -# Define a new event for a drag cancelled -wxEVT_COMMAND_AUINOTEBOOK_CANCEL_DRAG = wx.NewEventType() - -# Define events for editing a tab label -wxEVT_COMMAND_AUINOTEBOOK_BEGIN_LABEL_EDIT = wx.NewEventType() -wxEVT_COMMAND_AUINOTEBOOK_END_LABEL_EDIT = wx.NewEventType() - -# Create event binders -EVT_AUINOTEBOOK_PAGE_CLOSE = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, 1) -""" A tab in `AuiNotebook` is being closed. Can be vetoed by calling `Veto()`. """ -EVT_AUINOTEBOOK_PAGE_CLOSED = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, 1) -""" A tab in `AuiNotebook` has been closed. """ -EVT_AUINOTEBOOK_PAGE_CHANGED = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, 1) -""" The page selection was changed. """ -EVT_AUINOTEBOOK_PAGE_CHANGING = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, 1) -""" The page selection is being changed. """ -EVT_AUINOTEBOOK_BUTTON = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, 1) -""" The user clicked on a button in the `AuiNotebook` tab area. """ -EVT_AUINOTEBOOK_BEGIN_DRAG = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, 1) -""" A drag-and-drop operation on a notebook tab has started. """ -EVT_AUINOTEBOOK_END_DRAG = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, 1) -""" A drag-and-drop operation on a notebook tab has finished. """ -EVT_AUINOTEBOOK_DRAG_MOTION = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, 1) -""" A drag-and-drop operation on a notebook tab is ongoing. """ -EVT_AUINOTEBOOK_ALLOW_DND = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, 1) -""" Fires an event asking if it is OK to drag and drop a tab. """ -EVT_AUINOTEBOOK_DRAG_DONE = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, 1) -""" A drag-and-drop operation on a notebook tab has finished. """ -EVT_AUINOTEBOOK_TAB_MIDDLE_DOWN = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, 1) -""" The user clicked with the middle mouse button on a tab. """ -EVT_AUINOTEBOOK_TAB_MIDDLE_UP = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, 1) -""" The user clicked with the middle mouse button on a tab. """ -EVT_AUINOTEBOOK_TAB_RIGHT_DOWN = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, 1) -""" The user clicked with the right mouse button on a tab. """ -EVT_AUINOTEBOOK_TAB_RIGHT_UP = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, 1) -""" The user clicked with the right mouse button on a tab. """ -EVT_AUINOTEBOOK_BG_MIDDLE_DOWN = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BG_MIDDLE_DOWN, 1) -""" The user middle-clicked in the tab area but not over a tab or a button. """ -EVT_AUINOTEBOOK_BG_MIDDLE_UP = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BG_MIDDLE_UP, 1) -""" The user middle-clicked in the tab area but not over a tab or a button. """ -EVT_AUINOTEBOOK_BG_RIGHT_DOWN = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BG_RIGHT_DOWN, 1) -""" The user right-clicked in the tab area but not over a tab or a button. """ -EVT_AUINOTEBOOK_BG_RIGHT_UP = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BG_RIGHT_UP, 1) -""" The user right-clicked in the tab area but not over a tab or a button. """ -EVT_AUINOTEBOOK_BG_DCLICK = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, 1) -""" The user left-clicked on the tab area not occupied by `AuiNotebook` tabs. """ -EVT_AUINOTEBOOK_CANCEL_DRAG = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_CANCEL_DRAG, 1) -""" A drag and drop operation has been cancelled. """ -EVT_AUINOTEBOOK_TAB_DCLICK = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_TAB_DCLICK, 1) -""" The user double-clicked with the left mouse button on a tab. """ -EVT_AUINOTEBOOK_BEGIN_LABEL_EDIT = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_LABEL_EDIT, 1) -""" The user double-clicked with the left mouse button on a tab which text is editable. """ -EVT_AUINOTEBOOK_END_LABEL_EDIT = wx.PyEventBinder(wxEVT_COMMAND_AUINOTEBOOK_END_LABEL_EDIT, 1) -""" The user finished editing a tab label. """ - - -# ----------------------------------------------------------------------------- -# Auxiliary class: TabTextCtrl -# This is the temporary ExpandoTextCtrl created when you edit the text of a tab -# ----------------------------------------------------------------------------- - -class TabTextCtrl(ExpandoTextCtrl): - """ Control used for in-place edit. """ - - def __init__(self, owner, tab, page_index): - """ - Default class constructor. - For internal use: do not call it in your code! - - :param `owner`: the L{AuiTabCtrl} owning the tab; - :param `tab`: the actual L{AuiNotebookPage} tab; - :param `page_index`: the L{AuiNotebook} page index for the tab. - """ - - self._owner = owner - self._tabEdited = tab - self._pageIndex = page_index - self._startValue = tab.caption - self._finished = False - self._aboutToFinish = False - self._currentValue = self._startValue - - x, y, w, h = self._tabEdited.rect - - wnd = self._tabEdited.control - if wnd: - x += wnd.GetSize()[0] + 2 - h = 0 - - image_h = 0 - image_w = 0 - - image = tab.bitmap - - if image.IsOk(): - image_w, image_h = image.GetWidth(), image.GetHeight() - image_w += 6 - - dc = wx.ClientDC(self._owner) - h = max(image_h, dc.GetMultiLineTextExtent(tab.caption)[1]) - h = h + 2 - - # FIXME: what are all these hardcoded 4, 8 and 11s really? - x += image_w - w -= image_w + 4 - - y = (self._tabEdited.rect.height - h)/2 + 1 - - expandoStyle = wx.WANTS_CHARS - if wx.Platform in ["__WXGTK__", "__WXMAC__"]: - expandoStyle |= wx.SIMPLE_BORDER - xSize, ySize = w + 2, h - else: - expandoStyle |= wx.SUNKEN_BORDER - xSize, ySize = w + 2, h+2 - - ExpandoTextCtrl.__init__(self, self._owner, wx.ID_ANY, self._startValue, - wx.Point(x, y), wx.Size(xSize, ySize), - expandoStyle) - - if wx.Platform == "__WXMAC__": - self.SetFont(owner.GetFont()) - bs = self.GetBestSize() - self.SetSize((-1, bs.height)) - - self.Bind(wx.EVT_CHAR, self.OnChar) - self.Bind(wx.EVT_KEY_UP, self.OnKeyUp) - self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) - - - def AcceptChanges(self): - """ Accepts/refuses the changes made by the user. """ - - value = self.GetValue() - notebook = self._owner.GetParent() - - if value == self._startValue: - # nothing changed, always accept - # when an item remains unchanged, the owner - # needs to be notified that the user decided - # not to change the tree item label, and that - # the edit has been cancelled - notebook.OnRenameCancelled(self._pageIndex) - return True - - if not notebook.OnRenameAccept(self._pageIndex, value): - # vetoed by the user - return False - - # accepted, do rename the item - notebook.SetPageText(self._pageIndex, value) - - return True - - - def Finish(self): - """ Finish editing. """ - - if not self._finished: - - notebook = self._owner.GetParent() - - self._finished = True - self._owner.SetFocus() - notebook.ResetTextControl() - - - def OnChar(self, event): - """ - Handles the ``wx.EVT_CHAR`` event for L{TabTextCtrl}. - - :param `event`: a `wx.KeyEvent` event to be processed. - """ - - keycode = event.GetKeyCode() - shiftDown = event.ShiftDown() - - if keycode == wx.WXK_RETURN: - if shiftDown and self._tabEdited.IsMultiline(): - event.Skip() - else: - self._aboutToFinish = True - self.SetValue(self._currentValue) - # Notify the owner about the changes - self.AcceptChanges() - # Even if vetoed, close the control (consistent with MSW) - wx.CallAfter(self.Finish) - - elif keycode == wx.WXK_ESCAPE: - self.StopEditing() - - else: - event.Skip() - - - def OnKeyUp(self, event): - """ - Handles the ``wx.EVT_KEY_UP`` event for L{TabTextCtrl}. - - :param `event`: a `wx.KeyEvent` event to be processed. - """ - - if not self._finished: - - # auto-grow the textctrl: - mySize = self.GetSize() - - dc = wx.ClientDC(self) - sx, sy, dummy = dc.GetMultiLineTextExtent(self.GetValue() + "M") - - self.SetSize((sx, -1)) - self._currentValue = self.GetValue() - - event.Skip() - - - def OnKillFocus(self, event): - """ - Handles the ``wx.EVT_KILL_FOCUS`` event for L{TabTextCtrl}. - - :param `event`: a `wx.FocusEvent` event to be processed. - """ - - if not self._finished and not self._aboutToFinish: - - # We must finish regardless of success, otherwise we'll get - # focus problems: - if not self.AcceptChanges(): - self._owner.GetParent().OnRenameCancelled(self._pageIndex) - - # We must let the native text control handle focus, too, otherwise - # it could have problems with the cursor (e.g., in wxGTK). - event.Skip() - wx.CallAfter(self._owner.GetParent().ResetTextControl) - - - def StopEditing(self): - """ Suddenly stops the editing. """ - - self._owner.GetParent().OnRenameCancelled(self._pageIndex) - self.Finish() - - - def item(self): - """ Returns the item currently edited. """ - - return self._tabEdited - - -# ---------------------------------------------------------------------- - -class AuiNotebookPage(object): - """ - A simple class which holds information about tab captions, bitmaps and - colours. - """ - - def __init__(self): - """ - Default class constructor. - Used internally, do not call it in your code! - """ - - self.window = None # page's associated window - self.caption = "" # caption displayed on the tab - self.bitmap = wx.NullBitmap # tab's bitmap - self.dis_bitmap = wx.NullBitmap # tab's disabled bitmap - self.rect = wx.Rect() # tab's hit rectangle - self.active = False # True if the page is currently active - self.enabled = True # True if the page is currently enabled - self.hasCloseButton = True # True if the page has a close button using the style - # AUI_NB_CLOSE_ON_ALL_TABS - self.control = None # A control can now be inside a tab - self.renamable = False # If True, a tab can be renamed by a left double-click - - self.text_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNTEXT) - - self.access_time = datetime.datetime.now() # Last time this page was selected - - - def IsMultiline(self): - """ Returns whether the tab contains multiline text. """ - - return "\n" in self.caption - - -# ---------------------------------------------------------------------- - -class AuiTabContainerButton(object): - """ - A simple class which holds information about tab buttons and their state. - """ - - def __init__(self): - """ - Default class constructor. - Used internally, do not call it in your code! - """ - - self.id = -1 # button's id - self.cur_state = AUI_BUTTON_STATE_NORMAL # current state (normal, hover, pressed, etc.) - self.location = wx.LEFT # buttons location (wxLEFT, wxRIGHT, or wxCENTER) - self.bitmap = wx.NullBitmap # button's hover bitmap - self.dis_bitmap = wx.NullBitmap # button's disabled bitmap - self.rect = wx.Rect() # button's hit rectangle - - -# ---------------------------------------------------------------------- - -class CommandNotebookEvent(wx.PyCommandEvent): - """ A specialized command event class for events sent by L{AuiNotebook} . """ - - def __init__(self, command_type=None, win_id=0): - """ - Default class constructor. - - :param `command_type`: the event kind or an instance of `wx.PyCommandEvent`. - :param `win_id`: the window identification number. - """ - - if type(command_type) == types.IntType: - wx.PyCommandEvent.__init__(self, command_type, win_id) - else: - wx.PyCommandEvent.__init__(self, command_type.GetEventType(), command_type.GetId()) - - self.old_selection = -1 - self.selection = -1 - self.drag_source = None - self.dispatched = 0 - self.label = "" - self.editCancelled = False - - - def SetSelection(self, s): - """ - Sets the selection member variable. - - :param `s`: the new selection. - """ - - self.selection = s - self._commandInt = s - - - def GetSelection(self): - """ Returns the currently selected page, or -1 if none was selected. """ - - return self.selection - - - def SetOldSelection(self, s): - """ - Sets the id of the page selected before the change. - - :param `s`: the old selection. - """ - - self.old_selection = s - - - def GetOldSelection(self): - """ - Returns the page that was selected before the change, or -1 if none was - selected. - """ - - return self.old_selection - - - def SetDragSource(self, s): - """ - Sets the drag and drop source. - - :param `s`: the drag source. - """ - - self.drag_source = s - - - def GetDragSource(self): - """ Returns the drag and drop source. """ - - return self.drag_source - - - def SetDispatched(self, b): - """ - Sets the event as dispatched (used for automatic L{AuiNotebook} ). - - :param `b`: whether the event was dispatched or not. - """ - - self.dispatched = b - - - def GetDispatched(self): - """ Returns whether the event was dispatched (used for automatic L{AuiNotebook} ). """ - - return self.dispatched - - - def IsEditCancelled(self): - """ Returns the edit cancel flag (for ``EVT_AUINOTEBOOK_BEGIN`` | ``END_LABEL_EDIT`` only).""" - - return self.editCancelled - - - def SetEditCanceled(self, editCancelled): - """ - Sets the edit cancel flag (for ``EVT_AUINOTEBOOK_BEGIN`` | ``END_LABEL_EDIT`` only). - - :param `editCancelled`: whether the editing action has been cancelled or not. - """ - - self.editCancelled = editCancelled - - - def GetLabel(self): - """Returns the label-itemtext (for ``EVT_AUINOTEBOOK_BEGIN`` | ``END_LABEL_EDIT`` only).""" - - return self.label - - - def SetLabel(self, label): - """ - Sets the label. Useful only for ``EVT_AUINOTEBOOK_END_LABEL_EDIT``. - - :param `label`: the new label. - """ - - self.label = label - - -# ---------------------------------------------------------------------- - -class AuiNotebookEvent(CommandNotebookEvent): - """ A specialized command event class for events sent by L{AuiNotebook}. """ - - def __init__(self, command_type=None, win_id=0): - """ - Default class constructor. - - :param `command_type`: the event kind or an instance of `wx.PyCommandEvent`. - :param `win_id`: the window identification number. - """ - - CommandNotebookEvent.__init__(self, command_type, win_id) - - if type(command_type) == types.IntType: - self.notify = wx.NotifyEvent(command_type, win_id) - else: - self.notify = wx.NotifyEvent(command_type.GetEventType(), command_type.GetId()) - - - def GetNotifyEvent(self): - """ Returns the actual `wx.NotifyEvent`. """ - - return self.notify - - - def IsAllowed(self): - """ Returns whether the event is allowed or not. """ - - return self.notify.IsAllowed() - - - def Veto(self): - """ - Prevents the change announced by this event from happening. - - It is in general a good idea to notify the user about the reasons for - vetoing the change because otherwise the applications behaviour (which - just refuses to do what the user wants) might be quite surprising. - """ - - self.notify.Veto() - - - def Allow(self): - """ - This is the opposite of L{Veto}: it explicitly allows the event to be - processed. For most events it is not necessary to call this method as the - events are allowed anyhow but some are forbidden by default (this will - be mentioned in the corresponding event description). - """ - - self.notify.Allow() - - -# ---------------------------------------------------------------------------- # -# Class TabNavigatorWindow -# ---------------------------------------------------------------------------- # - -class TabNavigatorWindow(wx.Dialog): - """ - This class is used to create a modal dialog that enables "Smart Tabbing", - similar to what you would get by hitting ``Alt`` + ``Tab`` on Windows. - """ - - def __init__(self, parent=None, icon=None): - """ - Default class constructor. Used internally. - - :param `parent`: the L{TabNavigatorWindow} parent; - :param `icon`: the L{TabNavigatorWindow} icon. - """ - - wx.Dialog.__init__(self, parent, wx.ID_ANY, "", style=0) - - self._selectedItem = -1 - self._indexMap = [] - - if icon is None: - self._bmp = Mondrian.GetBitmap() - else: - self._bmp = icon - - if self._bmp.GetSize() != (16, 16): - img = self._bmp.ConvertToImage() - img.Rescale(16, 16, wx.IMAGE_QUALITY_HIGH) - self._bmp = wx.BitmapFromImage(img) - - sz = wx.BoxSizer(wx.VERTICAL) - - self._listBox = wx.ListBox(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(200, 150), [], wx.LB_SINGLE | wx.NO_BORDER) - - mem_dc = wx.MemoryDC() - mem_dc.SelectObject(wx.EmptyBitmap(1,1)) - font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) - font.SetWeight(wx.BOLD) - mem_dc.SetFont(font) - - panelHeight = mem_dc.GetCharHeight() - panelHeight += 4 # Place a spacer of 2 pixels - - # Out signpost bitmap is 24 pixels - if panelHeight < 24: - panelHeight = 24 - - self._panel = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(200, panelHeight)) - - sz.Add(self._panel) - sz.Add(self._listBox, 1, wx.EXPAND) - - self.SetSizer(sz) - - # Connect events to the list box - self._listBox.Bind(wx.EVT_KEY_UP, self.OnKeyUp) - self._listBox.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey) - self._listBox.Bind(wx.EVT_LISTBOX_DCLICK, self.OnItemSelected) - - # Connect paint event to the panel - self._panel.Bind(wx.EVT_PAINT, self.OnPanelPaint) - self._panel.Bind(wx.EVT_ERASE_BACKGROUND, self.OnPanelEraseBg) - - self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)) - self._listBox.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)) - self.PopulateListControl(parent) - - self.GetSizer().Fit(self) - self.GetSizer().SetSizeHints(self) - self.GetSizer().Layout() - self.Centre() - - # Set focus on the list box to avoid having to click on it to change - # the tab selection under GTK. - self._listBox.SetFocus() - - - def OnKeyUp(self, event): - """ - Handles the ``wx.EVT_KEY_UP`` for the L{TabNavigatorWindow}. - - :param `event`: a `wx.KeyEvent` event to be processed. - """ - - if event.GetKeyCode() == wx.WXK_CONTROL: - self.CloseDialog() - - - def OnNavigationKey(self, event): - """ - Handles the ``wx.EVT_NAVIGATION_KEY`` for the L{TabNavigatorWindow}. - - :param `event`: a `wx.NavigationKeyEvent` event to be processed. - """ - - selected = self._listBox.GetSelection() - bk = self.GetParent() - maxItems = bk.GetPageCount() - - if event.GetDirection(): - - # Select next page - if selected == maxItems - 1: - itemToSelect = 0 - else: - itemToSelect = selected + 1 - - else: - - # Previous page - if selected == 0: - itemToSelect = maxItems - 1 - else: - itemToSelect = selected - 1 - - self._listBox.SetSelection(itemToSelect) - - - def PopulateListControl(self, book): - """ - Populates the L{TabNavigatorWindow} listbox with a list of tabs. - - :param `book`: the actual L{AuiNotebook}. - """ - # Index of currently selected page - selection = book.GetSelection() - # Total number of pages - count = book.GetPageCount() - # List of (index, AuiNotebookPage) - pages = list(enumerate(book.GetTabContainer().GetPages())) - if book.GetAGWWindowStyleFlag() & AUI_NB_ORDER_BY_ACCESS: - # Sort pages using last access time. Most recently used is the - # first in line - pages.sort( - key = lambda element: element[1].access_time, - reverse = True - ) - else: - # Manually add the current selection as first item - # Remaining ones are added in the next loop - del pages[selection] - self._listBox.Append(book.GetPageText(selection)) - self._indexMap.append(selection) - - for (index, page) in pages: - self._listBox.Append(book.GetPageText(index)) - self._indexMap.append(index) - - # Select the next entry after the current selection - self._listBox.SetSelection(0) - dummy = wx.NavigationKeyEvent() - dummy.SetDirection(True) - self.OnNavigationKey(dummy) - - - def OnItemSelected(self, event): - """ - Handles the ``wx.EVT_LISTBOX_DCLICK`` event for the wx.ListBox inside L{TabNavigatorWindow}. - - :param `event`: a `wx.ListEvent` event to be processed. - """ - - self.CloseDialog() - - - def CloseDialog(self): - """ Closes the L{TabNavigatorWindow} dialog, setting selection in L{AuiNotebook}. """ - - bk = self.GetParent() - self._selectedItem = self._listBox.GetSelection() - self.EndModal(wx.ID_OK) - - - def GetSelectedPage(self): - """ Gets the page index that was selected when the dialog was closed. """ - - return self._indexMap[self._selectedItem] - - - def OnPanelPaint(self, event): - """ - Handles the ``wx.EVT_PAINT`` event for L{TabNavigatorWindow} top panel. - - :param `event`: a `wx.PaintEvent` event to be processed. - """ - - dc = wx.PaintDC(self._panel) - rect = self._panel.GetClientRect() - - bmp = wx.EmptyBitmap(rect.width, rect.height) - - mem_dc = wx.MemoryDC() - mem_dc.SelectObject(bmp) - - endColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW) - startColour = LightColour(endColour, 50) - mem_dc.GradientFillLinear(rect, startColour, endColour, wx.SOUTH) - - # Draw the caption title and place the bitmap - # get the bitmap optimal position, and draw it - bmpPt, txtPt = wx.Point(), wx.Point() - bmpPt.y = (rect.height - self._bmp.GetHeight())/2 - bmpPt.x = 3 - mem_dc.DrawBitmap(self._bmp, bmpPt.x, bmpPt.y, True) - - # get the text position, and draw it - font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) - font.SetWeight(wx.BOLD) - mem_dc.SetFont(font) - fontHeight = mem_dc.GetCharHeight() - - txtPt.x = bmpPt.x + self._bmp.GetWidth() + 4 - txtPt.y = (rect.height - fontHeight)/2 - mem_dc.SetTextForeground(wx.WHITE) - mem_dc.DrawText("Opened tabs:", txtPt.x, txtPt.y) - mem_dc.SelectObject(wx.NullBitmap) - - dc.DrawBitmap(bmp, 0, 0) - - - def OnPanelEraseBg(self, event): - """ - Handles the ``wx.EVT_ERASE_BACKGROUND`` event for L{TabNavigatorWindow} top panel. - - :param `event`: a `wx.EraseEvent` event to be processed. - - :note: This is intentionally empty, to reduce flicker. - """ - - pass - - -# ---------------------------------------------------------------------- -# -- AuiTabContainer class implementation -- - -class AuiTabContainer(object): - """ - AuiTabContainer is a class which contains information about each - tab. It also can render an entire tab control to a specified DC. - It's not a window class itself, because this code will be used by - the L{AuiManager}, where it is disadvantageous to have separate - windows for each tab control in the case of "docked tabs". - - A derived class, L{AuiTabCtrl}, is an actual `wx.Window`-derived window - which can be used as a tab control in the normal sense. - """ - - def __init__(self, auiNotebook): - """ - Default class constructor. - Used internally, do not call it in your code! - - :param `auiNotebook`: the parent L{AuiNotebook} window. - """ - - self._tab_offset = 0 - self._agwFlags = 0 - self._art = TA.AuiDefaultTabArt() - - self._buttons = [] - self._pages = [] - self._tab_close_buttons = [] - - self._rect = wx.Rect() - self._auiNotebook = auiNotebook - - self.AddButton(AUI_BUTTON_LEFT, wx.LEFT) - self.AddButton(AUI_BUTTON_RIGHT, wx.RIGHT) - self.AddButton(AUI_BUTTON_WINDOWLIST, wx.RIGHT) - self.AddButton(AUI_BUTTON_CLOSE, wx.RIGHT) - - - def SetArtProvider(self, art): - """ - Instructs L{AuiTabContainer} to use art provider specified by parameter `art` - for all drawing calls. This allows plugable look-and-feel features. - - :param `art`: an art provider. - - :note: The previous art provider object, if any, will be deleted by L{AuiTabContainer}. - """ - - del self._art - self._art = art - - if self._art: - self._art.SetAGWFlags(self._agwFlags) - - - def GetArtProvider(self): - """ Returns the current art provider being used. """ - - return self._art - - - def SetAGWFlags(self, agwFlags): - """ - Sets the tab art flags. - - :param `agwFlags`: a combination of the following values: - - ==================================== ================================== - Flag name Description - ==================================== ================================== - ``AUI_NB_TOP`` With this style, tabs are drawn along the top of the notebook - ``AUI_NB_LEFT`` With this style, tabs are drawn along the left of the notebook. Not implemented yet - ``AUI_NB_RIGHT`` With this style, tabs are drawn along the right of the notebook. Not implemented yet - ``AUI_NB_BOTTOM`` With this style, tabs are drawn along the bottom of the notebook - ``AUI_NB_TAB_SPLIT`` Allows the tab control to be split by dragging a tab - ``AUI_NB_TAB_MOVE`` Allows a tab to be moved horizontally by dragging - ``AUI_NB_TAB_EXTERNAL_MOVE`` Allows a tab to be moved to another tab control - ``AUI_NB_TAB_FIXED_WIDTH`` With this style, all tabs have the same width - ``AUI_NB_SCROLL_BUTTONS`` With this style, left and right scroll buttons are displayed - ``AUI_NB_WINDOWLIST_BUTTON`` With this style, a drop-down list of windows is available - ``AUI_NB_CLOSE_BUTTON`` With this style, a close button is available on the tab bar - ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` With this style, a close button is available on the active tab - ``AUI_NB_CLOSE_ON_ALL_TABS`` With this style, a close button is available on all tabs - ``AUI_NB_MIDDLE_CLICK_CLOSE`` Allows to close L{AuiNotebook} tabs by mouse middle button click - ``AUI_NB_SUB_NOTEBOOK`` This style is used by L{AuiManager} to create automatic AuiNotebooks - ``AUI_NB_HIDE_ON_SINGLE_TAB`` Hides the tab window if only one tab is present - ``AUI_NB_SMART_TABS`` Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows - ``AUI_NB_USE_IMAGES_DROPDOWN`` Uses images on dropdown window list menu instead of check items - ``AUI_NB_CLOSE_ON_TAB_LEFT`` Draws the tab close button on the left instead of on the right (a la Camino browser) - ``AUI_NB_TAB_FLOAT`` Allows the floating of single tabs. Known limitation: when the notebook is more or less full screen, tabs cannot be dragged far enough outside of the notebook to become floating pages - ``AUI_NB_DRAW_DND_TAB`` Draws an image representation of a tab while dragging (on by default) - ``AUI_NB_ORDER_BY_ACCESS`` Tab navigation order by last access time for the tabs - ``AUI_NB_NO_TAB_FOCUS`` Don't draw tab focus rectangle - ==================================== ================================== - - :todo: Implementation of flags ``AUI_NB_RIGHT`` and ``AUI_NB_LEFT``. - - """ - - self._agwFlags = agwFlags - - # check for new close button settings - self.RemoveButton(AUI_BUTTON_LEFT) - self.RemoveButton(AUI_BUTTON_RIGHT) - self.RemoveButton(AUI_BUTTON_WINDOWLIST) - self.RemoveButton(AUI_BUTTON_CLOSE) - - if agwFlags & AUI_NB_SCROLL_BUTTONS: - self.AddButton(AUI_BUTTON_LEFT, wx.LEFT) - self.AddButton(AUI_BUTTON_RIGHT, wx.RIGHT) - - if agwFlags & AUI_NB_WINDOWLIST_BUTTON: - self.AddButton(AUI_BUTTON_WINDOWLIST, wx.RIGHT) - - if agwFlags & AUI_NB_CLOSE_BUTTON: - self.AddButton(AUI_BUTTON_CLOSE, wx.RIGHT) - - if self._art: - self._art.SetAGWFlags(self._agwFlags) - - - def GetAGWFlags(self): - """ - Returns the tab art flags. - - See L{SetAGWFlags} for a list of possible return values. - - :see: L{SetAGWFlags} - """ - - return self._agwFlags - - - def SetNormalFont(self, font): - """ - Sets the normal font for drawing tab labels. - - :param `font`: a `wx.Font` object. - """ - - self._art.SetNormalFont(font) - - - def SetSelectedFont(self, font): - """ - Sets the selected tab font for drawing tab labels. - - :param `font`: a `wx.Font` object. - """ - - self._art.SetSelectedFont(font) - - - def SetMeasuringFont(self, font): - """ - Sets the font for calculating text measurements. - - :param `font`: a `wx.Font` object. - """ - - self._art.SetMeasuringFont(font) - - - def SetTabRect(self, rect): - """ - Sets the tab area rectangle. - - :param `rect`: an instance of `wx.Rect`, specifying the available area for L{AuiTabContainer}. - """ - - self._rect = rect - - if self._art: - minMaxTabWidth = self._auiNotebook.GetMinMaxTabWidth() - self._art.SetSizingInfo(rect.GetSize(), len(self._pages), minMaxTabWidth) - - - def AddPage(self, page, info): - """ - Adds a page to the tab control. - - :param `page`: the window associated with this tab; - :param `info`: an instance of L{AuiNotebookPage}. - """ - - page_info = info - page_info.window = page - - self._pages.append(page_info) - - # let the art provider know how many pages we have - if self._art: - minMaxTabWidth = self._auiNotebook.GetMinMaxTabWidth() - self._art.SetSizingInfo(self._rect.GetSize(), len(self._pages), minMaxTabWidth) - - return True - - - def InsertPage(self, page, info, idx): - """ - Inserts a page in the tab control in the position specified by `idx`. - - :param `page`: the window associated with this tab; - :param `info`: an instance of L{AuiNotebookPage}; - :param `idx`: the page insertion index. - """ - - page_info = info - page_info.window = page - - if idx >= len(self._pages): - self._pages.append(page_info) - else: - self._pages.insert(idx, page_info) - - # let the art provider know how many pages we have - if self._art: - minMaxTabWidth = self._auiNotebook.GetMinMaxTabWidth() - self._art.SetSizingInfo(self._rect.GetSize(), len(self._pages), minMaxTabWidth) - - return True - - - def MovePage(self, page, new_idx): - """ - Moves a page in a new position specified by `new_idx`. - - :param `page`: the window associated with this tab; - :param `new_idx`: the new page position. - """ - - idx = self.GetIdxFromWindow(page) - if idx == -1: - return False - - # get page entry, make a copy of it - p = self.GetPage(idx) - - # remove old page entry - self.RemovePage(page) - - # insert page where it should be - self.InsertPage(page, p, new_idx) - - return True - - - def RemovePage(self, wnd): - """ - Removes a page from the tab control. - - :param `wnd`: an instance of `wx.Window`, a window associated with this tab. - """ - - minMaxTabWidth = self._auiNotebook.GetMinMaxTabWidth() - - for page in self._pages: - if page.window == wnd: - self._pages.remove(page) - self._tab_offset = min(self._tab_offset, len(self._pages) - 1) - - # let the art provider know how many pages we have - if self._art: - self._art.SetSizingInfo(self._rect.GetSize(), len(self._pages), minMaxTabWidth) - - return True - - return False - - - def SetActivePage(self, wndOrInt): - """ - Sets the L{AuiTabContainer} active page. - - :param `wndOrInt`: an instance of `wx.Window` or an integer specifying a tab index. - """ - - if type(wndOrInt) == types.IntType: - - if wndOrInt >= len(self._pages): - return False - - wnd = self._pages[wndOrInt].window - - else: - wnd = wndOrInt - - found = False - - for indx, page in enumerate(self._pages): - if page.window == wnd: - page.active = True - found = True - else: - page.active = False - - return found - - - def SetNoneActive(self): - """ Sets all the tabs as inactive (non-selected). """ - - for page in self._pages: - page.active = False - - - def GetActivePage(self): - """ Returns the current selected tab or ``wx.NOT_FOUND`` if none is selected. """ - - for indx, page in enumerate(self._pages): - if page.active: - return indx - - return wx.NOT_FOUND - - - def GetWindowFromIdx(self, idx): - """ - Returns the window associated with the tab with index `idx`. - - :param `idx`: the tab index. - """ - - if idx >= len(self._pages): - return None - - return self._pages[idx].window - - - def GetIdxFromWindow(self, wnd): - """ - Returns the tab index based on the window `wnd` associated with it. - - :param `wnd`: an instance of `wx.Window`. - """ - - for indx, page in enumerate(self._pages): - if page.window == wnd: - return indx - - return wx.NOT_FOUND - - - def GetPage(self, idx): - """ - Returns the page specified by the given index. - - :param `idx`: the tab index. - """ - - if idx < 0 or idx >= len(self._pages): - raise Exception("Invalid Page index") - - return self._pages[idx] - - - def GetPages(self): - """ Returns a list of all the pages in this L{AuiTabContainer}. """ - - return self._pages - - - def GetPageCount(self): - """ Returns the number of pages in the L{AuiTabContainer}. """ - - return len(self._pages) - - - def GetEnabled(self, idx): - """ - Returns whether a tab is enabled or not. - - :param `idx`: the tab index. - """ - - if idx < 0 or idx >= len(self._pages): - return False - - return self._pages[idx].enabled - - - def EnableTab(self, idx, enable=True): - """ - Enables/disables a tab in the L{AuiTabContainer}. - - :param `idx`: the tab index; - :param `enable`: ``True`` to enable a tab, ``False`` to disable it. - """ - - if idx < 0 or idx >= len(self._pages): - raise Exception("Invalid Page index") - - self._pages[idx].enabled = enable - wnd = self.GetWindowFromIdx(idx) - wnd.Enable(enable) - - - def AddButton(self, id, location, normal_bitmap=wx.NullBitmap, disabled_bitmap=wx.NullBitmap): - """ - Adds a button in the tab area. - - :param `id`: the button identifier. This can be one of the following: - - ============================== ================================= - Button Identifier Description - ============================== ================================= - ``AUI_BUTTON_CLOSE`` Shows a close button on the tab area - ``AUI_BUTTON_WINDOWLIST`` Shows a window list button on the tab area - ``AUI_BUTTON_LEFT`` Shows a left button on the tab area - ``AUI_BUTTON_RIGHT`` Shows a right button on the tab area - ============================== ================================= - - :param `location`: the button location. Can be ``wx.LEFT`` or ``wx.RIGHT``; - :param `normal_bitmap`: the bitmap for an enabled tab; - :param `disabled_bitmap`: the bitmap for a disabled tab. - """ - - button = AuiTabContainerButton() - button.id = id - button.bitmap = normal_bitmap - button.dis_bitmap = disabled_bitmap - button.location = location - button.cur_state = AUI_BUTTON_STATE_NORMAL - - self._buttons.append(button) - - - def RemoveButton(self, id): - """ - Removes a button from the tab area. - - :param `id`: the button identifier. See L{AddButton} for a list of button identifiers. - - :see: L{AddButton} - """ - - for button in self._buttons: - if button.id == id: - self._buttons.remove(button) - return - - - def GetTabOffset(self): - """ Returns the tab offset. """ - - return self._tab_offset - - - def SetTabOffset(self, offset): - """ - Sets the tab offset. - - :param `offset`: the tab offset. - """ - - self._tab_offset = offset - - - def MinimizeTabOffset(self, dc, wnd, max_width): - """ - Minimize `self._tab_offset` to fit as many tabs as possible in the available space. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: an instance of `wx.Window`; - :param `max_width`: the maximum available width for the tabs. - """ - - total_width = 0 - - for i, page in reversed(list(enumerate(self._pages))): - - tab_button = self._tab_close_buttons[i] - (tab_width, tab_height), x_extent = self._art.GetTabSize(dc, wnd, page.caption, page.bitmap, page.active, tab_button.cur_state, page.control) - total_width += tab_width - - if total_width > max_width: - - tab_offset = i + 1 - - if tab_offset < self._tab_offset and tab_offset < len(self._pages): - self._tab_offset = tab_offset - - break - - if i == 0: - self._tab_offset = 0 - - - def Render(self, raw_dc, wnd): - """ - Renders the tab catalog to the specified `wx.DC`. - - It is a virtual function and can be overridden to provide custom drawing - capabilities. - - :param `raw_dc`: a `wx.DC` device context; - :param `wnd`: an instance of `wx.Window`. - """ - - if not raw_dc or not raw_dc.IsOk(): - return - - dc = wx.MemoryDC() - - # use the same layout direction as the window DC uses to ensure that the - # text is rendered correctly - dc.SetLayoutDirection(raw_dc.GetLayoutDirection()) - - page_count = len(self._pages) - button_count = len(self._buttons) - - # create off-screen bitmap - bmp = wx.EmptyBitmap(self._rect.GetWidth(), self._rect.GetHeight()) - dc.SelectObject(bmp) - - if not dc.IsOk(): - return - - # find out if size of tabs is larger than can be - # afforded on screen - total_width = visible_width = 0 - - for i in xrange(page_count): - page = self._pages[i] - - # determine if a close button is on this tab - close_button = False - if (self._agwFlags & AUI_NB_CLOSE_ON_ALL_TABS and page.hasCloseButton) or \ - (self._agwFlags & AUI_NB_CLOSE_ON_ACTIVE_TAB and page.active and page.hasCloseButton): - - close_button = True - - control = page.control - if control: - try: - control.GetSize() - except wx.PyDeadObjectError: - page.control = None - - size, x_extent = self._art.GetTabSize(dc, wnd, page.caption, page.bitmap, page.active, - (close_button and [AUI_BUTTON_STATE_NORMAL] or \ - [AUI_BUTTON_STATE_HIDDEN])[0], page.control) - - if i+1 < page_count: - total_width += x_extent - else: - total_width += size[0] - - if i >= self._tab_offset: - if i+1 < page_count: - visible_width += x_extent - else: - visible_width += size[0] - - if total_width > self._rect.GetWidth() or self._tab_offset != 0: - - # show left/right buttons - for button in self._buttons: - if button.id == AUI_BUTTON_LEFT or \ - button.id == AUI_BUTTON_RIGHT: - - button.cur_state &= ~AUI_BUTTON_STATE_HIDDEN - - else: - - # hide left/right buttons - for button in self._buttons: - if button.id == AUI_BUTTON_LEFT or \ - button.id == AUI_BUTTON_RIGHT: - - button.cur_state |= AUI_BUTTON_STATE_HIDDEN - - # determine whether left button should be enabled - for button in self._buttons: - if button.id == AUI_BUTTON_LEFT: - if self._tab_offset == 0: - button.cur_state |= AUI_BUTTON_STATE_DISABLED - else: - button.cur_state &= ~AUI_BUTTON_STATE_DISABLED - - if button.id == AUI_BUTTON_RIGHT: - if visible_width < self._rect.GetWidth() - 16*button_count: - button.cur_state |= AUI_BUTTON_STATE_DISABLED - else: - button.cur_state &= ~AUI_BUTTON_STATE_DISABLED - - # draw background - self._art.DrawBackground(dc, wnd, self._rect) - - # draw buttons - left_buttons_width = 0 - right_buttons_width = 0 - - # draw the buttons on the right side - offset = self._rect.x + self._rect.width - - for i in xrange(button_count): - button = self._buttons[button_count - i - 1] - - if button.location != wx.RIGHT: - continue - if button.cur_state & AUI_BUTTON_STATE_HIDDEN: - continue - - button_rect = wx.Rect(*self._rect) - button_rect.SetY(1) - button_rect.SetWidth(offset) - - button.rect = self._art.DrawButton(dc, wnd, button_rect, button, wx.RIGHT) - - offset -= button.rect.GetWidth() - right_buttons_width += button.rect.GetWidth() - - offset = 0 - - # draw the buttons on the left side - for i in xrange(button_count): - button = self._buttons[button_count - i - 1] - - if button.location != wx.LEFT: - continue - if button.cur_state & AUI_BUTTON_STATE_HIDDEN: - continue - - button_rect = wx.Rect(offset, 1, 1000, self._rect.height) - - button.rect = self._art.DrawButton(dc, wnd, button_rect, button, wx.LEFT) - - offset += button.rect.GetWidth() - left_buttons_width += button.rect.GetWidth() - - offset = left_buttons_width - - if offset == 0: - offset += self._art.GetIndentSize() - - # prepare the tab-close-button array - # make sure tab button entries which aren't used are marked as hidden - for i in xrange(page_count, len(self._tab_close_buttons)): - self._tab_close_buttons[i].cur_state = AUI_BUTTON_STATE_HIDDEN - - # make sure there are enough tab button entries to accommodate all tabs - while len(self._tab_close_buttons) < page_count: - tempbtn = AuiTabContainerButton() - tempbtn.id = AUI_BUTTON_CLOSE - tempbtn.location = wx.CENTER - tempbtn.cur_state = AUI_BUTTON_STATE_HIDDEN - self._tab_close_buttons.append(tempbtn) - - # buttons before the tab offset must be set to hidden - for i in xrange(self._tab_offset): - self._tab_close_buttons[i].cur_state = AUI_BUTTON_STATE_HIDDEN - if self._pages[i].control: - if self._pages[i].control.IsShown(): - self._pages[i].control.Hide() - - self.MinimizeTabOffset(dc, wnd, self._rect.GetWidth() - right_buttons_width - offset - 2) - - # draw the tabs - active = 999 - active_offset = 0 - - rect = wx.Rect(*self._rect) - rect.y = 0 - rect.height = self._rect.height - - for i in xrange(self._tab_offset, page_count): - - page = self._pages[i] - tab_button = self._tab_close_buttons[i] - - # determine if a close button is on this tab - if (self._agwFlags & AUI_NB_CLOSE_ON_ALL_TABS and page.hasCloseButton) or \ - (self._agwFlags & AUI_NB_CLOSE_ON_ACTIVE_TAB and page.active and page.hasCloseButton): - - if tab_button.cur_state == AUI_BUTTON_STATE_HIDDEN: - - tab_button.id = AUI_BUTTON_CLOSE - tab_button.cur_state = AUI_BUTTON_STATE_NORMAL - tab_button.location = wx.CENTER - - else: - - tab_button.cur_state = AUI_BUTTON_STATE_HIDDEN - - rect.x = offset - rect.width = self._rect.width - right_buttons_width - offset - 2 - - if rect.width <= 0: - break - - page.rect, tab_button.rect, x_extent = self._art.DrawTab(dc, wnd, page, rect, tab_button.cur_state) - - if page.active: - active = i - active_offset = offset - active_rect = wx.Rect(*rect) - - offset += x_extent - - lenPages = len(self._pages) - # make sure to deactivate buttons which are off the screen to the right - for j in xrange(i+1, len(self._tab_close_buttons)): - self._tab_close_buttons[j].cur_state = AUI_BUTTON_STATE_HIDDEN - if j > 0 and j <= lenPages: - if self._pages[j-1].control: - if self._pages[j-1].control.IsShown(): - self._pages[j-1].control.Hide() - - # draw the active tab again so it stands in the foreground - if active >= self._tab_offset and active < len(self._pages): - - page = self._pages[active] - tab_button = self._tab_close_buttons[active] - - rect.x = active_offset - dummy = self._art.DrawTab(dc, wnd, page, active_rect, tab_button.cur_state) - - raw_dc.Blit(self._rect.x, self._rect.y, self._rect.GetWidth(), self._rect.GetHeight(), dc, 0, 0) - - - def IsTabVisible(self, tabPage, tabOffset, dc, wnd): - """ - Returns whether a tab is visible or not. - - :param `tabPage`: the tab index; - :param `tabOffset`: the tab offset; - :param `dc`: a `wx.DC` device context; - :param `wnd`: an instance of `wx.Window` derived window. - """ - - if not dc or not dc.IsOk(): - return False - - page_count = len(self._pages) - button_count = len(self._buttons) - self.Render(dc, wnd) - - # Hasn't been rendered yet assume it's visible - if len(self._tab_close_buttons) < page_count: - return True - - if self._agwFlags & AUI_NB_SCROLL_BUTTONS: - # First check if both buttons are disabled - if so, there's no need to - # check further for visibility. - arrowButtonVisibleCount = 0 - for i in xrange(button_count): - - button = self._buttons[i] - if button.id == AUI_BUTTON_LEFT or \ - button.id == AUI_BUTTON_RIGHT: - - if button.cur_state & AUI_BUTTON_STATE_HIDDEN == 0: - arrowButtonVisibleCount += 1 - - # Tab must be visible - if arrowButtonVisibleCount == 0: - return True - - # If tab is less than the given offset, it must be invisible by definition - if tabPage < tabOffset: - return False - - # draw buttons - left_buttons_width = 0 - right_buttons_width = 0 - - offset = 0 - - # calculate size of the buttons on the right side - offset = self._rect.x + self._rect.width - - for i in xrange(button_count): - button = self._buttons[button_count - i - 1] - - if button.location != wx.RIGHT: - continue - if button.cur_state & AUI_BUTTON_STATE_HIDDEN: - continue - - offset -= button.rect.GetWidth() - right_buttons_width += button.rect.GetWidth() - - offset = 0 - - # calculate size of the buttons on the left side - for i in xrange(button_count): - button = self._buttons[button_count - i - 1] - - if button.location != wx.LEFT: - continue - if button.cur_state & AUI_BUTTON_STATE_HIDDEN: - continue - - offset += button.rect.GetWidth() - left_buttons_width += button.rect.GetWidth() - - offset = left_buttons_width - - if offset == 0: - offset += self._art.GetIndentSize() - - rect = wx.Rect(*self._rect) - rect.y = 0 - rect.height = self._rect.height - - # See if the given page is visible at the given tab offset (effectively scroll position) - for i in xrange(tabOffset, page_count): - - page = self._pages[i] - tab_button = self._tab_close_buttons[i] - - rect.x = offset - rect.width = self._rect.width - right_buttons_width - offset - 2 - - if rect.width <= 0: - return False # haven't found the tab, and we've run out of space, so return False - - size, x_extent = self._art.GetTabSize(dc, wnd, page.caption, page.bitmap, page.active, tab_button.cur_state, page.control) - offset += x_extent - - if i == tabPage: - - # If not all of the tab is visible, and supposing there's space to display it all, - # we could do better so we return False. - if (self._rect.width - right_buttons_width - offset - 2) <= 0 and (self._rect.width - right_buttons_width - left_buttons_width) > x_extent: - return False - else: - return True - - # Shouldn't really get here, but if it does, assume the tab is visible to prevent - # further looping in calling code. - return True - - - def MakeTabVisible(self, tabPage, win): - """ - Make the tab visible if it wasn't already. - - :param `tabPage`: the tab index; - :param `win`: an instance of `wx.Window` derived window. - """ - - dc = wx.ClientDC(win) - - if not self.IsTabVisible(tabPage, self.GetTabOffset(), dc, win): - for i in xrange(len(self._pages)): - if self.IsTabVisible(tabPage, i, dc, win): - self.SetTabOffset(i) - win.Refresh() - return - - - def TabHitTest(self, x, y): - """ - TabHitTest() tests if a tab was hit, passing the window pointer - back if that condition was fulfilled. - - :param `x`: the mouse `x` position; - :param `y`: the mouse `y` position. - """ - - if not self._rect.Contains((x,y)): - return None - - btn = self.ButtonHitTest(x, y) - if btn: - if btn in self._buttons: - return None - - for i in xrange(self._tab_offset, len(self._pages)): - page = self._pages[i] - if page.rect.Contains((x,y)): - return page.window - - return None - - - def ButtonHitTest(self, x, y): - """ - Tests if a button was hit. - - :param `x`: the mouse `x` position; - :param `y`: the mouse `y` position. - - :returns: and instance of L{AuiTabContainerButton} if a button was hit, ``None`` otherwise. - """ - - if not self._rect.Contains((x,y)): - return None - - for button in self._buttons: - if button.rect.Contains((x,y)) and \ - (button.cur_state & (AUI_BUTTON_STATE_HIDDEN|AUI_BUTTON_STATE_DISABLED)) == 0: - return button - - for button in self._tab_close_buttons: - if button.rect.Contains((x,y)) and \ - (button.cur_state & (AUI_BUTTON_STATE_HIDDEN|AUI_BUTTON_STATE_DISABLED)) == 0: - return button - - return None - - - def DoShowHide(self): - """ - This function shows the active window, then hides all of the other windows - (in that order). - """ - - pages = self.GetPages() - - # show new active page first - for page in pages: - if page.active: - page.window.Show(True) - break - - # hide all other pages - for page in pages: - if not page.active: - page.window.Show(False) - - -# ---------------------------------------------------------------------- -# -- AuiTabCtrl class implementation -- - -class AuiTabCtrl(wx.PyControl, AuiTabContainer): - """ - This is an actual `wx.Window`-derived window which can be used as a tab - control in the normal sense. - """ - - def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, - style=wx.NO_BORDER|wx.WANTS_CHARS|wx.TAB_TRAVERSAL): - """ - Default class constructor. - Used internally, do not call it in your code! - - :param `parent`: the L{AuiTabCtrl} parent; - :param `id`: an identifier for the control: a value of -1 is taken to mean a default; - :param `pos`: the control position. A value of (-1, -1) indicates a default position, - chosen by either the windowing system or wxPython, depending on platform; - :param `size`: the control size. A value of (-1, -1) indicates a default size, - chosen by either the windowing system or wxPython, depending on platform; - :param `style`: the window style. - """ - - wx.PyControl.__init__(self, parent, id, pos, size, style, name="AuiTabCtrl") - AuiTabContainer.__init__(self, parent) - - self._click_pt = wx.Point(-1, -1) - self._is_dragging = False - self._hover_button = None - self._pressed_button = None - self._drag_image = None - self._drag_img_offset = (0, 0) - self._on_button = False - - self.Bind(wx.EVT_PAINT, self.OnPaint) - self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) - self.Bind(wx.EVT_SIZE, self.OnSize) - self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) - self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick) - self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) - self.Bind(wx.EVT_MIDDLE_DOWN, self.OnMiddleDown) - self.Bind(wx.EVT_MIDDLE_UP, self.OnMiddleUp) - self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown) - self.Bind(wx.EVT_RIGHT_UP, self.OnRightUp) - self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) - self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) - self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) - self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.OnCaptureLost) - self.Bind(wx.EVT_MOTION, self.OnMotion) - self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow) - self.Bind(EVT_AUINOTEBOOK_BUTTON, self.OnButton) - - - def IsDragging(self): - """ Returns whether the user is dragging a tab with the mouse or not. """ - - return self._is_dragging - - - def GetDefaultBorder(self): - """ Returns the default border style for L{AuiTabCtrl}. """ - - return wx.BORDER_NONE - - - def OnPaint(self, event): - """ - Handles the ``wx.EVT_PAINT`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.PaintEvent` event to be processed. - """ - - dc = wx.PaintDC(self) - dc.SetFont(self.GetFont()) - - if self.GetPageCount() > 0: - self.Render(dc, self) - - - def OnEraseBackground(self, event): - """ - Handles the ``wx.EVT_ERASE_BACKGROUND`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.EraseEvent` event to be processed. - - :note: This is intentionally empty, to reduce flicker. - """ - - pass - - - def DoGetBestSize(self): - """ - Gets the size which best suits the window: for a control, it would be the - minimal size which doesn't truncate the control, for a panel - the same - size as it would have after a call to `Fit()`. - - :note: Overridden from `wx.PyControl`. - """ - - return wx.Size(self._rect.width, self._rect.height) - - - def OnSize(self, event): - """ - Handles the ``wx.EVT_SIZE`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.SizeEvent` event to be processed. - """ - - s = event.GetSize() - self.SetTabRect(wx.Rect(0, 0, s.GetWidth(), s.GetHeight())) - - - def OnLeftDown(self, event): - """ - Handles the ``wx.EVT_LEFT_DOWN`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - self.CaptureMouse() - self._click_pt = wx.Point(-1, -1) - self._is_dragging = False - self._click_tab = None - self._pressed_button = None - - wnd = self.TabHitTest(event.GetX(), event.GetY()) - - if wnd is not None: - new_selection = self.GetIdxFromWindow(wnd) - - # AuiNotebooks always want to receive this event - # even if the tab is already active, because they may - # have multiple tab controls - if new_selection != self.GetActivePage() or isinstance(self.GetParent(), AuiNotebook): - - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, self.GetId()) - e.SetSelection(new_selection) - e.SetOldSelection(self.GetActivePage()) - e.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e) - - self._click_pt.x = event.GetX() - self._click_pt.y = event.GetY() - self._click_tab = wnd - else: - page_index = self.GetActivePage() - if page_index != wx.NOT_FOUND: - self.GetWindowFromIdx(page_index).SetFocus() - - if self._hover_button: - self._pressed_button = self._hover_button - self._pressed_button.cur_state = AUI_BUTTON_STATE_PRESSED - self._on_button = True - self.Refresh() - self.Update() - - - def OnCaptureLost(self, event): - """ - Handles the ``wx.EVT_MOUSE_CAPTURE_LOST`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.MouseCaptureLostEvent` event to be processed. - """ - - if self._is_dragging: - self._is_dragging = False - self._on_button = False - - if self._drag_image: - self._drag_image.EndDrag() - del self._drag_image - self._drag_image = None - - event = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_CANCEL_DRAG, self.GetId()) - event.SetSelection(self.GetIdxFromWindow(self._click_tab)) - event.SetOldSelection(event.GetSelection()) - event.SetEventObject(self) - self.GetEventHandler().ProcessEvent(event) - - - def OnLeftUp(self, event): - """ - Handles the ``wx.EVT_LEFT_UP`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - self._on_button = False - - if self._is_dragging: - - if self.HasCapture(): - self.ReleaseMouse() - - self._is_dragging = False - if self._drag_image: - self._drag_image.EndDrag() - del self._drag_image - self._drag_image = None - self.GetParent().Refresh() - - evt = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, self.GetId()) - evt.SetSelection(self.GetIdxFromWindow(self._click_tab)) - evt.SetOldSelection(evt.GetSelection()) - evt.SetEventObject(self) - self.GetEventHandler().ProcessEvent(evt) - - return - - self.GetParent()._mgr.HideHint() - - if self.HasCapture(): - self.ReleaseMouse() - - if self._hover_button: - self._pressed_button = self._hover_button - - if self._pressed_button: - - # make sure we're still clicking the button - button = self.ButtonHitTest(event.GetX(), event.GetY()) - - if button is None: - return - - if button != self._pressed_button: - self._pressed_button = None - return - - self.Refresh() - self.Update() - - if self._pressed_button.cur_state & AUI_BUTTON_STATE_DISABLED == 0: - - evt = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, self.GetId()) - evt.SetSelection(self.GetIdxFromWindow(self._click_tab)) - evt.SetInt(self._pressed_button.id) - evt.SetEventObject(self) - eventHandler = self.GetEventHandler() - - if eventHandler is not None: - eventHandler.ProcessEvent(evt) - - self._pressed_button = None - - self._click_pt = wx.Point(-1, -1) - self._is_dragging = False - self._click_tab = None - - - def OnMiddleUp(self, event): - """ - Handles the ``wx.EVT_MIDDLE_UP`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - eventHandler = self.GetEventHandler() - if not isinstance(eventHandler, AuiTabCtrl): - event.Skip() - return - - x, y = event.GetX(), event.GetY() - wnd = self.TabHitTest(x, y) - - if wnd: - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, self.GetId()) - e.SetEventObject(self) - e.SetSelection(self.GetIdxFromWindow(wnd)) - self.GetEventHandler().ProcessEvent(e) - elif not self.ButtonHitTest(x, y): - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BG_MIDDLE_UP, self.GetId()) - e.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e) - - - def OnMiddleDown(self, event): - """ - Handles the ``wx.EVT_MIDDLE_DOWN`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - eventHandler = self.GetEventHandler() - if not isinstance(eventHandler, AuiTabCtrl): - event.Skip() - return - - x, y = event.GetX(), event.GetY() - wnd = self.TabHitTest(x, y) - - if wnd: - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, self.GetId()) - e.SetEventObject(self) - e.SetSelection(self.GetIdxFromWindow(wnd)) - self.GetEventHandler().ProcessEvent(e) - elif not self.ButtonHitTest(x, y): - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BG_MIDDLE_DOWN, self.GetId()) - e.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e) - - - def OnRightUp(self, event): - """ - Handles the ``wx.EVT_RIGHT_UP`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - x, y = event.GetX(), event.GetY() - wnd = self.TabHitTest(x, y) - - if wnd: - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, self.GetId()) - e.SetEventObject(self) - e.SetSelection(self.GetIdxFromWindow(wnd)) - self.GetEventHandler().ProcessEvent(e) - elif not self.ButtonHitTest(x, y): - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BG_RIGHT_UP, self.GetId()) - e.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e) - - - def OnRightDown(self, event): - """ - Handles the ``wx.EVT_RIGHT_DOWN`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - x, y = event.GetX(), event.GetY() - wnd = self.TabHitTest(x, y) - - if wnd: - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, self.GetId()) - e.SetEventObject(self) - e.SetSelection(self.GetIdxFromWindow(wnd)) - self.GetEventHandler().ProcessEvent(e) - elif not self.ButtonHitTest(x, y): - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BG_RIGHT_DOWN, self.GetId()) - e.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e) - - - def OnLeftDClick(self, event): - """ - Handles the ``wx.EVT_LEFT_DCLICK`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - x, y = event.GetX(), event.GetY() - wnd = self.TabHitTest(x, y) - - if wnd: - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_DCLICK, self.GetId()) - e.SetEventObject(self) - e.SetSelection(self.GetIdxFromWindow(wnd)) - self.GetEventHandler().ProcessEvent(e) - elif not self.ButtonHitTest(x, y): - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, self.GetId()) - e.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e) - - - def OnMotion(self, event): - """ - Handles the ``wx.EVT_MOTION`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - pos = event.GetPosition() - - # check if the mouse is hovering above a button - - button = self.ButtonHitTest(pos.x, pos.y) - wnd = self.TabHitTest(pos.x, pos.y) - - if wnd is not None: - mouse_tab = self.GetIdxFromWindow(wnd) - if not self._pages[mouse_tab].enabled: - self._hover_button = None - return - - if self._on_button: - return - - if button: - - if self._hover_button and button != self._hover_button: - self._hover_button.cur_state = AUI_BUTTON_STATE_NORMAL - self._hover_button = None - self.Refresh() - self.Update() - - if button.cur_state != AUI_BUTTON_STATE_HOVER: - button.cur_state = AUI_BUTTON_STATE_HOVER - self.Refresh() - self.Update() - self._hover_button = button - return - - else: - - if self._hover_button: - self._hover_button.cur_state = AUI_BUTTON_STATE_NORMAL - self._hover_button = None - self.Refresh() - self.Update() - - if not event.LeftIsDown() or self._click_pt == wx.Point(-1, -1): - return - - if not self.HasCapture(): - return - - wnd = self.TabHitTest(pos.x, pos.y) - - if not self._is_dragging: - - drag_x_threshold = wx.SystemSettings.GetMetric(wx.SYS_DRAG_X) - drag_y_threshold = wx.SystemSettings.GetMetric(wx.SYS_DRAG_Y) - - if abs(pos.x - self._click_pt.x) > drag_x_threshold or \ - abs(pos.y - self._click_pt.y) > drag_y_threshold: - - self._is_dragging = True - - if self._drag_image: - self._drag_image.EndDrag() - del self._drag_image - self._drag_image = None - - if self._agwFlags & AUI_NB_DRAW_DND_TAB: - # Create the custom draw image from the icons and the text of the item - mouse_tab = self.GetIdxFromWindow(wnd) - page = self._pages[mouse_tab] - tab_button = self._tab_close_buttons[mouse_tab] - self._drag_image = TabDragImage(self, page, tab_button.cur_state, self._art) - - if self._agwFlags & AUI_NB_TAB_FLOAT: - self._drag_image.BeginDrag(wx.Point(0,0), self, fullScreen=True) - else: - self._drag_image.BeginDragBounded(wx.Point(0,0), self, self.GetParent()) - - # Capture the mouse cursor position offset relative to - # The tab image location - self._drag_img_offset = (pos[0] - page.rect.x, - pos[1] - page.rect.y) - - self._drag_image.Show() - - if not wnd: - evt2 = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, self.GetId()) - evt2.SetSelection(self.GetIdxFromWindow(self._click_tab)) - evt2.SetOldSelection(evt2.GetSelection()) - evt2.SetEventObject(self) - self.GetEventHandler().ProcessEvent(evt2) - if evt2.GetDispatched(): - return - - evt3 = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, self.GetId()) - evt3.SetSelection(self.GetIdxFromWindow(self._click_tab)) - evt3.SetOldSelection(evt3.GetSelection()) - evt3.SetEventObject(self) - self.GetEventHandler().ProcessEvent(evt3) - - if self._drag_image: - # Apply the drag images offset - pos -= self._drag_img_offset - self._drag_image.Move(pos) - - - def OnLeaveWindow(self, event): - """ - Handles the ``wx.EVT_LEAVE_WINDOW`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.MouseEvent` event to be processed. - """ - - if self._hover_button: - self._hover_button.cur_state = AUI_BUTTON_STATE_NORMAL - self._hover_button = None - self.Refresh() - self.Update() - - - def OnButton(self, event): - """ - Handles the ``EVT_AUINOTEBOOK_BUTTON`` event for L{AuiTabCtrl}. - - :param `event`: a L{AuiNotebookEvent} event to be processed. - """ - - button = event.GetInt() - - if button == AUI_BUTTON_LEFT or button == AUI_BUTTON_RIGHT: - if button == AUI_BUTTON_LEFT: - if self.GetTabOffset() > 0: - - self.SetTabOffset(self.GetTabOffset()-1) - self.Refresh() - self.Update() - else: - self.SetTabOffset(self.GetTabOffset()+1) - self.Refresh() - self.Update() - - elif button == AUI_BUTTON_WINDOWLIST: - idx = self.GetArtProvider().ShowDropDown(self, self._pages, self.GetActivePage()) - - if idx != -1: - - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, self.GetId()) - e.SetSelection(idx) - e.SetOldSelection(self.GetActivePage()) - e.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e) - - else: - event.Skip() - - - def OnSetFocus(self, event): - """ - Handles the ``wx.EVT_SET_FOCUS`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.FocusEvent` event to be processed. - """ - - self.Refresh() - - - def OnKillFocus(self, event): - """ - Handles the ``wx.EVT_KILL_FOCUS`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.FocusEvent` event to be processed. - """ - - self.Refresh() - - - def OnKeyDown(self, event): - """ - Handles the ``wx.EVT_KEY_DOWN`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.KeyEvent` event to be processed. - """ - - key = event.GetKeyCode() - nb = self.GetParent() - - if key == wx.WXK_LEFT: - nb.AdvanceSelection(False) - self.SetFocus() - - elif key == wx.WXK_RIGHT: - nb.AdvanceSelection(True) - self.SetFocus() - - elif key == wx.WXK_HOME: - newPage = 0 - nb.SetSelection(newPage) - self.SetFocus() - - elif key == wx.WXK_END: - newPage = nb.GetPageCount() - 1 - nb.SetSelection(newPage) - self.SetFocus() - - elif key == wx.WXK_TAB: - if not event.ControlDown(): - flags = 0 - if not event.ShiftDown(): flags |= wx.NavigationKeyEvent.IsForward - if event.CmdDown(): flags |= wx.NavigationKeyEvent.WinChange - self.Navigate(flags) - else: - - if not nb or not isinstance(nb, AuiNotebook): - event.Skip() - return - - bForward = bWindowChange = 0 - if not event.ShiftDown(): bForward |= wx.NavigationKeyEvent.IsForward - if event.CmdDown(): bWindowChange |= wx.NavigationKeyEvent.WinChange - - keyEvent = wx.NavigationKeyEvent() - keyEvent.SetDirection(bForward) - keyEvent.SetWindowChange(bWindowChange) - keyEvent.SetFromTab(True) - keyEvent.SetEventObject(nb) - - if not nb.GetEventHandler().ProcessEvent(keyEvent): - - # Not processed? Do an explicit tab into the page. - win = self.GetWindowFromIdx(self.GetActivePage()) - if win: - win.SetFocus() - - self.SetFocus() - - return - - else: - event.Skip() - - - def OnKeyDown2(self, event): - """ - Deprecated. - - Handles the ``wx.EVT_KEY_DOWN`` event for L{AuiTabCtrl}. - - :param `event`: a `wx.KeyEvent` event to be processed. - - :warning: This method implementation is now deprecated. Refer to L{OnKeyDown} - for the correct one. - """ - - if self.GetActivePage() == -1: - event.Skip() - return - - # We can't leave tab processing to the system on Windows, tabs and keys - # get eaten by the system and not processed properly if we specify both - # wxTAB_TRAVERSAL and wxWANTS_CHARS. And if we specify just wxTAB_TRAVERSAL, - # we don't key arrow key events. - - key = event.GetKeyCode() - - if key == wx.WXK_NUMPAD_PAGEUP: - key = wx.WXK_PAGEUP - if key == wx.WXK_NUMPAD_PAGEDOWN: - key = wx.WXK_PAGEDOWN - if key == wx.WXK_NUMPAD_HOME: - key = wx.WXK_HOME - if key == wx.WXK_NUMPAD_END: - key = wx.WXK_END - if key == wx.WXK_NUMPAD_LEFT: - key = wx.WXK_LEFT - if key == wx.WXK_NUMPAD_RIGHT: - key = wx.WXK_RIGHT - - if key == wx.WXK_TAB or key == wx.WXK_PAGEUP or key == wx.WXK_PAGEDOWN: - - bCtrlDown = event.ControlDown() - bShiftDown = event.ShiftDown() - - bForward = (key == wx.WXK_TAB and not bShiftDown) or (key == wx.WXK_PAGEDOWN) - bWindowChange = (key == wx.WXK_PAGEUP) or (key == wx.WXK_PAGEDOWN) or bCtrlDown - bFromTab = (key == wx.WXK_TAB) - - nb = self.GetParent() - if not nb or not isinstance(nb, AuiNotebook): - event.Skip() - return - - keyEvent = wx.NavigationKeyEvent() - keyEvent.SetDirection(bForward) - keyEvent.SetWindowChange(bWindowChange) - keyEvent.SetFromTab(bFromTab) - keyEvent.SetEventObject(nb) - - if not nb.GetEventHandler().ProcessEvent(keyEvent): - - # Not processed? Do an explicit tab into the page. - win = self.GetWindowFromIdx(self.GetActivePage()) - if win: - win.SetFocus() - - return - - if len(self._pages) < 2: - event.Skip() - return - - newPage = -1 - - if self.GetLayoutDirection() == wx.Layout_RightToLeft: - forwardKey = wx.WXK_LEFT - backwardKey = wx.WXK_RIGHT - else: - forwardKey = wx.WXK_RIGHT - backwardKey = wx.WXK_LEFT - - if key == forwardKey: - if self.GetActivePage() == -1: - newPage = 0 - elif self.GetActivePage() < len(self._pages) - 1: - newPage = self.GetActivePage() + 1 - - elif key == backwardKey: - if self.GetActivePage() == -1: - newPage = len(self._pages) - 1 - elif self.GetActivePage() > 0: - newPage = self.GetActivePage() - 1 - - elif key == wx.WXK_HOME: - newPage = 0 - - elif key == wx.WXK_END: - newPage = len(self._pages) - 1 - - else: - event.Skip() - - if newPage != -1: - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, self.GetId()) - e.SetSelection(newPage) - e.SetOldSelection(newPage) - e.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e) - - else: - event.Skip() - - -# ---------------------------------------------------------------------- - -class TabFrame(wx.PyWindow): - """ - TabFrame is an interesting case. It's important that all child pages - of the multi-notebook control are all actually children of that control - (and not grandchildren). TabFrame facilitates this. There is one - instance of TabFrame for each tab control inside the multi-notebook. - - It's important to know that TabFrame is not a real window, but it merely - used to capture the dimensions/positioning of the internal tab control and - it's managed page windows. - """ - - def __init__(self, parent): - """ - Default class constructor. - Used internally, do not call it in your code! - """ - - pre = wx.PrePyWindow() - - self._tabs = None - self._rect = wx.Rect(0, 0, 200, 200) - self._tab_ctrl_height = 20 - self._tab_rect = wx.Rect() - self._parent = parent - - self.PostCreate(pre) - - - def SetTabCtrlHeight(self, h): - """ - Sets the tab control height. - - :param `h`: the tab area height. - """ - - self._tab_ctrl_height = h - - - def DoSetSize(self, x, y, width, height, flags=wx.SIZE_AUTO): - """ - Sets the position and size of the window in pixels. The `flags` - parameter indicates the interpretation of the other params if they are - equal to -1. - - :param `x`: the window `x` position; - :param `y`: the window `y` position; - :param `width`: the window width; - :param `height`: the window height; - :param `flags`: may have one of this bit set: - - =================================== ====================================== - Size Flags Description - =================================== ====================================== - ``wx.SIZE_AUTO`` A -1 indicates that a class-specific default should be used. - ``wx.SIZE_AUTO_WIDTH`` A -1 indicates that a class-specific default should be used for the width. - ``wx.SIZE_AUTO_HEIGHT`` A -1 indicates that a class-specific default should be used for the height. - ``wx.SIZE_USE_EXISTING`` Existing dimensions should be used if -1 values are supplied. - ``wx.SIZE_ALLOW_MINUS_ONE`` Allow dimensions of -1 and less to be interpreted as real dimensions, not default values. - ``wx.SIZE_FORCE`` Normally, if the position and the size of the window are already the same as the parameters of this function, nothing is done. but with this flag a window resize may be forced even in this case (supported in wx 2.6.2 and later and only implemented for MSW and ignored elsewhere currently) - =================================== ====================================== - - :note: Overridden from `wx.PyControl`. - """ - - self._rect = wx.Rect(x, y, max(1, width), max(1, height)) - self.DoSizing() - - - def DoGetSize(self): - """ - Returns the window size. - - :note: Overridden from `wx.PyControl`. - """ - - return self._rect.width, self._rect.height - - - def DoGetClientSize(self): - """ - Returns the window client size. - - :note: Overridden from `wx.PyControl`. - """ - - return self._rect.width, self._rect.height - - - def Show(self, show=True): - """ - Shows/hides the window. - - :param `show`: ``True`` to show the window, ``False`` otherwise. - - :note: Overridden from `wx.PyControl`, this method always returns ``False`` as - L{TabFrame} should never be phisically shown on screen. - """ - - return False - - - def DoSizing(self): - """ Does the actual sizing of the tab control. """ - - if not self._tabs: - return - - hideOnSingle = ((self._tabs.GetAGWFlags() & AUI_NB_HIDE_ON_SINGLE_TAB) and \ - self._tabs.GetPageCount() <= 1) - - if not hideOnSingle and not self._parent._hide_tabs: - tab_height = self._tab_ctrl_height - - self._tab_rect = wx.Rect(self._rect.x, self._rect.y, self._rect.width, self._tab_ctrl_height) - - if self._tabs.GetAGWFlags() & AUI_NB_BOTTOM: - self._tab_rect = wx.Rect(self._rect.x, self._rect.y + self._rect.height - tab_height, - self._rect.width, tab_height) - self._tabs.SetDimensions(self._rect.x, self._rect.y + self._rect.height - tab_height, - self._rect.width, tab_height) - self._tabs.SetTabRect(wx.Rect(0, 0, self._rect.width, tab_height)) - - else: - - self._tab_rect = wx.Rect(self._rect.x, self._rect.y, self._rect.width, tab_height) - self._tabs.SetDimensions(self._rect.x, self._rect.y, self._rect.width, tab_height) - self._tabs.SetTabRect(wx.Rect(0, 0, self._rect.width, tab_height)) - - # TODO: elif (GetAGWFlags() & AUI_NB_LEFT) - # TODO: elif (GetAGWFlags() & AUI_NB_RIGHT) - - self._tabs.Refresh() - self._tabs.Update() - - else: - - tab_height = 0 - self._tabs.SetDimensions(self._rect.x, self._rect.y, self._rect.width, tab_height) - self._tabs.SetTabRect(wx.Rect(0, 0, self._rect.width, tab_height)) - - pages = self._tabs.GetPages() - - for page in pages: - - height = self._rect.height - tab_height - - if height < 0: - # avoid passing negative height to wx.Window.SetSize(), this - # results in assert failures/GTK+ warnings - height = 0 - - if self._tabs.GetAGWFlags() & AUI_NB_BOTTOM: - page.window.SetDimensions(self._rect.x, self._rect.y, self._rect.width, height) - - else: - page.window.SetDimensions(self._rect.x, self._rect.y + tab_height, - self._rect.width, height) - - # TODO: elif (GetAGWFlags() & AUI_NB_LEFT) - # TODO: elif (GetAGWFlags() & AUI_NB_RIGHT) - - if repr(page.window.__class__).find("AuiMDIChildFrame") >= 0: - page.window.ApplyMDIChildFrameRect() - - - def Update(self): - """ - Calling this method immediately repaints the invalidated area of the window - and all of its children recursively while this would usually only happen when - the flow of control returns to the event loop. - - :note: Notice that this function doesn't invalidate any area of the window so - nothing happens if nothing has been invalidated (i.e. marked as requiring a redraw). - Use `Refresh` first if you want to immediately redraw the window unconditionally. - - :note: Overridden from `wx.PyControl`. - """ - - # does nothing - pass - - -# ---------------------------------------------------------------------- -# -- AuiNotebook class implementation -- - -class AuiNotebook(wx.PyPanel): - """ - AuiNotebook is a notebook control which implements many features common in - applications with dockable panes. Specifically, AuiNotebook implements functionality - which allows the user to rearrange tab order via drag-and-drop, split the tab window - into many different splitter configurations, and toggle through different themes to - customize the control's look and feel. - - An effort has been made to try to maintain an API as similar to that of `wx.Notebook`. - - The default theme that is used is L{AuiDefaultTabArt}, which provides a modern, glossy - look and feel. The theme can be changed by calling L{AuiNotebook.SetArtProvider}. - """ - - def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, - style=0, agwStyle=AUI_NB_DEFAULT_STYLE): - """ - Default class constructor. - - :param `parent`: the L{AuiNotebook} parent; - :param `id`: an identifier for the control: a value of -1 is taken to mean a default; - :param `pos`: the control position. A value of (-1, -1) indicates a default position, - chosen by either the windowing system or wxPython, depending on platform; - :param `size`: the control size. A value of (-1, -1) indicates a default size, - chosen by either the windowing system or wxPython, depending on platform; - :param `style`: the underlying `wx.PyPanel` window style; - :param `agwStyle`: the AGW-specific window style. This can be a combination of the following bits: - - ==================================== ================================== - Flag name Description - ==================================== ================================== - ``AUI_NB_TOP`` With this style, tabs are drawn along the top of the notebook - ``AUI_NB_LEFT`` With this style, tabs are drawn along the left of the notebook. Not implemented yet. - ``AUI_NB_RIGHT`` With this style, tabs are drawn along the right of the notebook. Not implemented yet. - ``AUI_NB_BOTTOM`` With this style, tabs are drawn along the bottom of the notebook - ``AUI_NB_TAB_SPLIT`` Allows the tab control to be split by dragging a tab - ``AUI_NB_TAB_MOVE`` Allows a tab to be moved horizontally by dragging - ``AUI_NB_TAB_EXTERNAL_MOVE`` Allows a tab to be moved to another tab control - ``AUI_NB_TAB_FIXED_WIDTH`` With this style, all tabs have the same width - ``AUI_NB_SCROLL_BUTTONS`` With this style, left and right scroll buttons are displayed - ``AUI_NB_WINDOWLIST_BUTTON`` With this style, a drop-down list of windows is available - ``AUI_NB_CLOSE_BUTTON`` With this style, a close button is available on the tab bar - ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` With this style, a close button is available on the active tab - ``AUI_NB_CLOSE_ON_ALL_TABS`` With this style, a close button is available on all tabs - ``AUI_NB_MIDDLE_CLICK_CLOSE`` Allows to close L{AuiNotebook} tabs by mouse middle button click - ``AUI_NB_SUB_NOTEBOOK`` This style is used by L{AuiManager} to create automatic AuiNotebooks - ``AUI_NB_HIDE_ON_SINGLE_TAB`` Hides the tab window if only one tab is present - ``AUI_NB_SMART_TABS`` Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows - ``AUI_NB_USE_IMAGES_DROPDOWN`` Uses images on dropdown window list menu instead of check items - ``AUI_NB_CLOSE_ON_TAB_LEFT`` Draws the tab close button on the left instead of on the right (a la Camino browser) - ``AUI_NB_TAB_FLOAT`` Allows the floating of single tabs. Known limitation: when the notebook is more or less full screen, tabs cannot be dragged far enough outside of the notebook to become floating pages - ``AUI_NB_DRAW_DND_TAB`` Draws an image representation of a tab while dragging (on by default) - ``AUI_NB_ORDER_BY_ACCESS`` Tab navigation order by last access time for the tabs - ``AUI_NB_NO_TAB_FOCUS`` Don't draw tab focus rectangle - ==================================== ================================== - - Default value for `agwStyle` is: - ``AUI_NB_DEFAULT_STYLE`` = ``AUI_NB_TOP`` | ``AUI_NB_TAB_SPLIT`` | ``AUI_NB_TAB_MOVE`` | ``AUI_NB_SCROLL_BUTTONS`` | ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` | ``AUI_NB_MIDDLE_CLICK_CLOSE`` | ``AUI_NB_DRAW_DND_TAB`` - - """ - - self._curpage = -1 - self._tab_id_counter = AuiBaseTabCtrlId - self._dummy_wnd = None - self._hide_tabs = False - self._sash_dclick_unsplit = False - self._tab_ctrl_height = 20 - self._requested_bmp_size = wx.Size(-1, -1) - self._requested_tabctrl_height = -1 - self._textCtrl = None - self._tabBounds = (-1, -1) - - wx.PyPanel.__init__(self, parent, id, pos, size, style|wx.BORDER_NONE|wx.TAB_TRAVERSAL) - self._mgr = framemanager.AuiManager() - self._tabs = AuiTabContainer(self) - - self.InitNotebook(agwStyle) - - - def GetTabContainer(self): - """ Returns the instance of L{AuiTabContainer}. """ - - return self._tabs - - - def InitNotebook(self, agwStyle): - """ - Contains common initialization code called by all constructors. - - :param `agwStyle`: the notebook style. - - :see: L{__init__} - """ - - self.SetName("AuiNotebook") - self._agwFlags = agwStyle - - self._popupWin = None - self._naviIcon = None - self._imageList = None - self._last_drag_x = 0 - - self._normal_font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) - self._selected_font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) - self._selected_font.SetWeight(wx.BOLD) - - self.SetArtProvider(TA.AuiDefaultTabArt()) - - self._dummy_wnd = wx.Window(self, wx.ID_ANY, wx.Point(0, 0), wx.Size(0, 0)) - self._dummy_wnd.SetSize((200, 200)) - self._dummy_wnd.Show(False) - - self._mgr.SetManagedWindow(self) - self._mgr.SetAGWFlags(AUI_MGR_DEFAULT) - self._mgr.SetDockSizeConstraint(1.0, 1.0) # no dock size constraint - - self._mgr.AddPane(self._dummy_wnd, framemanager.AuiPaneInfo().Name("dummy").Bottom().CaptionVisible(False).Show(False)) - self._mgr.Update() - - self.Bind(wx.EVT_SIZE, self.OnSize) - self.Bind(wx.EVT_CHILD_FOCUS, self.OnChildFocusNotebook) - self.Bind(EVT_AUINOTEBOOK_PAGE_CHANGING, self.OnTabClicked, - id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500) - self.Bind(EVT_AUINOTEBOOK_BEGIN_DRAG, self.OnTabBeginDrag, - id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500) - self.Bind(EVT_AUINOTEBOOK_END_DRAG, self.OnTabEndDrag, - id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500) - self.Bind(EVT_AUINOTEBOOK_DRAG_MOTION, self.OnTabDragMotion, - id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500) - self.Bind(EVT_AUINOTEBOOK_CANCEL_DRAG, self.OnTabCancelDrag, - id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500) - self.Bind(EVT_AUINOTEBOOK_BUTTON, self.OnTabButton, - id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500) - self.Bind(EVT_AUINOTEBOOK_TAB_MIDDLE_DOWN, self.OnTabMiddleDown, - id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500) - self.Bind(EVT_AUINOTEBOOK_TAB_MIDDLE_UP, self.OnTabMiddleUp, - id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500) - self.Bind(EVT_AUINOTEBOOK_TAB_RIGHT_DOWN, self.OnTabRightDown, - id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500) - self.Bind(EVT_AUINOTEBOOK_TAB_RIGHT_UP, self.OnTabRightUp, - id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500) - self.Bind(EVT_AUINOTEBOOK_BG_DCLICK, self.OnTabBgDClick, - id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500) - self.Bind(EVT_AUINOTEBOOK_TAB_DCLICK, self.OnTabDClick, - id=AuiBaseTabCtrlId, id2=AuiBaseTabCtrlId+500) - - self.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKeyNotebook) - - - def SetArtProvider(self, art): - """ - Sets the art provider to be used by the notebook. - - :param `art`: an art provider. - """ - - self._tabs.SetArtProvider(art) - self.UpdateTabCtrlHeight(force=True) - - - def SavePerspective(self): - """ - Saves the entire user interface layout into an encoded string, which can then - be stored by the application (probably using `wx.Config`). When a perspective - is restored using L{LoadPerspective}, the entire user interface will return - to the state it was when the perspective was saved. - """ - - # Build list of panes/tabs - tabs = "" - all_panes = self._mgr.GetAllPanes() - - for pane in all_panes: - - if pane.name == "dummy": - continue - - tabframe = pane.window - - if tabs: - tabs += "|" - - tabs += pane.name + "=" - - # add tab id's - page_count = tabframe._tabs.GetPageCount() - - for p in xrange(page_count): - - page = tabframe._tabs.GetPage(p) - page_idx = self._tabs.GetIdxFromWindow(page.window) - - if p: - tabs += "," - - if p == tabframe._tabs.GetActivePage(): - tabs += "+" - elif page_idx == self._curpage: - tabs += "*" - - tabs += "%u"%page_idx - - tabs += "@" - - # Add frame perspective - tabs += self._mgr.SavePerspective() - - return tabs - - - def LoadPerspective(self, layout): - """ - Loads a layout which was saved with L{SavePerspective}. - - :param `layout`: a string which contains a saved L{AuiNotebook} layout. - """ - - # Remove all tab ctrls (but still keep them in main index) - tab_count = self._tabs.GetPageCount() - for i in xrange(tab_count): - wnd = self._tabs.GetWindowFromIdx(i) - - # find out which onscreen tab ctrl owns this tab - ctrl, ctrl_idx = self.FindTab(wnd) - if not ctrl: - return False - - # remove the tab from ctrl - if not ctrl.RemovePage(wnd): - return False - - self.RemoveEmptyTabFrames() - - sel_page = 0 - tabs = layout[0:layout.index("@")] - to_break1 = False - - while 1: - - if "|" not in tabs: - to_break1 = True - tab_part = tabs - else: - tab_part = tabs[0:tabs.index('|')] - - if "=" not in tab_part: - # No pages in this perspective... - return False - - # Get pane name - pane_name = tab_part[0:tab_part.index("=")] - - # create a new tab frame - new_tabs = TabFrame(self) - self._tab_id_counter += 1 - new_tabs._tabs = AuiTabCtrl(self, self._tab_id_counter) - new_tabs._tabs.SetArtProvider(self._tabs.GetArtProvider().Clone()) - new_tabs.SetTabCtrlHeight(self._tab_ctrl_height) - new_tabs._tabs.SetAGWFlags(self._agwFlags) - dest_tabs = new_tabs._tabs - - # create a pane info structure with the information - # about where the pane should be added - pane_info = framemanager.AuiPaneInfo().Name(pane_name).Bottom().CaptionVisible(False) - self._mgr.AddPane(new_tabs, pane_info) - - # Get list of tab id's and move them to pane - tab_list = tab_part[tab_part.index("=")+1:] - to_break2, active_found = False, False - - while 1: - if "," not in tab_list: - to_break2 = True - tab = tab_list - else: - tab = tab_list[0:tab_list.index(",")] - tab_list = tab_list[tab_list.index(",")+1:] - - # Check if this page has an 'active' marker - c = tab[0] - if c in ['+', '*']: - tab = tab[1:] - - tab_idx = int(tab) - if tab_idx >= self.GetPageCount(): - to_break1 = True - break - - # Move tab to pane - page = self._tabs.GetPage(tab_idx) - newpage_idx = dest_tabs.GetPageCount() - dest_tabs.InsertPage(page.window, page, newpage_idx) - - if c == '+': - dest_tabs.SetActivePage(newpage_idx) - active_found = True - elif c == '*': - sel_page = tab_idx - - if to_break2: - break - - if not active_found: - dest_tabs.SetActivePage(0) - - new_tabs.DoSizing() - dest_tabs.DoShowHide() - dest_tabs.Refresh() - - if to_break1: - break - - tabs = tabs[tabs.index('|')+1:] - - # Load the frame perspective - frames = layout[layout.index('@')+1:] - self._mgr.LoadPerspective(frames) - - # Force refresh of selection - self._curpage = -1 - self.SetSelection(sel_page) - - return True - - - def SetTabCtrlHeight(self, height): - """ - Sets the tab height. - - By default, the tab control height is calculated by measuring the text - height and bitmap sizes on the tab captions. - - Calling this method will override that calculation and set the tab control - to the specified height parameter. A call to this method will override - any call to L{SetUniformBitmapSize}. Specifying -1 as the height will - return the control to its default auto-sizing behaviour. - - :param `height`: the tab control area height. - """ - - self._requested_tabctrl_height = height - - # if window is already initialized, recalculate the tab height - if self._dummy_wnd: - self.UpdateTabCtrlHeight() - - - def SetUniformBitmapSize(self, size): - """ - Ensures that all tabs will have the same height, even if some tabs - don't have bitmaps. Passing ``wx.DefaultSize`` to this - function will instruct the control to use dynamic tab height, which is - the default behaviour. Under the default behaviour, when a tab with a - large bitmap is added, the tab control's height will automatically - increase to accommodate the larger bitmap. - - :param `size`: an instance of `wx.Size` specifying the tab bitmap size. - """ - - self._requested_bmp_size = wx.Size(*size) - - # if window is already initialized, recalculate the tab height - if self._dummy_wnd: - self.UpdateTabCtrlHeight() - - - def UpdateTabCtrlHeight(self, force=False): - """ - UpdateTabCtrlHeight() does the actual tab resizing. It's meant - to be used interally. - - :param `force`: ``True`` to force the tab art to repaint. - """ - - # get the tab ctrl height we will use - height = self.CalculateTabCtrlHeight() - - # if the tab control height needs to change, update - # all of our tab controls with the new height - if self._tab_ctrl_height != height or force: - art = self._tabs.GetArtProvider() - - self._tab_ctrl_height = height - - all_panes = self._mgr.GetAllPanes() - for pane in all_panes: - - if pane.name == "dummy": - continue - - tab_frame = pane.window - tabctrl = tab_frame._tabs - tab_frame.SetTabCtrlHeight(self._tab_ctrl_height) - tabctrl.SetArtProvider(art.Clone()) - tab_frame.DoSizing() - - - def UpdateHintWindowSize(self): - """ Updates the L{AuiManager} hint window size. """ - - size = self.CalculateNewSplitSize() - - # the placeholder hint window should be set to this size - info = self._mgr.GetPane("dummy") - - if info.IsOk(): - info.MinSize(size) - info.BestSize(size) - self._dummy_wnd.SetSize(size) - - - def CalculateNewSplitSize(self): - """ Calculates the size of the new split. """ - - # count number of tab controls - tab_ctrl_count = 0 - all_panes = self._mgr.GetAllPanes() - - for pane in all_panes: - if pane.name == "dummy": - continue - - tab_ctrl_count += 1 - - # if there is only one tab control, the first split - # should happen around the middle - if tab_ctrl_count < 2: - new_split_size = self.GetClientSize() - new_split_size.x /= 2 - new_split_size.y /= 2 - - else: - - # this is in place of a more complicated calculation - # that needs to be implemented - new_split_size = wx.Size(180, 180) - - return new_split_size - - - def CalculateTabCtrlHeight(self): - """ Calculates the tab control area height. """ - - # if a fixed tab ctrl height is specified, - # just return that instead of calculating a - # tab height - if self._requested_tabctrl_height != -1: - return self._requested_tabctrl_height - - # find out new best tab height - art = self._tabs.GetArtProvider() - - return art.GetBestTabCtrlSize(self, self._tabs.GetPages(), self._requested_bmp_size) - - - def GetArtProvider(self): - """ Returns the associated art provider. """ - - return self._tabs.GetArtProvider() - - - def SetAGWWindowStyleFlag(self, agwStyle): - """ - Sets the AGW-specific style of the window. - - :param `agwStyle`: the new window style. This can be a combination of the following bits: - - ==================================== ================================== - Flag name Description - ==================================== ================================== - ``AUI_NB_TOP`` With this style, tabs are drawn along the top of the notebook - ``AUI_NB_LEFT`` With this style, tabs are drawn along the left of the notebook. Not implemented yet. - ``AUI_NB_RIGHT`` With this style, tabs are drawn along the right of the notebook. Not implemented yet. - ``AUI_NB_BOTTOM`` With this style, tabs are drawn along the bottom of the notebook - ``AUI_NB_TAB_SPLIT`` Allows the tab control to be split by dragging a tab - ``AUI_NB_TAB_MOVE`` Allows a tab to be moved horizontally by dragging - ``AUI_NB_TAB_EXTERNAL_MOVE`` Allows a tab to be moved to another tab control - ``AUI_NB_TAB_FIXED_WIDTH`` With this style, all tabs have the same width - ``AUI_NB_SCROLL_BUTTONS`` With this style, left and right scroll buttons are displayed - ``AUI_NB_WINDOWLIST_BUTTON`` With this style, a drop-down list of windows is available - ``AUI_NB_CLOSE_BUTTON`` With this style, a close button is available on the tab bar - ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` With this style, a close button is available on the active tab - ``AUI_NB_CLOSE_ON_ALL_TABS`` With this style, a close button is available on all tabs - ``AUI_NB_MIDDLE_CLICK_CLOSE`` Allows to close L{AuiNotebook} tabs by mouse middle button click - ``AUI_NB_SUB_NOTEBOOK`` This style is used by L{AuiManager} to create automatic AuiNotebooks - ``AUI_NB_HIDE_ON_SINGLE_TAB`` Hides the tab window if only one tab is present - ``AUI_NB_SMART_TABS`` Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows - ``AUI_NB_USE_IMAGES_DROPDOWN`` Uses images on dropdown window list menu instead of check items - ``AUI_NB_CLOSE_ON_TAB_LEFT`` Draws the tab close button on the left instead of on the right (a la Camino browser) - ``AUI_NB_TAB_FLOAT`` Allows the floating of single tabs. Known limitation: when the notebook is more or less full screen, tabs cannot be dragged far enough outside of the notebook to become floating pages - ``AUI_NB_DRAW_DND_TAB`` Draws an image representation of a tab while dragging (on by default) - ``AUI_NB_ORDER_BY_ACCESS`` Tab navigation order by last access time for the tabs - ``AUI_NB_NO_TAB_FOCUS`` Don't draw tab focus rectangle - ==================================== ================================== - - :note: Please note that some styles cannot be changed after the window - creation and that `Refresh` might need to be be called after changing the - others for the change to take place immediately. - - :todo: Implementation of flags ``AUI_NB_RIGHT`` and ``AUI_NB_LEFT``. - """ - - self._agwFlags = agwStyle - - # if the control is already initialized - if self._mgr.GetManagedWindow() == self: - - # let all of the tab children know about the new style - - all_panes = self._mgr.GetAllPanes() - for pane in all_panes: - if pane.name == "dummy": - continue - - tabframe = pane.window - tabctrl = tabframe._tabs - tabctrl.SetAGWFlags(self._agwFlags) - tabframe.DoSizing() - tabctrl.Refresh() - tabctrl.Update() - - - def GetAGWWindowStyleFlag(self): - """ - Returns the AGW-specific style of the window. - - :see: L{SetAGWWindowStyleFlag} for a list of possible AGW-specific window styles. - """ - - return self._agwFlags - - - def AddPage(self, page, caption, select=False, bitmap=wx.NullBitmap, disabled_bitmap=wx.NullBitmap, control=None): - """ - Adds a page. If the `select` parameter is ``True``, calling this will generate a - page change event. - - :param `page`: the page to be added; - :param `caption`: specifies the text for the new page; - :param `select`: specifies whether the page should be selected; - :param `bitmap`: the `wx.Bitmap` to display in the enabled tab; - :param `disabled_bitmap`: the `wx.Bitmap` to display in the disabled tab; - :param `control`: a `wx.Window` instance inside a tab (or ``None``). - """ - - return self.InsertPage(self.GetPageCount(), page, caption, select, bitmap, disabled_bitmap, control) - - - def InsertPage(self, page_idx, page, caption, select=False, bitmap=wx.NullBitmap, disabled_bitmap=wx.NullBitmap, - control=None): - """ - This is similar to L{AddPage}, but allows the ability to specify the insert location. - - :param `page_idx`: specifies the position for the new page; - :param `page`: the page to be added; - :param `caption`: specifies the text for the new page; - :param `select`: specifies whether the page should be selected; - :param `bitmap`: the `wx.Bitmap` to display in the enabled tab; - :param `disabled_bitmap`: the `wx.Bitmap` to display in the disabled tab; - :param `control`: a `wx.Window` instance inside a tab (or ``None``). - """ - - if not page: - return False - - page.Reparent(self) - info = AuiNotebookPage() - info.window = page - info.caption = caption - info.bitmap = bitmap - info.active = False - info.control = control - - originalPaneMgr = framemanager.GetManager(page) - if originalPaneMgr: - originalPane = originalPaneMgr.GetPane(page) - - if originalPane: - info.hasCloseButton = originalPane.HasCloseButton() - - if bitmap.IsOk() and not disabled_bitmap.IsOk(): - disabled_bitmap = MakeDisabledBitmap(bitmap) - info.dis_bitmap = disabled_bitmap - - # if there are currently no tabs, the first added - # tab must be active - if self._tabs.GetPageCount() == 0: - info.active = True - - self._tabs.InsertPage(page, info, page_idx) - - # if that was the first page added, even if - # select is False, it must become the "current page" - # (though no select events will be fired) - if not select and self._tabs.GetPageCount() == 1: - select = True - - active_tabctrl = self.GetActiveTabCtrl() - if page_idx >= active_tabctrl.GetPageCount(): - active_tabctrl.AddPage(page, info) - else: - active_tabctrl.InsertPage(page, info, page_idx) - - force = False - if control: - force = True - control.Reparent(active_tabctrl) - control.Show() - - self.UpdateTabCtrlHeight(force=force) - self.DoSizing() - active_tabctrl.DoShowHide() - - # adjust selected index - if self._curpage >= page_idx: - self._curpage += 1 - - if select: - self.SetSelectionToWindow(page) - - return True - - - def DeletePage(self, page_idx): - """ - Deletes a page at the given index. Calling this method will generate a page - change event. - - :param `page_idx`: the page index to be deleted. - - :note: L{DeletePage} removes a tab from the multi-notebook, and destroys the window as well. - - :see: L{RemovePage} - """ - - if page_idx >= self._tabs.GetPageCount(): - return False - - wnd = self._tabs.GetWindowFromIdx(page_idx) - # hide the window in advance, as this will - # prevent flicker - wnd.Show(False) - - self.RemoveControlFromPage(page_idx) - - if not self.RemovePage(page_idx): - return False - - wnd.Destroy() - - return True - - - def RemovePage(self, page_idx): - """ - Removes a page, without deleting the window pointer. - - :param `page_idx`: the page index to be removed. - - :note: L{RemovePage} removes a tab from the multi-notebook, but does not destroy the window. - - :see: L{DeletePage} - """ - - # save active window pointer - active_wnd = None - if self._curpage >= 0: - active_wnd = self._tabs.GetWindowFromIdx(self._curpage) - - # save pointer of window being deleted - wnd = self._tabs.GetWindowFromIdx(page_idx) - new_active = None - - # make sure we found the page - if not wnd: - return False - - # find out which onscreen tab ctrl owns this tab - ctrl, ctrl_idx = self.FindTab(wnd) - if not ctrl: - return False - - currentPage = ctrl.GetPage(ctrl_idx) - is_curpage = (self._curpage == page_idx) - is_active_in_split = currentPage.active - - # remove the tab from main catalog - if not self._tabs.RemovePage(wnd): - return False - - # remove the tab from the onscreen tab ctrl - ctrl.RemovePage(wnd) - - if is_active_in_split: - - ctrl_new_page_count = ctrl.GetPageCount() - - if ctrl_idx >= ctrl_new_page_count: - ctrl_idx = ctrl_new_page_count - 1 - - if ctrl_idx >= 0 and ctrl_idx < ctrl.GetPageCount(): - - ctrl_idx = self.FindNextActiveTab(ctrl_idx, ctrl) - - # set new page as active in the tab split - ctrl.SetActivePage(ctrl_idx) - - # if the page deleted was the current page for the - # entire tab control, then record the window - # pointer of the new active page for activation - if is_curpage: - new_active = ctrl.GetWindowFromIdx(ctrl_idx) - - else: - - # we are not deleting the active page, so keep it the same - new_active = active_wnd - - if not new_active: - - # we haven't yet found a new page to active, - # so select the next page from the main tab - # catalogue - - if 0 <= page_idx < self._tabs.GetPageCount(): - new_active = self._tabs.GetPage(page_idx).window - if not new_active and self._tabs.GetPageCount() > 0: - new_active = self._tabs.GetPage(0).window - - self.RemoveEmptyTabFrames() - - # set new active pane - if new_active: - if not self.IsBeingDeleted(): - self._curpage = -1 - self.SetSelectionToWindow(new_active) - else: - self._curpage = -1 - self._tabs.SetNoneActive() - - return True - - - def FindNextActiveTab(self, ctrl_idx, ctrl): - """ - Finds the next active tab (used mainly when L{AuiNotebook} has inactive/disabled - tabs in it). - - :param `ctrl_idx`: the index of the first (most obvious) tab to check for active status; - :param `ctrl`: an instance of L{AuiTabCtrl}. - """ - - if self.GetEnabled(ctrl_idx): - return ctrl_idx - - for indx in xrange(ctrl_idx, ctrl.GetPageCount()): - if self.GetEnabled(indx): - return indx - - for indx in xrange(ctrl_idx, -1, -1): - if self.GetEnabled(indx): - return indx - - return 0 - - - def HideAllTabs(self, hidden=True): - """ - Hides all tabs on the L{AuiNotebook} control. - - :param `hidden`: if ``True`` hides all tabs. - """ - - self._hide_tabs = hidden - - - def SetSashDClickUnsplit(self, unsplit=True): - """ - Sets whether to unsplit a splitted L{AuiNotebook} when double-clicking on a sash. - - :param `unsplit`: ``True`` to unsplit on sash double-clicking, ``False`` otherwise. - """ - - self._sash_dclick_unsplit = unsplit - - - def GetSashDClickUnsplit(self): - """ - Returns whether a splitted L{AuiNotebook} can be unsplitted by double-clicking - on the splitter sash. - """ - - return self._sash_dclick_unsplit - - - def SetMinMaxTabWidth(self, minTabWidth, maxTabWidth): - """ - Sets the minimum and/or the maximum tab widths for L{AuiNotebook} when the - ``AUI_NB_TAB_FIXED_WIDTH`` style is defined. - - Pass -1 to either `minTabWidth` or `maxTabWidth` to reset to the default tab - width behaviour for L{AuiNotebook}. - - :param `minTabWidth`: the minimum allowed tab width, in pixels; - :param `maxTabWidth`: the maximum allowed tab width, in pixels. - - :note: Minimum and maximum tabs widths are used only when the ``AUI_NB_TAB_FIXED_WIDTH`` - style is present. - """ - - if minTabWidth > maxTabWidth: - raise Exception("Minimum tab width must be less or equal than maximum tab width") - - self._tabBounds = (minTabWidth, maxTabWidth) - self.SetAGWWindowStyleFlag(self._agwFlags) - - - def GetMinMaxTabWidth(self): - """ - Returns the minimum and the maximum tab widths for L{AuiNotebook} when the - ``AUI_NB_TAB_FIXED_WIDTH`` style is defined. - - :note: Minimum and maximum tabs widths are used only when the ``AUI_NB_TAB_FIXED_WIDTH`` - style is present. - - :see: L{SetMinMaxTabWidth} for more information. - """ - - return self._tabBounds - - - def GetPageIndex(self, page_wnd): - """ - Returns the page index for the specified window. If the window is not - found in the notebook, ``wx.NOT_FOUND`` is returned. - """ - - return self._tabs.GetIdxFromWindow(page_wnd) - - - def SetPageText(self, page_idx, text): - """ - Sets the tab label for the page. - - :param `page_idx`: the page index; - :param `text`: the new tab label. - """ - - if page_idx >= self._tabs.GetPageCount(): - return False - - # update our own tab catalog - page_info = self._tabs.GetPage(page_idx) - should_refresh = page_info.caption != text - page_info.caption = text - - # update what's on screen - ctrl, ctrl_idx = self.FindTab(page_info.window) - if not ctrl: - return False - - info = ctrl.GetPage(ctrl_idx) - should_refresh = should_refresh or info.caption != text - info.caption = text - - if should_refresh: - ctrl.Refresh() - ctrl.Update() - - self.UpdateTabCtrlHeight(force=True) - - return True - - - def GetPageText(self, page_idx): - """ - Returns the tab label for the page. - - :param `page_idx`: the page index. - """ - - if page_idx >= self._tabs.GetPageCount(): - return "" - - # update our own tab catalog - page_info = self._tabs.GetPage(page_idx) - return page_info.caption - - - def SetPageBitmap(self, page_idx, bitmap): - """ - Sets the tab bitmap for the page. - - :param `page_idx`: the page index; - :param `bitmap`: an instance of `wx.Bitmap`. - """ - - if page_idx >= self._tabs.GetPageCount(): - return False - - # update our own tab catalog - page_info = self._tabs.GetPage(page_idx) - should_refresh = page_info.bitmap is not bitmap - page_info.bitmap = bitmap - if bitmap.IsOk() and not page_info.dis_bitmap.IsOk(): - page_info.dis_bitmap = MakeDisabledBitmap(bitmap) - - # tab height might have changed - self.UpdateTabCtrlHeight() - - # update what's on screen - ctrl, ctrl_idx = self.FindTab(page_info.window) - if not ctrl: - return False - - info = ctrl.GetPage(ctrl_idx) - should_refresh = should_refresh or info.bitmap is not bitmap - info.bitmap = bitmap - info.dis_bitmap = page_info.dis_bitmap - if should_refresh: - ctrl.Refresh() - ctrl.Update() - - return True - - - def GetPageBitmap(self, page_idx): - """ - Returns the tab bitmap for the page. - - :param `page_idx`: the page index. - """ - - if page_idx >= self._tabs.GetPageCount(): - return wx.NullBitmap - - # update our own tab catalog - page_info = self._tabs.GetPage(page_idx) - return page_info.bitmap - - - def SetImageList(self, imageList): - """ - Sets the image list for the L{AuiNotebook} control. - - :param `imageList`: an instance of `wx.ImageList`. - """ - - self._imageList = imageList - - - def AssignImageList(self, imageList): - """ - Sets the image list for the L{AuiNotebook} control. - - :param `imageList`: an instance of `wx.ImageList`. - """ - - self.SetImageList(imageList) - - - def GetImageList(self): - """ Returns the associated image list (if any). """ - - return self._imageList - - - def SetPageImage(self, page, image): - """ - Sets the image index for the given page. - - :param `page`: the page index; - :param `image`: an index into the image list which was set with L{SetImageList}. - """ - - if page >= self._tabs.GetPageCount(): - return False - - if not isinstance(image, types.IntType): - raise Exception("The image parameter must be an integer, you passed " \ - "%s"%repr(image)) - - if not self._imageList: - raise Exception("To use SetPageImage you need to associate an image list " \ - "Using SetImageList or AssignImageList") - - if image >= self._imageList.GetImageCount(): - raise Exception("Invalid image index (%d), the image list contains only" \ - " (%d) bitmaps"%(image, self._imageList.GetImageCount())) - - if image == -1: - self.SetPageBitmap(page, wx.NullBitmap) - return - - bitmap = self._imageList.GetBitmap(image) - self.SetPageBitmap(page, bitmap) - - - def GetPageImage(self, page): - """ - Returns the image index for the given page. - - :param `page`: the given page for which to retrieve the image index. - """ - - if page >= self._tabs.GetPageCount(): - return False - - bitmap = self.GetPageBitmap(page) - for indx in xrange(self._imageList.GetImageCount()): - imgListBmp = self._imageList.GetBitmap(indx) - if imgListBmp == bitmap: - return indx - - return wx.NOT_FOUND - - - def SetPageTextColour(self, page_idx, colour): - """ - Sets the tab text colour for the page. - - :param `page_idx`: the page index; - :param `colour`: an instance of `wx.Colour`. - """ - - if page_idx >= self._tabs.GetPageCount(): - return False - - # update our own tab catalog - page_info = self._tabs.GetPage(page_idx) - should_refresh = page_info.text_colour != colour - page_info.text_colour = colour - - # update what's on screen - ctrl, ctrl_idx = self.FindTab(page_info.window) - if not ctrl: - return False - - info = ctrl.GetPage(ctrl_idx) - should_refresh = should_refresh or info.text_colour != colour - info.text_colour = page_info.text_colour - - if should_refresh: - ctrl.Refresh() - ctrl.Update() - - return True - - - def GetPageTextColour(self, page_idx): - """ - Returns the tab text colour for the page. - - :param `page_idx`: the page index. - """ - - if page_idx >= self._tabs.GetPageCount(): - return wx.NullColour - - # update our own tab catalog - page_info = self._tabs.GetPage(page_idx) - return page_info.text_colour - - - def AddControlToPage(self, page_idx, control): - """ - Adds a control inside a tab (not in the tab area). - - :param `page_idx`: the page index; - :param `control`: an instance of `wx.Window`. - """ - - if page_idx >= self._tabs.GetPageCount(): - return False - - # update our own tab catalog - page_info = self._tabs.GetPage(page_idx) - page_info.control = control - - # tab height might have changed - self.UpdateTabCtrlHeight(force=True) - - # update what's on screen - ctrl, ctrl_idx = self.FindTab(page_info.window) - if not ctrl: - return False - - control.Reparent(ctrl) - - info = ctrl.GetPage(ctrl_idx) - info.control = control - ctrl.Refresh() - ctrl.Update() - - return True - - - def RemoveControlFromPage(self, page_idx): - """ - Removes a control from a tab (not from the tab area). - - :param `page_idx`: the page index. - """ - - if page_idx >= self._tabs.GetPageCount(): - return False - - page_info = self._tabs.GetPage(page_idx) - if page_info.control is None: - return False - - page_info.control.Destroy() - page_info.control = None - - # tab height might have changed - self.UpdateTabCtrlHeight(force=True) - - # update what's on screen - ctrl, ctrl_idx = self.FindTab(page_info.window) - if not ctrl: - return False - - info = ctrl.GetPage(ctrl_idx) - info.control = None - ctrl.Refresh() - ctrl.Update() - - return True - - - def SetCloseButton(self, page_idx, hasCloseButton): - """ - Sets whether a tab should display a close button or not. - - :param `page_idx`: the page index; - :param `hasCloseButton`: ``True`` if the page displays a close button. - - :note: This can only be called if ``AUI_NB_CLOSE_ON_ALL_TABS`` is specified. - """ - - if page_idx >= self._tabs.GetPageCount(): - return False - - if self._agwFlags & AUI_NB_CLOSE_ON_ALL_TABS == 0: - raise Exception("SetCloseButton can only be used with AUI_NB_CLOSE_ON_ALL_TABS style.") - - # update our own tab catalog - page_info = self._tabs.GetPage(page_idx) - page_info.hasCloseButton = hasCloseButton - - # update what's on screen - ctrl, ctrl_idx = self.FindTab(page_info.window) - if not ctrl: - return False - - info = ctrl.GetPage(ctrl_idx) - info.hasCloseButton = page_info.hasCloseButton - ctrl.Refresh() - ctrl.Update() - - return True - - - def HasCloseButton(self, page_idx): - """ - Returns whether a tab displays a close button or not. - - :param `page_idx`: the page index. - - :note: This can only be called if ``AUI_NB_CLOSE_ON_ALL_TABS`` is specified. - """ - - if page_idx >= self._tabs.GetPageCount(): - return False - - page_info = self._tabs.GetPage(page_idx) - return page_info.hasCloseButton - - - def GetSelection(self): - """ Returns the index of the currently active page, or -1 if none was selected. """ - - return self._curpage - - - def GetCurrentPage(self): - """ Returns the currently active page (not the index), or ``None`` if none was selected. """ - - if self._curpage >= 0 and self._curpage < self._tabs.GetPageCount(): - return self.GetPage(self._curpage) - - return None - - - def EnsureVisible(self, indx): - """ - Ensures the input page index `indx` is visible. - - :param `indx`: the page index. - """ - - self._tabs.MakeTabVisible(indx, self) - - - def SetSelection(self, new_page, force=False): - """ - Sets the page selection. Calling this method will generate a page change event. - - :param `new_page`: the index of the new selection; - :param `force`: whether to force the selection or not. - """ - wnd = self._tabs.GetWindowFromIdx(new_page) - - #Update page access time - self._tabs.GetPages()[new_page].access_time = datetime.datetime.now() - - if not wnd or not self.GetEnabled(new_page): - return self._curpage - - # don't change the page unless necessary - # however, clicking again on a tab should give it the focus. - if new_page == self._curpage and not force: - - ctrl, ctrl_idx = self.FindTab(wnd) - if wx.Window.FindFocus() != ctrl: - ctrl.SetFocus() - - return self._curpage - - evt = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, self.GetId()) - evt.SetSelection(new_page) - evt.SetOldSelection(self._curpage) - evt.SetEventObject(self) - - if not self.GetEventHandler().ProcessEvent(evt) or evt.IsAllowed(): - - old_curpage = self._curpage - self._curpage = new_page - - # program allows the page change - evt.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED) - self.GetEventHandler().ProcessEvent(evt) - - if not evt.IsAllowed(): # event is no longer allowed after handler - return self._curpage - - ctrl, ctrl_idx = self.FindTab(wnd) - - if ctrl: - self._tabs.SetActivePage(wnd) - ctrl.SetActivePage(ctrl_idx) - self.DoSizing() - ctrl.DoShowHide() - ctrl.MakeTabVisible(ctrl_idx, ctrl) - - # set fonts - all_panes = self._mgr.GetAllPanes() - for pane in all_panes: - if pane.name == "dummy": - continue - - tabctrl = pane.window._tabs - if tabctrl != ctrl: - tabctrl.SetSelectedFont(self._normal_font) - else: - tabctrl.SetSelectedFont(self._selected_font) - - tabctrl.Refresh() - tabctrl.Update() - - # Set the focus to the page if we're not currently focused on the tab. - # This is Firefox-like behaviour. - if wnd.IsShownOnScreen() and wx.Window.FindFocus() != ctrl: - wnd.SetFocus() - - return old_curpage - - return self._curpage - - - def SetSelectionToWindow(self, win): - """ - Sets the selection based on the input window `win`. - - :param `win`: a `wx.Window` derived window. - """ - - idx = self._tabs.GetIdxFromWindow(win) - - if idx == wx.NOT_FOUND: - raise Exception("invalid notebook page") - - if not self.GetEnabled(idx): - return - - # since a tab was clicked, let the parent know that we received - # the focus, even if we will assign that focus immediately - # to the child tab in the SetSelection call below - # (the child focus event will also let AuiManager, if any, - # know that the notebook control has been activated) - - parent = self.GetParent() - if parent: - eventFocus = wx.ChildFocusEvent(self) - parent.GetEventHandler().ProcessEvent(eventFocus) - - self.SetSelection(idx) - - - def SetSelectionToPage(self, page): - """ - Sets the selection based on the input page. - - :param `page`: an instance of L{AuiNotebookPage}. - """ - - self.SetSelectionToWindow(page.window) - - - def GetPageCount(self): - """ Returns the number of pages in the notebook. """ - - return self._tabs.GetPageCount() - - - def GetPage(self, page_idx): - """ - Returns the page specified by the given index. - - :param `page_idx`: the page index. - """ - - if page_idx >= self._tabs.GetPageCount(): - raise Exception("invalid notebook page") - - return self._tabs.GetWindowFromIdx(page_idx) - - - def GetPageInfo(self, page_idx): - """ - Returns the L{AuiNotebookPage} info structure specified by the given index. - - :param `page_idx`: the page index. - """ - - if page_idx >= self._tabs.GetPageCount(): - raise Exception("invalid notebook page") - - return self._tabs.GetPage(page_idx) - - - def GetEnabled(self, page_idx): - """ - Returns whether the page specified by the index `page_idx` is enabled. - - :param `page_idx`: the page index. - """ - - return self._tabs.GetEnabled(page_idx) - - - def EnableTab(self, page_idx, enable=True): - """ - Enables/disables a page in the notebook. - - :param `page_idx`: the page index; - :param `enable`: ``True`` to enable the page, ``False`` to disable it. - """ - - self._tabs.EnableTab(page_idx, enable) - self.Refresh() - - - def DoSizing(self): - """ Performs all sizing operations in each tab control. """ - - all_panes = self._mgr.GetAllPanes() - for pane in all_panes: - if pane.name == "dummy": - continue - - tabframe = pane.window - tabframe.DoSizing() - - - def GetAuiManager(self): - """ Returns the associated L{AuiManager}. """ - - return self._mgr - - - def GetActiveTabCtrl(self): - """ - Returns the active tab control. It is called to determine which control - gets new windows being added. - """ - - if self._curpage >= 0 and self._curpage < self._tabs.GetPageCount(): - - # find the tab ctrl with the current page - ctrl, idx = self.FindTab(self._tabs.GetPage(self._curpage).window) - if ctrl: - return ctrl - - # no current page, just find the first tab ctrl - all_panes = self._mgr.GetAllPanes() - for pane in all_panes: - if pane.name == "dummy": - continue - - tabframe = pane.window - return tabframe._tabs - - # If there is no tabframe at all, create one - tabframe = TabFrame(self) - tabframe.SetTabCtrlHeight(self._tab_ctrl_height) - self._tab_id_counter += 1 - tabframe._tabs = AuiTabCtrl(self, self._tab_id_counter) - - tabframe._tabs.SetAGWFlags(self._agwFlags) - tabframe._tabs.SetArtProvider(self._tabs.GetArtProvider().Clone()) - self._mgr.AddPane(tabframe, framemanager.AuiPaneInfo().Center().CaptionVisible(False). - PaneBorder((self._agwFlags & AUI_NB_SUB_NOTEBOOK) == 0)) - - self._mgr.Update() - - return tabframe._tabs - - - def FindTab(self, page): - """ - Finds the tab control that currently contains the window as well - as the index of the window in the tab control. It returns ``True`` if the - window was found, otherwise ``False``. - - :param `page`: an instance of L{AuiNotebookPage}. - """ - - all_panes = self._mgr.GetAllPanes() - for pane in all_panes: - if pane.name == "dummy": - continue - - tabframe = pane.window - - page_idx = tabframe._tabs.GetIdxFromWindow(page) - - if page_idx != -1: - - ctrl = tabframe._tabs - idx = page_idx - return ctrl, idx - - return None, wx.NOT_FOUND - - - def Split(self, page, direction): - """ - Performs a split operation programmatically. - - :param `page`: indicates the page that will be split off. This page will also become - the active page after the split. - :param `direction`: specifies where the pane should go, it should be one of the - following: ``wx.TOP``, ``wx.BOTTOM``, ``wx.LEFT``, or ``wx.RIGHT``. - """ - - cli_size = self.GetClientSize() - - # get the page's window pointer - wnd = self.GetPage(page) - if not wnd: - return - - # notebooks with 1 or less pages can't be split - if self.GetPageCount() < 2: - return - - # find out which tab control the page currently belongs to - - src_tabs, src_idx = self.FindTab(wnd) - if not src_tabs: - return - - # choose a split size - if self.GetPageCount() > 2: - split_size = self.CalculateNewSplitSize() - else: - # because there are two panes, always split them - # equally - split_size = self.GetClientSize() - split_size.x /= 2 - split_size.y /= 2 - - # create a new tab frame - new_tabs = TabFrame(self) - new_tabs._rect = wx.RectPS(wx.Point(0, 0), split_size) - new_tabs.SetTabCtrlHeight(self._tab_ctrl_height) - self._tab_id_counter += 1 - new_tabs._tabs = AuiTabCtrl(self, self._tab_id_counter) - - new_tabs._tabs.SetArtProvider(self._tabs.GetArtProvider().Clone()) - new_tabs._tabs.SetAGWFlags(self._agwFlags) - dest_tabs = new_tabs._tabs - - page_info = src_tabs.GetPage(src_idx) - if page_info.control: - self.ReparentControl(page_info.control, dest_tabs) - - # create a pane info structure with the information - # about where the pane should be added - pane_info = framemanager.AuiPaneInfo().Bottom().CaptionVisible(False) - - if direction == wx.LEFT: - - pane_info.Left() - mouse_pt = wx.Point(0, cli_size.y/2) - - elif direction == wx.RIGHT: - - pane_info.Right() - mouse_pt = wx.Point(cli_size.x, cli_size.y/2) - - elif direction == wx.TOP: - - pane_info.Top() - mouse_pt = wx.Point(cli_size.x/2, 0) - - elif direction == wx.BOTTOM: - - pane_info.Bottom() - mouse_pt = wx.Point(cli_size.x/2, cli_size.y) - - self._mgr.AddPane(new_tabs, pane_info, mouse_pt) - self._mgr.Update() - - # remove the page from the source tabs - page_info.active = False - - src_tabs.RemovePage(page_info.window) - - if src_tabs.GetPageCount() > 0: - src_tabs.SetActivePage(0) - src_tabs.DoShowHide() - src_tabs.Refresh() - - # add the page to the destination tabs - dest_tabs.InsertPage(page_info.window, page_info, 0) - - if src_tabs.GetPageCount() == 0: - self.RemoveEmptyTabFrames() - - self.DoSizing() - dest_tabs.DoShowHide() - dest_tabs.Refresh() - - # force the set selection function reset the selection - self._curpage = -1 - - # set the active page to the one we just split off - self.SetSelectionToPage(page_info) - - self.UpdateHintWindowSize() - - - def UnSplit(self): - """ Restores original view after a tab split. """ - - self.Freeze() - - # remember the tab now selected - nowSelected = self.GetSelection() - # select first tab as destination - self.SetSelection(0) - # iterate all other tabs - for idx in xrange(1, self.GetPageCount()): - # get win reference - win = self.GetPage(idx) - # get tab title - title = self.GetPageText(idx) - # get page bitmap - bmp = self.GetPageBitmap(idx) - # remove from notebook - self.RemovePage(idx) - # re-add in the same position so it will tab - self.InsertPage(idx, win, title, False, bmp) - # restore orignial selected tab - self.SetSelection(nowSelected) - - self.Thaw() - - - def ReparentControl(self, control, dest_tabs): - """ - Reparents a control added inside a tab. - - :param `control`: an instance of `wx.Window`; - :param `dest_tabs`: the destination L{AuiTabCtrl}. - """ - - control.Hide() - control.Reparent(dest_tabs) - - - def UnsplitDClick(self, part, sash_size, pos): - """ - Unsplit the L{AuiNotebook} on sash double-click. - - :param `part`: an UI part representing the sash; - :param `sash_size`: the sash size; - :param `pos`: the double-click mouse position. - - :warning: Due to a bug on MSW, for disabled pages `wx.FindWindowAtPoint` - returns the wrong window. See http://trac.wxwidgets.org/ticket/2942 - """ - - if not self._sash_dclick_unsplit: - # Unsplit not allowed - return - - pos1 = wx.Point(*pos) - pos2 = wx.Point(*pos) - if part.orientation == wx.HORIZONTAL: - pos1.y -= 2*sash_size - pos2.y += 2*sash_size + self.GetTabCtrlHeight() - elif part.orientation == wx.VERTICAL: - pos1.x -= 2*sash_size - pos2.x += 2*sash_size - else: - raise Exception("Invalid UI part orientation") - - pos1, pos2 = self.ClientToScreen(pos1), self.ClientToScreen(pos2) - win1, win2 = wx.FindWindowAtPoint(pos1), wx.FindWindowAtPoint(pos2) - - if isinstance(win1, wx.ScrollBar): - # Hopefully it will work - pos1 = wx.Point(*pos) - shift = wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X) + 2*(sash_size+1) - if part.orientation == wx.HORIZONTAL: - pos1.y -= shift - else: - pos1.x -= shift - - pos1 = self.ClientToScreen(pos1) - win1 = wx.FindWindowAtPoint(pos1) - - if isinstance(win2, wx.ScrollBar): - pos2 = wx.Point(*pos) - shift = wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X) + 2*(sash_size+1) - if part.orientation == wx.HORIZONTAL: - pos2.y += shift - else: - pos2.x += shift - - pos2 = self.ClientToScreen(pos2) - win2 = wx.FindWindowAtPoint(pos2) - - if not win1 or not win2: - # How did we get here? - return - - if isinstance(win1, AuiNotebook) or isinstance(win2, AuiNotebook): - # This is a bug on MSW, for disabled pages wx.FindWindowAtPoint - # returns the wrong window. - # See http://trac.wxwidgets.org/ticket/2942 - return - - tab_frame1, tab_frame2 = self.GetTabFrameFromWindow(win1), self.GetTabFrameFromWindow(win2) - - if not tab_frame1 or not tab_frame2: - return - - tab_ctrl_1, tab_ctrl_2 = tab_frame1._tabs, tab_frame2._tabs - - if tab_ctrl_1.GetPageCount() > tab_ctrl_2.GetPageCount(): - src_tabs = tab_ctrl_2 - dest_tabs = tab_ctrl_1 - else: - src_tabs = tab_ctrl_1 - dest_tabs = tab_ctrl_2 - - selection = -1 - page_count = dest_tabs.GetPageCount() - - for page in xrange(src_tabs.GetPageCount()-1, -1, -1): - # remove the page from the source tabs - page_info = src_tabs.GetPage(page) - if page_info.active: - selection = page_count + page - src_tabs.RemovePage(page_info.window) - - # add the page to the destination tabs - dest_tabs.AddPage(page_info.window, page_info) - if page_info.control: - self.ReparentControl(page_info.control, dest_tabs) - - self.RemoveEmptyTabFrames() - - dest_tabs.DoShowHide() - self.DoSizing() - dest_tabs.Refresh() - self._mgr.Update() - if selection > 0: - wx.CallAfter(dest_tabs.MakeTabVisible, selection, self) - - - def OnSize(self, event): - """ - Handles the ``wx.EVT_SIZE`` event for L{AuiNotebook}. - - :param `event`: a `wx.SizeEvent` event to be processed. - """ - - self.UpdateHintWindowSize() - event.Skip() - - - def OnTabClicked(self, event): - """ - Handles the ``EVT_AUINOTEBOOK_PAGE_CHANGING`` event for L{AuiNotebook}. - - :param `event`: a L{AuiNotebookEvent} event to be processed. - """ - - if self._textCtrl is not None: - self._textCtrl.StopEditing() - - ctrl = event.GetEventObject() - assert ctrl != None - - wnd = ctrl.GetWindowFromIdx(event.GetSelection()) - assert wnd != None - - self.SetSelectionToWindow(wnd) - - - def OnTabBgDClick(self, event): - """ - Handles the ``EVT_AUINOTEBOOK_BG_DCLICK`` event for L{AuiNotebook}. - - :param `event`: a L{AuiNotebookEvent} event to be processed. - """ - - if self._textCtrl is not None: - self._textCtrl.StopEditing() - - # notify owner that the tabbar background has been double-clicked - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, self.GetId()) - e.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e) - - - def OnTabDClick(self, event): - """ - Handles the ``EVT_AUINOTEBOOK_TAB_DCLICK`` event for L{AuiNotebook}. - - :param `event`: a L{AuiNotebookEvent} event to be processed. - """ - - # notify owner that the tabbar background has been double-clicked - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_DCLICK, self.GetId()) - e.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e) - - tabs = event.GetEventObject() - if not tabs.GetEnabled(event.GetSelection()): - return - - if not self.IsRenamable(event.GetSelection()): - return - - self.EditTab(event.GetSelection()) - - - def OnTabBeginDrag(self, event): - """ - Handles the ``EVT_AUINOTEBOOK_BEGIN_DRAG`` event for L{AuiNotebook}. - - :param `event`: a L{AuiNotebookEvent} event to be processed. - """ - - tabs = event.GetEventObject() - if not tabs.GetEnabled(event.GetSelection()): - return - - self._last_drag_x = 0 - - - def OnTabDragMotion(self, event): - """ - Handles the ``EVT_AUINOTEBOOK_DRAG_MOTION`` event for L{AuiNotebook}. - - :param `event`: a L{AuiNotebookEvent} event to be processed. - """ - - tabs = event.GetEventObject() - if not tabs.GetEnabled(event.GetSelection()): - return - - if self._textCtrl is not None: - self._textCtrl.StopEditing() - - screen_pt = wx.GetMousePosition() - client_pt = self.ScreenToClient(screen_pt) - zero = wx.Point(0, 0) - - src_tabs = event.GetEventObject() - dest_tabs = self.GetTabCtrlFromPoint(client_pt) - - if dest_tabs == src_tabs: - - # always hide the hint for inner-tabctrl drag - self._mgr.HideHint() - - # if tab moving is not allowed, leave - if not self._agwFlags & AUI_NB_TAB_MOVE: - return - - pt = dest_tabs.ScreenToClient(screen_pt) - - # this is an inner-tab drag/reposition - dest_location_tab = dest_tabs.TabHitTest(pt.x, pt.y) - - if dest_location_tab: - - src_idx = event.GetSelection() - dest_idx = dest_tabs.GetIdxFromWindow(dest_location_tab) - - # prevent jumpy drag - if (src_idx == dest_idx) or dest_idx == -1 or \ - (src_idx > dest_idx and self._last_drag_x <= pt.x) or \ - (src_idx < dest_idx and self._last_drag_x >= pt.x): - - self._last_drag_x = pt.x - return - - src_tab = dest_tabs.GetWindowFromIdx(src_idx) - dest_tabs.MovePage(src_tab, dest_idx) - self._tabs.MovePage(self._tabs.GetPage(src_idx).window, dest_idx) - dest_tabs.SetActivePage(dest_idx) - dest_tabs.DoShowHide() - dest_tabs.Refresh() - self._last_drag_x = pt.x - - return - - # if external drag is allowed, check if the tab is being dragged - # over a different AuiNotebook control - if self._agwFlags & AUI_NB_TAB_EXTERNAL_MOVE: - - tab_ctrl = wx.FindWindowAtPoint(screen_pt) - - # if we aren't over any window, stop here - if not tab_ctrl: - if self._agwFlags & AUI_NB_TAB_FLOAT: - if self.IsMouseWellOutsideWindow(): - hintRect = wx.RectPS(screen_pt, (400, 300)) - # Use CallAfter so we overwrite the hint that might be - # shown by our superclass: - wx.CallAfter(self._mgr.ShowHint, hintRect) - return - - # make sure we are not over the hint window - if not isinstance(tab_ctrl, wx.Frame): - while tab_ctrl: - if isinstance(tab_ctrl, AuiTabCtrl): - break - - tab_ctrl = tab_ctrl.GetParent() - - if tab_ctrl: - nb = tab_ctrl.GetParent() - - if nb != self: - - hint_rect = tab_ctrl.GetClientRect() - hint_rect.x, hint_rect.y = tab_ctrl.ClientToScreenXY(hint_rect.x, hint_rect.y) - self._mgr.ShowHint(hint_rect) - return - - else: - - if not dest_tabs: - # we are either over a hint window, or not over a tab - # window, and there is no where to drag to, so exit - return - - if self._agwFlags & AUI_NB_TAB_FLOAT: - if self.IsMouseWellOutsideWindow(): - hintRect = wx.RectPS(screen_pt, (400, 300)) - # Use CallAfter so we overwrite the hint that might be - # shown by our superclass: - wx.CallAfter(self._mgr.ShowHint, hintRect) - return - - # if there are less than two panes, split can't happen, so leave - if self._tabs.GetPageCount() < 2: - return - - # if tab moving is not allowed, leave - if not self._agwFlags & AUI_NB_TAB_SPLIT: - return - - if dest_tabs: - - hint_rect = dest_tabs.GetRect() - hint_rect.x, hint_rect.y = self.ClientToScreenXY(hint_rect.x, hint_rect.y) - self._mgr.ShowHint(hint_rect) - - else: - rect = self._mgr.CalculateHintRect(self._dummy_wnd, client_pt, zero) - if rect.IsEmpty(): - self._mgr.HideHint() - return - - hit_wnd = wx.FindWindowAtPoint(screen_pt) - if hit_wnd and not isinstance(hit_wnd, AuiNotebook): - tab_frame = self.GetTabFrameFromWindow(hit_wnd) - if tab_frame: - hint_rect = wx.Rect(*tab_frame._rect) - hint_rect.x, hint_rect.y = self.ClientToScreenXY(hint_rect.x, hint_rect.y) - rect.Intersect(hint_rect) - self._mgr.ShowHint(rect) - else: - self._mgr.DrawHintRect(self._dummy_wnd, client_pt, zero) - else: - self._mgr.DrawHintRect(self._dummy_wnd, client_pt, zero) - - - def OnTabEndDrag(self, event): - """ - Handles the ``EVT_AUINOTEBOOK_END_DRAG`` event for L{AuiNotebook}. - - :param `event`: a L{AuiNotebookEvent} event to be processed. - """ - - tabs = event.GetEventObject() - if not tabs.GetEnabled(event.GetSelection()): - return - - self._mgr.HideHint() - - src_tabs = event.GetEventObject() - if not src_tabs: - raise Exception("no source object?") - - # get the mouse position, which will be used to determine the drop point - mouse_screen_pt = wx.GetMousePosition() - mouse_client_pt = self.ScreenToClient(mouse_screen_pt) - - # check for an external move - if self._agwFlags & AUI_NB_TAB_EXTERNAL_MOVE: - tab_ctrl = wx.FindWindowAtPoint(mouse_screen_pt) - - while tab_ctrl: - - if isinstance(tab_ctrl, AuiTabCtrl): - break - - tab_ctrl = tab_ctrl.GetParent() - - if tab_ctrl: - - nb = tab_ctrl.GetParent() - - if nb != self: - - # find out from the destination control - # if it's ok to drop this tab here - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, self.GetId()) - e.SetSelection(event.GetSelection()) - e.SetOldSelection(event.GetSelection()) - e.SetEventObject(self) - e.SetDragSource(self) - e.Veto() # dropping must be explicitly approved by control owner - - nb.GetEventHandler().ProcessEvent(e) - - if not e.IsAllowed(): - - # no answer or negative answer - self._mgr.HideHint() - return - - # drop was allowed - src_idx = event.GetSelection() - src_page = src_tabs.GetWindowFromIdx(src_idx) - - # Check that it's not an impossible parent relationship - p = nb - while p and not p.IsTopLevel(): - if p == src_page: - return - - p = p.GetParent() - - # get main index of the page - main_idx = self._tabs.GetIdxFromWindow(src_page) - if main_idx == wx.NOT_FOUND: - raise Exception("no source page?") - - # make a copy of the page info - page_info = self._tabs.GetPage(main_idx) - - # remove the page from the source notebook - self.RemovePage(main_idx) - - # reparent the page - src_page.Reparent(nb) - - # Reparent the control in a tab (if any) - if page_info.control: - self.ReparentControl(page_info.control, tab_ctrl) - - # find out the insert idx - dest_tabs = tab_ctrl - pt = dest_tabs.ScreenToClient(mouse_screen_pt) - - target = dest_tabs.TabHitTest(pt.x, pt.y) - insert_idx = -1 - if target: - insert_idx = dest_tabs.GetIdxFromWindow(target) - - # add the page to the new notebook - if insert_idx == -1: - insert_idx = dest_tabs.GetPageCount() - - dest_tabs.InsertPage(page_info.window, page_info, insert_idx) - nb._tabs.AddPage(page_info.window, page_info) - - nb.DoSizing() - dest_tabs.DoShowHide() - dest_tabs.Refresh() - - # set the selection in the destination tab control - nb.SetSelectionToPage(page_info) - - # notify owner that the tab has been dragged - e2 = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, self.GetId()) - e2.SetSelection(event.GetSelection()) - e2.SetOldSelection(event.GetSelection()) - e2.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e2) - - # notify the target notebook that the tab has been dragged - e3 = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, nb.GetId()) - e3.SetSelection(insert_idx) - e3.SetOldSelection(insert_idx) - e3.SetEventObject(nb) - nb.GetEventHandler().ProcessEvent(e3) - - return - - if self._agwFlags & AUI_NB_TAB_FLOAT: - self._mgr.HideHint() - if self.IsMouseWellOutsideWindow(): - # Use CallAfter so we our superclass can deal with the event first - wx.CallAfter(self.FloatPage, self.GetSelection()) - event.Skip() - return - - # only perform a tab split if it's allowed - dest_tabs = None - - if self._agwFlags & AUI_NB_TAB_SPLIT and self._tabs.GetPageCount() >= 2: - - # If the pointer is in an existing tab frame, do a tab insert - hit_wnd = wx.FindWindowAtPoint(mouse_screen_pt) - tab_frame = self.GetTabFrameFromTabCtrl(hit_wnd) - insert_idx = -1 - - if tab_frame: - - dest_tabs = tab_frame._tabs - - if dest_tabs == src_tabs: - return - - pt = dest_tabs.ScreenToClient(mouse_screen_pt) - target = dest_tabs.TabHitTest(pt.x, pt.y) - - if target: - insert_idx = dest_tabs.GetIdxFromWindow(target) - - else: - - zero = wx.Point(0, 0) - rect = self._mgr.CalculateHintRect(self._dummy_wnd, mouse_client_pt, zero) - - if rect.IsEmpty(): - # there is no suitable drop location here, exit out - return - - # If there is no tabframe at all, create one - new_tabs = TabFrame(self) - new_tabs._rect = wx.RectPS(wx.Point(0, 0), self.CalculateNewSplitSize()) - new_tabs.SetTabCtrlHeight(self._tab_ctrl_height) - self._tab_id_counter += 1 - new_tabs._tabs = AuiTabCtrl(self, self._tab_id_counter) - new_tabs._tabs.SetArtProvider(self._tabs.GetArtProvider().Clone()) - new_tabs._tabs.SetAGWFlags(self._agwFlags) - - self._mgr.AddPane(new_tabs, framemanager.AuiPaneInfo().Bottom().CaptionVisible(False), mouse_client_pt) - self._mgr.Update() - dest_tabs = new_tabs._tabs - - # remove the page from the source tabs - page_info = src_tabs.GetPage(event.GetSelection()) - - if page_info.control: - self.ReparentControl(page_info.control, dest_tabs) - - page_info.active = False - src_tabs.RemovePage(page_info.window) - - if src_tabs.GetPageCount() > 0: - src_tabs.SetActivePage(0) - src_tabs.DoShowHide() - src_tabs.Refresh() - - # add the page to the destination tabs - if insert_idx == -1: - insert_idx = dest_tabs.GetPageCount() - - dest_tabs.InsertPage(page_info.window, page_info, insert_idx) - - if src_tabs.GetPageCount() == 0: - self.RemoveEmptyTabFrames() - - self.DoSizing() - dest_tabs.DoShowHide() - dest_tabs.Refresh() - - # force the set selection function reset the selection - self._curpage = -1 - - # set the active page to the one we just split off - self.SetSelectionToPage(page_info) - - self.UpdateHintWindowSize() - - # notify owner that the tab has been dragged - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, self.GetId()) - e.SetSelection(event.GetSelection()) - e.SetOldSelection(event.GetSelection()) - e.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e) - - - def OnTabCancelDrag(self, event): - """ - Handles the ``EVT_AUINOTEBOOK_CANCEL_DRAG`` event for L{AuiNotebook}. - - :param `event`: a L{AuiNotebookEvent} event to be processed. - """ - - tabs = event.GetEventObject() - if not tabs.GetEnabled(event.GetSelection()): - return - - self._mgr.HideHint() - - src_tabs = event.GetEventObject() - if not src_tabs: - raise Exception("no source object?") - - - def IsMouseWellOutsideWindow(self): - """ Returns whether the mouse is well outside the L{AuiNotebook} screen rectangle. """ - - screen_rect = self.GetScreenRect() - screen_rect.Inflate(50, 50) - - return not screen_rect.Contains(wx.GetMousePosition()) - - - def FloatPage(self, page_index): - """ - Float the page in `page_index` by reparenting it to a floating frame. - - :param `page_index`: the index of the page to be floated. - - :warning: When the notebook is more or less full screen, tabs cannot be dragged far - enough outside of the notebook to become floating pages. - """ - - root_manager = framemanager.GetManager(self) - page_title = self.GetPageText(page_index) - page_contents = self.GetPage(page_index) - page_bitmap = self.GetPageBitmap(page_index) - text_colour = self.GetPageTextColour(page_index) - info = self.GetPageInfo(page_index) - - if root_manager and root_manager != self._mgr: - root_manager = framemanager.GetManager(self) - - if hasattr(page_contents, "__floating_size__"): - floating_size = wx.Size(*page_contents.__floating_size__) - else: - floating_size = page_contents.GetBestSize() - if floating_size == wx.DefaultSize: - floating_size = wx.Size(300, 200) - - page_contents.__page_index__ = page_index - page_contents.__aui_notebook__ = self - page_contents.__text_colour__ = text_colour - page_contents.__control__ = info.control - - if info.control: - info.control.Reparent(page_contents) - info.control.Hide() - info.control = None - - self.RemovePage(page_index) - self.RemoveEmptyTabFrames() - - pane_info = framemanager.AuiPaneInfo().Float().FloatingPosition(wx.GetMousePosition()). \ - FloatingSize(floating_size).BestSize(floating_size).Name("__floating__%s"%page_title). \ - Caption(page_title).Icon(page_bitmap) - root_manager.AddPane(page_contents, pane_info) - root_manager.Bind(framemanager.EVT_AUI_PANE_CLOSE, self.OnCloseFloatingPage) - self.GetActiveTabCtrl().DoShowHide() - self.DoSizing() - root_manager.Update() - - else: - frame = wx.Frame(self, title=page_title, - style=wx.DEFAULT_FRAME_STYLE|wx.FRAME_TOOL_WINDOW| - wx.FRAME_FLOAT_ON_PARENT | wx.FRAME_NO_TASKBAR) - - if info.control: - info.control.Reparent(frame) - info.control.Hide() - - frame.bitmap = page_bitmap - frame.page_index = page_index - frame.text_colour = text_colour - frame.control = info.control - page_contents.Reparent(frame) - frame.Bind(wx.EVT_CLOSE, self.OnCloseFloatingPage) - frame.Move(wx.GetMousePosition()) - frame.Show() - self.RemovePage(page_index) - - self.RemoveEmptyTabFrames() - - wx.CallAfter(self.RemoveEmptyTabFrames) - - - def OnCloseFloatingPage(self, event): - """ - Handles the ``wx.EVT_CLOSE`` event for a floating page in L{AuiNotebook}. - - :param `event`: a `wx.CloseEvent` event to be processed. - """ - - root_manager = framemanager.GetManager(self) - if root_manager and root_manager != self._mgr: - pane = event.pane - if pane.name.startswith("__floating__"): - self.ReDockPage(pane) - return - - event.Skip() - else: - event.Skip() - frame = event.GetEventObject() - page_title = frame.GetTitle() - page_contents = list(frame.GetChildren())[-1] - page_contents.Reparent(self) - self.InsertPage(frame.page_index, page_contents, page_title, select=True, bitmap=frame.bitmap, control=frame.control) - - if frame.control: - src_tabs, idx = self.FindTab(page_contents) - frame.control.Reparent(src_tabs) - frame.control.Hide() - frame.control = None - - self.SetPageTextColour(frame.page_index, frame.text_colour) - - - def ReDockPage(self, pane): - """ - Re-docks a floating L{AuiNotebook} tab in the original position, when possible. - - :param `pane`: an instance of L{framemanager.AuiPaneInfo}. - """ - - root_manager = framemanager.GetManager(self) - - pane.window.__floating_size__ = wx.Size(*pane.floating_size) - page_index = pane.window.__page_index__ - text_colour = pane.window.__text_colour__ - control = pane.window.__control__ - - root_manager.DetachPane(pane.window) - self.InsertPage(page_index, pane.window, pane.caption, True, pane.icon, control=control) - - self.SetPageTextColour(page_index, text_colour) - self.GetActiveTabCtrl().DoShowHide() - self.DoSizing() - if control: - self.UpdateTabCtrlHeight(force=True) - - self._mgr.Update() - root_manager.Update() - - - def GetTabCtrlFromPoint(self, pt): - """ - Returns the tab control at the specified point. - - :param `pt`: a `wx.Point` object. - """ - - # if we've just removed the last tab from the source - # tab set, the remove the tab control completely - all_panes = self._mgr.GetAllPanes() - for pane in all_panes: - if pane.name == "dummy": - continue - - tabframe = pane.window - if tabframe._tab_rect.Contains(pt): - return tabframe._tabs - - return None - - - def GetTabFrameFromTabCtrl(self, tab_ctrl): - """ - Returns the tab frame associated with a tab control. - - :param `tab_ctrl`: an instance of L{AuiTabCtrl}. - """ - - # if we've just removed the last tab from the source - # tab set, the remove the tab control completely - all_panes = self._mgr.GetAllPanes() - for pane in all_panes: - if pane.name == "dummy": - continue - - tabframe = pane.window - if tabframe._tabs == tab_ctrl: - return tabframe - - return None - - - def GetTabFrameFromWindow(self, wnd): - """ - Returns the tab frame associated with a window. - - :param `wnd`: an instance of `wx.Window`. - """ - - all_panes = self._mgr.GetAllPanes() - for pane in all_panes: - if pane.name == "dummy": - continue - - tabframe = pane.window - for page in tabframe._tabs.GetPages(): - if wnd == page.window: - return tabframe - - return None - - - def RemoveEmptyTabFrames(self): - """ Removes all the empty tab frames. """ - - # if we've just removed the last tab from the source - # tab set, the remove the tab control completely - all_panes = self._mgr.GetAllPanes() - - for indx in xrange(len(all_panes)-1, -1, -1): - pane = all_panes[indx] - if pane.name == "dummy": - continue - - tab_frame = pane.window - if tab_frame._tabs.GetPageCount() == 0: - self._mgr.DetachPane(tab_frame) - tab_frame._tabs.Destroy() - tab_frame._tabs = None - del tab_frame - - # check to see if there is still a center pane - # if there isn't, make a frame the center pane - first_good = None - center_found = False - - all_panes = self._mgr.GetAllPanes() - for pane in all_panes: - if pane.name == "dummy": - continue - - if pane.dock_direction == AUI_DOCK_CENTRE: - center_found = True - if not first_good: - first_good = pane.window - - if not center_found and first_good: - self._mgr.GetPane(first_good).Centre() - - if not self.IsBeingDeleted(): - self._mgr.Update() - - - def OnChildFocusNotebook(self, event): - """ - Handles the ``wx.EVT_CHILD_FOCUS`` event for L{AuiNotebook}. - - :param `event`: a `wx.ChildFocusEvent` event to be processed. - """ - - # if we're dragging a tab, don't change the current selection. - # This code prevents a bug that used to happen when the hint window - # was hidden. In the bug, the focus would return to the notebook - # child, which would then enter this handler and call - # SetSelection, which is not desired turn tab dragging. - - event.Skip() - - all_panes = self._mgr.GetAllPanes() - for pane in all_panes: - if pane.name == "dummy": - continue - tabframe = pane.window - if tabframe._tabs.IsDragging(): - return - -## # change the tab selection to the child -## # which was focused -## idx = self._tabs.GetIdxFromWindow(event.GetWindow()) -## if idx != -1 and idx != self._curpage: -## self.SetSelection(idx) - - - def SetNavigatorIcon(self, bmp): - """ - Sets the icon used by the L{TabNavigatorWindow}. - - :param `bmp`: an instance of `wx.Bitmap`. - """ - - if isinstance(bmp, wx.Bitmap) and bmp.IsOk(): - # Make sure image is proper size - if bmp.GetSize() != (16, 16): - img = bmp.ConvertToImage() - img.Rescale(16, 16, wx.IMAGE_QUALITY_HIGH) - bmp = wx.BitmapFromImage(img) - self._naviIcon = bmp - else: - raise TypeError, "SetNavigatorIcon requires a valid bitmap" - - - def OnNavigationKeyNotebook(self, event): - """ - Handles the ``wx.EVT_NAVIGATION_KEY`` event for L{AuiNotebook}. - - :param `event`: a `wx.NavigationKeyEvent` event to be processed. - """ - - if event.IsWindowChange(): - if self._agwFlags & AUI_NB_SMART_TABS: - if not self._popupWin: - self._popupWin = TabNavigatorWindow(self, self._naviIcon) - self._popupWin.SetReturnCode(wx.ID_OK) - self._popupWin.ShowModal() - idx = self._popupWin.GetSelectedPage() - self._popupWin.Destroy() - self._popupWin = None - # Need to do CallAfter so that the selection and its - # associated events get processed outside the context of - # this key event. Not doing so causes odd issues with the - # window focus under certain use cases on Windows. - wx.CallAfter(self.SetSelection, idx, True) - else: - # a dialog is already opened - self._popupWin.OnNavigationKey(event) - return - else: - # change pages - # FIXME: the problem with this is that if we have a split notebook, - # we selection may go all over the place. - self.AdvanceSelection(event.GetDirection()) - - else: - # we get this event in 3 cases - # - # a) one of our pages might have generated it because the user TABbed - # out from it in which case we should propagate the event upwards and - # our parent will take care of setting the focus to prev/next sibling - # - # or - # - # b) the parent panel wants to give the focus to us so that we - # forward it to our selected page. We can't deal with this in - # OnSetFocus() because we don't know which direction the focus came - # from in this case and so can't choose between setting the focus to - # first or last panel child - # - # or - # - # c) we ourselves (see MSWTranslateMessage) generated the event - # - parent = self.GetParent() - - # the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE - isFromParent = event.GetEventObject() == parent - isFromSelf = event.GetEventObject() == self - - if isFromParent or isFromSelf: - - # no, it doesn't come from child, case (b) or (c): forward to a - # page but only if direction is backwards (TAB) or from ourselves, - if self.GetSelection() != wx.NOT_FOUND and (not event.GetDirection() or isFromSelf): - - # so that the page knows that the event comes from it's parent - # and is being propagated downwards - event.SetEventObject(self) - - page = self.GetPage(self.GetSelection()) - if not page.GetEventHandler().ProcessEvent(event): - page.SetFocus() - - #else: page manages focus inside it itself - - else: # otherwise set the focus to the notebook itself - - self.SetFocus() - - else: - - # send this event back for the 'wraparound' focus. - winFocus = event.GetCurrentFocus() - - if winFocus: - event.SetEventObject(self) - winFocus.GetEventHandler().ProcessEvent(event) - - - def OnTabButton(self, event): - """ - Handles the ``EVT_AUINOTEBOOK_BUTTON`` event for L{AuiNotebook}. - - :param `event`: a L{AuiNotebookEvent} event to be processed. - """ - - tabs = event.GetEventObject() - button_id = event.GetInt() - - if button_id == AUI_BUTTON_CLOSE: - - selection = event.GetSelection() - - if selection == -1: - - # if the close button is to the right, use the active - # page selection to determine which page to close - selection = tabs.GetActivePage() - - if selection == -1 or not tabs.GetEnabled(selection): - return - - if selection != -1: - - close_wnd = tabs.GetWindowFromIdx(selection) - - if close_wnd.GetName() == "__fake__page__": - # This is a notebook preview - previous_active, page_status = close_wnd.__previousStatus - for page, status in zip(tabs.GetPages(), page_status): - page.enabled = status - - main_idx = self._tabs.GetIdxFromWindow(close_wnd) - self.DeletePage(main_idx) - - if previous_active >= 0: - tabs.SetActivePage(previous_active) - page_count = tabs.GetPageCount() - selection = -1 - - for page in xrange(page_count): - # remove the page from the source tabs - page_info = tabs.GetPage(page) - if page_info.active: - selection = page - break - - tabs.DoShowHide() - self.DoSizing() - tabs.Refresh() - - if selection >= 0: - wx.CallAfter(tabs.MakeTabVisible, selection, self) - - # Don't fire the event - return - - # ask owner if it's ok to close the tab - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, self.GetId()) - idx = self._tabs.GetIdxFromWindow(close_wnd) - e.SetSelection(idx) - e.SetOldSelection(event.GetSelection()) - e.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e) - if not e.IsAllowed(): - return - - if repr(close_wnd.__class__).find("AuiMDIChildFrame") >= 0: - close_wnd.Close() - - else: - main_idx = self._tabs.GetIdxFromWindow(close_wnd) - self.DeletePage(main_idx) - - # notify owner that the tab has been closed - e2 = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, self.GetId()) - e2.SetSelection(idx) - e2.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e2) - - if self.GetPageCount() == 0: - mgr = self.GetAuiManager() - win = mgr.GetManagedWindow() - win.SendSizeEvent() - - - def OnTabMiddleDown(self, event): - """ - Handles the ``EVT_AUINOTEBOOK_TAB_MIDDLE_DOWN`` event for L{AuiNotebook}. - - :param `event`: a L{AuiNotebookEvent} event to be processed. - """ - - tabs = event.GetEventObject() - if not tabs.GetEnabled(event.GetSelection()): - return - - # patch event through to owner - wnd = tabs.GetWindowFromIdx(event.GetSelection()) - - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, self.GetId()) - e.SetSelection(self._tabs.GetIdxFromWindow(wnd)) - e.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e) - - - def OnTabMiddleUp(self, event): - """ - Handles the ``EVT_AUINOTEBOOK_TAB_MIDDLE_UP`` event for L{AuiNotebook}. - - :param `event`: a L{AuiNotebookEvent} event to be processed. - """ - - tabs = event.GetEventObject() - if not tabs.GetEnabled(event.GetSelection()): - return - - # if the AUI_NB_MIDDLE_CLICK_CLOSE is specified, middle - # click should act like a tab close action. However, first - # give the owner an opportunity to handle the middle up event - # for custom action - - wnd = tabs.GetWindowFromIdx(event.GetSelection()) - - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, self.GetId()) - e.SetSelection(self._tabs.GetIdxFromWindow(wnd)) - e.SetEventObject(self) - if self.GetEventHandler().ProcessEvent(e): - return - if not e.IsAllowed(): - return - - # check if we are supposed to close on middle-up - if self._agwFlags & AUI_NB_MIDDLE_CLICK_CLOSE == 0: - return - - # simulate the user pressing the close button on the tab - event.SetInt(AUI_BUTTON_CLOSE) - self.OnTabButton(event) - - - def OnTabRightDown(self, event): - """ - Handles the ``EVT_AUINOTEBOOK_TAB_RIGHT_DOWN`` event for L{AuiNotebook}. - - :param `event`: a L{AuiNotebookEvent} event to be processed. - """ - - tabs = event.GetEventObject() - if not tabs.GetEnabled(event.GetSelection()): - return - - # patch event through to owner - wnd = tabs.GetWindowFromIdx(event.GetSelection()) - - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, self.GetId()) - e.SetSelection(self._tabs.GetIdxFromWindow(wnd)) - e.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e) - - - def OnTabRightUp(self, event): - """ - Handles the ``EVT_AUINOTEBOOK_TAB_RIGHT_UP`` event for L{AuiNotebook}. - - :param `event`: a L{AuiNotebookEvent} event to be processed. - """ - - tabs = event.GetEventObject() - if not tabs.GetEnabled(event.GetSelection()): - return - - # patch event through to owner - wnd = tabs.GetWindowFromIdx(event.GetSelection()) - - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, self.GetId()) - e.SetSelection(self._tabs.GetIdxFromWindow(wnd)) - e.SetEventObject(self) - self.GetEventHandler().ProcessEvent(e) - - - def SetNormalFont(self, font): - """ - Sets the normal font for drawing tab labels. - - :param `font`: a `wx.Font` object. - """ - - self._normal_font = font - self.GetArtProvider().SetNormalFont(font) - - - def SetSelectedFont(self, font): - """ - Sets the selected tab font for drawing tab labels. - - :param `font`: a `wx.Font` object. - """ - - self._selected_font = font - self.GetArtProvider().SetSelectedFont(font) - - - def SetMeasuringFont(self, font): - """ - Sets the font for calculating text measurements. - - :param `font`: a `wx.Font` object. - """ - - self.GetArtProvider().SetMeasuringFont(font) - - - def SetFont(self, font): - """ - Sets the tab font. - - :param `font`: a `wx.Font` object. - - :note: Overridden from `wx.PyPanel`. - """ - - wx.PyPanel.SetFont(self, font) - - selectedFont = wx.Font(font.GetPointSize(), font.GetFamily(), - font.GetStyle(), wx.BOLD, font.GetUnderlined(), - font.GetFaceName(), font.GetEncoding()) - - self.SetNormalFont(font) - self.SetSelectedFont(selectedFont) - self.SetMeasuringFont(selectedFont) - - # Recalculate tab container size based on new font - self.UpdateTabCtrlHeight(force=False) - self.DoSizing() - - return True - - - def GetTabCtrlHeight(self): - """ Returns the tab control height. """ - - return self._tab_ctrl_height - - - def GetHeightForPageHeight(self, pageHeight): - """ - Gets the height of the notebook for a given page height. - - :param `pageHeight`: the given page height. - """ - - self.UpdateTabCtrlHeight() - - tabCtrlHeight = self.GetTabCtrlHeight() - decorHeight = 2 - return tabCtrlHeight + pageHeight + decorHeight - - - def AdvanceSelection(self, forward=True, wrap=True): - """ - Cycles through the tabs. - - :param `forward`: whether to advance forward or backward; - :param `wrap`: ``True`` to return to the first tab if we reach the last tab. - - :note: The call to this function generates the page changing events. - """ - - tabCtrl = self.GetActiveTabCtrl() - newPage = -1 - - focusWin = tabCtrl.FindFocus() - activePage = tabCtrl.GetActivePage() - lenPages = len(tabCtrl.GetPages()) - - if lenPages == 1: - return False - - if forward: - if lenPages > 1: - - if activePage == -1 or activePage == lenPages - 1: - if not wrap: - return False - - newPage = 0 - - elif activePage < lenPages - 1: - newPage = activePage + 1 - - else: - - if lenPages > 1: - if activePage == -1 or activePage == 0: - if not wrap: - return False - - newPage = lenPages - 1 - - elif activePage > 0: - newPage = activePage - 1 - - - if newPage != -1: - if not self.GetEnabled(newPage): - return False - - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, tabCtrl.GetId()) - e.SetSelection(newPage) - e.SetOldSelection(activePage) - e.SetEventObject(tabCtrl) - self.GetEventHandler().ProcessEvent(e) - -## if focusWin: -## focusWin.SetFocus() - - return True - - - def ShowWindowMenu(self): - """ - Shows the window menu for the active tab control associated with this - notebook, and returns ``True`` if a selection was made. - """ - - tabCtrl = self.GetActiveTabCtrl() - idx = tabCtrl.GetArtProvider().ShowDropDown(tabCtrl, tabCtrl.GetPages(), tabCtrl.GetActivePage()) - - if not self.GetEnabled(idx): - return False - - if idx != -1: - e = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, tabCtrl.GetId()) - e.SetSelection(idx) - e.SetOldSelection(tabCtrl.GetActivePage()) - e.SetEventObject(tabCtrl) - self.GetEventHandler().ProcessEvent(e) - - return True - - else: - - return False - - - def AddTabAreaButton(self, id, location, normal_bitmap=wx.NullBitmap, disabled_bitmap=wx.NullBitmap): - """ - Adds a button in the tab area. - - :param `id`: the button identifier. This can be one of the following: - - ============================== ================================= - Button Identifier Description - ============================== ================================= - ``AUI_BUTTON_CLOSE`` Shows a close button on the tab area - ``AUI_BUTTON_WINDOWLIST`` Shows a window list button on the tab area - ``AUI_BUTTON_LEFT`` Shows a left button on the tab area - ``AUI_BUTTON_RIGHT`` Shows a right button on the tab area - ============================== ================================= - - :param `location`: the button location. Can be ``wx.LEFT`` or ``wx.RIGHT``; - :param `normal_bitmap`: the bitmap for an enabled tab; - :param `disabled_bitmap`: the bitmap for a disabled tab. - """ - - active_tabctrl = self.GetActiveTabCtrl() - active_tabctrl.AddButton(id, location, normal_bitmap, disabled_bitmap) - - - def RemoveTabAreaButton(self, id): - """ - Removes a button from the tab area. - - :param `id`: the button identifier. See L{AddTabAreaButton} for a list of button identifiers. - - :see: L{AddTabAreaButton} - """ - - active_tabctrl = self.GetActiveTabCtrl() - active_tabctrl.RemoveButton(id) - - - def HasMultiplePages(self): - """ - This method should be overridden to return ``True`` if this window has multiple pages. All - standard class with multiple pages such as `wx.Notebook`, `wx.Listbook` and `wx.Treebook` - already override it to return ``True`` and user-defined classes with similar behaviour - should do it as well to allow the library to handle such windows appropriately. - - :note: Overridden from `wx.PyPanel`. - """ - - return True - - - def GetDefaultBorder(self): - """ Returns the default border style for L{AuiNotebook}. """ - - return wx.BORDER_NONE - - - def NotebookPreview(self, thumbnail_size=200): - """ - Generates a preview of all the pages in the notebook (MSW and GTK only). - - :param `thumbnail_size`: the maximum size of every page thumbnail. - - :note: this functionality is currently unavailable on wxMac. - """ - - if wx.Platform == "__WXMAC__": - return False - - tabCtrl = self.GetActiveTabCtrl() - activePage = tabCtrl.GetActivePage() - pages = tabCtrl.GetPages() - - pageStatus, pageText = [], [] - - for indx, page in enumerate(pages): - - pageStatus.append(page.enabled) - - if not page.enabled: - continue - - self.SetSelectionToPage(page) - pageText.append(page.caption) - - rect = page.window.GetScreenRect() - bmp = RescaleScreenShot(TakeScreenShot(rect), thumbnail_size) - - page.enabled = False - if indx == 0: - il = wx.ImageList(bmp.GetWidth(), bmp.GetHeight(), True) - - il.Add(bmp) - - # create the list control - listCtrl = wx.ListCtrl(self, style=wx.LC_ICON|wx.LC_AUTOARRANGE|wx.LC_HRULES|wx.LC_VRULES, - name="__fake__page__") - - # assign the image list to it - listCtrl.AssignImageList(il, wx.IMAGE_LIST_NORMAL) - listCtrl.__previousStatus = [activePage, pageStatus] - - # create some items for the list - for indx, text in enumerate(pageText): - listCtrl.InsertImageStringItem(10000, text, indx) - - self.AddPage(listCtrl, "AuiNotebook Preview", True, bitmap=auinotebook_preview.GetBitmap(), disabled_bitmap=wx.NullBitmap) - return True - - - def SetRenamable(self, page_idx, renamable): - """ - Sets whether a tab can be renamed via a left double-click or not. - - :param `page_idx`: the page index; - :param `renamable`: ``True`` if the page can be renamed. - """ - - if page_idx >= self._tabs.GetPageCount(): - return False - - # update our own tab catalog - page_info = self._tabs.GetPage(page_idx) - page_info.renamable = renamable - - # update what's on screen - ctrl, ctrl_idx = self.FindTab(page_info.window) - if not ctrl: - return False - - info = ctrl.GetPage(ctrl_idx) - info.renamable = page_info.renamable - - return True - - - def IsRenamable(self, page_idx): - """ - Returns whether a tab can be renamed or not. - - :param `page_idx`: the page index. - - :returns: ``True`` is a page can be renamed, ``False`` otherwise. - """ - - if page_idx >= self._tabs.GetPageCount(): - return False - - page_info = self._tabs.GetPage(page_idx) - return page_info.renamable - - - def OnRenameCancelled(self, page_index): - """ - Called by L{TabTextCtrl}, to cancel the changes and to send the - `EVT_AUINOTEBOOK_END_LABEL_EDIT` event. - - :param `page_index`: the page index in the notebook. - """ - - # let owner know that the edit was cancelled - evt = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_END_LABEL_EDIT, self.GetId()) - - evt.SetSelection(page_index) - evt.SetEventObject(self) - evt.SetLabel("") - evt.SetEditCanceled(True) - self.GetEventHandler().ProcessEvent(evt) - - - def OnRenameAccept(self, page_index, value): - """ - Called by L{TabTextCtrl}, to accept the changes and to send the - `EVT_AUINOTEBOOK_END_LABEL_EDIT` event. - - :param `page_index`: the page index in the notebook; - :param `value`: the new label for the tab. - """ - - evt = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_END_LABEL_EDIT, self.GetId()) - evt.SetSelection(page_index) - evt.SetEventObject(self) - evt.SetLabel(value) - evt.SetEditCanceled(False) - - return not self.GetEventHandler().ProcessEvent(evt) or evt.IsAllowed() - - - def ResetTextControl(self): - """ Called by L{TabTextCtrl} when it marks itself for deletion. """ - - if not self._textCtrl: - return - - self._textCtrl.Destroy() - self._textCtrl = None - - # tab height might have changed - self.UpdateTabCtrlHeight(force=True) - - - def EditTab(self, page_index): - """ - Starts the editing of an item label, sending a `EVT_AUINOTEBOOK_BEGIN_LABEL_EDIT` event. - - :param `page_index`: the page index we want to edit. - """ - - if page_index >= self._tabs.GetPageCount(): - return False - - if not self.IsRenamable(page_index): - return False - - page_info = self._tabs.GetPage(page_index) - ctrl, ctrl_idx = self.FindTab(page_info.window) - if not ctrl: - return False - - evt = AuiNotebookEvent(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_LABEL_EDIT, self.GetId()) - evt.SetSelection(page_index) - evt.SetEventObject(self) - if self.GetEventHandler().ProcessEvent(evt) and not evt.IsAllowed(): - # vetoed by user - return False - - if self._textCtrl is not None and page_info != self._textCtrl.item(): - self._textCtrl.StopEditing() - - self._textCtrl = TabTextCtrl(ctrl, page_info, page_index) - self._textCtrl.SetFocus() - - return True diff --git a/agw/aui/dockart.py b/agw/aui/dockart.py deleted file mode 100644 index 17da477..0000000 --- a/agw/aui/dockart.py +++ /dev/null @@ -1,1162 +0,0 @@ -""" -Dock art provider code - a dock provider provides all drawing functionality to -the AUI dock manager. This allows the dock manager to have a plugable look-and-feel. - -By default, a L{AuiManager} uses an instance of this class called L{AuiDefaultDockArt} -which provides bitmap art and a colour scheme that is adapted to the major platforms' -look. You can either derive from that class to alter its behaviour or write a -completely new dock art class. Call L{AuiManager.SetArtProvider} to make use this -new dock art. -""" - -__author__ = "Andrea Gavana " -__date__ = "31 March 2009" - - -import wx -import types - -from aui_utilities import BitmapFromBits, StepColour, ChopText, GetBaseColour -from aui_utilities import DrawGradientRectangle, DrawMACCloseButton -from aui_utilities import DarkenBitmap, LightContrastColour -from aui_constants import * - -optionActive = 2**14 - -_ctypes = False - -# Try to import winxptheme for ModernDockArt -if wx.Platform == "__WXMSW__": - try: - import ctypes - import winxptheme - _ctypes = True - except ImportError: - pass - -# -- AuiDefaultDockArt class implementation -- - -class AuiDefaultDockArt(object): - """ - Dock art provider code - a dock provider provides all drawing functionality - to the AUI dock manager. This allows the dock manager to have a plugable - look-and-feel. - - By default, a L{AuiManager} uses an instance of this class called L{AuiDefaultDockArt} - which provides bitmap art and a colour scheme that is adapted to the major - platforms' look. You can either derive from that class to alter its behaviour or - write a completely new dock art class. - - Call L{AuiManager.SetArtProvider} to make use this new dock art. - - - **Metric Ordinals** - - These are the possible pane dock art settings for L{AuiManager}: - - ================================================ ====================================== - Metric Ordinal Constant Description - ================================================ ====================================== - ``AUI_DOCKART_SASH_SIZE`` Customizes the sash size - ``AUI_DOCKART_CAPTION_SIZE`` Customizes the caption size - ``AUI_DOCKART_GRIPPER_SIZE`` Customizes the gripper size - ``AUI_DOCKART_PANE_BORDER_SIZE`` Customizes the pane border size - ``AUI_DOCKART_PANE_BUTTON_SIZE`` Customizes the pane button size - ``AUI_DOCKART_BACKGROUND_COLOUR`` Customizes the background colour - ``AUI_DOCKART_BACKGROUND_GRADIENT_COLOUR`` Customizes the background gradient colour - ``AUI_DOCKART_SASH_COLOUR`` Customizes the sash colour - ``AUI_DOCKART_ACTIVE_CAPTION_COLOUR`` Customizes the active caption colour - ``AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR`` Customizes the active caption gradient colour - ``AUI_DOCKART_INACTIVE_CAPTION_COLOUR`` Customizes the inactive caption colour - ``AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR`` Customizes the inactive gradient caption colour - ``AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR`` Customizes the active caption text colour - ``AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR`` Customizes the inactive caption text colour - ``AUI_DOCKART_BORDER_COLOUR`` Customizes the border colour - ``AUI_DOCKART_GRIPPER_COLOUR`` Customizes the gripper colour - ``AUI_DOCKART_CAPTION_FONT`` Customizes the caption font - ``AUI_DOCKART_GRADIENT_TYPE`` Customizes the gradient type (no gradient, vertical or horizontal) - ``AUI_DOCKART_DRAW_SASH_GRIP`` Draw a sash grip on the sash - ================================================ ====================================== - - - **Gradient Types** - - These are the possible gradient dock art settings for L{AuiManager}: - - ============================================ ====================================== - Gradient Constant Description - ============================================ ====================================== - ``AUI_GRADIENT_NONE`` No gradient on the captions - ``AUI_GRADIENT_VERTICAL`` Vertical gradient on the captions - ``AUI_GRADIENT_HORIZONTAL`` Horizontal gradient on the captions - ============================================ ====================================== - - - **Button States** - - These are the possible pane button / L{AuiNotebook} button / L{AuiToolBar} button states: - - ============================================ ====================================== - Button State Constant Description - ============================================ ====================================== - ``AUI_BUTTON_STATE_NORMAL`` Normal button state - ``AUI_BUTTON_STATE_HOVER`` Hovered button state - ``AUI_BUTTON_STATE_PRESSED`` Pressed button state - ``AUI_BUTTON_STATE_DISABLED`` Disabled button state - ``AUI_BUTTON_STATE_HIDDEN`` Hidden button state - ``AUI_BUTTON_STATE_CHECKED`` Checked button state - ============================================ ====================================== - - - **Button Identifiers** - - These are the possible pane button / L{AuiNotebook} button / L{AuiToolBar} button identifiers: - - ============================================ ====================================== - Button Identifier Description - ============================================ ====================================== - ``AUI_BUTTON_CLOSE`` Shows a close button on the pane - ``AUI_BUTTON_MAXIMIZE_RESTORE`` Shows a maximize/restore button on the pane - ``AUI_BUTTON_MINIMIZE`` Shows a minimize button on the pane - ``AUI_BUTTON_PIN`` Shows a pin button on the pane - ``AUI_BUTTON_OPTIONS`` Shows an option button on the pane (not implemented) - ``AUI_BUTTON_WINDOWLIST`` Shows a window list button on the pane (for L{AuiNotebook}) - ``AUI_BUTTON_LEFT`` Shows a left button on the pane (for L{AuiNotebook}) - ``AUI_BUTTON_RIGHT`` Shows a right button on the pane (for L{AuiNotebook}) - ``AUI_BUTTON_UP`` Shows an up button on the pane (not implemented) - ``AUI_BUTTON_DOWN`` Shows a down button on the pane (not implemented) - ``AUI_BUTTON_CUSTOM1`` Shows a custom button on the pane (not implemented) - ``AUI_BUTTON_CUSTOM2`` Shows a custom button on the pane (not implemented) - ``AUI_BUTTON_CUSTOM3`` Shows a custom button on the pane (not implemented) - ============================================ ====================================== - - """ - - def __init__(self): - """ Default class constructor. """ - - self.Init() - - isMac = wx.Platform == "__WXMAC__" - - if isMac: - self._caption_font = wx.SMALL_FONT - else: - self._caption_font = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False) - - self.SetDefaultPaneBitmaps(isMac) - self._restore_bitmap = wx.BitmapFromXPMData(restore_xpm) - - # default metric values - self._sash_size = 4 - - if isMac: - # This really should be implemented in wx.SystemSettings - # There is no way to do this that I am aware outside of using - # the cocoa python bindings. 8 pixels looks correct on my system - # so hard coding it for now. - - # How do I translate this?!? Not sure of the below implementation... - # SInt32 height; - # GetThemeMetric( kThemeMetricSmallPaneSplitterHeight , &height ); - # self._sash_size = height; - - self._sash_size = 8 # Carbon.Appearance.kThemeMetricPaneSplitterHeight - - elif wx.Platform == "__WXGTK__": - self._sash_size = wx.RendererNative.Get().GetSplitterParams(wx.GetTopLevelWindows()[0]).widthSash - - else: - self._sash_size = 4 - - self._caption_size = 19 - self._border_size = 1 - self._button_size = 14 - self._gripper_size = 9 - self._gradient_type = AUI_GRADIENT_VERTICAL - self._draw_sash = False - - - def Init(self): - """ Initializes the dock art. """ - - base_colour = GetBaseColour() - darker1_colour = StepColour(base_colour, 85) - darker2_colour = StepColour(base_colour, 75) - darker3_colour = StepColour(base_colour, 60) - darker4_colour = StepColour(base_colour, 40) - - self._background_colour = base_colour - self._background_gradient_colour = StepColour(base_colour, 180) - - isMac = wx.Platform == "__WXMAC__" - - if isMac: - self._active_caption_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT) - else: - self._active_caption_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_ACTIVECAPTION) - - self._active_caption_gradient_colour = LightContrastColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)) - self._active_caption_text_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT) - self._inactive_caption_colour = darker1_colour - self._inactive_caption_gradient_colour = StepColour(base_colour, 97) - self._inactive_caption_text_colour = wx.BLACK - - self._sash_brush = wx.Brush(base_colour) - self._background_brush = wx.Brush(base_colour) - self._border_pen = wx.Pen(darker2_colour) - self._gripper_brush = wx.Brush(base_colour) - self._gripper_pen1 = wx.Pen(darker4_colour) - self._gripper_pen2 = wx.Pen(darker3_colour) - self._gripper_pen3 = wx.WHITE_PEN - - - def GetMetric(self, id): - """ - Gets the value of a certain setting. - - :param `id`: can be one of the size values in `Metric Ordinals`. - """ - - - if id == AUI_DOCKART_SASH_SIZE: - return self._sash_size - elif id == AUI_DOCKART_CAPTION_SIZE: - return self._caption_size - elif id == AUI_DOCKART_GRIPPER_SIZE: - return self._gripper_size - elif id == AUI_DOCKART_PANE_BORDER_SIZE: - return self._border_size - elif id == AUI_DOCKART_PANE_BUTTON_SIZE: - return self._button_size - elif id == AUI_DOCKART_GRADIENT_TYPE: - return self._gradient_type - elif id == AUI_DOCKART_DRAW_SASH_GRIP: - return self._draw_sash - else: - raise Exception("Invalid Metric Ordinal.") - - - def SetMetric(self, id, new_val): - """ - Sets the value of a certain setting using `new_val` - - :param `id`: can be one of the size values in `Metric Ordinals`; - :param `new_val`: the new value of the setting. - """ - - if id == AUI_DOCKART_SASH_SIZE: - self._sash_size = new_val - elif id == AUI_DOCKART_CAPTION_SIZE: - self._caption_size = new_val - elif id == AUI_DOCKART_GRIPPER_SIZE: - self._gripper_size = new_val - elif id == AUI_DOCKART_PANE_BORDER_SIZE: - self._border_size = new_val - elif id == AUI_DOCKART_PANE_BUTTON_SIZE: - self._button_size = new_val - elif id == AUI_DOCKART_GRADIENT_TYPE: - self._gradient_type = new_val - elif id == AUI_DOCKART_DRAW_SASH_GRIP: - self._draw_sash = new_val - else: - raise Exception("Invalid Metric Ordinal.") - - - def GetColor(self, id): - """ - Gets the colour of a certain setting. - - :param `id`: can be one of the colour values in `Metric Ordinals`. - """ - - if id == AUI_DOCKART_BACKGROUND_COLOUR: - return self._background_brush.GetColour() - elif id == AUI_DOCKART_BACKGROUND_GRADIENT_COLOUR: - return self._background_gradient_colour - elif id == AUI_DOCKART_SASH_COLOUR: - return self._sash_brush.GetColour() - elif id == AUI_DOCKART_INACTIVE_CAPTION_COLOUR: - return self._inactive_caption_colour - elif id == AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR: - return self._inactive_caption_gradient_colour - elif id == AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR: - return self._inactive_caption_text_colour - elif id == AUI_DOCKART_ACTIVE_CAPTION_COLOUR: - return self._active_caption_colour - elif id == AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR: - return self._active_caption_gradient_colour - elif id == AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR: - return self._active_caption_text_colour - elif id == AUI_DOCKART_BORDER_COLOUR: - return self._border_pen.GetColour() - elif id == AUI_DOCKART_GRIPPER_COLOUR: - return self._gripper_brush.GetColour() - else: - raise Exception("Invalid Colour Ordinal.") - - - def SetColor(self, id, colour): - """ - Sets the colour of a certain setting. - - :param `id`: can be one of the colour values in `Metric Ordinals`; - :param `colour`: the new value of the setting. - """ - - if isinstance(colour, basestring): - colour = wx.NamedColour(colour) - elif isinstance(colour, types.TupleType): - colour = wx.Colour(*colour) - elif isinstance(colour, types.IntType): - colour = wx.ColourRGB(colour) - - if id == AUI_DOCKART_BACKGROUND_COLOUR: - self._background_brush.SetColour(colour) - elif id == AUI_DOCKART_BACKGROUND_GRADIENT_COLOUR: - self._background_gradient_colour = colour - elif id == AUI_DOCKART_SASH_COLOUR: - self._sash_brush.SetColour(colour) - elif id == AUI_DOCKART_INACTIVE_CAPTION_COLOUR: - self._inactive_caption_colour = colour - if not self._custom_pane_bitmaps and wx.Platform == "__WXMAC__": - # No custom bitmaps for the pane close button - # Change the MAC close bitmap colour - self._inactive_close_bitmap = DrawMACCloseButton(wx.WHITE, colour) - - elif id == AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR: - self._inactive_caption_gradient_colour = colour - elif id == AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR: - self._inactive_caption_text_colour = colour - elif id == AUI_DOCKART_ACTIVE_CAPTION_COLOUR: - self._active_caption_colour = colour - if not self._custom_pane_bitmaps and wx.Platform == "__WXMAC__": - # No custom bitmaps for the pane close button - # Change the MAC close bitmap colour - self._active_close_bitmap = DrawMACCloseButton(wx.WHITE, colour) - - elif id == AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR: - self._active_caption_gradient_colour = colour - elif id == AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR: - self._active_caption_text_colour = colour - elif id == AUI_DOCKART_BORDER_COLOUR: - self._border_pen.SetColour(colour) - elif id == AUI_DOCKART_GRIPPER_COLOUR: - self._gripper_brush.SetColour(colour) - self._gripper_pen1.SetColour(StepColour(colour, 40)) - self._gripper_pen2.SetColour(StepColour(colour, 60)) - else: - raise Exception("Invalid Colour Ordinal.") - - - GetColour = GetColor - SetColour = SetColor - - def SetFont(self, id, font): - """ - Sets a font setting. - - :param `id`: must be ``AUI_DOCKART_CAPTION_FONT``; - :param `font`: an instance of `wx.Font`. - """ - - if id == AUI_DOCKART_CAPTION_FONT: - self._caption_font = font - - - def GetFont(self, id): - """ - Gets a font setting. - - :param `id`: must be ``AUI_DOCKART_CAPTION_FONT``, otherwise `wx.NullFont` is returned. - """ - - if id == AUI_DOCKART_CAPTION_FONT: - return self._caption_font - - return wx.NullFont - - - def DrawSash(self, dc, window, orient, rect): - """ - Draws a sash between two windows. - - :param `dc`: a `wx.DC` device context; - :param `window`: an instance of `wx.Window`; - :param `orient`: the sash orientation; - :param `rect`: the sash rectangle. - """ - - # AG: How do we make this work?!? - # RendererNative does not use the sash_brush chosen by the user - # and the rect.GetSize() is ignored as the sash is always drawn - # 3 pixel wide - # wx.RendererNative.Get().DrawSplitterSash(window, dc, rect.GetSize(), pos, orient) - - dc.SetPen(wx.TRANSPARENT_PEN) - dc.SetBrush(self._sash_brush) - dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) - - draw_sash = self.GetMetric(AUI_DOCKART_DRAW_SASH_GRIP) - if draw_sash: - self.DrawSashGripper(dc, orient, rect) - - - def DrawBackground(self, dc, window, orient, rect): - """ - Draws a background. - - :param `dc`: a `wx.DC` device context; - :param `window`: an instance of `wx.Window`; - :param `orient`: the gradient (if any) orientation; - :param `rect`: the background rectangle. - """ - - dc.SetPen(wx.TRANSPARENT_PEN) - if wx.Platform == "__WXMAC__": - # we have to clear first, otherwise we are drawing a light striped pattern - # over an already darker striped background - dc.SetBrush(wx.WHITE_BRUSH) - dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) - - DrawGradientRectangle(dc, rect, self._background_brush.GetColour(), - self._background_gradient_colour, - AUI_GRADIENT_HORIZONTAL, rect.x, 700) - - - def DrawBorder(self, dc, window, rect, pane): - """ - Draws the pane border. - - :param `dc`: a `wx.DC` device context; - :param `window`: an instance of `wx.Window`; - :param `rect`: the border rectangle; - :param `pane`: the pane for which the border is drawn. - """ - - drect = wx.Rect(*rect) - - dc.SetPen(self._border_pen) - dc.SetBrush(wx.TRANSPARENT_BRUSH) - - border_width = self.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE) - - if pane.IsToolbar(): - - for ii in xrange(0, border_width): - - dc.SetPen(wx.WHITE_PEN) - dc.DrawLine(drect.x, drect.y, drect.x+drect.width, drect.y) - dc.DrawLine(drect.x, drect.y, drect.x, drect.y+drect.height) - dc.SetPen(self._border_pen) - dc.DrawLine(drect.x, drect.y+drect.height-1, - drect.x+drect.width, drect.y+drect.height-1) - dc.DrawLine(drect.x+drect.width-1, drect.y, - drect.x+drect.width-1, drect.y+drect.height) - drect.Deflate(1, 1) - - else: - - for ii in xrange(0, border_width): - - dc.DrawRectangle(drect.x, drect.y, drect.width, drect.height) - drect.Deflate(1, 1) - - - def DrawCaptionBackground(self, dc, rect, pane): - """ - Draws the text caption background in the pane. - - :param `dc`: a `wx.DC` device context; - :param `rect`: the text caption rectangle; - :param `pane`: the pane for which the text background is drawn. - """ - - active = pane.state & optionActive - - if self._gradient_type == AUI_GRADIENT_NONE: - if active: - dc.SetBrush(wx.Brush(self._active_caption_colour)) - else: - dc.SetBrush(wx.Brush(self._inactive_caption_colour)) - - dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) - - else: - - switch_gradient = pane.HasCaptionLeft() - gradient_type = self._gradient_type - if switch_gradient: - gradient_type = (self._gradient_type == AUI_GRADIENT_HORIZONTAL and [AUI_GRADIENT_VERTICAL] or \ - [AUI_GRADIENT_HORIZONTAL])[0] - - if active: - if wx.Platform == "__WXMAC__": - DrawGradientRectangle(dc, rect, self._active_caption_colour, - self._active_caption_gradient_colour, - gradient_type) - else: - DrawGradientRectangle(dc, rect, self._active_caption_gradient_colour, - self._active_caption_colour, - gradient_type) - else: - if wx.Platform == "__WXMAC__": - DrawGradientRectangle(dc, rect, self._inactive_caption_gradient_colour, - self._inactive_caption_colour, - gradient_type) - else: - DrawGradientRectangle(dc, rect, self._inactive_caption_colour, - self._inactive_caption_gradient_colour, - gradient_type) - - - def DrawIcon(self, dc, rect, pane): - """ - Draws the icon in the pane caption area. - - :param `dc`: a `wx.DC` device context; - :param `rect`: the pane caption rectangle; - :param `pane`: the pane for which the icon is drawn. - """ - - # Draw the icon centered vertically - if pane.icon.Ok(): - if pane.HasCaptionLeft(): - bmp = wx.ImageFromBitmap(pane.icon).Rotate90(clockwise=False) - dc.DrawBitmap(bmp.ConvertToBitmap(), rect.x+(rect.width-pane.icon.GetWidth())/2, rect.y+rect.height-2-pane.icon.GetHeight(), True) - else: - dc.DrawBitmap(pane.icon, rect.x+2, rect.y+(rect.height-pane.icon.GetHeight())/2, True) - - - def DrawCaption(self, dc, window, text, rect, pane): - """ - Draws the text in the pane caption. - - :param `dc`: a `wx.DC` device context; - :param `window`: an instance of `wx.Window`; - :param `text`: the text to be displayed; - :param `rect`: the pane caption rectangle; - :param `pane`: the pane for which the text is drawn. - """ - - dc.SetPen(wx.TRANSPARENT_PEN) - dc.SetFont(self._caption_font) - - self.DrawCaptionBackground(dc, rect, pane) - - if pane.state & optionActive: - dc.SetTextForeground(self._active_caption_text_colour) - else: - dc.SetTextForeground(self._inactive_caption_text_colour) - - w, h = dc.GetTextExtent("ABCDEFHXfgkj") - - clip_rect = wx.Rect(*rect) - btns = pane.CountButtons() - - captionLeft = pane.HasCaptionLeft() - variable = (captionLeft and [rect.height] or [rect.width])[0] - - variable -= 3 # text offset - variable -= 2 # button padding - - caption_offset = 0 - if pane.icon: - if captionLeft: - caption_offset += pane.icon.GetHeight() + 3 - else: - caption_offset += pane.icon.GetWidth() + 3 - - self.DrawIcon(dc, rect, pane) - - variable -= caption_offset - variable -= btns*(self._button_size + self._border_size) - draw_text = ChopText(dc, text, variable) - - if captionLeft: - dc.DrawRotatedText(draw_text, rect.x+(rect.width/2)-(h/2)-1, rect.y+rect.height-3-caption_offset, 90) - else: - dc.DrawText(draw_text, rect.x+3+caption_offset, rect.y+(rect.height/2)-(h/2)-1) - - - def RequestUserAttention(self, dc, window, text, rect, pane): - """ - Requests the user attention by intermittently highlighting the pane caption. - - :param `dc`: a `wx.DC` device context; - :param `window`: an instance of `wx.Window`; - :param `text`: the text to be displayed; - :param `rect`: the pane caption rectangle; - :param `pane`: the pane for which the text is drawn. - """ - - state = pane.state - pane.state &= ~optionActive - - for indx in xrange(6): - active = (indx%2 == 0 and [True] or [False])[0] - if active: - pane.state |= optionActive - else: - pane.state &= ~optionActive - - self.DrawCaptionBackground(dc, rect, pane) - self.DrawCaption(dc, window, text, rect, pane) - wx.SafeYield() - wx.MilliSleep(350) - - pane.state = state - - - def DrawGripper(self, dc, window, rect, pane): - """ - Draws a gripper on the pane. - - :param `dc`: a `wx.DC` device context; - :param `window`: an instance of `wx.Window`; - :param `rect`: the pane caption rectangle; - :param `pane`: the pane for which the gripper is drawn. - """ - - dc.SetPen(wx.TRANSPARENT_PEN) - dc.SetBrush(self._gripper_brush) - - dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) - - if not pane.HasGripperTop(): - y = 4 - while 1: - dc.SetPen(self._gripper_pen1) - dc.DrawPoint(rect.x+3, rect.y+y) - dc.SetPen(self._gripper_pen2) - dc.DrawPoint(rect.x+3, rect.y+y+1) - dc.DrawPoint(rect.x+4, rect.y+y) - dc.SetPen(self._gripper_pen3) - dc.DrawPoint(rect.x+5, rect.y+y+1) - dc.DrawPoint(rect.x+5, rect.y+y+2) - dc.DrawPoint(rect.x+4, rect.y+y+2) - y = y + 4 - if y > rect.GetHeight() - 4: - break - else: - x = 4 - while 1: - dc.SetPen(self._gripper_pen1) - dc.DrawPoint(rect.x+x, rect.y+3) - dc.SetPen(self._gripper_pen2) - dc.DrawPoint(rect.x+x+1, rect.y+3) - dc.DrawPoint(rect.x+x, rect.y+4) - dc.SetPen(self._gripper_pen3) - dc.DrawPoint(rect.x+x+1, rect.y+5) - dc.DrawPoint(rect.x+x+2, rect.y+5) - dc.DrawPoint(rect.x+x+2, rect.y+4) - x = x + 4 - if x > rect.GetWidth() - 4: - break - - - def DrawPaneButton(self, dc, window, button, button_state, _rect, pane): - """ - Draws a pane button in the pane caption area. - - :param `dc`: a `wx.DC` device context; - :param `window`: an instance of `wx.Window`; - :param `button`: the button to be drawn; - :param `button_state`: the pane button state; - :param `_rect`: the pane caption rectangle; - :param `pane`: the pane for which the button is drawn. - """ - - if not pane: - return - - if button == AUI_BUTTON_CLOSE: - if pane.state & optionActive: - bmp = self._active_close_bitmap - else: - bmp = self._inactive_close_bitmap - - elif button == AUI_BUTTON_PIN: - if pane.state & optionActive: - bmp = self._active_pin_bitmap - else: - bmp = self._inactive_pin_bitmap - - elif button == AUI_BUTTON_MAXIMIZE_RESTORE: - if pane.IsMaximized(): - if pane.state & optionActive: - bmp = self._active_restore_bitmap - else: - bmp = self._inactive_restore_bitmap - else: - if pane.state & optionActive: - bmp = self._active_maximize_bitmap - else: - bmp = self._inactive_maximize_bitmap - - elif button == AUI_BUTTON_MINIMIZE: - if pane.state & optionActive: - bmp = self._active_minimize_bitmap - else: - bmp = self._inactive_minimize_bitmap - - isVertical = pane.HasCaptionLeft() - - rect = wx.Rect(*_rect) - - if isVertical: - old_x = rect.x - rect.x = rect.x + (rect.width/2) - (bmp.GetWidth()/2) - rect.width = old_x + rect.width - rect.x - 1 - else: - old_y = rect.y - rect.y = rect.y + (rect.height/2) - (bmp.GetHeight()/2) - rect.height = old_y + rect.height - rect.y - 1 - - if button_state == AUI_BUTTON_STATE_PRESSED: - rect.x += 1 - rect.y += 1 - - if button_state in [AUI_BUTTON_STATE_HOVER, AUI_BUTTON_STATE_PRESSED]: - - if pane.state & optionActive: - - dc.SetBrush(wx.Brush(StepColour(self._active_caption_colour, 120))) - dc.SetPen(wx.Pen(StepColour(self._active_caption_colour, 70))) - - else: - - dc.SetBrush(wx.Brush(StepColour(self._inactive_caption_colour, 120))) - dc.SetPen(wx.Pen(StepColour(self._inactive_caption_colour, 70))) - - if wx.Platform != "__WXMAC__": - # draw the background behind the button - dc.DrawRectangle(rect.x, rect.y, 15, 15) - else: - # Darker the bitmap a bit - bmp = DarkenBitmap(bmp, self._active_caption_colour, StepColour(self._active_caption_colour, 110)) - - if isVertical: - bmp = wx.ImageFromBitmap(bmp).Rotate90(clockwise=False).ConvertToBitmap() - - # draw the button itself - dc.DrawBitmap(bmp, rect.x, rect.y, True) - - - def DrawSashGripper(self, dc, orient, rect): - """ - Draws a sash gripper on a sash between two windows. - - :param `dc`: a `wx.DC` device context; - :param `orient`: the sash orientation; - :param `rect`: the sash rectangle. - """ - - dc.SetBrush(self._gripper_brush) - - if orient == wx.HORIZONTAL: # horizontal sash - - x = rect.x + int((1.0/4.0)*rect.width) - xend = rect.x + int((3.0/4.0)*rect.width) - y = rect.y + (rect.height/2) - 1 - - while 1: - dc.SetPen(self._gripper_pen3) - dc.DrawRectangle(x, y, 2, 2) - dc.SetPen(self._gripper_pen2) - dc.DrawPoint(x+1, y+1) - x = x + 5 - - if x >= xend: - break - - else: - - y = rect.y + int((1.0/4.0)*rect.height) - yend = rect.y + int((3.0/4.0)*rect.height) - x = rect.x + (rect.width/2) - 1 - - while 1: - dc.SetPen(self._gripper_pen3) - dc.DrawRectangle(x, y, 2, 2) - dc.SetPen(self._gripper_pen2) - dc.DrawPoint(x+1, y+1) - y = y + 5 - - if y >= yend: - break - - - def SetDefaultPaneBitmaps(self, isMac): - """ - Assigns the default pane bitmaps. - - :param `isMac`: whether we are on wxMAC or not. - """ - - if isMac: - self._inactive_close_bitmap = DrawMACCloseButton(wx.WHITE, self._inactive_caption_colour) - self._active_close_bitmap = DrawMACCloseButton(wx.WHITE, self._active_caption_colour) - else: - self._inactive_close_bitmap = BitmapFromBits(close_bits, 16, 16, self._inactive_caption_text_colour) - self._active_close_bitmap = BitmapFromBits(close_bits, 16, 16, self._active_caption_text_colour) - - if isMac: - self._inactive_maximize_bitmap = BitmapFromBits(max_bits, 16, 16, wx.WHITE) - self._active_maximize_bitmap = BitmapFromBits(max_bits, 16, 16, wx.WHITE) - else: - self._inactive_maximize_bitmap = BitmapFromBits(max_bits, 16, 16, self._inactive_caption_text_colour) - self._active_maximize_bitmap = BitmapFromBits(max_bits, 16, 16, self._active_caption_text_colour) - - if isMac: - self._inactive_restore_bitmap = BitmapFromBits(restore_bits, 16, 16, wx.WHITE) - self._active_restore_bitmap = BitmapFromBits(restore_bits, 16, 16, wx.WHITE) - else: - self._inactive_restore_bitmap = BitmapFromBits(restore_bits, 16, 16, self._inactive_caption_text_colour) - self._active_restore_bitmap = BitmapFromBits(restore_bits, 16, 16, self._active_caption_text_colour) - - if isMac: - self._inactive_minimize_bitmap = BitmapFromBits(minimize_bits, 16, 16, wx.WHITE) - self._active_minimize_bitmap = BitmapFromBits(minimize_bits, 16, 16, wx.WHITE) - else: - self._inactive_minimize_bitmap = BitmapFromBits(minimize_bits, 16, 16, self._inactive_caption_text_colour) - self._active_minimize_bitmap = BitmapFromBits(minimize_bits, 16, 16, self._active_caption_text_colour) - - self._inactive_pin_bitmap = BitmapFromBits(pin_bits, 16, 16, self._inactive_caption_text_colour) - self._active_pin_bitmap = BitmapFromBits(pin_bits, 16, 16, self._active_caption_text_colour) - - self._custom_pane_bitmaps = False - - - def SetCustomPaneBitmap(self, bmp, button, active, maximize=False): - """ - Sets a custom button bitmap for the pane button. - - :param `bmp`: the actual bitmap to set; - :param `button`: the button identifier; - :param `active`: whether it is the bitmap for the active button or not; - :param `maximize`: used to distinguish between the maximize and restore bitmaps. - """ - - if bmp.GetWidth() > 16 or bmp.GetHeight() > 16: - raise Exception("The input bitmap is too big") - - if button == AUI_BUTTON_CLOSE: - if active: - self._active_close_bitmap = bmp - else: - self._inactive_close_bitmap = bmp - - if wx.Platform == "__WXMAC__": - self._custom_pane_bitmaps = True - - elif button == AUI_BUTTON_PIN: - if active: - self._active_pin_bitmap = bmp - else: - self._inactive_pin_bitmap = bmp - - elif button == AUI_BUTTON_MAXIMIZE_RESTORE: - if maximize: - if active: - self._active_maximize_bitmap = bmp - else: - self._inactive_maximize_bitmap = bmp - else: - if active: - self._active_restore_bitmap = bmp - else: - self._inactive_restore_bitmap = bmp - - elif button == AUI_BUTTON_MINIMIZE: - if active: - self._active_minimize_bitmap = bmp - else: - self._inactive_minimize_bitmap = bmp - - -if _ctypes: - class RECT(ctypes.Structure): - """ Used to handle L{ModernDockArt} on Windows XP/Vista/7. """ - _fields_ = [('left', ctypes.c_ulong),('top', ctypes.c_ulong),('right', ctypes.c_ulong),('bottom', ctypes.c_ulong)] - - def dump(self): - """ Dumps `self` as a `wx.Rect`. """ - return map(int, (self.left, self.top, self.right, self.bottom)) - - - class SIZE(ctypes.Structure): - """ Used to handle L{ModernDockArt} on Windows XP/Vista/7. """ - _fields_ = [('x', ctypes.c_long),('y', ctypes.c_long)] - - -class ModernDockArt(AuiDefaultDockArt): - """ - ModernDockArt is a custom `AuiDockArt` class, that implements a look similar to - Firefox and other recents applications. - - Is uses the `winxptheme` module and XP themes whenever possible, so it should - look good even if the user has a custom theme. - - :note: This dock art is Windows only and will only work if you have installed - Mark Hammond's `pywin32` module (http://sourceforge.net/projects/pywin32/). - """ - - def __init__(self, win): - """ - Default class constructor. - - :param `win`: the window managed by L{AuiManager}. - """ - - AuiDefaultDockArt.__init__(self) - - self.win = win - - # Get the size of a small close button (themed) - hwnd = self.win.GetHandle() - - self.hTheme1 = winxptheme.OpenThemeData(hwnd, "Window") - - self.usingTheme = True - - if not self.hTheme1: - self.usingTheme = False - - self._button_size = 13 - - self._button_border_size = 3 - self._caption_text_indent = 6 - self._caption_size = 22 - - # We only highlight the active pane with the caption text being in bold. - # So we do not want a special colour for active elements. - self._active_close_bitmap = self._inactive_close_bitmap - - self.Init() - - - def Init(self): - """ Initializes the dock art. """ - - AuiDefaultDockArt.Init(self) - - self._active_caption_colour = self._inactive_caption_colour - self._active_caption_text_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_CAPTIONTEXT) - self._inactive_caption_text_colour = self._active_caption_text_colour - - - def DrawCaption(self, dc, window, text, rect, pane): - """ - Draws the text in the pane caption. - - :param `dc`: a `wx.DC` device context; - :param `window`: an instance of `wx.Window`; - :param `text`: the text to be displayed; - :param `rect`: the pane caption rectangle; - :param `pane`: the pane for which the text is drawn. - """ - - dc.SetPen(wx.TRANSPARENT_PEN) - self.DrawCaptionBackground(dc, rect, pane) - - active = ((pane.state & optionActive) and [True] or [False])[0] - - self._caption_font.SetWeight(wx.FONTWEIGHT_BOLD) - dc.SetFont(self._caption_font) - - if active: - dc.SetTextForeground(self._active_caption_text_colour) - else: - dc.SetTextForeground(self._inactive_caption_text_colour) - - w, h = dc.GetTextExtent("ABCDEFHXfgkj") - - clip_rect = wx.Rect(*rect) - btns = pane.CountButtons() - - captionLeft = pane.HasCaptionLeft() - variable = (captionLeft and [rect.height] or [rect.width])[0] - - variable -= 3 # text offset - variable -= 2 # button padding - - caption_offset = 0 - if pane.icon: - if captionLeft: - caption_offset += pane.icon.GetHeight() + 3 - else: - caption_offset += pane.icon.GetWidth() + 3 - - self.DrawIcon(dc, rect, pane) - - diff = -2 - if self.usingTheme: - diff = -1 - - variable -= caption_offset - variable -= btns*(self._button_size + self._button_border_size) - draw_text = ChopText(dc, text, variable) - - if captionLeft: - dc.DrawRotatedText(draw_text, rect.x+(rect.width/2)-(h/2)-diff, rect.y+rect.height-3-caption_offset, 90) - else: - dc.DrawText(draw_text, rect.x+3+caption_offset, rect.y+(rect.height/2)-(h/2)-diff) - - - def DrawCaptionBackground(self, dc, rect, pane): - """ - Draws the text caption background in the pane. - - :param `dc`: a `wx.DC` device context; - :param `rect`: the text caption rectangle; - :param `pane`: the pane for which we are drawing the caption background. - """ - - dc.SetBrush(self._background_brush) - dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) - - active = ((pane.state & optionActive) and [True] or [False])[0] - - if self.usingTheme: - - rectangle = wx.Rect() - - rc = RECT(rectangle.x, rectangle.y, rectangle.width, rectangle.height) - - # If rect x/y values are negative rc.right/bottom values will overflow and winxptheme.DrawThemeBackground - # will raise a TypeError. Ensure they are never negative. - rect.x = max(0, rect.x) - rect.y = max(0, rect.y) - - rc.top = rect.x - rc.left = rect.y - rc.right = rect.x + rect.width - rc.bottom = rect.y + rect.height - - if active: - winxptheme.DrawThemeBackground(self.hTheme1, dc.GetHDC(), 5, 1, (rc.top, rc.left, rc.right, rc.bottom), None) - else: - winxptheme.DrawThemeBackground(self.hTheme1, dc.GetHDC(), 5, 2, (rc.top, rc.left, rc.right, rc.bottom), None) - - else: - - AuiDefaultDockArt.DrawCaptionBackground(self, dc, rect, pane) - - - def RequestUserAttention(self, dc, window, text, rect, pane): - """ - Requests the user attention by intermittently highlighting the pane caption. - - :param `dc`: a `wx.DC` device context; - :param `window`: an instance of `wx.Window`; - :param `text`: the text to be displayed; - :param `rect`: the pane caption rectangle; - :param `pane`: the pane for which the text is drawn. - """ - - state = pane.state - pane.state &= ~optionActive - - for indx in xrange(6): - active = (indx%2 == 0 and [True] or [False])[0] - if active: - pane.state |= optionActive - else: - pane.state &= ~optionActive - - self.DrawCaptionBackground(dc, rect, pane) - self.DrawCaption(dc, window, text, rect, pane) - wx.SafeYield() - wx.MilliSleep(350) - - pane.state = state - - - def DrawPaneButton(self, dc, window, button, button_state, rect, pane): - """ - Draws a pane button in the pane caption area. - - :param `dc`: a `wx.DC` device context; - :param `window`: an instance of `wx.Window`; - :param `button`: the button to be drawn; - :param `button_state`: the pane button state; - :param `rect`: the pane caption rectangle; - :param `pane`: the pane for which the button is drawn. - """ - - if self.usingTheme: - - hTheme = self.hTheme1 - - # Get the real button position (compensating for borders) - drect = wx.Rect(rect.x, rect.y, self._button_size, self._button_size) - - # Draw the themed close button - rc = RECT(0, 0, 0, 0) - if pane.HasCaptionLeft(): - rc.top = rect.x + self._button_border_size - rc.left = int(rect.y + 1.5*self._button_border_size) - rc.right = rect.x + self._button_size + self._button_border_size - rc.bottom = int(rect.y + self._button_size + 1.5*self._button_border_size) - else: - rc.top = rect.x - self._button_border_size - rc.left = int(rect.y + 1.5*self._button_border_size) - rc.right = rect.x + self._button_size- self._button_border_size - rc.bottom = int(rect.y + self._button_size + 1.5*self._button_border_size) - - if button == AUI_BUTTON_CLOSE: - btntype = 19 - - elif button == AUI_BUTTON_PIN: - btntype = 23 - - elif button == AUI_BUTTON_MAXIMIZE_RESTORE: - if not pane.IsMaximized(): - btntype = 17 - else: - btntype = 21 - else: - btntype = 15 - - state = 4 # CBS_DISABLED - - if pane.state & optionActive: - - if button_state == AUI_BUTTON_STATE_NORMAL: - state = 1 # CBS_NORMAL - - elif button_state == AUI_BUTTON_STATE_HOVER: - state = 2 # CBS_HOT - - elif button_state == AUI_BUTTON_STATE_PRESSED: - state = 3 # CBS_PUSHED - - else: - raise Exception("ERROR: Unknown State.") - - else: # inactive pane - - if button_state == AUI_BUTTON_STATE_NORMAL: - state = 5 # CBS_NORMAL - - elif button_state == AUI_BUTTON_STATE_HOVER: - state = 6 # CBS_HOT - - elif button_state == AUI_BUTTON_STATE_PRESSED: - state = 7 # CBS_PUSHED - - else: - raise Exception("ERROR: Unknown State.") - - try: - winxptheme.DrawThemeBackground(hTheme, dc.GetHDC(), btntype, state, (rc.top, rc.left, rc.right, rc.bottom), None) - except TypeError: - return - - else: - - # Fallback to default closebutton if themes are not enabled - rect2 = wx.Rect(rect.x-4, rect.y+2, rect.width, rect.height) - AuiDefaultDockArt.DrawPaneButton(self, dc, window, button, button_state, rect2, pane) - diff --git a/agw/aui/framemanager.py b/agw/aui/framemanager.py deleted file mode 100644 index 9b277bf..0000000 --- a/agw/aui/framemanager.py +++ /dev/null @@ -1,10385 +0,0 @@ -# --------------------------------------------------------------------------- # -# AUI Library wxPython IMPLEMENTATION -# -# Original C++ Code From Kirix (wxAUI). You Can Find It At: -# -# License: wxWidgets license -# -# http:#www.kirix.com/en/community/opensource/wxaui/about_wxaui.html -# -# Current wxAUI Version Tracked: wxWidgets 2.9.0 SVN HEAD -# -# -# Python Code By: -# -# Andrea Gavana, @ 23 Dec 2005 -# Latest Revision: 10 Mar 2011, 15.00 GMT -# -# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please -# Write To Me At: -# -# andrea.gavana@gmail.com -# gavana@kpo.kz -# -# Or, Obviously, To The wxPython Mailing List!!! -# -# End Of Comments -# --------------------------------------------------------------------------- # - -""" -Description -=========== - -framemanager is the central module of the AUI class framework. - -L{AuiManager} manages the panes associated with it for a particular `wx.Frame`, using -a pane's L{AuiPaneInfo} information to determine each pane's docking and floating -behavior. AuiManager uses wxPython' sizer mechanism to plan the layout of each frame. -It uses a replaceable dock art class to do all drawing, so all drawing is localized -in one area, and may be customized depending on an application's specific needs. - -AuiManager works as follows: the programmer adds panes to the class, or makes -changes to existing pane properties (dock position, floating state, show state, etc...). -To apply these changes, AuiManager's L{AuiManager.Update} function is called. This batch -processing can be used to avoid flicker, by modifying more than one pane at a time, -and then "committing" all of the changes at once by calling `Update()`. - -Panes can be added quite easily:: - - text1 = wx.TextCtrl(self, -1) - text2 = wx.TextCtrl(self, -1) - self._mgr.AddPane(text1, AuiPaneInfo().Left().Caption("Pane Number One")) - self._mgr.AddPane(text2, AuiPaneInfo().Bottom().Caption("Pane Number Two")) - - self._mgr.Update() - - -Later on, the positions can be modified easily. The following will float an -existing pane in a tool window:: - - self._mgr.GetPane(text1).Float() - - -Layers, Rows and Directions, Positions -====================================== - -Inside AUI, the docking layout is figured out by checking several pane parameters. -Four of these are important for determining where a pane will end up. - -**Direction** - Each docked pane has a direction, `Top`, `Bottom`, `Left`, `Right`, or `Center`. -This is fairly self-explanatory. The pane will be placed in the location specified -by this variable. - -**Position** - More than one pane can be placed inside of a "dock". Imagine two panes -being docked on the left side of a window. One pane can be placed over another. -In proportionally managed docks, the pane position indicates it's sequential position, -starting with zero. So, in our scenario with two panes docked on the left side, the -top pane in the dock would have position 0, and the second one would occupy position 1. - -**Row** - A row can allow for two docks to be placed next to each other. One of the most -common places for this to happen is in the toolbar. Multiple toolbar rows are allowed, -the first row being in row 0, and the second in row 1. Rows can also be used on -vertically docked panes. - -**Layer** - A layer is akin to an onion. Layer 0 is the very center of the managed pane. -Thus, if a pane is in layer 0, it will be closest to the center window (also sometimes -known as the "content window"). Increasing layers "swallow up" all layers of a lower -value. This can look very similar to multiple rows, but is different because all panes -in a lower level yield to panes in higher levels. The best way to understand layers -is by running the AUI sample (`AUI.py`). -""" - -__author__ = "Andrea Gavana " -__date__ = "31 March 2009" - - -import wx -import time -import types -import warnings - -import auibar -import auibook -import tabmdi -import dockart -import tabart - -from aui_utilities import Clip, PaneCreateStippleBitmap, GetDockingImage, GetSlidingPoints - -from aui_constants import * - -# Define this as a translation function -_ = wx.GetTranslation - -_winxptheme = False -if wx.Platform == "__WXMSW__": - try: - import winxptheme - _winxptheme = True - except ImportError: - pass - -# wxPython version string -_VERSION_STRING = wx.VERSION_STRING - -# AUI Events -wxEVT_AUI_PANE_BUTTON = wx.NewEventType() -wxEVT_AUI_PANE_CLOSE = wx.NewEventType() -wxEVT_AUI_PANE_MAXIMIZE = wx.NewEventType() -wxEVT_AUI_PANE_RESTORE = wx.NewEventType() -wxEVT_AUI_RENDER = wx.NewEventType() -wxEVT_AUI_FIND_MANAGER = wx.NewEventType() -wxEVT_AUI_PANE_MINIMIZE = wx.NewEventType() -wxEVT_AUI_PANE_MIN_RESTORE = wx.NewEventType() -wxEVT_AUI_PANE_FLOATING = wx.NewEventType() -wxEVT_AUI_PANE_FLOATED = wx.NewEventType() -wxEVT_AUI_PANE_DOCKING = wx.NewEventType() -wxEVT_AUI_PANE_DOCKED = wx.NewEventType() -wxEVT_AUI_PANE_ACTIVATED = wx.NewEventType() -wxEVT_AUI_PERSPECTIVE_CHANGED = wx.NewEventType() - -EVT_AUI_PANE_BUTTON = wx.PyEventBinder(wxEVT_AUI_PANE_BUTTON, 0) -""" Fires an event when the user left-clicks on a pane button. """ -EVT_AUI_PANE_CLOSE = wx.PyEventBinder(wxEVT_AUI_PANE_CLOSE, 0) -""" A pane in `AuiManager` has been closed. """ -EVT_AUI_PANE_MAXIMIZE = wx.PyEventBinder(wxEVT_AUI_PANE_MAXIMIZE, 0) -""" A pane in `AuiManager` has been maximized. """ -EVT_AUI_PANE_RESTORE = wx.PyEventBinder(wxEVT_AUI_PANE_RESTORE, 0) -""" A pane in `AuiManager` has been restored from a maximized state. """ -EVT_AUI_RENDER = wx.PyEventBinder(wxEVT_AUI_RENDER, 0) -""" Fires an event every time the AUI frame is being repainted. """ -EVT_AUI_FIND_MANAGER = wx.PyEventBinder(wxEVT_AUI_FIND_MANAGER, 0) -""" Used to find which AUI manager is controlling a certain pane. """ -EVT_AUI_PANE_MINIMIZE = wx.PyEventBinder(wxEVT_AUI_PANE_MINIMIZE, 0) -""" A pane in `AuiManager` has been minimized. """ -EVT_AUI_PANE_MIN_RESTORE = wx.PyEventBinder(wxEVT_AUI_PANE_MIN_RESTORE, 0) -""" A pane in `AuiManager` has been restored from a minimized state. """ -EVT_AUI_PANE_FLOATING = wx.PyEventBinder(wxEVT_AUI_PANE_FLOATING, 0) -""" A pane in `AuiManager` is about to be floated. """ -EVT_AUI_PANE_FLOATED = wx.PyEventBinder(wxEVT_AUI_PANE_FLOATED, 0) -""" A pane in `AuiManager` has been floated. """ -EVT_AUI_PANE_DOCKING = wx.PyEventBinder(wxEVT_AUI_PANE_DOCKING, 0) -""" A pane in `AuiManager` is about to be docked. """ -EVT_AUI_PANE_DOCKED = wx.PyEventBinder(wxEVT_AUI_PANE_DOCKED, 0) -""" A pane in `AuiManager` has been docked. """ -EVT_AUI_PANE_ACTIVATED = wx.PyEventBinder(wxEVT_AUI_PANE_ACTIVATED, 0) -""" A pane in `AuiManager` has been activated. """ -EVT_AUI_PERSPECTIVE_CHANGED = wx.PyEventBinder(wxEVT_AUI_PERSPECTIVE_CHANGED, 0) -""" The layout in `AuiManager` has been changed. """ - -# ---------------------------------------------------------------------------- # - -class AuiDockInfo(object): - """ A class to store all properties of a dock. """ - - def __init__(self): - """ - Default class constructor. - Used internally, do not call it in your code! - """ - - object.__init__(self) - - self.dock_direction = 0 - self.dock_layer = 0 - self.dock_row = 0 - self.size = 0 - self.min_size = 0 - self.resizable = True - self.fixed = False - self.toolbar = False - self.rect = wx.Rect() - self.panes = [] - - - def IsOk(self): - """ - Returns whether a dock is valid or not. - - In order to be valid, a dock needs to have a non-zero `dock_direction`. - """ - - return self.dock_direction != 0 - - - def IsHorizontal(self): - """ Returns whether the dock is horizontal or not. """ - - return self.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM] - - - def IsVertical(self): - """ Returns whether the dock is vertical or not. """ - - return self.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT, AUI_DOCK_CENTER] - - -# ---------------------------------------------------------------------------- # - -class AuiDockingGuideInfo(object): - """ A class which holds information about VS2005 docking guide windows. """ - - def __init__(self, other=None): - """ - Default class constructor. - Used internally, do not call it in your code! - - :param `other`: another instance of L{AuiDockingGuideInfo}. - """ - - if other: - self.Assign(other) - else: - # window representing the docking target - self.host = None - # dock direction (top, bottom, left, right, center) - self.dock_direction = AUI_DOCK_NONE - - - def Assign(self, other): - """ - Assigns the properties of the `other` L{AuiDockingGuideInfo} to `self`. - - :param `other`: another instance of L{AuiDockingGuideInfo}. - """ - - self.host = other.host - self.dock_direction = other.dock_direction - - - def Host(self, h): - """ - Hosts a docking guide window. - - :param `h`: an instance of L{AuiSingleDockingGuide} or L{AuiCenterDockingGuide}. - """ - - self.host = h - return self - - - def Left(self): - """ Sets the guide window to left docking. """ - - self.dock_direction = AUI_DOCK_LEFT - return self - - - def Right(self): - """ Sets the guide window to right docking. """ - - self.dock_direction = AUI_DOCK_RIGHT - return self - - - def Top(self): - """ Sets the guide window to top docking. """ - - self.dock_direction = AUI_DOCK_TOP - return self - - - def Bottom(self): - """ Sets the guide window to bottom docking. """ - - self.dock_direction = AUI_DOCK_BOTTOM - return self - - - def Center(self): - """ Sets the guide window to center docking. """ - - self.dock_direction = AUI_DOCK_CENTER - return self - - - def Centre(self): - """ Sets the guide window to centre docking. """ - - self.dock_direction = AUI_DOCK_CENTRE - return self - - -# ---------------------------------------------------------------------------- # - -class AuiDockUIPart(object): - """ A class which holds attributes for a UI part in the interface. """ - - typeCaption = 0 - typeGripper = 1 - typeDock = 2 - typeDockSizer = 3 - typePane = 4 - typePaneSizer = 5 - typeBackground = 6 - typePaneBorder = 7 - typePaneButton = 8 - - def __init__(self): - """ - Default class constructor. - Used internally, do not call it in your code! - """ - - self.orientation = wx.VERTICAL - self.type = 0 - self.rect = wx.Rect() - - -# ---------------------------------------------------------------------------- # - -class AuiPaneButton(object): - """ A simple class which describes the caption pane button attributes. """ - - def __init__(self, button_id): - """ - Default class constructor. - Used internally, do not call it in your code! - - :param `button_id`: the pane button identifier. - """ - - self.button_id = button_id - - -# ---------------------------------------------------------------------------- # - -# event declarations/classes - -class AuiManagerEvent(wx.PyCommandEvent): - """ A specialized command event class for events sent by L{AuiManager}. """ - - def __init__(self, eventType, id=1): - """ - Default class constructor. - - :param `eventType`: the event kind; - :param `id`: the event identification number. - """ - - wx.PyCommandEvent.__init__(self, eventType, id) - - self.manager = None - self.pane = None - self.button = 0 - self.veto_flag = False - self.canveto_flag = True - self.dc = None - - - def SetManager(self, mgr): - """ - Associates a L{AuiManager} to the current event. - - :param `mgr`: an instance of L{AuiManager}. - """ - - self.manager = mgr - - - def SetDC(self, pdc): - """ - Associates a `wx.DC` device context to this event. - - :param `pdc`: a `wx.DC` device context object. - """ - - self.dc = pdc - - - def SetPane(self, p): - """ - Associates a L{AuiPaneInfo} instance to this event. - - :param `p`: a L{AuiPaneInfo} instance. - """ - - self.pane = p - - - def SetButton(self, b): - """ - Associates a L{AuiPaneButton} instance to this event. - - :param `b`: a L{AuiPaneButton} instance. - """ - - self.button = b - - - def GetManager(self): - """ Returns the associated L{AuiManager} (if any). """ - - return self.manager - - - def GetDC(self): - """ Returns the associated `wx.DC` device context (if any). """ - - return self.dc - - - def GetPane(self): - """ Returns the associated L{AuiPaneInfo} structure (if any). """ - - return self.pane - - - def GetButton(self): - """ Returns the associated L{AuiPaneButton} instance (if any). """ - - return self.button - - - def Veto(self, veto=True): - """ - Prevents the change announced by this event from happening. - - It is in general a good idea to notify the user about the reasons for - vetoing the change because otherwise the applications behaviour (which - just refuses to do what the user wants) might be quite surprising. - - :param `veto`: ``True`` to veto the event, ``False`` otherwise. - """ - - self.veto_flag = veto - - - def GetVeto(self): - """ Returns whether the event has been vetoed or not. """ - - return self.veto_flag - - - def SetCanVeto(self, can_veto): - """ - Sets whether the event can be vetoed or not. - - :param `can_veto`: a bool flag. ``True`` if the event can be vetoed, ``False`` otherwise. - """ - - self.canveto_flag = can_veto - - - def CanVeto(self): - """ Returns whether the event can be vetoed and has been vetoed. """ - - return self.canveto_flag and self.veto_flag - - -# ---------------------------------------------------------------------------- # - -class AuiPaneInfo(object): - """ - AuiPaneInfo specifies all the parameters for a pane. These parameters specify where - the pane is on the screen, whether it is docked or floating, or hidden. In addition, - these parameters specify the pane's docked position, floating position, preferred - size, minimum size, caption text among many other parameters. - """ - - optionFloating = 2**0 - optionHidden = 2**1 - optionLeftDockable = 2**2 - optionRightDockable = 2**3 - optionTopDockable = 2**4 - optionBottomDockable = 2**5 - optionFloatable = 2**6 - optionMovable = 2**7 - optionResizable = 2**8 - optionPaneBorder = 2**9 - optionCaption = 2**10 - optionGripper = 2**11 - optionDestroyOnClose = 2**12 - optionToolbar = 2**13 - optionActive = 2**14 - optionGripperTop = 2**15 - optionMaximized = 2**16 - optionDockFixed = 2**17 - optionNotebookDockable = 2**18 - optionMinimized = 2**19 - optionLeftSnapped = 2**20 - optionRightSnapped = 2**21 - optionTopSnapped = 2**22 - optionBottomSnapped = 2**23 - optionFlyOut = 2**24 - optionCaptionLeft = 2**25 - - buttonClose = 2**26 - buttonMaximize = 2**27 - buttonMinimize = 2**28 - buttonPin = 2**29 - - buttonCustom1 = 2**30 - buttonCustom2 = 2**31 - buttonCustom3 = 2**32 - - savedHiddenState = 2**33 # used internally - actionPane = 2**34 # used internally - wasMaximized = 2**35 # used internally - needsRestore = 2**36 # used internally - - - def __init__(self): - """ Default class constructor. """ - - self.window = None - self.frame = None - self.state = 0 - self.dock_direction = AUI_DOCK_LEFT - self.dock_layer = 0 - self.dock_row = 0 - self.dock_pos = 0 - self.minimize_mode = AUI_MINIMIZE_POS_SMART - self.floating_pos = wx.Point(-1, -1) - self.floating_size = wx.Size(-1, -1) - self.best_size = wx.Size(-1, -1) - self.min_size = wx.Size(-1, -1) - self.max_size = wx.Size(-1, -1) - self.dock_proportion = 0 - self.caption = "" - self.buttons = [] - self.name = "" - self.icon = wx.NullIcon - self.rect = wx.Rect() - self.notebook_id = -1 - self.transparent = 255 - self.needsTransparency = False - self.previousDockPos = None - self.previousDockSize = 0 - self.snapped = 0 - - self.DefaultPane() - - - def dock_direction_get(self): - """ - Getter for the `dock_direction`. - - :see: L{dock_direction_set} for a set of valid docking directions. - """ - - if self.IsMaximized(): - return AUI_DOCK_CENTER - else: - return self._dock_direction - - - def dock_direction_set(self, value): - """ - Setter for the `dock_direction`. - - :param `value`: the docking direction. This cab ne one of the following bits: - - ============================ ======= ============================================= - Dock Flag Value Description - ============================ ======= ============================================= - ``AUI_DOCK_NONE`` 0 No docking direction. - ``AUI_DOCK_TOP`` 1 Top docking direction. - ``AUI_DOCK_RIGHT`` 2 Right docking direction. - ``AUI_DOCK_BOTTOM`` 3 Bottom docking direction. - ``AUI_DOCK_LEFT`` 4 Left docking direction. - ``AUI_DOCK_CENTER`` 5 Center docking direction. - ``AUI_DOCK_CENTRE`` 5 Centre docking direction. - ``AUI_DOCK_NOTEBOOK_PAGE`` 6 Automatic AuiNotebooks docking style. - ============================ ======= ============================================= - - """ - - self._dock_direction = value - - dock_direction = property(dock_direction_get, dock_direction_set) - - def IsOk(self): - """ - Returns ``True`` if the L{AuiPaneInfo} structure is valid. - - :note: A pane structure is valid if it has an associated window. - """ - - return self.window != None - - - def IsMaximized(self): - """ Returns ``True`` if the pane is maximized. """ - - return self.HasFlag(self.optionMaximized) - - - def IsMinimized(self): - """ Returns ``True`` if the pane is minimized. """ - - return self.HasFlag(self.optionMinimized) - - - def IsFixed(self): - """ Returns ``True`` if the pane cannot be resized. """ - - return not self.HasFlag(self.optionResizable) - - - def IsResizeable(self): - """ Returns ``True`` if the pane can be resized. """ - - return self.HasFlag(self.optionResizable) - - - def IsShown(self): - """ Returns ``True`` if the pane is currently shown. """ - - return not self.HasFlag(self.optionHidden) - - - def IsFloating(self): - """ Returns ``True`` if the pane is floating. """ - - return self.HasFlag(self.optionFloating) - - - def IsDocked(self): - """ Returns ``True`` if the pane is docked. """ - - return not self.HasFlag(self.optionFloating) - - - def IsToolbar(self): - """ Returns ``True`` if the pane contains a toolbar. """ - - return self.HasFlag(self.optionToolbar) - - - def IsTopDockable(self): - """ - Returns ``True`` if the pane can be docked at the top - of the managed frame. - """ - - return self.HasFlag(self.optionTopDockable) - - - def IsBottomDockable(self): - """ - Returns ``True`` if the pane can be docked at the bottom - of the managed frame. - """ - - return self.HasFlag(self.optionBottomDockable) - - - def IsLeftDockable(self): - """ - Returns ``True`` if the pane can be docked at the left - of the managed frame. - """ - - return self.HasFlag(self.optionLeftDockable) - - - def IsRightDockable(self): - """ - Returns ``True`` if the pane can be docked at the right - of the managed frame. - """ - - return self.HasFlag(self.optionRightDockable) - - - def IsDockable(self): - """ Returns ``True`` if the pane can be docked. """ - - return self.IsTopDockable() or self.IsBottomDockable() or self.IsLeftDockable() or \ - self.IsRightDockable() or self.IsNotebookDockable() - - - def IsFloatable(self): - """ - Returns ``True`` if the pane can be undocked and displayed as a - floating window. - """ - - return self.HasFlag(self.optionFloatable) - - - def IsMovable(self): - """ - Returns ``True`` if the docked frame can be undocked or moved to - another dock position. - """ - - return self.HasFlag(self.optionMovable) - - - def IsDestroyOnClose(self): - """ - Returns ``True`` if the pane should be destroyed when it is closed. - - Normally a pane is simply hidden when the close button is clicked. Calling L{DestroyOnClose} - with a ``True`` input parameter will cause the window to be destroyed when the user clicks - the pane's close button. - """ - - return self.HasFlag(self.optionDestroyOnClose) - - - def IsNotebookDockable(self): - """ - Returns ``True`` if a pane can be docked on top to another to create a - L{AuiNotebook}. - """ - - return self.HasFlag(self.optionNotebookDockable) - - - def IsTopSnappable(self): - """ Returns ``True`` if the pane can be snapped at the top of the managed frame. """ - - return self.HasFlag(self.optionTopSnapped) - - - def IsBottomSnappable(self): - """ Returns ``True`` if the pane can be snapped at the bottom of the managed frame. """ - - return self.HasFlag(self.optionBottomSnapped) - - - def IsLeftSnappable(self): - """ Returns ``True`` if the pane can be snapped on the left of the managed frame. """ - - return self.HasFlag(self.optionLeftSnapped) - - - def IsRightSnappable(self): - """ Returns ``True`` if the pane can be snapped on the right of the managed frame. """ - - return self.HasFlag(self.optionRightSnapped) - - - def IsSnappable(self): - """ Returns ``True`` if the pane can be snapped. """ - - return self.IsTopSnappable() or self.IsBottomSnappable() or self.IsLeftSnappable() or \ - self.IsRightSnappable() - - - def IsFlyOut(self): - """ Returns ``True`` if the floating pane has a "fly-out" effect. """ - - return self.HasFlag(self.optionFlyOut) - - - def HasCaption(self): - """ Returns ``True`` if the pane displays a caption. """ - - return self.HasFlag(self.optionCaption) - - - def HasCaptionLeft(self): - """ Returns ``True`` if the pane displays a caption on the left (rotated by 90 degrees). """ - - return self.HasFlag(self.optionCaptionLeft) - - - def HasGripper(self): - """ Returns ``True`` if the pane displays a gripper. """ - - return self.HasFlag(self.optionGripper) - - - def HasBorder(self): - """ Returns ``True`` if the pane displays a border. """ - - return self.HasFlag(self.optionPaneBorder) - - - def HasCloseButton(self): - """ Returns ``True`` if the pane displays a button to close the pane. """ - - return self.HasFlag(self.buttonClose) - - - def HasMaximizeButton(self): - """ Returns ``True`` if the pane displays a button to maximize the pane. """ - - return self.HasFlag(self.buttonMaximize) - - - def HasMinimizeButton(self): - """ Returns ``True`` if the pane displays a button to minimize the pane. """ - - return self.HasFlag(self.buttonMinimize) - - - def GetMinimizeMode(self): - """ - Returns the minimization style for this pane. - - Possible return values are: - - ============================== ========= ============================== - Minimize Mode Flag Hex Value Description - ============================== ========= ============================== - ``AUI_MINIMIZE_POS_SMART`` 0x01 Minimizes the pane on the closest tool bar - ``AUI_MINIMIZE_POS_TOP`` 0x02 Minimizes the pane on the top tool bar - ``AUI_MINIMIZE_POS_LEFT`` 0x03 Minimizes the pane on its left tool bar - ``AUI_MINIMIZE_POS_RIGHT`` 0x04 Minimizes the pane on its right tool bar - ``AUI_MINIMIZE_POS_BOTTOM`` 0x05 Minimizes the pane on its bottom tool bar - ``AUI_MINIMIZE_POS_MASK`` 0x07 Mask to filter the position flags - ``AUI_MINIMIZE_CAPT_HIDE`` 0x0 Hides the caption of the minimized pane - ``AUI_MINIMIZE_CAPT_SMART`` 0x08 Displays the caption in the best rotation (horizontal or clockwise) - ``AUI_MINIMIZE_CAPT_HORZ`` 0x10 Displays the caption horizontally - ``AUI_MINIMIZE_CAPT_MASK`` 0x18 Mask to filter the caption flags - ============================== ========= ============================== - - The flags can be filtered with the following masks: - - ============================== ========= ============================== - Minimize Mask Flag Hex Value Description - ============================== ========= ============================== - ``AUI_MINIMIZE_POS_MASK`` 0x07 Filters the position flags - ``AUI_MINIMIZE_CAPT_MASK`` 0x18 Filters the caption flags - ============================== ========= ============================== - - """ - - return self.minimize_mode - - - def HasPinButton(self): - """ Returns ``True`` if the pane displays a button to float the pane. """ - - return self.HasFlag(self.buttonPin) - - - def HasGripperTop(self): - """ Returns ``True`` if the pane displays a gripper at the top. """ - - return self.HasFlag(self.optionGripperTop) - - - def Window(self, w): - """ - Associate a `wx.Window` derived window to this pane. - - This normally does not need to be specified, as the window pointer is - automatically assigned to the L{AuiPaneInfo} structure as soon as it is - added to the manager. - - :param `w`: a `wx.Window` derived window. - """ - - self.window = w - return self - - - def Name(self, name): - """ - Sets the name of the pane so it can be referenced in lookup functions. - - If a name is not specified by the user, a random name is assigned to the pane - when it is added to the manager. - - :param `name`: a string specifying the pane name. - - :warning: If you are using L{AuiManager.SavePerspective} and L{AuiManager.LoadPerspective}, you will have - to specify a name for your pane using L{Name}, as randomly generated names can - not be properly restored. - """ - - self.name = name - return self - - - def Caption(self, caption): - """ - Sets the caption of the pane. - - :param `caption`: a string specifying the pane caption. - """ - - self.caption = caption - return self - - - def Left(self): - """ - Sets the pane dock position to the left side of the frame. - - :note: This is the same thing as calling L{Direction} with ``AUI_DOCK_LEFT`` as - parameter. - """ - - self.dock_direction = AUI_DOCK_LEFT - return self - - - def Right(self): - """ - Sets the pane dock position to the right side of the frame. - - :note: This is the same thing as calling L{Direction} with ``AUI_DOCK_RIGHT`` as - parameter. - """ - - self.dock_direction = AUI_DOCK_RIGHT - return self - - - def Top(self): - """ - Sets the pane dock position to the top of the frame. - - :note: This is the same thing as calling L{Direction} with ``AUI_DOCK_TOP`` as - parameter. - """ - - self.dock_direction = AUI_DOCK_TOP - return self - - - def Bottom(self): - """ - Sets the pane dock position to the bottom of the frame. - - :note: This is the same thing as calling L{Direction} with ``AUI_DOCK_BOTTOM`` as - parameter. - """ - - self.dock_direction = AUI_DOCK_BOTTOM - return self - - - def Center(self): - """ - Sets the pane to the center position of the frame. - - The centre pane is the space in the middle after all border panes (left, top, - right, bottom) are subtracted from the layout. - - :note: This is the same thing as calling L{Direction} with ``AUI_DOCK_CENTER`` as - parameter. - """ - - self.dock_direction = AUI_DOCK_CENTER - return self - - - def Centre(self): - """ - Sets the pane to the center position of the frame. - - The centre pane is the space in the middle after all border panes (left, top, - right, bottom) are subtracted from the layout. - - :note: This is the same thing as calling L{Direction} with ``AUI_DOCK_CENTRE`` as - parameter. - """ - - self.dock_direction = AUI_DOCK_CENTRE - return self - - - def Direction(self, direction): - """ - Determines the direction of the docked pane. It is functionally the - same as calling L{Left}, L{Right}, L{Top} or L{Bottom}, except that docking direction - may be specified programmatically via the parameter `direction`. - - :param `direction`: the direction of the docked pane. - - :see: L{dock_direction_set} for a list of valid docking directions. - """ - - self.dock_direction = direction - return self - - - def Layer(self, layer): - """ - Determines the layer of the docked pane. - - The dock layer is similar to an onion, the inner-most layer being layer 0. Each - shell moving in the outward direction has a higher layer number. This allows for - more complex docking layout formation. - - :param `layer`: the layer of the docked pane. - """ - - self.dock_layer = layer - return self - - - def Row(self, row): - """ - Determines the row of the docked pane. - - :param `row`: the row of the docked pane. - """ - - self.dock_row = row - return self - - - def Position(self, pos): - """ - Determines the position of the docked pane. - - :param `pos`: the position of the docked pane. - """ - - self.dock_pos = pos - return self - - - def MinSize(self, arg1=None, arg2=None): - """ - Sets the minimum size of the pane. - - This method is split in 2 versions depending on the input type. If `arg1` is - a `wx.Size` object, then L{MinSize1} is called. Otherwise, L{MinSize2} is called. - - :param `arg1`: a `wx.Size` object, a (x, y) tuple or or a `x` coordinate. - :param `arg2`: a `y` coordinate (only if `arg1` is a `x` coordinate, otherwise unused). - """ - - if isinstance(arg1, wx.Size): - ret = self.MinSize1(arg1) - elif isinstance(arg1, types.TupleType): - ret = self.MinSize1(wx.Size(*arg1)) - else: - ret = self.MinSize2(arg1, arg2) - - return ret - - - def MinSize1(self, size): - """ - Sets the minimum size of the pane. - - :see: L{MinSize} for an explanation of input parameters. - """ - self.min_size = size - return self - - - def MinSize2(self, x, y): - """ - Sets the minimum size of the pane. - - :see: L{MinSize} for an explanation of input parameters. - """ - - self.min_size = wx.Size(x, y) - return self - - - def MaxSize(self, arg1=None, arg2=None): - """ - Sets the maximum size of the pane. - - This method is split in 2 versions depending on the input type. If `arg1` is - a `wx.Size` object, then L{MaxSize1} is called. Otherwise, L{MaxSize2} is called. - - :param `arg1`: a `wx.Size` object, a (x, y) tuple or a `x` coordinate. - :param `arg2`: a `y` coordinate (only if `arg1` is a `x` coordinate, otherwise unused). - """ - - if isinstance(arg1, wx.Size): - ret = self.MaxSize1(arg1) - elif isinstance(arg1, types.TupleType): - ret = self.MaxSize1(wx.Size(*arg1)) - else: - ret = self.MaxSize2(arg1, arg2) - - return ret - - - def MaxSize1(self, size): - """ - Sets the maximum size of the pane. - - :see: L{MaxSize} for an explanation of input parameters. - """ - - self.max_size = size - return self - - - def MaxSize2(self, x, y): - """ - Sets the maximum size of the pane. - - :see: L{MaxSize} for an explanation of input parameters. - """ - - self.max_size.Set(x,y) - return self - - - def BestSize(self, arg1=None, arg2=None): - """ - Sets the ideal size for the pane. The docking manager will attempt to use - this size as much as possible when docking or floating the pane. - - This method is split in 2 versions depending on the input type. If `arg1` is - a `wx.Size` object, then L{BestSize1} is called. Otherwise, L{BestSize2} is called. - - :param `arg1`: a `wx.Size` object, a (x, y) tuple or a `x` coordinate. - :param `arg2`: a `y` coordinate (only if `arg1` is a `x` coordinate, otherwise unused). - """ - - if isinstance(arg1, wx.Size): - ret = self.BestSize1(arg1) - elif isinstance(arg1, types.TupleType): - ret = self.BestSize1(wx.Size(*arg1)) - else: - ret = self.BestSize2(arg1, arg2) - - return ret - - - def BestSize1(self, size): - """ - Sets the best size of the pane. - - :see: L{BestSize} for an explanation of input parameters. - """ - - self.best_size = size - return self - - - def BestSize2(self, x, y): - """ - Sets the best size of the pane. - - :see: L{BestSize} for an explanation of input parameters. - """ - - self.best_size.Set(x,y) - return self - - - def FloatingPosition(self, pos): - """ - Sets the position of the floating pane. - - :param `pos`: a `wx.Point` or a tuple indicating the pane floating position. - """ - - self.floating_pos = wx.Point(*pos) - return self - - - def FloatingSize(self, size): - """ - Sets the size of the floating pane. - - :param `size`: a `wx.Size` or a tuple indicating the pane floating size. - """ - - self.floating_size = wx.Size(*size) - return self - - - def Maximize(self): - """ Makes the pane take up the full area.""" - - return self.SetFlag(self.optionMaximized, True) - - - def Minimize(self): - """ - Makes the pane minimized in a L{AuiToolBar}. - - Clicking on the minimize button causes a new L{AuiToolBar} to be created - and added to the frame manager, (currently the implementation is such that - panes at West will have a toolbar at the right, panes at South will have - toolbars at the bottom etc...) and the pane is hidden in the manager. - - Clicking on the restore button on the newly created toolbar will result in the - toolbar being removed and the original pane being restored. - """ - - return self.SetFlag(self.optionMinimized, True) - - - def MinimizeMode(self, mode): - """ - Sets the expected minimized mode if the MinimizeButton() is visible. - - The minimized pane can have a specific position in the work space: - - ============================== ========= ============================== - Minimize Mode Flag Hex Value Description - ============================== ========= ============================== - ``AUI_MINIMIZE_POS_SMART`` 0x01 Minimizes the pane on the closest tool bar - ``AUI_MINIMIZE_POS_TOP`` 0x02 Minimizes the pane on the top tool bar - ``AUI_MINIMIZE_POS_LEFT`` 0x03 Minimizes the pane on its left tool bar - ``AUI_MINIMIZE_POS_RIGHT`` 0x04 Minimizes the pane on its right tool bar - ``AUI_MINIMIZE_POS_BOTTOM`` 0x05 Minimizes the pane on its bottom tool bar - ============================== ========= ============================== - - The caption of the minimized pane can be displayed in different modes: - - ============================== ========= ============================== - Caption Mode Flag Hex Value Description - ============================== ========= ============================== - ``AUI_MINIMIZE_CAPT_HIDE`` 0x0 Hides the caption of the minimized pane - ``AUI_MINIMIZE_CAPT_SMART`` 0x08 Displays the caption in the best rotation (horizontal in the top and in the bottom tool bar or clockwise in the right and in the left tool bar) - ``AUI_MINIMIZE_CAPT_HORZ`` 0x10 Displays the caption horizontally - ============================== ========= ============================== - - """ - - self.minimize_mode = mode - return self - - - def Restore(self): - """ Is the reverse of L{Maximize} and L{Minimize}.""" - - return self.SetFlag(self.optionMaximized or self.optionMinimized, False) - - - def Fixed(self): - """ - Forces a pane to be fixed size so that it cannot be resized. - After calling L{Fixed}, L{IsFixed} will return ``True``. - """ - - return self.SetFlag(self.optionResizable, False) - - - def Resizable(self, resizable=True): - """ - Allows a pane to be resizable if `resizable` is ``True``, and forces - it to be a fixed size if `resizeable` is ``False``. - - If `resizable` is ``False``, this is simply an antonym for L{Fixed}. - - :param `resizable`: whether the pane will be resizeable or not. - """ - - return self.SetFlag(self.optionResizable, resizable) - - - def Transparent(self, alpha): - """ - Makes the pane transparent when floating. - - :param `alpha`: an integer value between 0 and 255 for pane transparency. - """ - - if alpha < 0 or alpha > 255: - raise Exception("Invalid transparency value (%s)"%repr(alpha)) - - self.transparent = alpha - self.needsTransparency = True - - - def Dock(self): - """ - Indicates that a pane should be docked. It is the opposite of L{Float}. - """ - - if self.IsNotebookPage(): - self.notebook_id = -1 - self.dock_direction = AUI_DOCK_NONE - - return self.SetFlag(self.optionFloating, False) - - - def Float(self): - """ - Indicates that a pane should be floated. It is the opposite of L{Dock}. - """ - - if self.IsNotebookPage(): - self.notebook_id = -1 - self.dock_direction = AUI_DOCK_NONE - - return self.SetFlag(self.optionFloating, True) - - - def Hide(self): - """ - Indicates that a pane should be hidden. - - Calling L{Show} (``False``) achieve the same effect. - """ - - return self.SetFlag(self.optionHidden, True) - - - def Show(self, show=True): - """ - Indicates that a pane should be shown. - - :param `show`: whether the pane should be shown or not. - """ - - return self.SetFlag(self.optionHidden, not show) - - - # By defaulting to 1000, the tab will get placed at the end - def NotebookPage(self, id, tab_position=1000): - """ - Forces a pane to be a notebook page, so that the pane can be - docked on top to another to create a L{AuiNotebook}. - - :param `id`: the notebook id; - :param `tab_position`: the tab number of the pane once docked in a notebook. - """ - - # Remove any floating frame - self.Dock() - self.notebook_id = id - self.dock_pos = tab_position - self.dock_row = 0 - self.dock_layer = 0 - self.dock_direction = AUI_DOCK_NOTEBOOK_PAGE - - return self - - - def NotebookControl(self, id): - """ - Forces a pane to be a notebook control (L{AuiNotebook}). - - :param `id`: the notebook id. - """ - - self.notebook_id = id - self.window = None - self.buttons = [] - - if self.dock_direction == AUI_DOCK_NOTEBOOK_PAGE: - self.dock_direction = AUI_DOCK_NONE - - return self - - - def HasNotebook(self): - """ Returns whether a pane has a L{AuiNotebook} or not. """ - - return self.notebook_id >= 0 - - - def IsNotebookPage(self): - """ Returns whether the pane is a notebook page in a L{AuiNotebook}. """ - - return self.notebook_id >= 0 and self.dock_direction == AUI_DOCK_NOTEBOOK_PAGE - - - def IsNotebookControl(self): - """ Returns whether the pane is a notebook control (L{AuiNotebook}). """ - - return not self.IsNotebookPage() and self.HasNotebook() - - - def SetNameFromNotebookId(self): - """ Sets the pane name once docked in a L{AuiNotebook} using the notebook id. """ - - if self.notebook_id >= 0: - self.name = "__notebook_%d"%self.notebook_id - - return self - - - def CaptionVisible(self, visible=True, left=False): - """ - Indicates that a pane caption should be visible. If `visible` is ``False``, no pane - caption is drawn. - - :param `visible`: whether the caption should be visible or not; - :param `left`: whether the caption should be drawn on the left (rotated by 90 degrees) or not. - """ - - if left: - self.SetFlag(self.optionCaption, False) - return self.SetFlag(self.optionCaptionLeft, visible) - - self.SetFlag(self.optionCaptionLeft, False) - return self.SetFlag(self.optionCaption, visible) - - - def PaneBorder(self, visible=True): - """ - Indicates that a border should be drawn for the pane. - - :param `visible`: whether the pane border should be visible or not. - """ - - return self.SetFlag(self.optionPaneBorder, visible) - - - def Gripper(self, visible=True): - """ - Indicates that a gripper should be drawn for the pane. - - :param `visible`: whether the gripper should be visible or not. - """ - - return self.SetFlag(self.optionGripper, visible) - - - def GripperTop(self, attop=True): - """ - Indicates that a gripper should be drawn at the top of the pane. - - :param `attop`: whether the gripper should be drawn at the top or not. - """ - - return self.SetFlag(self.optionGripperTop, attop) - - - def CloseButton(self, visible=True): - """ - Indicates that a close button should be drawn for the pane. - - :param `visible`: whether the close button should be visible or not. - """ - - return self.SetFlag(self.buttonClose, visible) - - - def MaximizeButton(self, visible=True): - """ - Indicates that a maximize button should be drawn for the pane. - - :param `visible`: whether the maximize button should be visible or not. - """ - - return self.SetFlag(self.buttonMaximize, visible) - - - def MinimizeButton(self, visible=True): - """ - Indicates that a minimize button should be drawn for the pane. - - :param `visible`: whether the minimize button should be visible or not. - """ - - return self.SetFlag(self.buttonMinimize, visible) - - - def PinButton(self, visible=True): - """ - Indicates that a pin button should be drawn for the pane. - - :param `visible`: whether the pin button should be visible or not. - """ - - return self.SetFlag(self.buttonPin, visible) - - - def DestroyOnClose(self, b=True): - """ - Indicates whether a pane should be destroyed when it is closed. - - Normally a pane is simply hidden when the close button is clicked. Setting - `b` to ``True`` will cause the window to be destroyed when the user clicks - the pane's close button. - - :param `b`: whether the pane should be destroyed when it is closed or not. - """ - - return self.SetFlag(self.optionDestroyOnClose, b) - - - def TopDockable(self, b=True): - """ - Indicates whether a pane can be docked at the top of the frame. - - :param `b`: whether the pane can be docked at the top or not. - """ - - return self.SetFlag(self.optionTopDockable, b) - - - def BottomDockable(self, b=True): - """ - Indicates whether a pane can be docked at the bottom of the frame. - - :param `b`: whether the pane can be docked at the bottom or not. - """ - - return self.SetFlag(self.optionBottomDockable, b) - - - def LeftDockable(self, b=True): - """ - Indicates whether a pane can be docked on the left of the frame. - - :param `b`: whether the pane can be docked at the left or not. - """ - - return self.SetFlag(self.optionLeftDockable, b) - - - def RightDockable(self, b=True): - """ - Indicates whether a pane can be docked on the right of the frame. - - :param `b`: whether the pane can be docked at the right or not. - """ - - return self.SetFlag(self.optionRightDockable, b) - - - def Floatable(self, b=True): - """ - Sets whether the user will be able to undock a pane and turn it - into a floating window. - - :param `b`: whether the pane can be floated or not. - """ - - return self.SetFlag(self.optionFloatable, b) - - - def Movable(self, b=True): - """ - Indicates whether a pane can be moved. - - :param `b`: whether the pane can be moved or not. - """ - - return self.SetFlag(self.optionMovable, b) - - - def NotebookDockable(self, b=True): - """ - Indicates whether a pane can be docked in an automatic L{AuiNotebook}. - - :param `b`: whether the pane can be docked in a notebook or not. - """ - - return self.SetFlag(self.optionNotebookDockable, b) - - - def DockFixed(self, b=True): - """ - Causes the containing dock to have no resize sash. This is useful - for creating panes that span the entire width or height of a dock, but should - not be resizable in the other direction. - - :param `b`: whether the pane will have a resize sash or not. - """ - - return self.SetFlag(self.optionDockFixed, b) - - - def Dockable(self, b=True): - """ - Specifies whether a frame can be docked or not. It is the same as specifying - L{TopDockable} . L{BottomDockable} . L{LeftDockable} . L{RightDockable} . - - :param `b`: whether the frame can be docked or not. - """ - - return self.TopDockable(b).BottomDockable(b).LeftDockable(b).RightDockable(b) - - - def TopSnappable(self, b=True): - """ - Indicates whether a pane can be snapped at the top of the main frame. - - :param `b`: whether the pane can be snapped at the top of the main frame or not. - """ - - return self.SetFlag(self.optionTopSnapped, b) - - - def BottomSnappable(self, b=True): - """ - Indicates whether a pane can be snapped at the bottom of the main frame. - - :param `b`: whether the pane can be snapped at the bottom of the main frame or not. - """ - - return self.SetFlag(self.optionBottomSnapped, b) - - - def LeftSnappable(self, b=True): - """ - Indicates whether a pane can be snapped on the left of the main frame. - - :param `b`: whether the pane can be snapped at the left of the main frame or not. - """ - - return self.SetFlag(self.optionLeftSnapped, b) - - - def RightSnappable(self, b=True): - """ - Indicates whether a pane can be snapped on the right of the main frame. - - :param `b`: whether the pane can be snapped at the right of the main frame or not. - """ - - return self.SetFlag(self.optionRightSnapped, b) - - - def Snappable(self, b=True): - """ - Indicates whether a pane can be snapped on the main frame. This is - equivalent as calling L{TopSnappable} . L{BottomSnappable} . L{LeftSnappable} . L{RightSnappable} . - - :param `b`: whether the pane can be snapped on the main frame or not. - """ - - return self.TopSnappable(b).BottomSnappable(b).LeftSnappable(b).RightSnappable(b) - - - def FlyOut(self, b=True): - """ - Indicates whether a pane, when floating, has a "fly-out" effect - (i.e., floating panes which only show themselves when moused over). - - :param `b`: whether the pane can be snapped on the main frame or not. - """ - - return self.SetFlag(self.optionFlyOut, b) - - - # Copy over the members that pertain to docking position - def SetDockPos(self, source): - """ - Copies the `source` pane members that pertain to docking position to `self`. - - :param `source`: the source pane from where to copy the attributes. - """ - - self.dock_direction = source.dock_direction - self.dock_layer = source.dock_layer - self.dock_row = source.dock_row - self.dock_pos = source.dock_pos - self.dock_proportion = source.dock_proportion - self.floating_pos = wx.Point(*source.floating_pos) - self.floating_size = wx.Size(*source.floating_size) - self.rect = wx.Rect(*source.rect) - - return self - - - def DefaultPane(self): - """ Specifies that the pane should adopt the default pane settings. """ - - state = self.state - state |= self.optionTopDockable | self.optionBottomDockable | \ - self.optionLeftDockable | self.optionRightDockable | \ - self.optionNotebookDockable | \ - self.optionFloatable | self.optionMovable | self.optionResizable | \ - self.optionCaption | self.optionPaneBorder | self.buttonClose - - self.state = state - - return self - - - def CentrePane(self): - """ - Specifies that the pane should adopt the default center pane settings. - - Centre panes usually do not have caption bars. This function provides an easy way of - preparing a pane to be displayed in the center dock position. - """ - - return self.CenterPane() - - - def CenterPane(self): - """ - Specifies that the pane should adopt the default center pane settings. - - Centre panes usually do not have caption bars. This function provides an easy way of - preparing a pane to be displayed in the center dock position. - """ - - self.state = 0 - return self.Center().PaneBorder().Resizable() - - - def ToolbarPane(self): - """ Specifies that the pane should adopt the default toolbar pane settings. """ - - self.DefaultPane() - state = self.state - - state |= (self.optionToolbar | self.optionGripper) - state &= ~(self.optionResizable | self.optionCaption | self.optionCaptionLeft) - - if self.dock_layer == 0: - self.dock_layer = 10 - - self.state = state - - return self - - - def Icon(self, icon): - """ - Specifies whether an icon is drawn on the left of the caption text when - the pane is docked. If `icon` is ``None`` or `wx.NullIcon`, no icon is drawn on - the caption space. - - :param icon: an icon to draw on the caption space, or ``None``. - """ - - if icon is None: - icon = wx.NullIcon - - self.icon = icon - return self - - - def SetFlag(self, flag, option_state): - """ - Turns the property given by `flag` on or off with the `option_state` - parameter. - - :param `flag`: the property to set; - :param `option_state`: either ``True`` or ``False``. - """ - - state = self.state - - if option_state: - state |= flag - else: - state &= ~flag - - self.state = state - - if flag in [self.buttonClose, self.buttonMaximize, self.buttonMinimize, self.buttonPin]: - self.ResetButtons() - - return self - - - def HasFlag(self, flag): - """ - Returns ``True`` if the the property specified by flag is active for the pane. - - :param `flag`: the property to check for activity. - """ - - return (self.state & flag and [True] or [False])[0] - - - def ResetButtons(self): - """ - Resets all the buttons and recreates them from scratch depending on the - L{AuiPaneInfo} flags. - """ - - floating = self.HasFlag(self.optionFloating) - self.buttons = [] - - if not floating and self.HasMinimizeButton(): - button = AuiPaneButton(AUI_BUTTON_MINIMIZE) - self.buttons.append(button) - - if not floating and self.HasMaximizeButton(): - button = AuiPaneButton(AUI_BUTTON_MAXIMIZE_RESTORE) - self.buttons.append(button) - - if not floating and self.HasPinButton(): - button = AuiPaneButton(AUI_BUTTON_PIN) - self.buttons.append(button) - - if self.HasCloseButton(): - button = AuiPaneButton(AUI_BUTTON_CLOSE) - self.buttons.append(button) - - - def CountButtons(self): - """ Returns the number of visible buttons in the docked pane. """ - - n = 0 - - if self.HasCaption() or self.HasCaptionLeft(): - if isinstance(wx.GetTopLevelParent(self.window), AuiFloatingFrame): - return 1 - - if self.HasCloseButton(): - n += 1 - if self.HasMaximizeButton(): - n += 1 - if self.HasMinimizeButton(): - n += 1 - if self.HasPinButton(): - n += 1 - - return n - - - def IsHorizontal(self): - """ Returns ``True`` if the pane `dock_direction` is horizontal. """ - - return self.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM] - - def IsVertical(self): - """ Returns ``True`` if the pane `dock_direction` is vertical. """ - - return self.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT] - - -# Null AuiPaneInfo reference -NonePaneInfo = AuiPaneInfo() - - -# ---------------------------------------------------------------------------- # - -class AuiDockingGuide(wx.Frame): - """ Base class for L{AuiCenterDockingGuide} and L{AuiSingleDockingGuide}.""" - - def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition, - size=wx.DefaultSize, style=wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP | - wx.FRAME_NO_TASKBAR | wx.NO_BORDER, name="AuiDockingGuide"): - """ - Default class constructor. Used internally, do not call it in your code! - - :param `parent`: the L{AuiDockingGuide} parent; - :param `id`: the window identifier. It may take a value of -1 to indicate a default value. - :param `title`: the caption to be displayed on the frame's title bar. - :param `pos`: the window position. A value of (-1, -1) indicates a default position, - chosen by either the windowing system or wxPython, depending on platform. - :param `size`: the window size. A value of (-1, -1) indicates a default size, chosen by - either the windowing system or wxPython, depending on platform. - :param `style`: the window style. - :param `name`: the name of the window. This parameter is used to associate a name with the - item, allowing the application user to set Motif resource values for individual windows. - """ - - wx.Frame.__init__(self, parent, id, title, pos, size, style, name=name) - - - def HitTest(self, x, y): - """ - To be overridden by parent classes. - - :param `x`: the `x` mouse position; - :param `y`: the `y` mouse position. - """ - - return 0 - - - def ValidateNotebookDocking(self, valid): - """ - To be overridden by parent classes. - - :param `valid`: whether a pane can be docked on top to another to form an automatic - L{AuiNotebook}. - """ - - return 0 - -# ============================================================================ -# implementation -# ============================================================================ - -# --------------------------------------------------------------------------- -# AuiDockingGuideWindow -# --------------------------------------------------------------------------- - -class AuiDockingGuideWindow(wx.Window): - """ Target class for L{AuiSingleDockingGuide} and L{AuiCenterDockingGuide}. """ - - def __init__(self, parent, rect, direction=0, center=False, useAero=False): - """ - Default class constructor. Used internally, do not call it in your code! - - :param `parent`: the L{AuiDockingGuideWindow} parent; - :param `rect`: the window rect; - :param `direction`: one of ``wx.TOP``, ``wx.BOTTOM``, ``wx.LEFT``, ``wx.RIGHT``, - ``wx.CENTER``; - :param `center`: whether the calling class is a L{AuiCenterDockingGuide}; - :param `useAero`: whether to use the new Aero-style bitmaps or Whidbey-style bitmaps - for the docking guide. - """ - - wx.Window.__init__(self, parent, -1, rect.GetPosition(), rect.GetSize(), wx.NO_BORDER) - - self._direction = direction - self._center = center - self._valid = True - self._useAero = useAero - - self._bmp_unfocus, self._bmp_focus = GetDockingImage(direction, useAero, center) - - self._currentImage = self._bmp_unfocus - self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) - - self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) - self.Bind(wx.EVT_PAINT, self.OnPaint) - - - def SetValid(self, valid): - """ - Sets the docking direction as valid or invalid. - - :param `valid`: whether the docking direction is allowed or not. - """ - - self._valid = valid - - - def IsValid(self): - """ Returns whether the docking direction is valid. """ - - return self._valid - - - def OnEraseBackground(self, event): - """ - Handles the ``wx.EVT_ERASE_BACKGROUND`` event for L{AuiDockingGuideWindow}. - - :param `event`: a `wx.EraseEvent` to be processed. - - :note: This is intentionally empty to reduce flickering while drawing. - """ - - pass - - - def DrawBackground(self, dc): - """ - Draws the docking guide background. - - :param `dc`: a `wx.DC` device context object. - """ - - rect = self.GetClientRect() - - dc.SetPen(wx.TRANSPARENT_PEN) - dc.SetBrush(wx.Brush(colourTargetBackground)) - dc.DrawRectangleRect(rect) - - dc.SetPen(wx.Pen(colourTargetBorder)) - - left = rect.GetLeft() - top = rect.GetTop() - right = rect.GetRight() - bottom = rect.GetBottom() - - if self._direction != wx.CENTER: - - if not self._center or self._direction != wx.BOTTOM: - dc.DrawLine(left, top, right+1, top) - if not self._center or self._direction != wx.RIGHT: - dc.DrawLine(left, top, left, bottom+1) - if not self._center or self._direction != wx.LEFT: - dc.DrawLine(right, top, right, bottom+1) - if not self._center or self._direction != wx.TOP: - dc.DrawLine(left, bottom, right+1, bottom) - - dc.SetPen(wx.Pen(colourTargetShade)) - - if self._direction != wx.RIGHT: - dc.DrawLine(left + 1, top + 1, left + 1, bottom) - if self._direction != wx.BOTTOM: - dc.DrawLine(left + 1, top + 1, right, top + 1) - - - def DrawDottedLine(self, dc, point, length, vertical): - """ - Draws a dotted line (not used if the docking guide images are ok). - - :param `dc`: a `wx.DC` device context object; - :param `point`: a `wx.Point` where to start drawing the dotted line; - :param `length`: the length of the dotted line; - :param `vertical`: whether it is a vertical docking guide window or not. - """ - - for i in xrange(0, length, 2): - dc.DrawPoint(point.x, point.y) - if vertical: - point.y += 2 - else: - point.x += 2 - - - def DrawIcon(self, dc): - """ - Draws the docking guide icon (not used if the docking guide images are ok). - - :param `dc`: a `wx.DC` device context object. - """ - - rect = wx.Rect(*self.GetClientRect()) - point = wx.Point() - length = 0 - - rect.Deflate(4, 4) - dc.SetPen(wx.Pen(colourIconBorder)) - dc.SetBrush(wx.Brush(colourIconBackground)) - dc.DrawRectangleRect(rect) - - right1 = rect.GetRight() + 1 - bottom1 = rect.GetBottom() + 1 - - dc.SetPen(wx.Pen(colourIconShadow)) - dc.DrawLine(rect.x + 1, bottom1, right1 + 1, bottom1) - dc.DrawLine(right1, rect.y + 1, right1, bottom1 + 1) - - rect.Deflate(1, 1) - - if self._direction == wx.TOP: - rect.height -= rect.height / 2 - point = rect.GetBottomLeft() - length = rect.width - - elif self._direction == wx.LEFT: - rect.width -= rect.width / 2 - point = rect.GetTopRight() - length = rect.height - - elif self._direction == wx.RIGHT: - rect.x += rect.width / 2 - rect.width -= rect.width / 2 - point = rect.GetTopLeft() - length = rect.height - - elif self._direction == wx.BOTTOM: - rect.y += rect.height / 2 - rect.height -= rect.height / 2 - point = rect.GetTopLeft() - length = rect.width - - elif self._direction == wx.CENTER: - rect.Deflate(1, 1) - point = rect.GetTopLeft() - length = rect.width - - dc.GradientFillLinear(rect, colourIconDockingPart1, - colourIconDockingPart2, self._direction) - - dc.SetPen(wx.Pen(colourIconBorder)) - - if self._direction == wx.CENTER: - self.DrawDottedLine(dc, rect.GetTopLeft(), rect.width, False) - self.DrawDottedLine(dc, rect.GetTopLeft(), rect.height, True) - self.DrawDottedLine(dc, rect.GetBottomLeft(), rect.width, False) - self.DrawDottedLine(dc, rect.GetTopRight(), rect.height, True) - - elif self._direction in [wx.TOP, wx.BOTTOM]: - self.DrawDottedLine(dc, point, length, False) - - else: - self.DrawDottedLine(dc, point, length, True) - - - def DrawArrow(self, dc): - """ - Draws the docking guide arrow icon (not used if the docking guide images are ok). - - :param `dc`: a `wx.DC` device context object. - """ - - rect = self.GetClientRect() - point = wx.Point() - - point.x = (rect.GetLeft() + rect.GetRight()) / 2 - point.y = (rect.GetTop() + rect.GetBottom()) / 2 - rx, ry = wx.Size(), wx.Size() - - if self._direction == wx.TOP: - rx = wx.Size(1, 0) - ry = wx.Size(0, 1) - - elif self._direction == wx.LEFT: - rx = wx.Size(0, -1) - ry = wx.Size(1, 0) - - elif self._direction == wx.RIGHT: - rx = wx.Size(0, 1) - ry = wx.Size(-1, 0) - - elif self._direction == wx.BOTTOM: - rx = wx.Size(-1, 0) - ry = wx.Size(0, -1) - - point.x += ry.x*3 - point.y += ry.y*3 - - dc.SetPen(wx.Pen(colourIconArrow)) - - for i in xrange(4): - pt1 = wx.Point(point.x - rx.x*i, point.y - rx.y*i) - pt2 = wx.Point(point.x + rx.x*(i+1), point.y + rx.y*(i+1)) - dc.DrawLinePoint(pt1, pt2) - point.x += ry.x - point.y += ry.y - - - def OnPaint(self, event): - """ - Handles the ``wx.EVT_PAINT`` event for L{AuiDockingGuideWindow}. - - :param `event`: a `wx.PaintEvent` to be processed. - """ - - dc = wx.AutoBufferedPaintDC(self) - if self._currentImage.IsOk() and self._valid: - dc.DrawBitmap(self._currentImage, 0, 0, True) - else: - self.Draw(dc) - - - def Draw(self, dc): - """ - Draws the whole docking guide window (not used if the docking guide images are ok). - - :param `dc`: a `wx.DC` device context object. - """ - - self.DrawBackground(dc) - - if self._valid: - self.DrawIcon(dc) - self.DrawArrow(dc) - - - def UpdateDockGuide(self, pos): - """ - Updates the docking guide images depending on the mouse position, using focused - images if the mouse is inside the docking guide or unfocused images if it is - outside. - - :param `pos`: a `wx.Point` mouse position. - """ - - inside = self.GetScreenRect().Contains(pos) - - if inside: - image = self._bmp_focus - else: - image = self._bmp_unfocus - - if image != self._currentImage: - self._currentImage = image - self.Refresh() - self.Update() - - -# --------------------------------------------------------------------------- -# AuiSingleDockingGuide -# --------------------------------------------------------------------------- - -class AuiSingleDockingGuide(AuiDockingGuide): - """ A docking guide window for single docking hint (not diamond-shaped HUD). """ - - def __init__(self, parent, direction=0): - """ - Default class constructor. Used internally, do not call it in your code! - - :param `parent`: the L{AuiSingleDockingGuide} parent; - :param `direction`: one of ``wx.TOP``, ``wx.BOTTOM``, ``wx.LEFT``, ``wx.RIGHT``. - """ - - self._direction = direction - - style = wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP | \ - wx.FRAME_NO_TASKBAR | wx.NO_BORDER - - # Use of FRAME_SHAPED on wxMac causes the frame to be visible - # breaking the docking hints. - if wx.Platform != '__WXMAC__': - style |= wx.FRAME_SHAPED - - AuiDockingGuide.__init__(self, parent, style=style, name="auiSingleDockTarget") - - self.Hide() - - useAero = GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_AERO_DOCKING_GUIDES - useWhidbey = GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_WHIDBEY_DOCKING_GUIDES - - self._useAero = useAero or useWhidbey - self._valid = True - - if useAero: - sizeX, sizeY = aeroguideSizeX, aeroguideSizeY - elif useWhidbey: - sizeX, sizeY = whidbeySizeX, whidbeySizeY - else: - sizeX, sizeY = guideSizeX, guideSizeY - - if direction not in [wx.TOP, wx.BOTTOM]: - sizeX, sizeY = sizeY, sizeX - - if self._useAero: - self.CreateShapesWithStyle(useWhidbey) - - if wx.Platform == "__WXGTK__": - self.Bind(wx.EVT_WINDOW_CREATE, self.SetGuideShape) - else: - self.SetGuideShape() - - self.SetSize(self.region.GetBox().GetSize()) - else: - self.SetSize((sizeX, sizeY)) - - self.rect = wx.Rect(0, 0, sizeX, sizeY) - - if self._useAero: - useAero = (useWhidbey and [2] or [1])[0] - else: - useAero = 0 - - self.target = AuiDockingGuideWindow(self, self.rect, direction, False, useAero) - - - def CreateShapesWithStyle(self, useWhidbey): - """ - Creates the docking guide window shape based on which docking bitmaps are used. - - :param `useWhidbey`: if ``True``, use Whidbey-style bitmaps; if ``False``, use the - Aero-style bitmaps. - """ - - sizeX, sizeY = aeroguideSizeX, aeroguideSizeY - if useWhidbey: - sizeX, sizeY = whidbeySizeX, whidbeySizeY - - if self._direction not in [wx.TOP, wx.BOTTOM]: - sizeX, sizeY = sizeY, sizeX - - useAero = (useWhidbey and [2] or [1])[0] - bmp, dummy = GetDockingImage(self._direction, useAero, False) - region = wx.RegionFromBitmap(bmp) - - self.region = region - - - def AeroMove(self, pos): - """ - Moves the docking window to the new position. Overridden in children classes. - - :param `pos`: the new docking guide position. - """ - - pass - - - def SetGuideShape(self, event=None): - """ - Sets the correct shape for the docking guide window. - - :param `event`: on wxGTK, a `wx.WindowCreateEvent` event to process. - """ - - self.SetShape(self.region) - - if event is not None: - # Skip the event on wxGTK - event.Skip() - wx.CallAfter(wx.SafeYield, self, True) - - - def SetShape(self, region): - """ - If the platform supports it, sets the shape of the window to that depicted by `region`. - The system will not display or respond to any mouse event for the pixels that lie - outside of the region. To reset the window to the normal rectangular shape simply call - L{SetShape} again with an empty region. - - :param `region`: the shape of the frame. - - :note: Overridden for wxMac. - """ - - if wx.Platform == '__WXMAC__': - # HACK so we don't crash when SetShape is called - return - else: - super(AuiSingleDockingGuide, self).SetShape(region) - - - def SetValid(self, valid): - """ - Sets the docking direction as valid or invalid. - - :param `valid`: whether the docking direction is allowed or not. - """ - - self._valid = valid - - - def IsValid(self): - """ Returns whether the docking direction is valid. """ - - return self._valid - - - def UpdateDockGuide(self, pos): - """ - Updates the docking guide images depending on the mouse position, using focused - images if the mouse is inside the docking guide or unfocused images if it is - outside. - - :param `pos`: a `wx.Point` mouse position. - """ - - self.target.UpdateDockGuide(pos) - - - def HitTest(self, x, y): - """ - Checks if the mouse position is inside the target window rect. - - :param `x`: the `x` mouse position; - :param `y`: the `y` mouse position. - """ - - if self.target.GetScreenRect().Contains((x, y)): - return wx.ALL - - return -1 - - -# --------------------------------------------------------------------------- -# AuiCenterDockingGuide -# --------------------------------------------------------------------------- - -class AuiCenterDockingGuide(AuiDockingGuide): - """ A docking guide window for multiple docking hint (diamond-shaped HUD). """ - - def __init__(self, parent): - """ - Default class constructor. - Used internally, do not call it in your code! - - :param `parent`: the L{AuiCenterDockingGuide} parent. - """ - - AuiDockingGuide.__init__(self, parent, style=wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP | - wx.FRAME_NO_TASKBAR | wx.NO_BORDER | wx.FRAME_SHAPED, - name="auiCenterDockTarget") - - self.Hide() - - self.CreateShapesWithStyle() - self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) - - if wx.Platform == "__WXGTK__": - self.Bind(wx.EVT_WINDOW_CREATE, self.SetGuideShape) - else: - self.SetGuideShape() - - self.SetSize(self.region.GetBox().GetSize()) - - self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) - self.Bind(wx.EVT_PAINT, self.OnPaint) - - - def CreateShapesWithStyle(self): - """ Creates the docking guide window shape based on which docking bitmaps are used. """ - - useAero = (GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_AERO_DOCKING_GUIDES) != 0 - useWhidbey = (GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_WHIDBEY_DOCKING_GUIDES) != 0 - - self._useAero = 0 - if useAero: - self._useAero = 1 - elif useWhidbey: - self._useAero = 2 - - if useAero: - sizeX, sizeY = aeroguideSizeX, aeroguideSizeY - elif useWhidbey: - sizeX, sizeY = whidbeySizeX, whidbeySizeY - else: - sizeX, sizeY = guideSizeX, guideSizeY - - rectLeft = wx.Rect(0, sizeY, sizeY, sizeX) - rectTop = wx.Rect(sizeY, 0, sizeX, sizeY) - rectRight = wx.Rect(sizeY+sizeX, sizeY, sizeY, sizeX) - rectBottom = wx.Rect(sizeY, sizeX + sizeY, sizeX, sizeY) - rectCenter = wx.Rect(sizeY, sizeY, sizeX, sizeX) - - if not self._useAero: - - self.targetLeft = AuiDockingGuideWindow(self, rectLeft, wx.LEFT, True, useAero) - self.targetTop = AuiDockingGuideWindow(self, rectTop, wx.TOP, True, useAero) - self.targetRight = AuiDockingGuideWindow(self, rectRight, wx.RIGHT, True, useAero) - self.targetBottom = AuiDockingGuideWindow(self, rectBottom, wx.BOTTOM, True, useAero) - self.targetCenter = AuiDockingGuideWindow(self, rectCenter, wx.CENTER, True, useAero) - - - # top-left diamond - tld = [wx.Point(rectTop.x, rectTop.y+rectTop.height-8), - wx.Point(rectLeft.x+rectLeft.width-8, rectLeft.y), - rectTop.GetBottomLeft()] - # bottom-left diamond - bld = [wx.Point(rectLeft.x+rectLeft.width-8, rectLeft.y+rectLeft.height), - wx.Point(rectBottom.x, rectBottom.y+8), - rectBottom.GetTopLeft()] - # top-right diamond - trd = [wx.Point(rectTop.x+rectTop.width, rectTop.y+rectTop.height-8), - wx.Point(rectRight.x+8, rectRight.y), - rectRight.GetTopLeft()] - # bottom-right diamond - brd = [wx.Point(rectRight.x+8, rectRight.y+rectRight.height), - wx.Point(rectBottom.x+rectBottom.width, rectBottom.y+8), - rectBottom.GetTopRight()] - - self._triangles = [tld[0:2], bld[0:2], - [wx.Point(rectTop.x+rectTop.width-1, rectTop.y+rectTop.height-8), - wx.Point(rectRight.x+7, rectRight.y)], - [wx.Point(rectRight.x+7, rectRight.y+rectRight.height), - wx.Point(rectBottom.x+rectBottom.width-1, rectBottom.y+8)]] - - region = wx.Region() - region.UnionRect(rectLeft) - region.UnionRect(rectTop) - region.UnionRect(rectRight) - region.UnionRect(rectBottom) - region.UnionRect(rectCenter) - region.UnionRegion(wx.RegionFromPoints(tld)) - region.UnionRegion(wx.RegionFromPoints(bld)) - region.UnionRegion(wx.RegionFromPoints(trd)) - region.UnionRegion(wx.RegionFromPoints(brd)) - - elif useAero: - - self._aeroBmp = aero_dock_pane.GetBitmap() - region = wx.RegionFromBitmap(self._aeroBmp) - - self._allAeroBmps = [aero_dock_pane_left.GetBitmap(), aero_dock_pane_top.GetBitmap(), - aero_dock_pane_right.GetBitmap(), aero_dock_pane_bottom.GetBitmap(), - aero_dock_pane_center.GetBitmap(), aero_dock_pane.GetBitmap()] - self._deniedBitmap = aero_denied.GetBitmap() - self._aeroRects = [rectLeft, rectTop, rectRight, rectBottom, rectCenter] - self._valid = True - - elif useWhidbey: - - self._aeroBmp = whidbey_dock_pane.GetBitmap() - region = wx.RegionFromBitmap(self._aeroBmp) - - self._allAeroBmps = [whidbey_dock_pane_left.GetBitmap(), whidbey_dock_pane_top.GetBitmap(), - whidbey_dock_pane_right.GetBitmap(), whidbey_dock_pane_bottom.GetBitmap(), - whidbey_dock_pane_center.GetBitmap(), whidbey_dock_pane.GetBitmap()] - self._deniedBitmap = whidbey_denied.GetBitmap() - self._aeroRects = [rectLeft, rectTop, rectRight, rectBottom, rectCenter] - self._valid = True - - - self.region = region - - - def SetGuideShape(self, event=None): - """ - Sets the correct shape for the docking guide window. - - :param `event`: on wxGTK, a `wx.WindowCreateEvent` event to process. - """ - - self.SetShape(self.region) - - if event is not None: - # Skip the event on wxGTK - event.Skip() - wx.CallAfter(wx.SafeYield, self, True) - - - def UpdateDockGuide(self, pos): - """ - Updates the docking guides images depending on the mouse position, using focused - images if the mouse is inside the docking guide or unfocused images if it is - outside. - - :param `pos`: a `wx.Point` mouse position. - """ - - if not self._useAero: - for target in self.GetChildren(): - target.UpdateDockGuide(pos) - else: - lenRects = len(self._aeroRects) - for indx, rect in enumerate(self._aeroRects): - if rect.Contains(pos): - if self._allAeroBmps[indx] != self._aeroBmp: - if indx < lenRects - 1 or (indx == lenRects - 1 and self._valid): - self._aeroBmp = self._allAeroBmps[indx] - self.Refresh() - else: - self._aeroBmp = self._allAeroBmps[-1] - self.Refresh() - - return - - if self._aeroBmp != self._allAeroBmps[-1]: - self._aeroBmp = self._allAeroBmps[-1] - self.Refresh() - - - def HitTest(self, x, y): - """ - Checks if the mouse position is inside the target windows rect. - - :param `x`: the `x` mouse position; - :param `y`: the `y` mouse position. - """ - - if not self._useAero: - if self.targetLeft.GetScreenRect().Contains((x, y)): - return wx.LEFT - if self.targetTop.GetScreenRect().Contains((x, y)): - return wx.UP - if self.targetRight.GetScreenRect().Contains((x, y)): - return wx.RIGHT - if self.targetBottom.GetScreenRect().Contains((x, y)): - return wx.DOWN - if self.targetCenter.IsValid() and self.targetCenter.GetScreenRect().Contains((x, y)): - return wx.CENTER - else: - constants = [wx.LEFT, wx.UP, wx.RIGHT, wx.DOWN, wx.CENTER] - lenRects = len(self._aeroRects) - for indx, rect in enumerate(self._aeroRects): - if rect.Contains((x, y)): - if indx < lenRects or (indx == lenRects-1 and self._valid): - return constants[indx] - - return -1 - - - def ValidateNotebookDocking(self, valid): - """ - Sets whether a pane can be docked on top of another to create an automatic - L{AuiNotebook}. - - :param `valid`: whether a pane can be docked on top to another to form an automatic - L{AuiNotebook}. - """ - - if not self._useAero: - if self.targetCenter.IsValid() != valid: - self.targetCenter.SetValid(valid) - self.targetCenter.Refresh() - else: - if self._valid != valid: - self._valid = valid - self.Refresh() - - - def AeroMove(self, pos): - """ - Moves the docking guide window to the new position. - - :param `pos`: the new docking guide position. - """ - - if not self._useAero: - return - - useWhidbey = (GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_WHIDBEY_DOCKING_GUIDES) != 0 - - if useWhidbey: - sizeX, sizeY = whidbeySizeX, whidbeySizeY - else: - sizeX, sizeY = aeroguideSizeX, aeroguideSizeY - - size = self.GetSize() - - leftRect, topRect, rightRect, bottomRect, centerRect = self._aeroRects - thePos = pos + wx.Point((size.x-sizeY)/2, (size.y-sizeX)/2) - - centerRect.SetPosition(thePos) - - leftRect.SetPosition(thePos + wx.Point(-sizeY, 0)) - topRect.SetPosition(thePos + wx.Point(0, -sizeY)) - rightRect.SetPosition(thePos + wx.Point(sizeX, 0)) - bottomRect.SetPosition(thePos + wx.Point(0, sizeX)) - - - def OnEraseBackground(self, event): - """ - Handles the ``wx.EVT_ERASE_BACKGROUND`` event for L{AuiCenterDockingGuide}. - - :param `event`: `wx.EraseEvent` to be processed. - - :note: This is intentionally empty to reduce flickering while drawing. - """ - - pass - - - def OnPaint(self, event): - """ - Handles the ``wx.EVT_PAINT`` event for L{AuiCenterDockingGuide}. - - :param `event`: a `wx.PaintEvent` to be processed. - """ - - dc = wx.AutoBufferedPaintDC(self) - - if self._useAero: - dc.SetBrush(wx.TRANSPARENT_BRUSH) - dc.SetPen(wx.TRANSPARENT_PEN) - else: - dc.SetBrush(wx.Brush(colourTargetBackground)) - dc.SetPen(wx.Pen(colourTargetBorder)) - - rect = self.GetClientRect() - dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) - - if self._useAero: - dc.DrawBitmap(self._aeroBmp, 0, 0, True) - if not self._valid: - diff = (self._useAero == 2 and [1] or [0])[0] - bmpX, bmpY = self._deniedBitmap.GetWidth(), self._deniedBitmap.GetHeight() - xPos, yPos = (rect.x + (rect.width)/2 - bmpX/2), (rect.y + (rect.height)/2 - bmpY/2) - dc.DrawBitmap(self._deniedBitmap, xPos+1, yPos+diff, True) - - return - - dc.SetPen(wx.Pen(colourTargetBorder, 2)) - for pts in self._triangles: - dc.DrawLinePoint(pts[0], pts[1]) - - -# ---------------------------------------------------------------------------- -# AuiDockingHintWindow -# ---------------------------------------------------------------------------- - -class AuiDockingHintWindow(wx.Frame): - """ The original wxAUI docking window hint. """ - - def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition, - size=wx.Size(1, 1), style=wx.FRAME_TOOL_WINDOW | wx.FRAME_FLOAT_ON_PARENT | - wx.FRAME_NO_TASKBAR | wx.NO_BORDER | wx.FRAME_SHAPED, - name="auiHintWindow"): - """ - Default class constructor. Used internally, do not call it in your code! - - :param `parent`: the L{AuiDockingGuide} parent; - :param `id`: the window identifier. It may take a value of -1 to indicate a default value. - :param `title`: the caption to be displayed on the frame's title bar; - :param `pos`: the window position. A value of (-1, -1) indicates a default position, - chosen by either the windowing system or wxPython, depending on platform; - :param `size`: the window size. A value of (-1, -1) indicates a default size, chosen by - either the windowing system or wxPython, depending on platform; - :param `style`: the window style; - :param `name`: the name of the window. This parameter is used to associate a name with the - item, allowing the application user to set Motif resource values for individual windows. - """ - if wx.Platform == '__WXMAC__' and style & wx.FRAME_SHAPED: - # Having the shaped frame causes the frame to not be visible - # with the transparent style hints. - style -= wx.FRAME_SHAPED - - wx.Frame.__init__(self, parent, id, title, pos, size, style, name=name) - - self._blindMode = False - self.SetBackgroundColour(colourHintBackground) - - # Can't set background colour on a frame on wxMac - # so add a panel to set the colour on. - if wx.Platform == '__WXMAC__': - sizer = wx.BoxSizer(wx.HORIZONTAL) - self.panel = wx.Panel(self) - sizer.Add(self.panel, 1, wx.EXPAND) - self.SetSizer(sizer) - self.panel.SetBackgroundColour(colourHintBackground) - - self.Bind(wx.EVT_SIZE, self.OnSize) - - - def MakeVenetianBlinds(self): - """ - Creates the "venetian blind" effect if L{AuiManager} has the ``AUI_MGR_VENETIAN_BLINDS_HINT`` - flag set. - """ - - amount = 128 - size = self.GetClientSize() - region = wx.Region(0, 0, size.x, 1) - - for y in xrange(size.y): - - # Reverse the order of the bottom 4 bits - j = (y & 8 and [1] or [0])[0] | (y & 4 and [2] or [0])[0] | \ - (y & 2 and [4] or [0])[0] | (y & 1 and [8] or [0])[0] - - if 16*j+8 < amount: - region.Union(0, y, size.x, 1) - - self.SetShape(region) - - - def SetBlindMode(self, agwFlags): - """ - Sets whether venetian blinds or transparent hints will be shown as docking hint. - This depends on the L{AuiManager} flags. - - :param `agwFlags`: the L{AuiManager} flags. - """ - - self._blindMode = (agwFlags & AUI_MGR_VENETIAN_BLINDS_HINT) != 0 - - if self._blindMode or not self.CanSetTransparent(): - self.MakeVenetianBlinds() - self.SetTransparent(255) - - else: - self.SetShape(wx.Region()) - if agwFlags & AUI_MGR_HINT_FADE == 0: - self.SetTransparent(80) - else: - self.SetTransparent(0) - - - def SetShape(self, region): - """ - If the platform supports it, sets the shape of the window to that depicted by `region`. - The system will not display or respond to any mouse event for the pixels that lie - outside of the region. To reset the window to the normal rectangular shape simply call - L{SetShape} again with an empty region. - - :param `region`: the shape of the frame (an instance of `wx.Region`). - - :note: Overridden for wxMac. - """ - - if wx.Platform == '__WXMAC__': - # HACK so we don't crash when SetShape is called - return - else: - super(AuiDockingHintWindow, self).SetShape(region) - - - def Show(self, show=True): - """ - Show the hint window. - - :param `show`: whether to show or hide the hint docking window. - """ - - super(AuiDockingHintWindow, self).Show(show) - if wx.Platform == '__WXMAC__': - # Need to manually do layout since its a borderless frame. - self.Layout() - - - def OnSize(self, event): - """ - Handles the ``wx.EVT_SIZE`` event for L{AuiDockingHintWindow}. - - :param `event`: a `wx.SizeEvent` to be processed. - """ - - if self._blindMode or not self.CanSetTransparent(): - self.MakeVenetianBlinds() - - -# ---------------------------------------------------------------------------- # - -# -- AuiFloatingFrame class implementation -- - -class AuiFloatingFrame(wx.MiniFrame): - """ AuiFloatingFrame is the frame class that holds floating panes. """ - - def __init__(self, parent, owner_mgr, pane=None, id=wx.ID_ANY, title="", - style=wx.FRAME_TOOL_WINDOW | wx.FRAME_FLOAT_ON_PARENT | - wx.FRAME_NO_TASKBAR | wx.CLIP_CHILDREN): - """ - Default class constructor. Used internally, do not call it in your code! - - :param `parent`: the L{AuiFloatingFrame} parent; - :param `owner_mgr`: the L{AuiManager} that manages the floating pane; - :param `pane`: the L{AuiPaneInfo} pane that is about to float; - :param `id`: the window identifier. It may take a value of -1 to indicate a default value. - :param `title`: the caption to be displayed on the frame's title bar. - :param `style`: the window style. - """ - - if pane and pane.IsResizeable(): - style += wx.RESIZE_BORDER - if pane: - self._is_toolbar = pane.IsToolbar() - - self._useNativeMiniframes = False - if AuiManager_UseNativeMiniframes(owner_mgr): - # On wxMac we always use native miniframes - self._useNativeMiniframes = True - style += wx.CAPTION + wx.SYSTEM_MENU - if pane.HasCloseButton(): - style += wx.CLOSE_BOX - if pane.HasMaximizeButton(): - style += wx.MAXIMIZE_BOX - if pane.HasMinimizeButton(): - style += wx.MINIMIZE_BOX - - wx.MiniFrame.__init__(self, parent, id, title, pos=pane.floating_pos, - size=pane.floating_size, style=style, name="auiFloatingFrame") - - self._fly_timer = wx.Timer(self, wx.ID_ANY) - self._check_fly_timer = wx.Timer(self, wx.ID_ANY) - - self.Bind(wx.EVT_CLOSE, self.OnClose) - self.Bind(wx.EVT_SIZE, self.OnSize) - self.Bind(wx.EVT_ACTIVATE, self.OnActivate) - self.Bind(wx.EVT_TIMER, self.OnCheckFlyTimer, self._check_fly_timer) - self.Bind(wx.EVT_TIMER, self.OnFlyTimer, self._fly_timer) - self.Bind(EVT_AUI_FIND_MANAGER, self.OnFindManager) - - if self._useNativeMiniframes: - self.Bind(wx.EVT_MOVE, self.OnMoveEvent) - self.Bind(wx.EVT_MOVING, self.OnMoveEvent) - self.Bind(wx.EVT_IDLE, self.OnIdle) - self._useNativeMiniframes = True - self.SetExtraStyle(wx.WS_EX_PROCESS_IDLE) - else: - self.Bind(wx.EVT_MOVE, self.OnMove) - - self._fly = False - self._send_size = True - self._alpha_amount = 255 - - self._owner_mgr = owner_mgr - self._moving = False - self._lastDirection = None - self._transparent = 255 - - self._last_rect = wx.Rect() - self._last2_rect = wx.Rect() - self._last3_rect = wx.Rect() - - self._mgr = AuiManager() - self._mgr.SetManagedWindow(self) - self._mgr.SetArtProvider(owner_mgr.GetArtProvider()) - self._mgr.SetAGWFlags(owner_mgr.GetAGWFlags()) - - - def CopyAttributes(self, pane): - """ - Copies all the attributes of the input `pane` into another L{AuiPaneInfo}. - - :param `pane`: the source L{AuiPaneInfo} from where to copy attributes. - """ - - contained_pane = AuiPaneInfo() - - contained_pane.name = pane.name - contained_pane.caption = pane.caption - contained_pane.window = pane.window - contained_pane.frame = pane.frame - contained_pane.state = pane.state - contained_pane.dock_direction = pane.dock_direction - contained_pane.dock_layer = pane.dock_layer - contained_pane.dock_row = pane.dock_row - contained_pane.dock_pos = pane.dock_pos - contained_pane.best_size = wx.Size(*pane.best_size) - contained_pane.min_size = wx.Size(*pane.min_size) - contained_pane.max_size = wx.Size(*pane.max_size) - contained_pane.floating_pos = wx.Point(*pane.floating_pos) - contained_pane.floating_size = wx.Size(*pane.floating_size) - contained_pane.dock_proportion = pane.dock_proportion - contained_pane.buttons = pane.buttons - contained_pane.rect = wx.Rect(*pane.rect) - contained_pane.icon = pane.icon - contained_pane.notebook_id = pane.notebook_id - contained_pane.transparent = pane.transparent - contained_pane.snapped = pane.snapped - contained_pane.minimize_mode = pane.minimize_mode - - return contained_pane - - - def SetPaneWindow(self, pane): - """ - Sets all the properties of a pane. - - :param `pane`: the L{AuiPaneInfo} to analyze. - """ - - self._is_toolbar = pane.IsToolbar() - self._pane_window = pane.window - - if isinstance(pane.window, auibar.AuiToolBar): - pane.window.SetAuiManager(self._mgr) - - self._pane_window.Reparent(self) - - contained_pane = self.CopyAttributes(pane) - - contained_pane.Dock().Center().Show(). \ - CaptionVisible(False). \ - PaneBorder(False). \ - Layer(0).Row(0).Position(0) - - if not contained_pane.HasGripper() and not self._useNativeMiniframes: - contained_pane.CaptionVisible(True) - - indx = self._owner_mgr._panes.index(pane) - - # Carry over the minimum size - pane_min_size = pane.window.GetMinSize() - - # if the best size is smaller than the min size - # then set the min size to the best size as well - pane_best_size = contained_pane.best_size - if pane_best_size.IsFullySpecified() and (pane_best_size.x < pane_min_size.x or \ - pane_best_size.y < pane_min_size.y): - - pane_min_size = pane_best_size - self._pane_window.SetMinSize(pane_min_size) - - # if the frame window's max size is greater than the min size - # then set the max size to the min size as well - cur_max_size = self.GetMaxSize() - if cur_max_size.IsFullySpecified() and (cur_max_size.x < pane_min_size.x or \ - cur_max_size.y < pane_min_size.y): - self.SetMaxSize(pane_min_size) - - art_provider = self._mgr.GetArtProvider() - caption_size = art_provider.GetMetric(AUI_DOCKART_CAPTION_SIZE) - button_size = art_provider.GetMetric(AUI_DOCKART_PANE_BUTTON_SIZE) + \ - 4*art_provider.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE) - - min_size = pane.window.GetMinSize() - - if min_size.y < caption_size or min_size.x < button_size: - new_x, new_y = min_size.x, min_size.y - if min_size.y < caption_size: - new_y = (pane.IsResizeable() and [2*wx.SystemSettings.GetMetric(wx.SYS_EDGE_Y)+caption_size] or [1])[0] - if min_size.x < button_size: - new_x = (pane.IsResizeable() and [2*wx.SystemSettings.GetMetric(wx.SYS_EDGE_X)+button_size] or [1])[0] - - self.SetMinSize((new_x, new_y)) - else: - self.SetMinSize(min_size) - - self._mgr.AddPane(self._pane_window, contained_pane) - self._mgr.Update() - - if pane.min_size.IsFullySpecified(): - # because SetSizeHints() calls Fit() too (which sets the window - # size to its minimum allowed), we keep the size before calling - # SetSizeHints() and reset it afterwards... - tmp = self.GetSize() - self.GetSizer().SetSizeHints(self) - self.SetSize(tmp) - - self.SetTitle(pane.caption) - - if pane.floating_size != wx.Size(-1, -1): - self.SetSize(pane.floating_size) - else: - size = pane.best_size - if size == wx.Size(-1, -1): - size = pane.min_size - if size == wx.Size(-1, -1): - size = self._pane_window.GetSize() - if self._owner_mgr and pane.HasGripper(): - if pane.HasGripperTop(): - size.y += self._owner_mgr._art.GetMetric(AUI_DOCKART_GRIPPER_SIZE) - else: - size.x += self._owner_mgr._art.GetMetric(AUI_DOCKART_GRIPPER_SIZE) - - if not self._useNativeMiniframes: - size.y += self._owner_mgr._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) - - pane.floating_size = size - - self.SetClientSize(size) - - self._owner_mgr._panes[indx] = pane - - self._fly_step = abs(pane.floating_size.y - \ - (caption_size + 2*wx.SystemSettings.GetMetric(wx.SYS_EDGE_Y)))/10 - - self._floating_size = wx.Size(*self.GetSize()) - - if pane.IsFlyOut(): - self._check_fly_timer.Start(50) - - - def GetOwnerManager(self): - """ Returns the L{AuiManager} that manages the pane. """ - - return self._owner_mgr - - - def OnSize(self, event): - """ - Handles the ``wx.EVT_SIZE`` event for L{AuiFloatingFrame}. - - :param `event`: a `wx.SizeEvent` to be processed. - """ - - if self._owner_mgr and self._send_size: - self._owner_mgr.OnFloatingPaneResized(self._pane_window, event.GetSize()) - - - def OnClose(self, event): - """ - Handles the ``wx.EVT_CLOSE`` event for L{AuiFloatingFrame}. - - :param `event`: a `wx.CloseEvent` to be processed. - """ - - if self._owner_mgr: - self._owner_mgr.OnFloatingPaneClosed(self._pane_window, event) - - if not event.GetVeto(): - self._mgr.DetachPane(self._pane_window) - - if isinstance(self._pane_window, auibar.AuiToolBar): - self._pane_window.SetAuiManager(self._owner_mgr) - - # if we do not do this, then we can crash... - if self._owner_mgr and self._owner_mgr._action_window == self: - self._owner_mgr._action_window = None - - self.Destroy() - - - def OnActivate(self, event): - """ - Handles the ``wx.EVT_ACTIVATE`` event for L{AuiFloatingFrame}. - - :param `event`: a `wx.ActivateEvent` to be processed. - """ - - if self._owner_mgr and event.GetActive(): - self._owner_mgr.OnFloatingPaneActivated(self._pane_window) - - - def OnMove(self, event): - """ - Handles the ``wx.EVT_MOVE`` event for L{AuiFloatingFrame}. - - :param `event`: a `wx.MoveEvent` to be processed. - - :note: This event is not processed on wxMAC or if L{AuiManager} is not using the - ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style. - """ - - if self._owner_mgr: - self._owner_mgr.OnFloatingPaneMoved(self._pane_window, event) - - - def OnMoveEvent(self, event): - """ - Handles the ``wx.EVT_MOVE`` and ``wx.EVT_MOVING`` events for L{AuiFloatingFrame}. - - :param `event`: a `wx.MoveEvent` to be processed. - - :note: This event is only processed on wxMAC or if L{AuiManager} is using the - ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style. - """ - - win_rect = self.GetRect() - - if win_rect == self._last_rect: - return - - # skip the first move event - if self._last_rect.IsEmpty(): - self._last_rect = wx.Rect(*win_rect) - return - - # skip if moving too fast to avoid massive redraws and - # jumping hint windows - if abs(win_rect.x - self._last_rect.x) > 3 or abs(win_rect.y - self._last_rect.y) > 3: - self._last3_rect = wx.Rect(*self._last2_rect) - self._last2_rect = wx.Rect(*self._last_rect) - self._last_rect = wx.Rect(*win_rect) - return - - # prevent frame redocking during resize - if self._last_rect.GetSize() != win_rect.GetSize(): - self._last3_rect = wx.Rect(*self._last2_rect) - self._last2_rect = wx.Rect(*self._last_rect) - self._last_rect = wx.Rect(*win_rect) - return - - self._last3_rect = wx.Rect(*self._last2_rect) - self._last2_rect = wx.Rect(*self._last_rect) - self._last_rect = wx.Rect(*win_rect) - - if _VERSION_STRING < "2.9": - leftDown = wx.GetMouseState().LeftDown() - else: - leftDown = wx.GetMouseState().LeftIsDown() - - if not leftDown: - return - - if not self._moving: - self.OnMoveStart(event) - self._moving = True - - if self._last3_rect.IsEmpty(): - return - - self.OnMoving(event) - - - def OnIdle(self, event): - """ - Handles the ``wx.EVT_IDLE`` event for L{AuiFloatingFrame}. - - :param `event`: a `wx.IdleEvent` event to be processed. - - :note: This event is only processed on wxMAC or if L{AuiManager} is using the - ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style. - """ - - if self._moving: - if _VERSION_STRING < "2.9": - leftDown = wx.GetMouseState().LeftDown() - else: - leftDown = wx.GetMouseState().LeftIsDown() - - if not leftDown: - self._moving = False - self.OnMoveFinished() - else: - event.RequestMore() - - - def OnMoveStart(self, event): - """ - The user has just started moving the floating pane. - - :param `event`: an instance of `wx.MouseEvent`. - - :note: This method is used only on wxMAC or if L{AuiManager} is using the - ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style. - """ - - # notify the owner manager that the pane has started to move - if self._owner_mgr: - if self._owner_mgr._from_move: - return - self._owner_mgr._action_window = self._pane_window - point = wx.GetMousePosition() - action_offset = point - self.GetPosition() - - if self._is_toolbar: - self._owner_mgr._toolbar_action_offset = action_offset - self._owner_mgr.OnMotion_DragToolbarPane(point) - else: - self._owner_mgr._action_offset = action_offset - self._owner_mgr.OnMotion_DragFloatingPane(point) - - - def OnMoving(self, event): - """ - The user is moving the floating pane. - - :param `event`: an instance of `wx.MouseEvent`. - - :note: This method is used only on wxMAC or if L{AuiManager} is using the - ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style. - """ - - # notify the owner manager that the pane is moving - self.OnMoveStart(event) - - - def OnMoveFinished(self): - """ - The user has just finished moving the floating pane. - - :note: This method is used only on wxMAC or if L{AuiManager} is using the - ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style. - """ - - # notify the owner manager that the pane has finished moving - if self._owner_mgr: - self._owner_mgr._action_window = self._pane_window - point = wx.GetMousePosition() - if self._is_toolbar: - self._owner_mgr.OnLeftUp_DragToolbarPane(point) - else: - self._owner_mgr.OnLeftUp_DragFloatingPane(point) - - self._owner_mgr.OnFloatingPaneMoved(self._pane_window, point) - - - def OnCheckFlyTimer(self, event): - """ - Handles the ``wx.EVT_TIMER`` event for L{AuiFloatingFrame}. - - :param `event`: a `wx.TimerEvent` to be processed. - - :note: This is used solely for "fly-out" panes. - """ - - if self._owner_mgr: - pane = self._mgr.GetPane(self._pane_window) - if pane.IsFlyOut(): - if self.IsShownOnScreen(): - self.FlyOut() - - - def OnFindManager(self, event): - """ - Handles the ``EVT_AUI_FIND_MANAGER`` event for L{AuiFloatingFrame}. - - :param `event`: a L{AuiManagerEvent} event to be processed. - """ - - event.SetManager(self._owner_mgr) - - - def FlyOut(self): - """ Starts the flying in and out of a floating pane. """ - - if self._fly_timer.IsRunning(): - return - - if _VERSION_STRING < "2.9": - leftDown = wx.GetMouseState().LeftDown() - else: - leftDown = wx.GetMouseState().LeftIsDown() - - if leftDown: - return - - rect = wx.Rect(*self.GetScreenRect()) - rect.Inflate(10, 10) - - if rect.Contains(wx.GetMousePosition()): - if not self._fly: - return - self._send_size = False - self._fly_timer.Start(5) - else: - if self._fly: - return - self._send_size = False - self._fly_timer.Start(5) - - - def OnFlyTimer(self, event): - """ - Handles the ``wx.EVT_TIMER`` event for L{AuiFloatingFrame}. - - :param `event`: a `wx.TimerEvent` to be processed. - """ - - current_size = self.GetClientSize() - floating_size = wx.Size(*self._owner_mgr.GetPane(self._pane_window).floating_size) - - if floating_size.y == -1: - floating_size = self._floating_size - - if not self._fly: - min_size = self._mgr.GetArtProvider().GetMetric(AUI_DOCKART_CAPTION_SIZE) - - if wx.Platform != "__WXMSW__": - min_size += 2*wx.SystemSettings.GetMetric(wx.SYS_EDGE_Y) - - if current_size.y - self._fly_step <= min_size: - self.SetClientSize((current_size.x, min_size)) - self._fly = True - self._fly_timer.Stop() - self._send_size = True - else: - self.SetClientSize((current_size.x, current_size.y-self._fly_step)) - - else: - if current_size.y + self._fly_step >= floating_size.y: - self.SetClientSize((current_size.x, floating_size.y)) - self._fly = False - self._fly_timer.Stop() - self._send_size = True - else: - self.SetClientSize((current_size.x, current_size.y+self._fly_step)) - - self.Update() - self.Refresh() - - - def FadeOut(self): - """ Actually starts the fading out of the floating pane. """ - - while 1: - self._alpha_amount -= 10 - if self._alpha_amount <= 0: - self._alpha_amount = 255 - return - - self.SetTransparent(self._alpha_amount) - wx.SafeYield() - wx.MilliSleep(15) - - -# -- static utility functions -- - -def DrawResizeHint(dc, rect): - """ - Draws a resize hint while a sash is dragged. - - :param `rect`: a `wx.Rect` rectangle which specifies the sash dimensions. - """ - - if wx.Platform == "__WXMSW__" and wx.App.GetComCtl32Version() >= 600: - if wx.GetOsVersion()[1] > 5: - # Windows Vista - dc.SetPen(wx.Pen("black", 2, wx.SOLID)) - dc.SetBrush(wx.TRANSPARENT_BRUSH) - else: - # Draw the nice XP style splitter - dc.SetPen(wx.TRANSPARENT_PEN) - dc.SetBrush(wx.BLACK_BRUSH) - dc.SetLogicalFunction(wx.INVERT) - dc.DrawRectangleRect(rect) - dc.SetLogicalFunction(wx.COPY) - else: - stipple = PaneCreateStippleBitmap() - brush = wx.BrushFromBitmap(stipple) - dc.SetBrush(brush) - dc.SetPen(wx.TRANSPARENT_PEN) - - dc.SetLogicalFunction(wx.XOR) - dc.DrawRectangleRect(rect) - - -def CopyDocksAndPanes(src_docks, src_panes): - """ - This utility function creates shallow copies of - the dock and pane info. L{AuiDockInfo} usually contain pointers - to L{AuiPaneInfo} classes, thus this function is necessary to reliably - reconstruct that relationship in the new dock info and pane info arrays. - - :param `src_docks`: a list of L{AuiDockInfo} classes; - :param `src_panes`: a list of L{AuiPaneInfo} classes. - """ - - dest_docks = src_docks - dest_panes = src_panes - - for ii in xrange(len(dest_docks)): - dock = dest_docks[ii] - for jj in xrange(len(dock.panes)): - for kk in xrange(len(src_panes)): - if dock.panes[jj] == src_panes[kk]: - dock.panes[jj] = dest_panes[kk] - - return dest_docks, dest_panes - - -def CopyDocksAndPanes2(src_docks, src_panes): - """ - This utility function creates full copies of - the dock and pane info. L{AuiDockInfo} usually contain pointers - to L{AuiPaneInfo} classes, thus this function is necessary to reliably - reconstruct that relationship in the new dock info and pane info arrays. - - :param `src_docks`: a list of L{AuiDockInfo} classes; - :param `src_panes`: a list of L{AuiPaneInfo} classes. - """ - - dest_docks = [] - - for ii in xrange(len(src_docks)): - dest_docks.append(AuiDockInfo()) - dest_docks[ii].dock_direction = src_docks[ii].dock_direction - dest_docks[ii].dock_layer = src_docks[ii].dock_layer - dest_docks[ii].dock_row = src_docks[ii].dock_row - dest_docks[ii].size = src_docks[ii].size - dest_docks[ii].min_size = src_docks[ii].min_size - dest_docks[ii].resizable = src_docks[ii].resizable - dest_docks[ii].fixed = src_docks[ii].fixed - dest_docks[ii].toolbar = src_docks[ii].toolbar - dest_docks[ii].panes = src_docks[ii].panes - dest_docks[ii].rect = wx.Rect(*src_docks[ii].rect) - - dest_panes = [] - - for ii in xrange(len(src_panes)): - dest_panes.append(AuiPaneInfo()) - dest_panes[ii].name = src_panes[ii].name - dest_panes[ii].caption = src_panes[ii].caption - dest_panes[ii].window = src_panes[ii].window - dest_panes[ii].frame = src_panes[ii].frame - dest_panes[ii].state = src_panes[ii].state - dest_panes[ii].dock_direction = src_panes[ii].dock_direction - dest_panes[ii].dock_layer = src_panes[ii].dock_layer - dest_panes[ii].dock_row = src_panes[ii].dock_row - dest_panes[ii].dock_pos = src_panes[ii].dock_pos - dest_panes[ii].best_size = wx.Size(*src_panes[ii].best_size) - dest_panes[ii].min_size = wx.Size(*src_panes[ii].min_size) - dest_panes[ii].max_size = wx.Size(*src_panes[ii].max_size) - dest_panes[ii].floating_pos = wx.Point(*src_panes[ii].floating_pos) - dest_panes[ii].floating_size = wx.Size(*src_panes[ii].floating_size) - dest_panes[ii].dock_proportion = src_panes[ii].dock_proportion - dest_panes[ii].buttons = src_panes[ii].buttons - dest_panes[ii].rect = wx.Rect(*src_panes[ii].rect) - dest_panes[ii].icon = src_panes[ii].icon - dest_panes[ii].notebook_id = src_panes[ii].notebook_id - dest_panes[ii].transparent = src_panes[ii].transparent - dest_panes[ii].snapped = src_panes[ii].snapped - dest_panes[ii].minimize_mode = src_panes[ii].minimize_mode - - for ii in xrange(len(dest_docks)): - dock = dest_docks[ii] - for jj in xrange(len(dock.panes)): - for kk in xrange(len(src_panes)): - if dock.panes[jj] == src_panes[kk]: - dock.panes[jj] = dest_panes[kk] - - dest_docks[ii] = dock - - return dest_docks, dest_panes - - -def GetMaxLayer(docks, dock_direction): - """ - This is an internal function which returns - the highest layer inside the specified dock. - - :param `docks`: a list of L{AuiDockInfo}; - :param `dock_direction`: the L{AuiDockInfo} docking direction to analyze. - """ - - max_layer = 0 - - for dock in docks: - if dock.dock_direction == dock_direction and dock.dock_layer > max_layer and not dock.fixed: - max_layer = dock.dock_layer - - return max_layer - - -def GetMaxRow(panes, dock_direction, dock_layer): - """ - This is an internal function which returns - the highest layer inside the specified dock. - - :param `panes`: a list of L{AuiPaneInfo}; - :param `dock_direction`: the L{AuiPaneInfo} docking direction to analyze; - :param `dock_layer`: the L{AuiPaneInfo} layer to analyze. - """ - - max_row = 0 - - for pane in panes: - if pane.dock_direction == dock_direction and pane.dock_layer == dock_layer and \ - pane.dock_row > max_row: - max_row = pane.dock_row - - return max_row - - -def DoInsertDockLayer(panes, dock_direction, dock_layer): - """ - This is an internal function that inserts a new dock - layer by incrementing all existing dock layer values by one. - - :param `panes`: a list of L{AuiPaneInfo}; - :param `dock_direction`: the L{AuiPaneInfo} docking direction to analyze; - :param `dock_layer`: the L{AuiPaneInfo} layer to analyze. - """ - - for ii in xrange(len(panes)): - pane = panes[ii] - if not pane.IsFloating() and pane.dock_direction == dock_direction and pane.dock_layer >= dock_layer: - pane.dock_layer = pane.dock_layer + 1 - - panes[ii] = pane - - return panes - - -def DoInsertDockRow(panes, dock_direction, dock_layer, dock_row): - """ - This is an internal function that inserts a new dock - row by incrementing all existing dock row values by one. - - :param `panes`: a list of L{AuiPaneInfo}; - :param `dock_direction`: the L{AuiPaneInfo} docking direction to analyze; - :param `dock_layer`: the L{AuiPaneInfo} layer to analyze; - :param `dock_row`: the L{AuiPaneInfo} row to analyze. - """ - - for pane in panes: - if not pane.IsFloating() and pane.dock_direction == dock_direction and \ - pane.dock_layer == dock_layer and pane.dock_row >= dock_row: - pane.dock_row += 1 - - return panes - - -def DoInsertPane(panes, dock_direction, dock_layer, dock_row, dock_pos): - """ - This is an internal function that inserts a new pane - by incrementing all existing dock position values by one. - - :param `panes`: a list of L{AuiPaneInfo}; - :param `dock_direction`: the L{AuiPaneInfo} docking direction to analyze; - :param `dock_layer`: the L{AuiPaneInfo} layer to analyze; - :param `dock_row`: the L{AuiPaneInfo} row to analyze; - :param `dock_pos`: the L{AuiPaneInfo} row to analyze. - """ - - for ii in xrange(len(panes)): - pane = panes[ii] - if not pane.IsFloating() and pane.dock_direction == dock_direction and \ - pane.dock_layer == dock_layer and pane.dock_row == dock_row and \ - pane.dock_pos >= dock_pos: - pane.dock_pos = pane.dock_pos + 1 - - panes[ii] = pane - - return panes - - -def FindDocks(docks, dock_direction, dock_layer=-1, dock_row=-1, reverse=False): - """ - This is an internal function that returns a list of docks which meet - the specified conditions in the parameters and returns a sorted array - (sorted by layer and then row). - - :param `docks`: a list of L{AuiDockInfo}; - :param `dock_direction`: the L{AuiDockInfo} docking direction to analyze; - :param `dock_layer`: the L{AuiDockInfo} layer to analyze; - :param `dock_row`: the L{AuiDockInfo} row to analyze; - """ - - matchDocks = [(d.dock_layer, d.dock_row, d.dock_direction, d) for d in docks if \ - (dock_direction == -1 or dock_direction == d.dock_direction) and \ - ((dock_layer == -1 or dock_layer == d.dock_layer) and \ - (dock_row == -1 or dock_row == d.dock_row))] - - arr = [x[-1] for x in sorted(matchDocks, reverse=reverse)] - - return arr - - -def FindOppositeDocks(docks, dock_direction): - """ - This is an internal function that returns a list of docks - which is related to the opposite direction. - - :param `docks`: a list of L{AuiDockInfo}; - :param `dock_direction`: the L{AuiDockInfo} docking direction to analyze; - """ - - if dock_direction == AUI_DOCK_LEFT: - arr = FindDocks(docks, AUI_DOCK_RIGHT, -1, -1) - elif dock_direction == AUI_DOCK_TOP: - arr = FindDocks(docks, AUI_DOCK_BOTTOM, -1, -1) - elif dock_direction == AUI_DOCK_RIGHT: - arr = FindDocks(docks, AUI_DOCK_LEFT, -1, -1) - elif dock_direction == AUI_DOCK_BOTTOM: - arr = FindDocks(docks, AUI_DOCK_TOP, -1, -1) - - return arr - - -def FindPaneInDock(dock, window): - """ - This method looks up a specified window pointer inside a dock. - If found, the corresponding L{AuiPaneInfo} pointer is returned, otherwise ``None``. - - :param `dock`: a L{AuiDockInfo} structure; - :param `window`: a `wx.Window` derived window (associated to a pane). - """ - - for p in dock.panes: - if p.window == window: - return p - - return None - - -def GetToolBarDockOffsets(docks): - """ - Returns the toolbar dock offsets (top-left and bottom-right). - - :param `docks`: a list of L{AuiDockInfo} to analyze. - """ - - top_left = wx.Size(0, 0) - bottom_right = wx.Size(0, 0) - - for dock in docks: - if dock.toolbar: - dock_direction = dock.dock_direction - if dock_direction == AUI_DOCK_LEFT: - top_left.x += dock.rect.width - bottom_right.x += dock.rect.width - - elif dock_direction == AUI_DOCK_TOP: - top_left.y += dock.rect.height - bottom_right.y += dock.rect.height - - elif dock_direction == AUI_DOCK_RIGHT: - bottom_right.x += dock.rect.width - - elif dock_direction == AUI_DOCK_BOTTOM: - bottom_right.y += dock.rect.height - - return top_left, bottom_right - - -def GetInternalFrameRect(window, docks): - """ - Returns the window rectangle excluding toolbars. - - :param `window`: a `wx.Window` derived window; - :param `docks`: a list of L{AuiDockInfo} structures. - """ - - frameRect = wx.Rect() - - frameRect.SetTopLeft(window.ClientToScreen(window.GetClientAreaOrigin())) - frameRect.SetSize(window.GetClientSize()) - - top_left, bottom_right = GetToolBarDockOffsets(docks) - - # make adjustments for toolbars - frameRect.x += top_left.x - frameRect.y += top_left.y - frameRect.width -= bottom_right.x - frameRect.height -= bottom_right.y - - return frameRect - - -def CheckOutOfWindow(window, pt): - """ - Checks if a point is outside the window rectangle. - - :param `window`: a `wx.Window` derived window; - :param `pt`: a `wx.Point` object. - """ - - auiWindowMargin = 30 - marginRect = wx.Rect(*window.GetClientRect()) - marginRect.Inflate(auiWindowMargin, auiWindowMargin) - - return not marginRect.Contains(pt) - - -def CheckEdgeDrop(window, docks, pt): - """ - Checks on which edge of a window the drop action has taken place. - - :param `window`: a `wx.Window` derived window; - :param `docks`: a list of L{AuiDockInfo} structures; - :param `pt`: a `wx.Point` object. - """ - - screenPt = window.ClientToScreen(pt) - clientSize = window.GetClientSize() - frameRect = GetInternalFrameRect(window, docks) - - if screenPt.y >= frameRect.GetTop() and screenPt.y < frameRect.GetBottom(): - if pt.x < auiLayerInsertOffset and pt.x > auiLayerInsertOffset - auiLayerInsertPixels: - return wx.LEFT - - if pt.x >= clientSize.x - auiLayerInsertOffset and \ - pt.x < clientSize.x - auiLayerInsertOffset + auiLayerInsertPixels: - return wx.RIGHT - - if screenPt.x >= frameRect.GetLeft() and screenPt.x < frameRect.GetRight(): - if pt.y < auiLayerInsertOffset and pt.y > auiLayerInsertOffset - auiLayerInsertPixels: - return wx.TOP - - if pt.y >= clientSize.y - auiLayerInsertOffset and \ - pt.y < clientSize.y - auiLayerInsertOffset + auiLayerInsertPixels: - return wx.BOTTOM - - return -1 - - -def RemovePaneFromDocks(docks, pane, exc=None): - """ - Removes a pane window from all docks - with a possible exception specified by parameter `exc`. - - :param `docks`: a list of L{AuiDockInfo} structures; - :param `pane`: the L{AuiPaneInfo} pane to be removed; - :param `exc`: the possible pane exception. - """ - - for ii in xrange(len(docks)): - d = docks[ii] - if d == exc: - continue - pi = FindPaneInDock(d, pane.window) - if pi: - d.panes.remove(pi) - - docks[ii] = d - - return docks - - -def RenumberDockRows(docks): - """ - Takes a dock and assigns sequential numbers - to existing rows. Basically it takes out the gaps so if a - dock has rows with numbers 0, 2, 5, they will become 0, 1, 2. - - :param `docks`: a list of L{AuiDockInfo} structures. - """ - - for ii in xrange(len(docks)): - dock = docks[ii] - dock.dock_row = ii - for jj in xrange(len(dock.panes)): - dock.panes[jj].dock_row = ii - - docks[ii] = dock - - return docks - - -def SetActivePane(panes, active_pane): - """ - Sets the active pane, as well as cycles through - every other pane and makes sure that all others' active flags - are turned off. - - :param `panes`: a list of L{AuiPaneInfo} structures; - :param `active_pane`: the pane to be made active (if found). - """ - - for pane in panes: - pane.state &= ~AuiPaneInfo.optionActive - - for pane in panes: - if pane.window == active_pane and not pane.IsNotebookPage(): - pane.state |= AuiPaneInfo.optionActive - return True, panes - - return False, panes - - -def ShowDockingGuides(guides, show): - """ - Shows or hide the docking guide windows. - - :param `guides`: a list of L{AuiDockingGuideInfo} classes; - :param `show`: whether to show or hide the docking guide windows. - """ - - for target in guides: - - if show and not target.host.IsShown(): - target.host.Show() - target.host.Update() - - elif not show and target.host.IsShown(): - target.host.Hide() - - -def RefreshDockingGuides(guides): - """ - Refreshes the docking guide windows. - - :param `guides`: a list of L{AuiDockingGuideInfo} classes; - """ - - for target in guides: - if target.host.IsShown(): - target.host.Refresh() - - -def PaneSortFunc(p1, p2): - """ - This function is used to sort panes by dock position. - - :param `p1`: a L{AuiPaneInfo} instance; - :param `p2`: another L{AuiPaneInfo} instance. - """ - - return (p1.dock_pos < p2.dock_pos and [-1] or [1])[0] - - -def GetNotebookRoot(panes, notebook_id): - """ - Returns the L{AuiPaneInfo} which has the specified `notebook_id`. - - :param `panes`: a list of L{AuiPaneInfo} instances; - :param `notebook_id`: the target notebook id. - """ - - for paneInfo in panes: - if paneInfo.IsNotebookControl() and paneInfo.notebook_id == notebook_id: - return paneInfo - - return None - - -def EscapeDelimiters(s): - """ - Changes ``;`` into ``\`` and ``|`` into ``\|`` in the input string. - - :param `s`: the string to be analyzed. - - :note: This is an internal functions which is used for saving perspectives. - """ - - result = s.replace(";", "\\") - result = result.replace("|", "|\\") - - return result - - -def IsDifferentDockingPosition(pane1, pane2): - """ - Returns whether `pane1` and `pane2` are in a different docking position - based on pane status, docking direction, docking layer and docking row. - - :param `pane1`: a L{AuiPaneInfo} instance; - :param `pane2`: another L{AuiPaneInfo} instance. - """ - - return pane1.IsFloating() != pane2.IsFloating() or \ - pane1.dock_direction != pane2.dock_direction or \ - pane1.dock_layer != pane2.dock_layer or \ - pane1.dock_row != pane2.dock_row - - -# Convenience function -def AuiManager_HasLiveResize(manager): - """ - Static function which returns if the input `manager` should have "live resize" - behaviour. - - :param `manager`: an instance of L{AuiManager}. - - :note: This method always returns ``True`` on wxMac as this platform doesn't have - the ability to use `wx.ScreenDC` to draw sashes. - """ - - # With Core Graphics on Mac, it's not possible to show sash feedback, - # so we'll always use live update instead. - - if wx.Platform == "__WXMAC__": - return True - else: - return (manager.GetAGWFlags() & AUI_MGR_LIVE_RESIZE) == AUI_MGR_LIVE_RESIZE - - -# Convenience function -def AuiManager_UseNativeMiniframes(manager): - """ - Static function which returns if the input `manager` should use native `wx.MiniFrame` as - floating panes. - - :param `manager`: an instance of L{AuiManager}. - - :note: This method always returns ``True`` on wxMac as this platform doesn't have - the ability to use custom drawn miniframes. - """ - - # With Core Graphics on Mac, it's not possible to show sash feedback, - # so we'll always use live update instead. - - if wx.Platform == "__WXMAC__": - return True - else: - return (manager.GetAGWFlags() & AUI_MGR_USE_NATIVE_MINIFRAMES) == AUI_MGR_USE_NATIVE_MINIFRAMES - - -def GetManager(window): - """ - This function will return the aui manager for a given window. - - :param `window`: this parameter should be any child window or grand-child - window (and so on) of the frame/window managed by L{AuiManager}. The window - does not need to be managed by the manager itself, nor does it even need - to be a child or sub-child of a managed window. It must however be inside - the window hierarchy underneath the managed window. - """ - - if not isinstance(wx.GetTopLevelParent(window), AuiFloatingFrame): - if isinstance(window, auibar.AuiToolBar): - return window.GetAuiManager() - - evt = AuiManagerEvent(wxEVT_AUI_FIND_MANAGER) - evt.SetManager(None) - evt.ResumePropagation(wx.EVENT_PROPAGATE_MAX) - - if not window.GetEventHandler().ProcessEvent(evt): - return None - - return evt.GetManager() - - -# ---------------------------------------------------------------------------- # - -class AuiManager(wx.EvtHandler): - """ - AuiManager manages the panes associated with it for a particular `wx.Frame`, - using a pane's L{AuiPaneInfo} information to determine each pane's docking and - floating behavior. L{AuiManager} uses wxPython's sizer mechanism to plan the - layout of each frame. It uses a replaceable dock art class to do all drawing, - so all drawing is localized in one area, and may be customized depending on an - applications' specific needs. - - L{AuiManager} works as follows: the programmer adds panes to the class, or makes - changes to existing pane properties (dock position, floating state, show state, etc...). - To apply these changes, the L{AuiManager.Update} function is called. This batch - processing can be used to avoid flicker, by modifying more than one pane at a time, - and then "committing" all of the changes at once by calling `Update()`. - - Panes can be added quite easily:: - - text1 = wx.TextCtrl(self, -1) - text2 = wx.TextCtrl(self, -1) - self._mgr.AddPane(text1, AuiPaneInfo().Left().Caption("Pane Number One")) - self._mgr.AddPane(text2, AuiPaneInfo().Bottom().Caption("Pane Number Two")) - - self._mgr.Update() - - - Later on, the positions can be modified easily. The following will float an - existing pane in a tool window:: - - self._mgr.GetPane(text1).Float() - - - **Layers, Rows and Directions, Positions:** - - Inside AUI, the docking layout is figured out by checking several pane parameters. - Four of these are important for determining where a pane will end up. - - **Direction** - Each docked pane has a direction, `Top`, `Bottom`, `Left`, `Right`, or `Center`. - This is fairly self-explanatory. The pane will be placed in the location specified - by this variable. - - **Position** - More than one pane can be placed inside of a "dock". Imagine two panes - being docked on the left side of a window. One pane can be placed over another. - In proportionally managed docks, the pane position indicates it's sequential position, - starting with zero. So, in our scenario with two panes docked on the left side, the - top pane in the dock would have position 0, and the second one would occupy position 1. - - **Row** - A row can allow for two docks to be placed next to each other. One of the most - common places for this to happen is in the toolbar. Multiple toolbar rows are allowed, - the first row being in row 0, and the second in row 1. Rows can also be used on - vertically docked panes. - - **Layer** - A layer is akin to an onion. Layer 0 is the very center of the managed pane. - Thus, if a pane is in layer 0, it will be closest to the center window (also sometimes - known as the "content window"). Increasing layers "swallow up" all layers of a lower - value. This can look very similar to multiple rows, but is different because all panes - in a lower level yield to panes in higher levels. The best way to understand layers - is by running the AUI sample (`AUI.py`). - """ - - def __init__(self, managed_window=None, agwFlags=None): - """ - Default class constructor. - - :param `managed_window`: specifies the window which should be managed; - :param `agwFlags`: specifies options which allow the frame management behavior to be - modified. `agwFlags` can be a combination of the following style bits: - - ==================================== ================================== - Flag name Description - ==================================== ================================== - ``AUI_MGR_ALLOW_FLOATING`` Allow floating of panes - ``AUI_MGR_ALLOW_ACTIVE_PANE`` If a pane becomes active, "highlight" it in the interface - ``AUI_MGR_TRANSPARENT_DRAG`` If the platform supports it, set transparency on a floating pane while it is dragged by the user - ``AUI_MGR_TRANSPARENT_HINT`` If the platform supports it, show a transparent hint window when the user is about to dock a floating pane - ``AUI_MGR_VENETIAN_BLINDS_HINT`` Show a "venetian blind" effect when the user is about to dock a floating pane - ``AUI_MGR_RECTANGLE_HINT`` Show a rectangle hint effect when the user is about to dock a floating pane - ``AUI_MGR_HINT_FADE`` If the platform supports it, the hint window will fade in and out - ``AUI_MGR_NO_VENETIAN_BLINDS_FADE`` Disables the "venetian blind" fade in and out - ``AUI_MGR_LIVE_RESIZE`` Live resize when the user drag a sash - ``AUI_MGR_ANIMATE_FRAMES`` Fade-out floating panes when they are closed (all platforms which support frames transparency) and show a moving rectangle when they are docked (Windows < Vista and GTK only) - ``AUI_MGR_AERO_DOCKING_GUIDES`` Use the new Aero-style bitmaps as docking guides - ``AUI_MGR_PREVIEW_MINIMIZED_PANES`` Slide in and out minimized panes to preview them - ``AUI_MGR_WHIDBEY_DOCKING_GUIDES`` Use the new Whidbey-style bitmaps as docking guides - ``AUI_MGR_SMOOTH_DOCKING`` Performs a "smooth" docking of panes (a la PyQT) - ``AUI_MGR_USE_NATIVE_MINIFRAMES`` Use miniframes with native caption bar as floating panes instead or custom drawn caption bars (forced on wxMac) - ``AUI_MGR_AUTONB_NO_CAPTION`` Panes that merge into an automatic notebook will not have the pane caption visible - ==================================== ================================== - - Default value for `agwFlags` is: - ``AUI_MGR_DEFAULT`` = ``AUI_MGR_ALLOW_FLOATING`` | ``AUI_MGR_TRANSPARENT_HINT`` | ``AUI_MGR_HINT_FADE`` | ``AUI_MGR_NO_VENETIAN_BLINDS_FADE`` - - :note: If using the ``AUI_MGR_USE_NATIVE_MINIFRAMES``, double-clicking on a - floating pane caption will not re-dock the pane, but simply maximize it (if - L{AuiPaneInfo.MaximizeButton} has been set to ``True``) or do nothing. - """ - - wx.EvtHandler.__init__(self) - - self._action = actionNone - self._action_window = None - self._hover_button = None - self._art = dockart.AuiDefaultDockArt() - self._hint_window = None - self._active_pane = None - self._has_maximized = False - self._has_minimized = False - - self._frame = None - self._dock_constraint_x = 0.3 - self._dock_constraint_y = 0.3 - self._reserved = None - - self._panes = [] - self._docks = [] - self._uiparts = [] - - self._guides = [] - self._notebooks = [] - - self._masterManager = None - self._currentDragItem = -1 - self._lastknowndocks = {} - - self._hint_fadetimer = wx.Timer(self, wx.ID_ANY) - self._hint_fademax = 50 - self._last_hint = wx.Rect() - - self._from_move = False - self._last_rect = wx.Rect() - - if agwFlags is None: - agwFlags = AUI_MGR_DEFAULT - - self._agwFlags = agwFlags - self._is_docked = (False, wx.RIGHT, wx.TOP, 0) - self._snap_limits = (15, 15) - - if wx.Platform == "__WXMSW__": - self._animation_step = 30.0 - else: - self._animation_step = 5.0 - - self._hint_rect = wx.Rect() - - self._preview_timer = wx.Timer(self, wx.ID_ANY) - self._sliding_frame = None - - self._autoNBTabArt = tabart.AuiDefaultTabArt() - self._autoNBStyle = AUI_NB_DEFAULT_STYLE | AUI_NB_BOTTOM | \ - AUI_NB_SUB_NOTEBOOK | AUI_NB_TAB_EXTERNAL_MOVE - self._autoNBStyle -= AUI_NB_DRAW_DND_TAB - - if managed_window: - self.SetManagedWindow(managed_window) - - self.Bind(wx.EVT_PAINT, self.OnPaint) - self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) - self.Bind(wx.EVT_SIZE, self.OnSize) - self.Bind(wx.EVT_SET_CURSOR, self.OnSetCursor) - self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) - self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick) - self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) - self.Bind(wx.EVT_MOTION, self.OnMotion) - self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow) - self.Bind(wx.EVT_CHILD_FOCUS, self.OnChildFocus) - self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.OnCaptureLost) - self.Bind(wx.EVT_TIMER, self.OnHintFadeTimer, self._hint_fadetimer) - self.Bind(wx.EVT_TIMER, self.SlideIn, self._preview_timer) - - self.Bind(wx.EVT_MOVE, self.OnMove) - self.Bind(wx.EVT_SYS_COLOUR_CHANGED, self.OnSysColourChanged) - - self.Bind(EVT_AUI_PANE_BUTTON, self.OnPaneButton) - self.Bind(EVT_AUI_RENDER, self.OnRender) - self.Bind(EVT_AUI_FIND_MANAGER, self.OnFindManager) - self.Bind(EVT_AUI_PANE_MIN_RESTORE, self.OnRestoreMinimizedPane) - self.Bind(EVT_AUI_PANE_DOCKED, self.OnPaneDocked) - - self.Bind(auibook.EVT_AUINOTEBOOK_BEGIN_DRAG, self.OnTabBeginDrag) - self.Bind(auibook.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnTabPageClose) - self.Bind(auibook.EVT_AUINOTEBOOK_PAGE_CHANGED, self.OnTabSelected) - - - def CreateFloatingFrame(self, parent, pane_info): - """ - Creates a floating frame for the windows. - - :param `parent`: the floating frame parent; - :param `pane_info`: the L{AuiPaneInfo} class with all the pane's information. - """ - - return AuiFloatingFrame(parent, self, pane_info) - - - def CanDockPanel(self, p): - """ - Returns whether a pane can be docked or not. - - :param `p`: the L{AuiPaneInfo} class with all the pane's information. - """ - - # is the pane dockable? - if not p.IsDockable(): - return False - - # if a key modifier is pressed while dragging the frame, - # don't dock the window - return not (wx.GetKeyState(wx.WXK_CONTROL) or wx.GetKeyState(wx.WXK_ALT)) - - - def GetPaneByWidget(self, window): - """ - This version of L{GetPane} looks up a pane based on a - 'pane window'. - - :param `window`: a `wx.Window` derived window. - - :see: L{GetPane} - """ - - for p in self._panes: - if p.window == window: - return p - - return NonePaneInfo - - - def GetPaneByName(self, name): - """ - This version of L{GetPane} looks up a pane based on a - 'pane name'. - - :param `name`: the pane name. - - :see: L{GetPane} - """ - - for p in self._panes: - if p.name == name: - return p - - return NonePaneInfo - - - def GetPane(self, item): - """ - Looks up a L{AuiPaneInfo} structure based - on the supplied window pointer. Upon failure, L{GetPane} - returns an empty L{AuiPaneInfo}, a condition which can be checked - by calling L{AuiPaneInfo.IsOk}. - - The pane info's structure may then be modified. Once a pane's - info is modified, L{Update} must be called to - realize the changes in the UI. - - :param `item`: either a pane name or a `wx.Window`. - """ - - if isinstance(item, basestring): - return self.GetPaneByName(item) - else: - return self.GetPaneByWidget(item) - - - def GetAllPanes(self): - """ Returns a reference to all the pane info structures. """ - - return self._panes - - - def ShowPane(self, window, show): - """ - Shows or hides a pane based on the window passed as input. - - :param `window`: a `wx.Window` derived window; - :param `show`: ``True`` to show the pane, ``False`` otherwise. - """ - - p = self.GetPane(window) - - if p.IsOk(): - if p.IsNotebookPage(): - if show: - - notebook = self._notebooks[p.notebook_id] - id = notebook.GetPageIndex(p.window) - if id >= 0: - notebook.SetSelection(id) - self.ShowPane(notebook, True) - - else: - p.Show(show) - - if p.frame: - p.frame.Raise() - - self.Update() - - - def HitTest(self, x, y): - """ - This is an internal function which determines - which UI item the specified coordinates are over. - - :param `x`: specifies a x position in client coordinates; - :param `y`: specifies a y position in client coordinates. - """ - - result = None - - for item in self._uiparts: - # we are not interested in typeDock, because this space - # isn't used to draw anything, just for measurements - # besides, the entire dock area is covered with other - # rectangles, which we are interested in. - if item.type == AuiDockUIPart.typeDock: - continue - - # if we already have a hit on a more specific item, we are not - # interested in a pane hit. If, however, we don't already have - # a hit, returning a pane hit is necessary for some operations - if item.type in [AuiDockUIPart.typePane, AuiDockUIPart.typePaneBorder] and result: - continue - - # if the point is inside the rectangle, we have a hit - if item.rect.Contains((x, y)): - result = item - - return result - - - def PaneHitTest(self, panes, pt): - """ - Similar to L{HitTest}, but it checks in which L{AuiPaneInfo} rectangle the - input point belongs to. - - :param `panes`: a list of L{AuiPaneInfo} instances; - :param `pt`: a `wx.Point` object. - """ - - for paneInfo in panes: - if paneInfo.IsDocked() and paneInfo.IsShown() and paneInfo.rect.Contains(pt): - return paneInfo - - return NonePaneInfo - - - # SetAGWFlags() and GetAGWFlags() allow the owner to set various - # options which are global to AuiManager - - def SetAGWFlags(self, agwFlags): - """ - This method is used to specify L{AuiManager}'s settings flags. - - :param `agwFlags`: specifies options which allow the frame management behavior - to be modified. `agwFlags` can be one of the following style bits: - - ==================================== ================================== - Flag name Description - ==================================== ================================== - ``AUI_MGR_ALLOW_FLOATING`` Allow floating of panes - ``AUI_MGR_ALLOW_ACTIVE_PANE`` If a pane becomes active, "highlight" it in the interface - ``AUI_MGR_TRANSPARENT_DRAG`` If the platform supports it, set transparency on a floating pane while it is dragged by the user - ``AUI_MGR_TRANSPARENT_HINT`` If the platform supports it, show a transparent hint window when the user is about to dock a floating pane - ``AUI_MGR_VENETIAN_BLINDS_HINT`` Show a "venetian blind" effect when the user is about to dock a floating pane - ``AUI_MGR_RECTANGLE_HINT`` Show a rectangle hint effect when the user is about to dock a floating pane - ``AUI_MGR_HINT_FADE`` If the platform supports it, the hint window will fade in and out - ``AUI_MGR_NO_VENETIAN_BLINDS_FADE`` Disables the "venetian blind" fade in and out - ``AUI_MGR_LIVE_RESIZE`` Live resize when the user drag a sash - ``AUI_MGR_ANIMATE_FRAMES`` Fade-out floating panes when they are closed (all platforms which support frames transparency) and show a moving rectangle when they are docked (Windows < Vista and GTK only) - ``AUI_MGR_AERO_DOCKING_GUIDES`` Use the new Aero-style bitmaps as docking guides - ``AUI_MGR_PREVIEW_MINIMIZED_PANES`` Slide in and out minimized panes to preview them - ``AUI_MGR_WHIDBEY_DOCKING_GUIDES`` Use the new Whidbey-style bitmaps as docking guides - ``AUI_MGR_SMOOTH_DOCKING`` Performs a "smooth" docking of panes (a la PyQT) - ``AUI_MGR_USE_NATIVE_MINIFRAMES`` Use miniframes with native caption bar as floating panes instead or custom drawn caption bars (forced on wxMac) - ``AUI_MGR_AUTONB_NO_CAPTION`` Panes that merge into an automatic notebook will not have the pane caption visible - ==================================== ================================== - - :note: If using the ``AUI_MGR_USE_NATIVE_MINIFRAMES``, double-clicking on a - floating pane caption will not re-dock the pane, but simply maximize it (if - L{AuiPaneInfo.MaximizeButton} has been set to ``True``) or do nothing. - - """ - - self._agwFlags = agwFlags - - if len(self._guides) > 0: - self.CreateGuideWindows() - - if self._hint_window and agwFlags & AUI_MGR_RECTANGLE_HINT == 0: - self.CreateHintWindow() - - - def GetAGWFlags(self): - """ - Returns the current manager's flags. - - :see: L{SetAGWFlags} for a list of possible L{AuiManager} flags. - """ - - return self._agwFlags - - - def SetManagedWindow(self, managed_window): - """ - Called to specify the frame or window which is to be managed by L{AuiManager}. - Frame management is not restricted to just frames. Child windows or custom - controls are also allowed. - - :param `managed_window`: specifies the window which should be managed by - the AUI manager. - """ - - if not managed_window: - raise Exception("Specified managed window must be non-null. ") - - self._frame = managed_window - self._frame.PushEventHandler(self) - - # if the owner is going to manage an MDI parent frame, - # we need to add the MDI client window as the default - # center pane - - if isinstance(self._frame, wx.MDIParentFrame): - mdi_frame = self._frame - client_window = mdi_frame.GetClientWindow() - - if not client_window: - raise Exception("Client window is None!") - - self.AddPane(client_window, AuiPaneInfo().Name("mdiclient"). - CenterPane().PaneBorder(False)) - - elif isinstance(self._frame, tabmdi.AuiMDIParentFrame): - - mdi_frame = self._frame - client_window = mdi_frame.GetClientWindow() - - if not client_window: - raise Exception("Client window is None!") - - self.AddPane(client_window, AuiPaneInfo().Name("mdiclient"). - CenterPane().PaneBorder(False)) - - - def GetManagedWindow(self): - """ Returns the window being managed by L{AuiManager}. """ - - return self._frame - - - def SetFrame(self, managed_window): - """ - Called to specify the frame or window which is to be managed by L{AuiManager}. - Frame management is not restricted to just frames. Child windows or custom - controls are also allowed. - - :param `managed_window`: specifies the window which should be managed by - the AUI manager. - - :warning: This method is now deprecated, use L{SetManagedWindow} instead. - """ - - DeprecationWarning("This method is deprecated, use SetManagedWindow instead.") - return self.SetManagedWindow(managed_window) - - - def GetFrame(self): - """ - Returns the window being managed by L{AuiManager}. - - :warning: This method is now deprecated, use L{GetManagedWindow} instead. - """ - - DeprecationWarning("This method is deprecated, use GetManagedWindow instead.") - return self._frame - - - def CreateGuideWindows(self): - """ Creates the VS2005 HUD guide windows. """ - - self.DestroyGuideWindows() - - self._guides.append(AuiDockingGuideInfo().Left(). - Host(AuiSingleDockingGuide(self._frame, wx.LEFT))) - self._guides.append(AuiDockingGuideInfo().Top(). - Host(AuiSingleDockingGuide(self._frame, wx.TOP))) - self._guides.append(AuiDockingGuideInfo().Right(). - Host(AuiSingleDockingGuide(self._frame, wx.RIGHT))) - self._guides.append(AuiDockingGuideInfo().Bottom(). - Host(AuiSingleDockingGuide(self._frame, wx.BOTTOM))) - self._guides.append(AuiDockingGuideInfo().Centre(). - Host(AuiCenterDockingGuide(self._frame))) - - - def DestroyGuideWindows(self): - """ Destroys the VS2005 HUD guide windows. """ - - for guide in self._guides: - if guide.host: - guide.host.Destroy() - - self._guides = [] - - - def CreateHintWindow(self): - """ Creates the standard wxAUI hint window. """ - - self.DestroyHintWindow() - - self._hint_window = AuiDockingHintWindow(self._frame) - self._hint_window.SetBlindMode(self._agwFlags) - - - def DestroyHintWindow(self): - """ Destroys the standard wxAUI hint window. """ - - if self._hint_window: - - self._hint_window.Destroy() - self._hint_window = None - - - def UnInit(self): - """ - Uninitializes the framework and should be called before a managed frame or - window is destroyed. L{UnInit} is usually called in the managed `wx.Frame`/`wx.Window` - destructor. - - It is necessary to call this function before the managed frame or window is - destroyed, otherwise the manager cannot remove its custom event handlers - from a window. - """ - - if self._frame: - self._frame.RemoveEventHandler(self) - - - def GetArtProvider(self): - """ Returns the current art provider being used. """ - - return self._art - - - def ProcessMgrEvent(self, event): - """ - Process the AUI events sent to the manager. - - :param `event`: the event to process, an instance of L{AuiManagerEvent}. - """ - - # first, give the owner frame a chance to override - if self._frame: - if self._frame.GetEventHandler().ProcessEvent(event): - return - - self.ProcessEvent(event) - - - def FireEvent(self, evtType, pane, canVeto=False): - """ - Fires one of the ``EVT_AUI_PANE_FLOATED``/``FLOATING``/``DOCKING``/``DOCKED``/``ACTIVATED`` event. - - :param `evtType`: one of the aforementioned events; - :param `pane`: the L{AuiPaneInfo} instance associated to this event; - :param `canVeto`: whether the event can be vetoed or not. - """ - - event = AuiManagerEvent(evtType) - event.SetPane(pane) - event.SetCanVeto(canVeto) - self.ProcessMgrEvent(event) - - return event - - - def CanUseModernDockArt(self): - """ - Returns whether L{ModernDockArt} can be used (Windows XP / Vista / 7 only, - requires Mark Hammonds's `pywin32` package). - """ - - if not _winxptheme: - return False - - # Get the size of a small close button (themed) - hwnd = self._frame.GetHandle() - hTheme = winxptheme.OpenThemeData(hwnd, "Window") - - if not hTheme: - return False - - return True - - - def SetArtProvider(self, art_provider): - """ - Instructs L{AuiManager} to use art provider specified by the parameter - `art_provider` for all drawing calls. This allows plugable look-and-feel - features. - - :param `art_provider`: a AUI dock art provider. - - :note: The previous art provider object, if any, will be deleted by L{AuiManager}. - """ - - # delete the last art provider, if any - del self._art - - # assign the new art provider - self._art = art_provider - - for pane in self.GetAllPanes(): - if pane.IsFloating() and pane.frame: - pane.frame._mgr.SetArtProvider(art_provider) - pane.frame._mgr.Update() - - - def AddPane(self, window, arg1=None, arg2=None, target=None): - """ - Tells the frame manager to start managing a child window. There - are four versions of this function. The first verison allows the full spectrum - of pane parameter possibilities (L{AddPane1}). The second version is used for - simpler user interfaces which do not require as much configuration (L{AddPane2}). - The L{AddPane3} version allows a drop position to be specified, which will determine - where the pane will be added. The L{AddPane4} version allows to turn the target - L{AuiPaneInfo} pane into a notebook and the added pane into a page. - - In wxPython, simply call L{AddPane}. - - :param `window`: the child window to manage; - :param `arg1`: a L{AuiPaneInfo} or an integer value (direction); - :param `arg2`: a L{AuiPaneInfo} or a `wx.Point` (drop position); - :param `target`: a L{AuiPaneInfo} to be turned into a notebook - and new pane added to it as a page. (additionally, target can be any pane in - an existing notebook) - """ - - if target in self._panes: - return self.AddPane4(window, arg1, target) - - if type(arg1) == type(1): - # This Is Addpane2 - if arg1 is None: - arg1 = wx.LEFT - if arg2 is None: - arg2 = "" - return self.AddPane2(window, arg1, arg2) - else: - if isinstance(arg2, wx.Point): - return self.AddPane3(window, arg1, arg2) - else: - return self.AddPane1(window, arg1) - - - def AddPane1(self, window, pane_info): - """ See comments on L{AddPane}. """ - - # check if the pane has a valid window - if not window: - return False - - # check if the pane already exists - if self.GetPane(pane_info.window).IsOk(): - return False - - # check if the pane name already exists, this could reveal a - # bug in the library user's application - already_exists = False - if pane_info.name != "" and self.GetPane(pane_info.name).IsOk(): - warnings.warn("A pane with the name '%s' already exists in the manager!"%pane_info.name) - already_exists = True - - # if the new pane is docked then we should undo maximize - if pane_info.IsDocked(): - self.RestoreMaximizedPane() - - self._panes.append(pane_info) - pinfo = self._panes[-1] - - # set the pane window - pinfo.window = window - - # if the pane's name identifier is blank, create a random string - if pinfo.name == "" or already_exists: - pinfo.name = ("%s%08x%08x%08x")%(pinfo.window.GetName(), time.time(), - time.clock(), len(self._panes)) - - # set initial proportion (if not already set) - if pinfo.dock_proportion == 0: - pinfo.dock_proportion = 100000 - - floating = isinstance(self._frame, AuiFloatingFrame) - - pinfo.buttons = [] - - if not floating and pinfo.HasMinimizeButton(): - button = AuiPaneButton(AUI_BUTTON_MINIMIZE) - pinfo.buttons.append(button) - - if not floating and pinfo.HasMaximizeButton(): - button = AuiPaneButton(AUI_BUTTON_MAXIMIZE_RESTORE) - pinfo.buttons.append(button) - - if not floating and pinfo.HasPinButton(): - button = AuiPaneButton(AUI_BUTTON_PIN) - pinfo.buttons.append(button) - - if pinfo.HasCloseButton(): - button = AuiPaneButton(AUI_BUTTON_CLOSE) - pinfo.buttons.append(button) - - if pinfo.HasGripper(): - if isinstance(pinfo.window, auibar.AuiToolBar): - # prevent duplicate gripper -- both AuiManager and AuiToolBar - # have a gripper control. The toolbar's built-in gripper - # meshes better with the look and feel of the control than ours, - # so turn AuiManager's gripper off, and the toolbar's on. - - tb = pinfo.window - pinfo.SetFlag(AuiPaneInfo.optionGripper, False) - tb.SetGripperVisible(True) - - if pinfo.window: - if pinfo.best_size == wx.Size(-1, -1): - pinfo.best_size = pinfo.window.GetClientSize() - - if isinstance(pinfo.window, wx.ToolBar): - # GetClientSize() doesn't get the best size for - # a toolbar under some newer versions of wxWidgets, - # so use GetBestSize() - pinfo.best_size = pinfo.window.GetBestSize() - - # this is needed for Win2000 to correctly fill toolbar backround - # it should probably be repeated once system colour change happens - if wx.Platform == "__WXMSW__" and pinfo.window.UseBgCol(): - pinfo.window.SetBackgroundColour(self.GetArtProvider().GetColour(AUI_DOCKART_BACKGROUND_COLOUR)) - - if pinfo.min_size != wx.Size(-1, -1): - if pinfo.best_size.x < pinfo.min_size.x: - pinfo.best_size.x = pinfo.min_size.x - if pinfo.best_size.y < pinfo.min_size.y: - pinfo.best_size.y = pinfo.min_size.y - - self._panes[-1] = pinfo - if isinstance(window, auibar.AuiToolBar): - window.SetAuiManager(self) - - return True - - - def AddPane2(self, window, direction, caption): - """ See comments on L{AddPane}. """ - - pinfo = AuiPaneInfo() - pinfo.Caption(caption) - - if direction == wx.TOP: - pinfo.Top() - elif direction == wx.BOTTOM: - pinfo.Bottom() - elif direction == wx.LEFT: - pinfo.Left() - elif direction == wx.RIGHT: - pinfo.Right() - elif direction == wx.CENTER: - pinfo.CenterPane() - - return self.AddPane(window, pinfo) - - - def AddPane3(self, window, pane_info, drop_pos): - """ See comments on L{AddPane}. """ - - if not self.AddPane(window, pane_info): - return False - - pane = self.GetPane(window) - indx = self._panes.index(pane) - - ret, pane = self.DoDrop(self._docks, self._panes, pane, drop_pos, wx.Point(0, 0)) - self._panes[indx] = pane - - return True - - - def AddPane4(self, window, pane_info, target): - """ See comments on L{AddPane}. """ - - if not self.AddPane(window, pane_info): - return False - - paneInfo = self.GetPane(window) - - if not paneInfo.IsNotebookDockable(): - return self.AddPane1(window, pane_info) - if not target.IsNotebookDockable() and not target.IsNotebookControl(): - return self.AddPane1(window, pane_info) - - if not target.HasNotebook(): - self.CreateNotebookBase(self._panes, target) - - # Add new item to notebook - paneInfo.NotebookPage(target.notebook_id) - - # we also want to remove our captions sometimes - self.RemoveAutoNBCaption(paneInfo) - self.UpdateNotebook() - - return True - - - def InsertPane(self, window, pane_info, insert_level=AUI_INSERT_PANE): - """ - This method is used to insert either a previously unmanaged pane window - into the frame manager, or to insert a currently managed pane somewhere else. - L{InsertPane} will push all panes, rows, or docks aside and insert the window - into the position specified by `pane_info`. - - Because `pane_info` can specify either a pane, dock row, or dock layer, the - `insert_level` parameter is used to disambiguate this. The parameter `insert_level` - can take a value of ``AUI_INSERT_PANE``, ``AUI_INSERT_ROW`` or ``AUI_INSERT_DOCK``. - - :param `window`: the window to be inserted and managed; - :param `pane_info`: the insert location for the new window; - :param `insert_level`: the insertion level of the new pane. - """ - - if not window: - raise Exception("Invalid window passed to InsertPane.") - - # shift the panes around, depending on the insert level - if insert_level == AUI_INSERT_PANE: - self._panes = DoInsertPane(self._panes, pane_info.dock_direction, - pane_info.dock_layer, pane_info.dock_row, - pane_info.dock_pos) - - elif insert_level == AUI_INSERT_ROW: - self._panes = DoInsertDockRow(self._panes, pane_info.dock_direction, - pane_info.dock_layer, pane_info.dock_row) - - elif insert_level == AUI_INSERT_DOCK: - self._panes = DoInsertDockLayer(self._panes, pane_info.dock_direction, - pane_info.dock_layer) - - # if the window already exists, we are basically just moving/inserting the - # existing window. If it doesn't exist, we need to add it and insert it - existing_pane = self.GetPane(window) - indx = self._panes.index(existing_pane) - - if not existing_pane.IsOk(): - - return self.AddPane(window, pane_info) - - else: - - if pane_info.IsFloating(): - existing_pane.Float() - if pane_info.floating_pos != wx.Point(-1, -1): - existing_pane.FloatingPosition(pane_info.floating_pos) - if pane_info.floating_size != wx.Size(-1, -1): - existing_pane.FloatingSize(pane_info.floating_size) - else: - # if the new pane is docked then we should undo maximize - self.RestoreMaximizedPane() - - existing_pane.Direction(pane_info.dock_direction) - existing_pane.Layer(pane_info.dock_layer) - existing_pane.Row(pane_info.dock_row) - existing_pane.Position(pane_info.dock_pos) - - self._panes[indx] = existing_pane - - return True - - - def DetachPane(self, window): - """ - Tells the L{AuiManager} to stop managing the pane specified - by `window`. The window, if in a floated frame, is reparented to the frame - managed by L{AuiManager}. - - :param `window`: the window to be un-managed. - """ - - for p in self._panes: - if p.window == window: - if p.frame: - # we have a floating frame which is being detached. We need to - # reparent it to self._frame and destroy the floating frame - - # reduce flicker - p.window.SetSize((1, 1)) - if p.frame.IsShown(): - p.frame.Show(False) - - if self._action_window == p.frame: - self._action_window = None - - # reparent to self._frame and destroy the pane - p.window.Reparent(self._frame) - p.frame.SetSizer(None) - p.frame.Destroy() - p.frame = None - - elif p.IsNotebookPage(): - notebook = self._notebooks[p.notebook_id] - id = notebook.GetPageIndex(p.window) - notebook.RemovePage(id) - - # make sure there are no references to this pane in our uiparts, - # just in case the caller doesn't call Update() immediately after - # the DetachPane() call. This prevets obscure crashes which would - # happen at window repaint if the caller forgets to call Update() - counter = 0 - for pi in xrange(len(self._uiparts)): - part = self._uiparts[counter] - if part.pane == p: - self._uiparts.pop(counter) - counter -= 1 - - counter += 1 - - self._panes.remove(p) - return True - - return False - - - def ClosePane(self, pane_info): - """ - Destroys or hides the pane depending on its flags. - - :param `pane_info`: a L{AuiPaneInfo} instance. - """ - - # if we were maximized, restore - if pane_info.IsMaximized(): - self.RestorePane(pane_info) - - if pane_info.frame: - if self._agwFlags & AUI_MGR_ANIMATE_FRAMES: - pane_info.frame.FadeOut() - - # first, hide the window - if pane_info.window and pane_info.window.IsShown(): - pane_info.window.Show(False) - - # make sure that we are the parent of this window - if pane_info.window and pane_info.window.GetParent() != self._frame: - pane_info.window.Reparent(self._frame) - - # if we have a frame, destroy it - if pane_info.frame: - pane_info.frame.Destroy() - pane_info.frame = None - - elif pane_info.IsNotebookPage(): - # if we are a notebook page, remove ourselves... - # the code would index out of bounds - # if the last page of a sub-notebook was closed - # because the notebook would be deleted, before this - # code is executed. - # This code just prevents an out-of bounds error. - if self._notebooks: - nid = pane_info.notebook_id - if nid >= 0 and nid < len(self._notebooks): - notebook = self._notebooks[nid] - page_idx = notebook.GetPageIndex(pane_info.window) - if page_idx >= 0: - notebook.RemovePage(page_idx) - - # now we need to either destroy or hide the pane - to_destroy = 0 - if pane_info.IsDestroyOnClose(): - to_destroy = pane_info.window - self.DetachPane(to_destroy) - else: - if isinstance(pane_info.window, auibar.AuiToolBar) and pane_info.IsFloating(): - tb = pane_info.window - if pane_info.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT]: - tb.SetAGWWindowStyleFlag(tb.GetAGWWindowStyleFlag() | AUI_TB_VERTICAL) - - pane_info.Dock().Hide() - - if pane_info.IsNotebookControl(): - - notebook = self._notebooks[pane_info.notebook_id] - while notebook.GetPageCount(): - window = notebook.GetPage(0) - notebook.RemovePage(0) - info = self.GetPane(window) - if info.IsOk(): - info.notebook_id = -1 - info.dock_direction = AUI_DOCK_NONE - # Note: this could change our paneInfo reference ... - self.ClosePane(info) - - if to_destroy: - to_destroy.Destroy() - - - def MaximizePane(self, pane_info, savesizes=True): - """ - Maximizes the input pane. - - :param `pane_info`: a L{AuiPaneInfo} instance. - :param `savesizes`: whether to save previous dock sizes. - """ - - if savesizes: - self.SavePreviousDockSizes(pane_info) - - for p in self._panes: - - # save hidden state - p.SetFlag(p.savedHiddenState, p.HasFlag(p.optionHidden)) - - if not p.IsToolbar() and not p.IsFloating(): - p.Restore() - - # hide the pane, because only the newly - # maximized pane should show - p.Hide() - - pane_info.previousDockPos = pane_info.dock_pos - - # mark ourselves maximized - pane_info.Maximize() - pane_info.Show() - self._has_maximized = True - - # last, show the window - if pane_info.window and not pane_info.window.IsShown(): - pane_info.window.Show(True) - - - def SavePreviousDockSizes(self, pane_info): - """ - Stores the previous dock sizes, to be used in a "restore" action later. - - :param `pane_info`: a L{AuiPaneInfo} instance. - """ - - for d in self._docks: - if not d.toolbar: - for p in d.panes: - p.previousDockSize = d.size - if pane_info is not p: - p.SetFlag(p.needsRestore, True) - - - def RestorePane(self, pane_info): - """ - Restores the input pane from a previous maximized or minimized state. - - :param `pane_info`: a L{AuiPaneInfo} instance. - """ - - # restore all the panes - for p in self._panes: - if not p.IsToolbar(): - p.SetFlag(p.optionHidden, p.HasFlag(p.savedHiddenState)) - - pane_info.SetFlag(pane_info.needsRestore, True) - - # mark ourselves non-maximized - pane_info.Restore() - self._has_maximized = False - self._has_minimized = False - - # last, show the window - if pane_info.window and not pane_info.window.IsShown(): - pane_info.window.Show(True) - - - def RestoreMaximizedPane(self): - """ Restores the current maximized pane (if any). """ - - # restore all the panes - for p in self._panes: - if p.IsMaximized(): - self.RestorePane(p) - break - - - def ActivatePane(self, window): - """ - Activates the pane to which `window` is associated. - - :param `window`: a `wx.Window` derived window. - """ - - if self.GetAGWFlags() & AUI_MGR_ALLOW_ACTIVE_PANE: - while window: - ret, self._panes = SetActivePane(self._panes, window) - if ret: - break - - window = window.GetParent() - - self.RefreshCaptions() - self.FireEvent(wxEVT_AUI_PANE_ACTIVATED, window, canVeto=False) - - - def CreateNotebook(self): - """ - Creates an automatic L{AuiNotebook} when a pane is docked on - top of another pane. - """ - - notebook = auibook.AuiNotebook(self._frame, -1, wx.Point(0, 0), wx.Size(0, 0), agwStyle=self._autoNBStyle) - - # This is so we can get the tab-drag event. - notebook.GetAuiManager().SetMasterManager(self) - notebook.SetArtProvider(self._autoNBTabArt.Clone()) - self._notebooks.append(notebook) - - return notebook - - - def SetAutoNotebookTabArt(self, art): - """ - Sets the default tab art provider for automatic notebooks. - - :param `art`: a tab art provider. - """ - - for nb in self._notebooks: - nb.SetArtProvider(art.Clone()) - nb.Refresh() - nb.Update() - - self._autoNBTabArt = art - - - def GetAutoNotebookTabArt(self): - """ Returns the default tab art provider for automatic notebooks. """ - - return self._autoNBTabArt - - - def SetAutoNotebookStyle(self, agwStyle): - """ - Sets the default AGW-specific window style for automatic notebooks. - - :param `agwStyle`: the underlying L{AuiNotebook} window style. - This can be a combination of the following bits: - - ==================================== ================================== - Flag name Description - ==================================== ================================== - ``AUI_NB_TOP`` With this style, tabs are drawn along the top of the notebook - ``AUI_NB_LEFT`` With this style, tabs are drawn along the left of the notebook. Not implemented yet. - ``AUI_NB_RIGHT`` With this style, tabs are drawn along the right of the notebook. Not implemented yet. - ``AUI_NB_BOTTOM`` With this style, tabs are drawn along the bottom of the notebook - ``AUI_NB_TAB_SPLIT`` Allows the tab control to be split by dragging a tab - ``AUI_NB_TAB_MOVE`` Allows a tab to be moved horizontally by dragging - ``AUI_NB_TAB_EXTERNAL_MOVE`` Allows a tab to be moved to another tab control - ``AUI_NB_TAB_FIXED_WIDTH`` With this style, all tabs have the same width - ``AUI_NB_SCROLL_BUTTONS`` With this style, left and right scroll buttons are displayed - ``AUI_NB_WINDOWLIST_BUTTON`` With this style, a drop-down list of windows is available - ``AUI_NB_CLOSE_BUTTON`` With this style, a close button is available on the tab bar - ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` With this style, a close button is available on the active tab - ``AUI_NB_CLOSE_ON_ALL_TABS`` With this style, a close button is available on all tabs - ``AUI_NB_MIDDLE_CLICK_CLOSE`` Allows to close L{AuiNotebook} tabs by mouse middle button click - ``AUI_NB_SUB_NOTEBOOK`` This style is used by {AuiManager} to create automatic AuiNotebooks - ``AUI_NB_HIDE_ON_SINGLE_TAB`` Hides the tab window if only one tab is present - ``AUI_NB_SMART_TABS`` Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows - ``AUI_NB_USE_IMAGES_DROPDOWN`` Uses images on dropdown window list menu instead of check items - ``AUI_NB_CLOSE_ON_TAB_LEFT`` Draws the tab close button on the left instead of on the right (a la Camino browser) - ``AUI_NB_TAB_FLOAT`` Allows the floating of single tabs. Known limitation: when the notebook is more or less full screen, tabs cannot be dragged far enough outside of the notebook to become floating pages - ``AUI_NB_DRAW_DND_TAB`` Draws an image representation of a tab while dragging (on by default) - ==================================== ================================== - - """ - - for nb in self._notebooks: - nb.SetAGWWindowStyleFlag(agwStyle) - nb.Refresh() - nb.Update() - - self._autoNBStyle = agwStyle - - - def GetAutoNotebookStyle(self): - """ - Returns the default AGW-specific window style for automatic notebooks. - - :see: L{SetAutoNotebookStyle} method for a list of possible styles. - """ - - return self._autoNBStyle - - - def SavePaneInfo(self, pane): - """ - This method is similar to L{SavePerspective}, with the exception - that it only saves information about a single pane. It is used in - combination with L{LoadPaneInfo}. - - :param `pane`: a L{AuiPaneInfo} instance to save. - """ - - result = "name=" + EscapeDelimiters(pane.name) + ";" - result += "caption=" + EscapeDelimiters(pane.caption) + ";" - - result += "state=%u;"%pane.state - result += "dir=%d;"%pane.dock_direction - result += "layer=%d;"%pane.dock_layer - result += "row=%d;"%pane.dock_row - result += "pos=%d;"%pane.dock_pos - result += "prop=%d;"%pane.dock_proportion - result += "bestw=%d;"%pane.best_size.x - result += "besth=%d;"%pane.best_size.y - result += "minw=%d;"%pane.min_size.x - result += "minh=%d;"%pane.min_size.y - result += "maxw=%d;"%pane.max_size.x - result += "maxh=%d;"%pane.max_size.y - result += "floatx=%d;"%pane.floating_pos.x - result += "floaty=%d;"%pane.floating_pos.y - result += "floatw=%d;"%pane.floating_size.x - result += "floath=%d;"%pane.floating_size.y - result += "notebookid=%d;"%pane.notebook_id - result += "transparent=%d"%pane.transparent - - return result - - - def LoadPaneInfo(self, pane_part, pane): - """ - This method is similar to to L{LoadPerspective}, with the exception that - it only loads information about a single pane. It is used in combination - with L{SavePaneInfo}. - - :param `pane_part`: the string to analyze; - :param `pane`: the L{AuiPaneInfo} structure in which to load `pane_part`. - """ - - # replace escaped characters so we can - # split up the string easily - pane_part = pane_part.replace("\\|", "\a") - pane_part = pane_part.replace("\\;", "\b") - - options = pane_part.split(";") - for items in options: - - val_name, value = items.split("=") - val_name = val_name.strip() - - if val_name == "name": - pane.name = value - elif val_name == "caption": - pane.caption = value - elif val_name == "state": - pane.state = int(value) - elif val_name == "dir": - pane.dock_direction = int(value) - elif val_name == "layer": - pane.dock_layer = int(value) - elif val_name == "row": - pane.dock_row = int(value) - elif val_name == "pos": - pane.dock_pos = int(value) - elif val_name == "prop": - pane.dock_proportion = int(value) - elif val_name == "bestw": - pane.best_size.x = int(value) - elif val_name == "besth": - pane.best_size.y = int(value) - pane.best_size = wx.Size(pane.best_size.x, pane.best_size.y) - elif val_name == "minw": - pane.min_size.x = int(value) - elif val_name == "minh": - pane.min_size.y = int(value) - pane.min_size = wx.Size(pane.min_size.x, pane.min_size.y) - elif val_name == "maxw": - pane.max_size.x = int(value) - elif val_name == "maxh": - pane.max_size.y = int(value) - pane.max_size = wx.Size(pane.max_size.x, pane.max_size.y) - elif val_name == "floatx": - pane.floating_pos.x = int(value) - elif val_name == "floaty": - pane.floating_pos.y = int(value) - pane.floating_pos = wx.Point(pane.floating_pos.x, pane.floating_pos.y) - elif val_name == "floatw": - pane.floating_size.x = int(value) - elif val_name == "floath": - pane.floating_size.y = int(value) - pane.floating_size = wx.Size(pane.floating_size.x, pane.floating_size.y) - elif val_name == "notebookid": - pane.notebook_id = int(value) - elif val_name == "transparent": - pane.transparent = int(value) - else: - raise Exception("Bad perspective string") - - # replace escaped characters so we can - # split up the string easily - pane.name = pane.name.replace("\a", "|") - pane.name = pane.name.replace("\b", ";") - pane.caption = pane.caption.replace("\a", "|") - pane.caption = pane.caption.replace("\b", ";") - pane_part = pane_part.replace("\a", "|") - pane_part = pane_part.replace("\b", ";") - - return pane - - - def SavePerspective(self): - """ - Saves the entire user interface layout into an encoded string, which can then - be stored by the application (probably using `wx.Config`). - - When a perspective is restored using L{LoadPerspective}, the entire user - interface will return to the state it was when the perspective was saved. - """ - - result = "layout2|" - - for pane in self._panes: - result += self.SavePaneInfo(pane) + "|" - - for dock in self._docks: - result = result + ("dock_size(%d,%d,%d)=%d|")%(dock.dock_direction, - dock.dock_layer, - dock.dock_row, - dock.size) - return result - - - def LoadPerspective(self, layout, update=True): - """ - Loads a layout which was saved with L{SavePerspective}. - - If the `update` flag parameter is ``True``, L{Update} will be - automatically invoked, thus realizing the saved perspective on screen. - - :param `layout`: a string which contains a saved AUI layout; - :param `update`: whether to update immediately the window or not. - """ - - input = layout - - # check layout string version - # 'layout1' = wxAUI 0.9.0 - wxAUI 0.9.2 - # 'layout2' = wxAUI 0.9.2 (wxWidgets 2.8) - index = input.find("|") - part = input[0:index].strip() - input = input[index+1:] - - if part != "layout2": - return False - - # mark all panes currently managed as docked and hidden - for pane in self._panes: - pane.Dock().Hide() - - # clear out the dock array; this will be reconstructed - self._docks = [] - - # replace escaped characters so we can - # split up the string easily - input = input.replace("\\|", "\a") - input = input.replace("\\;", "\b") - - while 1: - - pane = AuiPaneInfo() - index = input.find("|") - pane_part = input[0:index].strip() - input = input[index+1:] - - # if the string is empty, we're done parsing - if pane_part == "": - break - - if pane_part[0:9] == "dock_size": - index = pane_part.find("=") - val_name = pane_part[0:index] - value = pane_part[index+1:] - - index = val_name.find("(") - piece = val_name[index+1:] - index = piece.find(")") - piece = piece[0:index] - - vals = piece.split(",") - dir = int(vals[0]) - layer = int(vals[1]) - row = int(vals[2]) - size = int(value) - - dock = AuiDockInfo() - dock.dock_direction = dir - dock.dock_layer = layer - dock.dock_row = row - dock.size = size - self._docks.append(dock) - - continue - - # Undo our escaping as LoadPaneInfo needs to take an unescaped - # name so it can be called by external callers - pane_part = pane_part.replace("\a", "|") - pane_part = pane_part.replace("\b", ";") - - pane = self.LoadPaneInfo(pane_part, pane) - - p = self.GetPane(pane.name) - - if not p.IsOk(): - if pane.IsNotebookControl(): - # notebook controls - auto add... - self._panes.append(pane) - indx = self._panes.index(pane) - else: - # the pane window couldn't be found - # in the existing layout -- skip it - continue - - else: - indx = self._panes.index(p) - pane.window = p.window - pane.frame = p.frame - pane.buttons = p.buttons - self._panes[indx] = pane - - if isinstance(pane.window, auibar.AuiToolBar) and (pane.IsFloatable() or pane.IsDockable()): - pane.window.SetGripperVisible(True) - - if update: - self.Update() - - return True - - - def GetPanePositionsAndSizes(self, dock): - """ - Returns all the panes positions and sizes in a dock. - - :param `dock`: a L{AuiDockInfo} instance. - """ - - caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) - pane_border_size = self._art.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE) - gripper_size = self._art.GetMetric(AUI_DOCKART_GRIPPER_SIZE) - - positions = [] - sizes = [] - - action_pane = -1 - pane_count = len(dock.panes) - - # find the pane marked as our action pane - for pane_i in xrange(pane_count): - pane = dock.panes[pane_i] - if pane.HasFlag(AuiPaneInfo.actionPane): - if action_pane != -1: - raise Exception("Too many action panes!") - action_pane = pane_i - - # set up each panes default position, and - # determine the size (width or height, depending - # on the dock's orientation) of each pane - for pane in dock.panes: - positions.append(pane.dock_pos) - size = 0 - - if pane.HasBorder(): - size += pane_border_size*2 - - if dock.IsHorizontal(): - if pane.HasGripper() and not pane.HasGripperTop(): - size += gripper_size - - if pane.HasCaptionLeft(): - size += caption_size - - size += pane.best_size.x - - else: - if pane.HasGripper() and pane.HasGripperTop(): - size += gripper_size - - if pane.HasCaption() and not pane.HasCaptionLeft(): - size += caption_size - - size += pane.best_size.y - - sizes.append(size) - - # if there is no action pane, just return the default - # positions (as specified in pane.pane_pos) - if action_pane == -1: - return positions, sizes - - offset = 0 - for pane_i in xrange(action_pane-1, -1, -1): - amount = positions[pane_i+1] - (positions[pane_i] + sizes[pane_i]) - if amount >= 0: - offset += amount - else: - positions[pane_i] -= -amount - - offset += sizes[pane_i] - - # if the dock mode is fixed, make sure none of the panes - # overlap we will bump panes that overlap - offset = 0 - for pane_i in xrange(action_pane, pane_count): - amount = positions[pane_i] - offset - if amount >= 0: - offset += amount - else: - positions[pane_i] += -amount - - offset += sizes[pane_i] - - return positions, sizes - - - def LayoutAddPane(self, cont, dock, pane, uiparts, spacer_only): - """ - Adds a pane into the existing layout (in an existing dock). - - :param `cont`: a `wx.Sizer` object; - :param `dock`: the L{AuiDockInfo} structure in which to add the pane; - :param `pane`: the L{AuiPaneInfo} instance to add to the dock; - :param `uiparts`: a list of UI parts in the interface; - :param `spacer_only`: whether to add a simple spacer or a real window. - """ - - sizer_item = wx.SizerItem() - caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) - gripper_size = self._art.GetMetric(AUI_DOCKART_GRIPPER_SIZE) - pane_border_size = self._art.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE) - pane_button_size = self._art.GetMetric(AUI_DOCKART_PANE_BUTTON_SIZE) - - # find out the orientation of the item (orientation for panes - # is the same as the dock's orientation) - - if dock.IsHorizontal(): - orientation = wx.HORIZONTAL - else: - orientation = wx.VERTICAL - - # this variable will store the proportion - # value that the pane will receive - pane_proportion = pane.dock_proportion - - horz_pane_sizer = wx.BoxSizer(wx.HORIZONTAL) - vert_pane_sizer = wx.BoxSizer(wx.VERTICAL) - - if pane.HasGripper(): - - part = AuiDockUIPart() - if pane.HasGripperTop(): - sizer_item = vert_pane_sizer.Add((1, gripper_size), 0, wx.EXPAND) - else: - sizer_item = horz_pane_sizer.Add((gripper_size, 1), 0, wx.EXPAND) - - part.type = AuiDockUIPart.typeGripper - part.dock = dock - part.pane = pane - part.button = None - part.orientation = orientation - part.cont_sizer = horz_pane_sizer - part.sizer_item = sizer_item - uiparts.append(part) - - button_count = len(pane.buttons) - button_width_total = button_count*pane_button_size - if button_count >= 1: - button_width_total += 3 - - caption, captionLeft = pane.HasCaption(), pane.HasCaptionLeft() - button_count = len(pane.buttons) - - if captionLeft: - caption_sizer = wx.BoxSizer(wx.VERTICAL) - - # add pane buttons to the caption - dummy_parts = [] - for btn_id in xrange(len(pane.buttons)-1, -1, -1): - sizer_item = caption_sizer.Add((caption_size, pane_button_size), 0, wx.EXPAND) - part = AuiDockUIPart() - part.type = AuiDockUIPart.typePaneButton - part.dock = dock - part.pane = pane - part.button = pane.buttons[btn_id] - part.orientation = orientation - part.cont_sizer = caption_sizer - part.sizer_item = sizer_item - dummy_parts.append(part) - - sizer_item = caption_sizer.Add((caption_size, 1), 1, wx.EXPAND) - vert_pane_sizer = wx.BoxSizer(wx.HORIZONTAL) - - # create the caption sizer - part = AuiDockUIPart() - - part.type = AuiDockUIPart.typeCaption - part.dock = dock - part.pane = pane - part.button = None - part.orientation = orientation - part.cont_sizer = vert_pane_sizer - part.sizer_item = sizer_item - caption_part_idx = len(uiparts) - uiparts.append(part) - uiparts.extend(dummy_parts) - - elif caption: - - caption_sizer = wx.BoxSizer(wx.HORIZONTAL) - sizer_item = caption_sizer.Add((1, caption_size), 1, wx.EXPAND) - - # create the caption sizer - part = AuiDockUIPart() - - part.type = AuiDockUIPart.typeCaption - part.dock = dock - part.pane = pane - part.button = None - part.orientation = orientation - part.cont_sizer = vert_pane_sizer - part.sizer_item = sizer_item - caption_part_idx = len(uiparts) - uiparts.append(part) - - # add pane buttons to the caption - for button in pane.buttons: - sizer_item = caption_sizer.Add((pane_button_size, caption_size), 0, wx.EXPAND) - part = AuiDockUIPart() - part.type = AuiDockUIPart.typePaneButton - part.dock = dock - part.pane = pane - part.button = button - part.orientation = orientation - part.cont_sizer = caption_sizer - part.sizer_item = sizer_item - uiparts.append(part) - - if caption or captionLeft: - # if we have buttons, add a little space to the right - # of them to ease visual crowding - if button_count >= 1: - if captionLeft: - caption_sizer.Add((caption_size, 3), 0, wx.EXPAND) - else: - caption_sizer.Add((3, caption_size), 0, wx.EXPAND) - - # add the caption sizer - sizer_item = vert_pane_sizer.Add(caption_sizer, 0, wx.EXPAND) - uiparts[caption_part_idx].sizer_item = sizer_item - - # add the pane window itself - if spacer_only or not pane.window: - sizer_item = vert_pane_sizer.Add((1, 1), 1, wx.EXPAND) - else: - sizer_item = vert_pane_sizer.Add(pane.window, 1, wx.EXPAND) - vert_pane_sizer.SetItemMinSize(pane.window, (1, 1)) - - part = AuiDockUIPart() - part.type = AuiDockUIPart.typePane - part.dock = dock - part.pane = pane - part.button = None - part.orientation = orientation - part.cont_sizer = vert_pane_sizer - part.sizer_item = sizer_item - uiparts.append(part) - - # determine if the pane should have a minimum size if the pane is - # non-resizable (fixed) then we must set a minimum size. Alternatively, - # if the pane.min_size is set, we must use that value as well - - min_size = pane.min_size - if pane.IsFixed(): - if min_size == wx.Size(-1, -1): - min_size = pane.best_size - pane_proportion = 0 - - if min_size != wx.Size(-1, -1): - vert_pane_sizer.SetItemMinSize(len(vert_pane_sizer.GetChildren())-1, (min_size.x, min_size.y)) - - # add the vertical/horizontal sizer (caption, pane window) to the - # horizontal sizer (gripper, vertical sizer) - horz_pane_sizer.Add(vert_pane_sizer, 1, wx.EXPAND) - - # finally, add the pane sizer to the dock sizer - if pane.HasBorder(): - # allowing space for the pane's border - sizer_item = cont.Add(horz_pane_sizer, pane_proportion, - wx.EXPAND | wx.ALL, pane_border_size) - part = AuiDockUIPart() - part.type = AuiDockUIPart.typePaneBorder - part.dock = dock - part.pane = pane - part.button = None - part.orientation = orientation - part.cont_sizer = cont - part.sizer_item = sizer_item - uiparts.append(part) - else: - sizer_item = cont.Add(horz_pane_sizer, pane_proportion, wx.EXPAND) - - return uiparts - - - def LayoutAddDock(self, cont, dock, uiparts, spacer_only): - """ - Adds a dock into the existing layout. - - :param `cont`: a `wx.Sizer` object; - :param `dock`: the L{AuiDockInfo} structure to add to the layout; - :param `uiparts`: a list of UI parts in the interface; - :param `spacer_only`: whether to add a simple spacer or a real window. - """ - - sizer_item = wx.SizerItem() - part = AuiDockUIPart() - - sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE) - orientation = (dock.IsHorizontal() and [wx.HORIZONTAL] or [wx.VERTICAL])[0] - - # resizable bottom and right docks have a sash before them - if not self._has_maximized and not dock.fixed and \ - dock.dock_direction in [AUI_DOCK_BOTTOM, AUI_DOCK_RIGHT]: - - sizer_item = cont.Add((sash_size, sash_size), 0, wx.EXPAND) - - part.type = AuiDockUIPart.typeDockSizer - part.orientation = orientation - part.dock = dock - part.pane = None - part.button = None - part.cont_sizer = cont - part.sizer_item = sizer_item - uiparts.append(part) - - # create the sizer for the dock - dock_sizer = wx.BoxSizer(orientation) - - # add each pane to the dock - has_maximized_pane = False - pane_count = len(dock.panes) - - if dock.fixed: - - # figure out the real pane positions we will - # use, without modifying the each pane's pane_pos member - pane_positions, pane_sizes = self.GetPanePositionsAndSizes(dock) - - offset = 0 - for pane_i in xrange(pane_count): - - pane = dock.panes[pane_i] - pane_pos = pane_positions[pane_i] - - if pane.IsMaximized(): - has_maximized_pane = True - - amount = pane_pos - offset - if amount > 0: - - if dock.IsVertical(): - sizer_item = dock_sizer.Add((1, amount), 0, wx.EXPAND) - else: - sizer_item = dock_sizer.Add((amount, 1), 0, wx.EXPAND) - - part = AuiDockUIPart() - part.type = AuiDockUIPart.typeBackground - part.dock = dock - part.pane = None - part.button = None - part.orientation = (orientation==wx.HORIZONTAL and \ - [wx.VERTICAL] or [wx.HORIZONTAL])[0] - part.cont_sizer = dock_sizer - part.sizer_item = sizer_item - uiparts.append(part) - - offset = offset + amount - - uiparts = self.LayoutAddPane(dock_sizer, dock, pane, uiparts, spacer_only) - - offset = offset + pane_sizes[pane_i] - - # at the end add a very small stretchable background area - sizer_item = dock_sizer.Add((0, 0), 1, wx.EXPAND) - part = AuiDockUIPart() - part.type = AuiDockUIPart.typeBackground - part.dock = dock - part.pane = None - part.button = None - part.orientation = orientation - part.cont_sizer = dock_sizer - part.sizer_item = sizer_item - uiparts.append(part) - - else: - - for pane_i in xrange(pane_count): - - pane = dock.panes[pane_i] - - if pane.IsMaximized(): - has_maximized_pane = True - - # if this is not the first pane being added, - # we need to add a pane sizer - if not self._has_maximized and pane_i > 0: - sizer_item = dock_sizer.Add((sash_size, sash_size), 0, wx.EXPAND) - part = AuiDockUIPart() - part.type = AuiDockUIPart.typePaneSizer - part.dock = dock - part.pane = dock.panes[pane_i-1] - part.button = None - part.orientation = (orientation==wx.HORIZONTAL and \ - [wx.VERTICAL] or [wx.HORIZONTAL])[0] - part.cont_sizer = dock_sizer - part.sizer_item = sizer_item - uiparts.append(part) - - uiparts = self.LayoutAddPane(dock_sizer, dock, pane, uiparts, spacer_only) - - if dock.dock_direction == AUI_DOCK_CENTER or has_maximized_pane: - sizer_item = cont.Add(dock_sizer, 1, wx.EXPAND) - else: - sizer_item = cont.Add(dock_sizer, 0, wx.EXPAND) - - part = AuiDockUIPart() - part.type = AuiDockUIPart.typeDock - part.dock = dock - part.pane = None - part.button = None - part.orientation = orientation - part.cont_sizer = cont - part.sizer_item = sizer_item - uiparts.append(part) - - if dock.IsHorizontal(): - cont.SetItemMinSize(dock_sizer, (0, dock.size)) - else: - cont.SetItemMinSize(dock_sizer, (dock.size, 0)) - - # top and left docks have a sash after them - if not self._has_maximized and not dock.fixed and \ - dock.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_LEFT]: - - sizer_item = cont.Add((sash_size, sash_size), 0, wx.EXPAND) - - part = AuiDockUIPart() - part.type = AuiDockUIPart.typeDockSizer - part.dock = dock - part.pane = None - part.button = None - part.orientation = orientation - part.cont_sizer = cont - part.sizer_item = sizer_item - uiparts.append(part) - - return uiparts - - - def LayoutAll(self, panes, docks, uiparts, spacer_only=False, oncheck=True): - """ - Layouts all the UI structures in the interface. - - :param `panes`: a list of L{AuiPaneInfo} instances; - :param `docks`: a list of L{AuiDockInfo} classes; - :param `uiparts`: a list of UI parts in the interface; - :param `spacer_only`: whether to add a simple spacer or a real window; - :param `oncheck`: whether to store the results in a class member or not. - """ - - container = wx.BoxSizer(wx.VERTICAL) - - pane_border_size = self._art.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE) - caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) - cli_size = self._frame.GetClientSize() - - # empty all docks out - for dock in docks: - dock.panes = [] - if dock.fixed: - # always reset fixed docks' sizes, because - # the contained windows may have been resized - dock.size = 0 - - dock_count = len(docks) - - # iterate through all known panes, filing each - # of them into the appropriate dock. If the - # pane does not exist in the dock, add it - for p in panes: - - # don't layout hidden panes. - if p.IsShown(): - - # find any docks with the same dock direction, dock layer, and - # dock row as the pane we are working on - arr = FindDocks(docks, p.dock_direction, p.dock_layer, p.dock_row) - - if arr: - dock = arr[0] - - else: - # dock was not found, so we need to create a new one - d = AuiDockInfo() - d.dock_direction = p.dock_direction - d.dock_layer = p.dock_layer - d.dock_row = p.dock_row - docks.append(d) - dock = docks[-1] - - if p.HasFlag(p.needsRestore) and not p.HasFlag(p.wasMaximized): - - isHor = dock.IsHorizontal() - sashSize = self._art.GetMetric(AUI_DOCKART_SASH_SIZE) - - # get the sizes of any docks that might - # overlap with our restored dock - - # make list of widths or heights from the size in the dock rects - sizes = [d.rect[2:][isHor] for \ - d in docks if d.IsOk() and \ - (d.IsHorizontal() == isHor) and \ - not d.toolbar and \ - d.dock_direction != AUI_DOCK_CENTER] - - frameRect = GetInternalFrameRect(self._frame, self._docks) - - # set max size allowing for sashes and absolute minimum - maxsize = frameRect[2:][isHor] - sum(sizes) - (len(sizes)*10) - (sashSize*len(sizes)) - dock.size = min(p.previousDockSize,maxsize) - - else: - dock.size = 0 - - if p.HasFlag(p.wasMaximized): - self.MaximizePane(p, savesizes=False) - p.SetFlag(p.wasMaximized, False) - - if p.HasFlag(p.needsRestore): - if p.previousDockPos is not None: - DoInsertPane(dock.panes, dock.dock_direction, dock.dock_layer, dock.dock_row, p.previousDockPos) - p.dock_pos = p.previousDockPos - p.previousDockPos = None - p.SetFlag(p.needsRestore, False) - - if p.IsDocked(): - # remove the pane from any existing docks except this one - docks = RemovePaneFromDocks(docks, p, dock) - - # pane needs to be added to the dock, - # if it doesn't already exist - if not FindPaneInDock(dock, p.window): - dock.panes.append(p) - else: - # remove the pane from any existing docks - docks = RemovePaneFromDocks(docks, p) - - # remove any empty docks - docks = [dock for dock in docks if dock.panes] - - dock_count = len(docks) - # configure the docks further - for ii, dock in enumerate(docks): - # sort the dock pane array by the pane's - # dock position (dock_pos), in ascending order - dock.panes.sort(PaneSortFunc) - dock_pane_count = len(dock.panes) - - # for newly created docks, set up their initial size - if dock.size == 0: - size = 0 - for pane in dock.panes: - pane_size = pane.best_size - if pane_size == wx.Size(-1, -1): - pane_size = pane.min_size - if pane_size == wx.Size(-1, -1) and pane.window: - pane_size = pane.window.GetSize() - if dock.IsHorizontal(): - size = max(pane_size.y, size) - else: - size = max(pane_size.x, size) - - # add space for the border (two times), but only - # if at least one pane inside the dock has a pane border - for pane in dock.panes: - if pane.HasBorder(): - size = size + pane_border_size*2 - break - - # if pane is on the top or bottom, add the caption height, - # but only if at least one pane inside the dock has a caption - if dock.IsHorizontal(): - for pane in dock.panes: - if pane.HasCaption() and not pane.HasCaptionLeft(): - size = size + caption_size - break - else: - for pane in dock.panes: - if pane.HasCaptionLeft() and not pane.HasCaption(): - size = size + caption_size - break - - # new dock's size may not be more than the dock constraint - # parameter specifies. See SetDockSizeConstraint() - max_dock_x_size = int(self._dock_constraint_x*float(cli_size.x)) - max_dock_y_size = int(self._dock_constraint_y*float(cli_size.y)) - if cli_size <= wx.Size(20, 20): - max_dock_x_size = 10000 - max_dock_y_size = 10000 - - if dock.IsHorizontal(): - size = min(size, max_dock_y_size) - else: - size = min(size, max_dock_x_size) - - # absolute minimum size for a dock is 10 pixels - if size < 10: - size = 10 - - dock.size = size - - # determine the dock's minimum size - plus_border = False - plus_caption = False - plus_caption_left = False - dock_min_size = 0 - for pane in dock.panes: - if pane.min_size != wx.Size(-1, -1): - if pane.HasBorder(): - plus_border = True - if pane.HasCaption(): - plus_caption = True - if pane.HasCaptionLeft(): - plus_caption_left = True - if dock.IsHorizontal(): - if pane.min_size.y > dock_min_size: - dock_min_size = pane.min_size.y - else: - if pane.min_size.x > dock_min_size: - dock_min_size = pane.min_size.x - - if plus_border: - dock_min_size += pane_border_size*2 - if plus_caption and dock.IsHorizontal(): - dock_min_size += caption_size - if plus_caption_left and dock.IsVertical(): - dock_min_size += caption_size - - dock.min_size = dock_min_size - - # if the pane's current size is less than it's - # minimum, increase the dock's size to it's minimum - if dock.size < dock.min_size: - dock.size = dock.min_size - - # determine the dock's mode (fixed or proportional) - # determine whether the dock has only toolbars - action_pane_marked = False - dock.fixed = True - dock.toolbar = True - for pane in dock.panes: - if not pane.IsFixed(): - dock.fixed = False - if not pane.IsToolbar(): - dock.toolbar = False - if pane.HasFlag(AuiPaneInfo.optionDockFixed): - dock.fixed = True - if pane.HasFlag(AuiPaneInfo.actionPane): - action_pane_marked = True - - # if the dock mode is proportional and not fixed-pixel, - # reassign the dock_pos to the sequential 0, 1, 2, 3 - # e.g. remove gaps like 1, 2, 30, 500 - if not dock.fixed: - for jj in xrange(dock_pane_count): - pane = dock.panes[jj] - pane.dock_pos = jj - - # if the dock mode is fixed, and none of the panes - # are being moved right now, make sure the panes - # do not overlap each other. If they do, we will - # adjust the panes' positions - if dock.fixed and not action_pane_marked: - pane_positions, pane_sizes = self.GetPanePositionsAndSizes(dock) - offset = 0 - for jj in xrange(dock_pane_count): - pane = dock.panes[jj] - pane.dock_pos = pane_positions[jj] - amount = pane.dock_pos - offset - if amount >= 0: - offset += amount - else: - pane.dock_pos += -amount - - offset += pane_sizes[jj] - dock.panes[jj] = pane - - if oncheck: - self._docks[ii] = dock - - # shrink docks if needed -## docks = self.SmartShrink(docks, AUI_DOCK_TOP) -## docks = self.SmartShrink(docks, AUI_DOCK_LEFT) - - if oncheck: - self._docks = docks - - # discover the maximum dock layer - max_layer = 0 - dock_count = len(docks) - - for ii in xrange(dock_count): - max_layer = max(max_layer, docks[ii].dock_layer) - - # clear out uiparts - uiparts = [] - - # create a bunch of box sizers, - # from the innermost level outwards. - cont = None - middle = None - - if oncheck: - docks = self._docks - - for layer in xrange(max_layer+1): - # find any docks in this layer - arr = FindDocks(docks, -1, layer, -1) - # if there aren't any, skip to the next layer - if not arr: - continue - - old_cont = cont - - # create a container which will hold this layer's - # docks (top, bottom, left, right) - cont = wx.BoxSizer(wx.VERTICAL) - - # find any top docks in this layer - arr = FindDocks(docks, AUI_DOCK_TOP, layer, -1) - for row in arr: - uiparts = self.LayoutAddDock(cont, row, uiparts, spacer_only) - - # fill out the middle layer (which consists - # of left docks, content area and right docks) - - middle = wx.BoxSizer(wx.HORIZONTAL) - - # find any left docks in this layer - arr = FindDocks(docks, AUI_DOCK_LEFT, layer, -1) - for row in arr: - uiparts = self.LayoutAddDock(middle, row, uiparts, spacer_only) - - # add content dock (or previous layer's sizer - # to the middle - if not old_cont: - # find any center docks - arr = FindDocks(docks, AUI_DOCK_CENTER, -1, -1) - if arr: - for row in arr: - uiparts = self.LayoutAddDock(middle, row, uiparts, spacer_only) - - elif not self._has_maximized: - # there are no center docks, add a background area - sizer_item = middle.Add((1, 1), 1, wx.EXPAND) - part = AuiDockUIPart() - part.type = AuiDockUIPart.typeBackground - part.pane = None - part.dock = None - part.button = None - part.cont_sizer = middle - part.sizer_item = sizer_item - uiparts.append(part) - else: - middle.Add(old_cont, 1, wx.EXPAND) - - # find any right docks in this layer - arr = FindDocks(docks, AUI_DOCK_RIGHT, layer, -1, reverse=True) - for row in arr: - uiparts = self.LayoutAddDock(middle, row, uiparts, spacer_only) - - if len(middle.GetChildren()) > 0: - cont.Add(middle, 1, wx.EXPAND) - - # find any bottom docks in this layer - arr = FindDocks(docks, AUI_DOCK_BOTTOM, layer, -1, reverse=True) - for row in arr: - uiparts = self.LayoutAddDock(cont, row, uiparts, spacer_only) - - if not cont: - # no sizer available, because there are no docks, - # therefore we will create a simple background area - cont = wx.BoxSizer(wx.VERTICAL) - sizer_item = cont.Add((1, 1), 1, wx.EXPAND) - part = AuiDockUIPart() - part.type = AuiDockUIPart.typeBackground - part.pane = None - part.dock = None - part.button = None - part.cont_sizer = middle - part.sizer_item = sizer_item - uiparts.append(part) - - if oncheck: - self._uiparts = uiparts - self._docks = docks - - container.Add(cont, 1, wx.EXPAND) - - if oncheck: - return container - else: - return container, panes, docks, uiparts - - - def SetDockSizeConstraint(self, width_pct, height_pct): - """ - When a user creates a new dock by dragging a window into a docked position, - often times the large size of the window will create a dock that is unwieldly - large. - - L{AuiManager} by default limits the size of any new dock to 1/3 of the window - size. For horizontal docks, this would be 1/3 of the window height. For vertical - docks, 1/3 of the width. Calling this function will adjust this constraint value. - - The numbers must be between 0.0 and 1.0. For instance, calling L{SetDockSizeConstraint} - with (0.5, 0.5) will cause new docks to be limited to half of the size of the entire - managed window. - - :param `width_pct`: a float number representing the x dock size constraint; - :param `width_pct`: a float number representing the y dock size constraint. - """ - - self._dock_constraint_x = max(0.0, min(1.0, width_pct)) - self._dock_constraint_y = max(0.0, min(1.0, height_pct)) - - - def GetDockSizeConstraint(self): - """ - Returns the current dock constraint values. - - :see: L{SetDockSizeConstraint} - """ - - return self._dock_constraint_x, self._dock_constraint_y - - - def Update(self): - """ - This method is called after any number of changes are made to any of the - managed panes. L{Update} must be invoked after L{AddPane} or L{InsertPane} are - called in order to "realize" or "commit" the changes. - - In addition, any number of changes may be made to L{AuiPaneInfo} structures - (retrieved with L{GetPane}), but to realize the changes, L{Update} - must be called. This construction allows pane flicker to be avoided by updating - the whole layout at one time. - """ - - self._hover_button = None - self._action_part = None - - # destroy floating panes which have been - # redocked or are becoming non-floating - for p in self._panes: - if p.IsFloating() or not p.frame: - continue - - # because the pane is no longer in a floating, we need to - # reparent it to self._frame and destroy the floating frame - # reduce flicker - p.window.SetSize((1, 1)) - - # the following block is a workaround for bug #1531361 - # (see wxWidgets sourceforge page). On wxGTK (only), when - # a frame is shown/hidden, a move event unfortunately - # also gets fired. Because we may be dragging around - # a pane, we need to cancel that action here to prevent - # a spurious crash. - if self._action_window == p.frame: - if self._frame.HasCapture(): - self._frame.ReleaseMouse() - self._action = actionNone - self._action_window = None - - # hide the frame - if p.frame.IsShown(): - p.frame.Show(False) - - if self._action_window == p.frame: - self._action_window = None - - # reparent to self._frame and destroy the pane - p.window.Reparent(self._frame) - if isinstance(p.window, auibar.AuiToolBar): - p.window.SetAuiManager(self) - - if p.frame: - p.frame.SetSizer(None) - p.frame.Destroy() - p.frame = None - - # Only the master manager should create/destroy notebooks... - if not self._masterManager: - self.UpdateNotebook() - - # delete old sizer first - self._frame.SetSizer(None) - - # create a layout for all of the panes - sizer = self.LayoutAll(self._panes, self._docks, self._uiparts, False) - - # hide or show panes as necessary, - # and float panes as necessary - - pane_count = len(self._panes) - - for ii in xrange(pane_count): - p = self._panes[ii] - pFrame = p.frame - - if p.IsFloating(): - if pFrame is None: - # we need to create a frame for this - # pane, which has recently been floated - frame = self.CreateFloatingFrame(self._frame, p) - - # on MSW and Mac, if the owner desires transparent dragging, and - # the dragging is happening right now, then the floating - # window should have this style by default - if self._action in [actionDragFloatingPane, actionDragToolbarPane] and \ - self._agwFlags & AUI_MGR_TRANSPARENT_DRAG: - frame.SetTransparent(150) - - if p.IsToolbar(): - bar = p.window - if isinstance(bar, auibar.AuiToolBar): - bar.SetGripperVisible(False) - agwStyle = bar.GetAGWWindowStyleFlag() - bar.SetAGWWindowStyleFlag(agwStyle & ~AUI_TB_VERTICAL) - bar.Realize() - - s = p.window.GetMinSize() - p.BestSize(s) - p.FloatingSize(wx.DefaultSize) - - frame.SetPaneWindow(p) - p.needsTransparency = True - p.frame = pFrame = frame - if p.IsShown() and not frame.IsShown(): - frame.Show() - frame.Update() - else: - - # frame already exists, make sure it's position - # and size reflect the information in AuiPaneInfo - if pFrame.GetPosition() != p.floating_pos or pFrame.GetSize() != p.floating_size: - pFrame.SetDimensions(p.floating_pos.x, p.floating_pos.y, - p.floating_size.x, p.floating_size.y, wx.SIZE_USE_EXISTING) - - # update whether the pane is resizable or not - style = p.frame.GetWindowStyleFlag() - if p.IsFixed(): - style &= ~wx.RESIZE_BORDER - else: - style |= wx.RESIZE_BORDER - - p.frame.SetWindowStyleFlag(style) - - if pFrame.IsShown() != p.IsShown(): - p.needsTransparency = True - pFrame.Show(p.IsShown()) - - if pFrame.GetTitle() != p.caption: - pFrame.SetTitle(p.caption) - if p.icon.IsOk(): - pFrame.SetIcon(wx.IconFromBitmap(p.icon)) - - else: - - if p.IsToolbar(): -# self.SwitchToolBarOrientation(p) - p.best_size = p.window.GetBestSize() - - if p.window and not p.IsNotebookPage() and p.window.IsShown() != p.IsShown(): - p.window.Show(p.IsShown()) - - if pFrame and p.needsTransparency: - if pFrame.IsShown() and pFrame._transparent != p.transparent: - pFrame.SetTransparent(p.transparent) - pFrame._transparent = p.transparent - - p.needsTransparency = False - - # if "active panes" are no longer allowed, clear - # any optionActive values from the pane states - if self._agwFlags & AUI_MGR_ALLOW_ACTIVE_PANE == 0: - p.state &= ~AuiPaneInfo.optionActive - - self._panes[ii] = p - - old_pane_rects = [] - pane_count = len(self._panes) - - for p in self._panes: - r = wx.Rect() - if p.window and p.IsShown() and p.IsDocked(): - r = p.rect - - old_pane_rects.append(r) - - # apply the new sizer - self._frame.SetSizer(sizer) - self._frame.SetAutoLayout(False) - self.DoFrameLayout() - - # now that the frame layout is done, we need to check - # the new pane rectangles against the old rectangles that - # we saved a few lines above here. If the rectangles have - # changed, the corresponding panes must also be updated - for ii in xrange(pane_count): - p = self._panes[ii] - if p.window and p.IsShown() and p.IsDocked(): - if p.rect != old_pane_rects[ii]: - p.window.Refresh() - p.window.Update() - - if wx.Platform == "__WXMAC__": - self._frame.Refresh() - else: - self.Repaint() - - if not self._masterManager: - e = self.FireEvent(wxEVT_AUI_PERSPECTIVE_CHANGED, None, canVeto=False) - - - def UpdateNotebook(self): - """ Updates the automatic L{AuiNotebook} in the layout (if any exists). """ - - # Workout how many notebooks we need. - max_notebook = -1 - - # destroy floating panes which have been - # redocked or are becoming non-floating - for paneInfo in self._panes: - if max_notebook < paneInfo.notebook_id: - max_notebook = paneInfo.notebook_id - - # We are the master of our domain - extra_notebook = len(self._notebooks) - max_notebook += 1 - - for i in xrange(extra_notebook, max_notebook): - self.CreateNotebook() - - # Remove pages from notebooks that no-longer belong there ... - for nb, notebook in enumerate(self._notebooks): - pages = notebook.GetPageCount() - pageCounter, allPages = 0, pages - - # Check each tab ... - for page in xrange(pages): - - if page >= allPages: - break - - window = notebook.GetPage(pageCounter) - paneInfo = self.GetPane(window) - if paneInfo.IsOk() and paneInfo.notebook_id != nb: - notebook.RemovePage(pageCounter) - window.Hide() - window.Reparent(self._frame) - pageCounter -= 1 - allPages -= 1 - - pageCounter += 1 - - notebook.DoSizing() - - # Add notebook pages that aren't there already... - for paneInfo in self._panes: - if paneInfo.IsNotebookPage(): - - title = (paneInfo.caption == "" and [paneInfo.name] or [paneInfo.caption])[0] - - notebook = self._notebooks[paneInfo.notebook_id] - page_id = notebook.GetPageIndex(paneInfo.window) - - if page_id < 0: - - paneInfo.window.Reparent(notebook) - notebook.AddPage(paneInfo.window, title, True, paneInfo.icon) - - # Update title and icon ... - else: - - notebook.SetPageText(page_id, title) - notebook.SetPageBitmap(page_id, paneInfo.icon) - - notebook.DoSizing() - - # Wire-up newly created notebooks - elif paneInfo.IsNotebookControl() and not paneInfo.window: - paneInfo.window = self._notebooks[paneInfo.notebook_id] - - # Delete empty notebooks, and convert notebooks with 1 page to - # normal panes... - remap_ids = [-1]*len(self._notebooks) - nb_idx = 0 - - for nb, notebook in enumerate(self._notebooks): - if notebook.GetPageCount() == 1: - - # Convert notebook page to pane... - window = notebook.GetPage(0) - child_pane = self.GetPane(window) - notebook_pane = self.GetPane(notebook) - if child_pane.IsOk() and notebook_pane.IsOk(): - - child_pane.SetDockPos(notebook_pane) - child_pane.window.Hide() - child_pane.window.Reparent(self._frame) - child_pane.frame = None - child_pane.notebook_id = -1 - if notebook_pane.IsFloating(): - child_pane.Float() - - self.DetachPane(notebook) - - notebook.RemovePage(0) - notebook.Destroy() - - else: - - raise Exception("Odd notebook docking") - - elif notebook.GetPageCount() == 0: - - self.DetachPane(notebook) - notebook.Destroy() - - else: - - # Correct page ordering. The original wxPython code - # for this did not work properly, and would misplace - # windows causing errors. - notebook.Freeze() - self._notebooks[nb_idx] = notebook - pages = notebook.GetPageCount() - selected = notebook.GetPage(notebook.GetSelection()) - - # Take each page out of the notebook, group it with - # its current pane, and sort the list by pane.dock_pos - # order - pages_and_panes = [] - for idx in reversed(range(pages)): - page = notebook.GetPage(idx) - pane = self.GetPane(page) - pages_and_panes.append((page, pane)) - notebook.RemovePage(idx) - sorted_pnp = sorted(pages_and_panes, key=lambda tup: tup[1].dock_pos) - - # Grab the attributes from the panes which are ordered - # correctly, and copy those attributes to the original - # panes. (This avoids having to change the ordering - # of self._panes) Then, add the page back into the notebook - sorted_attributes = [self.GetAttributes(tup[1]) - for tup in sorted_pnp] - for attrs, tup in zip(sorted_attributes, pages_and_panes): - pane = tup[1] - self.SetAttributes(pane, attrs) - notebook.AddPage(pane.window, pane.caption) - - notebook.SetSelection(notebook.GetPageIndex(selected), True) - notebook.DoSizing() - notebook.Thaw() - - # It's a keeper. - remap_ids[nb] = nb_idx - nb_idx += 1 - - # Apply remap... - nb_count = len(self._notebooks) - - if nb_count != nb_idx: - - self._notebooks = self._notebooks[0:nb_idx] - for p in self._panes: - if p.notebook_id >= 0: - p.notebook_id = remap_ids[p.notebook_id] - if p.IsNotebookControl(): - p.SetNameFromNotebookId() - - # Make sure buttons are correct ... - for notebook in self._notebooks: - want_max = True - want_min = True - want_close = True - - pages = notebook.GetPageCount() - for page in xrange(pages): - - win = notebook.GetPage(page) - pane = self.GetPane(win) - if pane.IsOk(): - - if not pane.HasCloseButton(): - want_close = False - if not pane.HasMaximizeButton(): - want_max = False - if not pane.HasMinimizeButton(): - want_min = False - - notebook_pane = self.GetPane(notebook) - if notebook_pane.IsOk(): - if notebook_pane.HasMinimizeButton() != want_min: - if want_min: - button = AuiPaneButton(AUI_BUTTON_MINIMIZE) - notebook_pane.state |= AuiPaneInfo.buttonMinimize - notebook_pane.buttons.append(button) - - # todo: remove min/max - - if notebook_pane.HasMaximizeButton() != want_max: - if want_max: - button = AuiPaneButton(AUI_BUTTON_MAXIMIZE_RESTORE) - notebook_pane.state |= AuiPaneInfo.buttonMaximize - notebook_pane.buttons.append(button) - - # todo: remove min/max - - if notebook_pane.HasCloseButton() != want_close: - if want_close: - button = AuiPaneButton(AUI_BUTTON_CLOSE) - notebook_pane.state |= AuiPaneInfo.buttonClose - notebook_pane.buttons.append(button) - - # todo: remove close - - - def SmartShrink(self, docks, direction): - """ - Used to intelligently shrink the docks' size (if needed). - - :param `docks`: a list of L{AuiDockInfo} instances; - :param `direction`: the direction in which to shrink. - """ - - sashSize = self._art.GetMetric(AUI_DOCKART_SASH_SIZE) - caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) - clientSize = self._frame.GetClientSize() - ourDocks = FindDocks(docks, direction, -1, -1) - oppositeDocks = FindOppositeDocks(docks, direction) - oppositeSize = self.GetOppositeDockTotalSize(docks, direction) - ourSize = 0 - - for dock in ourDocks: - ourSize += dock.size - - if not dock.toolbar: - ourSize += sashSize - - shrinkSize = ourSize + oppositeSize - - if direction == AUI_DOCK_TOP or direction == AUI_DOCK_BOTTOM: - shrinkSize -= clientSize.y - else: - shrinkSize -= clientSize.x - - if shrinkSize <= 0: - return docks - - # Combine arrays - for dock in oppositeDocks: - ourDocks.append(dock) - - oppositeDocks = [] - - for dock in ourDocks: - if dock.toolbar or not dock.resizable: - continue - - dockRange = dock.size - dock.min_size - - if dock.min_size == 0: - dockRange -= sashSize - if direction == AUI_DOCK_TOP or direction == AUI_DOCK_BOTTOM: - dockRange -= caption_size - - if dockRange >= shrinkSize: - - dock.size -= shrinkSize - return docks - - else: - - dock.size -= dockRange - shrinkSize -= dockRange - - return docks - - - def UpdateDockingGuides(self, paneInfo): - """ - Updates the docking guide windows positions and appearance. - - :param `paneInfo`: a L{AuiPaneInfo} instance. - """ - - if len(self._guides) == 0: - self.CreateGuideWindows() - - captionSize = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) - frameRect = GetInternalFrameRect(self._frame, self._docks) - mousePos = wx.GetMousePosition() - - for indx, guide in enumerate(self._guides): - - pt = wx.Point() - guide_size = guide.host.GetSize() - if not guide.host: - raise Exception("Invalid docking host") - - direction = guide.dock_direction - - if direction == AUI_DOCK_LEFT: - pt.x = frameRect.x + guide_size.x / 2 + 16 - pt.y = frameRect.y + frameRect.height / 2 - - elif direction == AUI_DOCK_TOP: - pt.x = frameRect.x + frameRect.width / 2 - pt.y = frameRect.y + guide_size.y / 2 + 16 - - elif direction == AUI_DOCK_RIGHT: - pt.x = frameRect.x + frameRect.width - guide_size.x / 2 - 16 - pt.y = frameRect.y + frameRect.height / 2 - - elif direction == AUI_DOCK_BOTTOM: - pt.x = frameRect.x + frameRect.width / 2 - pt.y = frameRect.y + frameRect.height - guide_size.y / 2 - 16 - - elif direction == AUI_DOCK_CENTER: - rc = paneInfo.window.GetScreenRect() - pt.x = rc.x + rc.width / 2 - pt.y = rc.y + rc.height / 2 - if paneInfo.HasCaption(): - pt.y -= captionSize / 2 - elif paneInfo.HasCaptionLeft(): - pt.x -= captionSize / 2 - - # guide will be centered around point 'pt' - targetPosition = wx.Point(pt.x - guide_size.x / 2, pt.y - guide_size.y / 2) - - if guide.host.GetPosition() != targetPosition: - guide.host.Move(targetPosition) - - guide.host.AeroMove(targetPosition) - - if guide.dock_direction == AUI_DOCK_CENTER: - guide.host.ValidateNotebookDocking(paneInfo.IsNotebookDockable()) - - guide.host.UpdateDockGuide(mousePos) - - paneInfo.window.Lower() - - - def DoFrameLayout(self): - """ - This is an internal function which invokes `wx.Sizer.Layout` - on the frame's main sizer, then measures all the various UI items - and updates their internal rectangles. - - :note: This should always be called instead of calling - `self._managed_window.Layout()` directly. - """ - - self._frame.Layout() - - for part in self._uiparts: - # get the rectangle of the UI part - # originally, this code looked like this: - # part.rect = wx.Rect(part.sizer_item.GetPosition(), - # part.sizer_item.GetSize()) - # this worked quite well, with one exception: the mdi - # client window had a "deferred" size variable - # that returned the wrong size. It looks like - # a bug in wx, because the former size of the window - # was being returned. So, we will retrieve the part's - # rectangle via other means - - part.rect = part.sizer_item.GetRect() - flag = part.sizer_item.GetFlag() - border = part.sizer_item.GetBorder() - - if flag & wx.TOP: - part.rect.y -= border - part.rect.height += border - if flag & wx.LEFT: - part.rect.x -= border - part.rect.width += border - if flag & wx.BOTTOM: - part.rect.height += border - if flag & wx.RIGHT: - part.rect.width += border - - if part.type == AuiDockUIPart.typeDock: - part.dock.rect = part.rect - if part.type == AuiDockUIPart.typePane: - part.pane.rect = part.rect - - - def GetPanePart(self, wnd): - """ - Looks up the pane border UI part of the - pane specified. This allows the caller to get the exact rectangle - of the pane in question, including decorations like caption and border. - - :param `wnd`: the window to which the pane border belongs to. - """ - - for part in self._uiparts: - if part.type == AuiDockUIPart.typePaneBorder and \ - part.pane and part.pane.window == wnd: - return part - - for part in self._uiparts: - if part.type == AuiDockUIPart.typePane and \ - part.pane and part.pane.window == wnd: - return part - - return None - - - def GetDockPixelOffset(self, test): - """ - This is an internal function which returns - a dock's offset in pixels from the left side of the window - (for horizontal docks) or from the top of the window (for - vertical docks). - - This value is necessary for calculating fixed-pane/toolbar offsets - when they are dragged. - - :param `test`: a fake L{AuiPaneInfo} for testing purposes. - """ - - # the only way to accurately calculate the dock's - # offset is to actually run a theoretical layout - docks, panes = CopyDocksAndPanes2(self._docks, self._panes) - panes.append(test) - - sizer, panes, docks, uiparts = self.LayoutAll(panes, docks, [], True, False) - client_size = self._frame.GetClientSize() - sizer.SetDimension(0, 0, client_size.x, client_size.y) - sizer.Layout() - - for part in uiparts: - pos = part.sizer_item.GetPosition() - size = part.sizer_item.GetSize() - part.rect = wx.RectPS(pos, size) - if part.type == AuiDockUIPart.typeDock: - part.dock.rect = part.rect - - sizer.Destroy() - - for dock in docks: - if test.dock_direction == dock.dock_direction and \ - test.dock_layer == dock.dock_layer and \ - test.dock_row == dock.dock_row: - - if dock.IsVertical(): - return dock.rect.y - else: - return dock.rect.x - - return 0 - - - def GetPartnerDock(self, dock): - """ - Returns the partner dock for the input dock. - - :param `dock`: a L{AuiDockInfo} instance. - """ - - for layer in xrange(dock.dock_layer, -1, -1): - - bestDock = None - - for tmpDock in self._docks: - - if tmpDock.dock_layer != layer: - continue - - if tmpDock.dock_direction != dock.dock_direction: - continue - - if tmpDock.dock_layer < dock.dock_layer: - - if not bestDock or tmpDock.dock_row < bestDock.dock_row: - bestDock = tmpDock - - elif tmpDock.dock_row > dock.dock_row: - - if not bestDock or tmpDock.dock_row > bestDock.dock_row: - bestDock = tmpDock - - if bestDock: - return bestDock - - return None - - - def GetPartnerPane(self, dock, pane): - """ - Returns the partner pane for the input pane. They both need to live - in the same L{AuiDockInfo}. - - :param `dock`: a L{AuiDockInfo} instance; - :param `pane`: a L{AuiPaneInfo} class. - """ - - panePosition = -1 - - for i, tmpPane in enumerate(dock.panes): - if tmpPane.window == pane.window: - panePosition = i - elif not tmpPane.IsFixed() and panePosition != -1: - return tmpPane - - return None - - - def GetTotalPixSizeAndProportion(self, dock): - """ - Returns the dimensions and proportion of the input dock. - - :param `dock`: the L{AuiDockInfo} structure to analyze. - """ - - totalPixsize = 0 - totalProportion = 0 - - # determine the total proportion of all resizable panes, - # and the total size of the dock minus the size of all - # the fixed panes - for tmpPane in dock.panes: - - if tmpPane.IsFixed(): - continue - - totalProportion += tmpPane.dock_proportion - - if dock.IsHorizontal(): - totalPixsize += tmpPane.rect.width - else: - totalPixsize += tmpPane.rect.height - -## if tmpPane.min_size.IsFullySpecified(): -## -## if dock.IsHorizontal(): -## totalPixsize -= tmpPane.min_size.x -## else: -## totalPixsize -= tmpPane.min_size.y - - return totalPixsize, totalProportion - - - def GetOppositeDockTotalSize(self, docks, direction): - """ - Returns the dimensions of the dock which lives opposite of the input dock. - - :param `docks`: a list of L{AuiDockInfo} structures to analyze; - :param `direction`: the direction in which to look for the opposite dock. - """ - - sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE) - caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) - pane_border_size = self._art.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE) - minSizeMax = 0 - result = sash_size - vertical = False - - if direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]: - vertical = True - - # Get minimum size of the most inner area - for tmpDock in docks: - - if tmpDock.dock_layer != 0: - continue - - if tmpDock.dock_direction != AUI_DOCK_CENTER and tmpDock.IsVertical() != vertical: - continue - - for tmpPane in tmpDock.panes: - - minSize = pane_border_size*2 - sash_size - - if vertical: - minSize += tmpPane.min_size.y + caption_size - else: - minSize += tmpPane.min_size.x - - if minSize > minSizeMax: - minSizeMax = minSize - - result += minSizeMax - - # Get opposite docks - oppositeDocks = FindOppositeDocks(docks, direction) - - # Sum size of the opposite docks and their sashes - for dock in oppositeDocks: - result += dock.size - # if it's not a toolbar add the sash_size too - if not dock.toolbar: - result += sash_size - - return result - - - def CalculateDockSizerLimits(self, dock): - """ - Calculates the minimum and maximum sizes allowed for the input dock. - - :param `dock`: the L{AuiDockInfo} structure to analyze. - """ - - docks, panes = CopyDocksAndPanes2(self._docks, self._panes) - - sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE) - caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) - opposite_size = self.GetOppositeDockTotalSize(docks, dock.dock_direction) - - for tmpDock in docks: - - if tmpDock.dock_direction == dock.dock_direction and \ - tmpDock.dock_layer == dock.dock_layer and \ - tmpDock.dock_row == dock.dock_row: - - tmpDock.size = 1 - break - - sizer, panes, docks, uiparts = self.LayoutAll(panes, docks, [], True, False) - client_size = self._frame.GetClientSize() - sizer.SetDimension(0, 0, client_size.x, client_size.y) - sizer.Layout() - - for part in uiparts: - - part.rect = wx.RectPS(part.sizer_item.GetPosition(), part.sizer_item.GetSize()) - if part.type == AuiDockUIPart.typeDock: - part.dock.rect = part.rect - - sizer.Destroy() - new_dock = None - - for tmpDock in docks: - if tmpDock.dock_direction == dock.dock_direction and \ - tmpDock.dock_layer == dock.dock_layer and \ - tmpDock.dock_row == dock.dock_row: - - new_dock = tmpDock - break - - partnerDock = self.GetPartnerDock(dock) - - if partnerDock: - partnerRange = partnerDock.size - partnerDock.min_size - if partnerDock.min_size == 0: - partnerRange -= sash_size - if dock.IsHorizontal(): - partnerRange -= caption_size - - direction = dock.dock_direction - - if direction == AUI_DOCK_LEFT: - minPix = new_dock.rect.x + new_dock.rect.width - maxPix = dock.rect.x + dock.rect.width - maxPix += partnerRange - - elif direction == AUI_DOCK_TOP: - minPix = new_dock.rect.y + new_dock.rect.height - maxPix = dock.rect.y + dock.rect.height - maxPix += partnerRange - - elif direction == AUI_DOCK_RIGHT: - minPix = dock.rect.x - partnerRange - sash_size - maxPix = new_dock.rect.x - sash_size - - elif direction == AUI_DOCK_BOTTOM: - minPix = dock.rect.y - partnerRange - sash_size - maxPix = new_dock.rect.y - sash_size - - return minPix, maxPix - - direction = new_dock.dock_direction - - if direction == AUI_DOCK_LEFT: - minPix = new_dock.rect.x + new_dock.rect.width - maxPix = client_size.x - opposite_size - sash_size - - elif direction == AUI_DOCK_TOP: - minPix = new_dock.rect.y + new_dock.rect.height - maxPix = client_size.y - opposite_size - sash_size - - elif direction == AUI_DOCK_RIGHT: - minPix = opposite_size - maxPix = new_dock.rect.x - sash_size - - elif direction == AUI_DOCK_BOTTOM: - minPix = opposite_size - maxPix = new_dock.rect.y - sash_size - - return minPix, maxPix - - - def CalculatePaneSizerLimits(self, dock, pane): - """ - Calculates the minimum and maximum sizes allowed for the input pane. - - :param `dock`: the L{AuiDockInfo} structure to which `pane` belongs to; - :param `pane`: a L{AuiPaneInfo} class for which calculation are requested. - """ - - if pane.IsFixed(): - if dock.IsHorizontal(): - minPix = maxPix = pane.rect.x + 1 + pane.rect.width - else: - minPix = maxPix = pane.rect.y + 1 + pane.rect.height - - return minPix, maxPix - - totalPixsize, totalProportion = self.GetTotalPixSizeAndProportion(dock) - partnerPane = self.GetPartnerPane(dock, pane) - - if dock.IsHorizontal(): - - minPix = pane.rect.x + 1 - maxPix = pane.rect.x + 1 + pane.rect.width - - if pane.min_size.IsFullySpecified(): - minPix += pane.min_size.x - else: - minPix += 1 - - if partnerPane: - maxPix += partnerPane.rect.width - - if partnerPane.min_size.IsFullySpecified(): - maxPix -= partnerPane.min_size.x - 1 - - else: - minPix = maxPix - - else: - - minPix = pane.rect.y + 1 - maxPix = pane.rect.y + 1 + pane.rect.height - - if pane.min_size.IsFullySpecified(): - minPix += pane.min_size.y - else: - minPix += 1 - - if partnerPane: - maxPix += partnerPane.rect.height - - if partnerPane.min_size.IsFullySpecified(): - maxPix -= partnerPane.min_size.y - 1 - - else: - minPix = maxPix - - return minPix, maxPix - - - def CheckMovableSizer(self, part): - """ - Checks if a UI part can be actually resized. - - :param `part`: a UI part. - """ - - # a dock may not be resized if it has a single - # pane which is not resizable - if part.type == AuiDockUIPart.typeDockSizer and part.dock and \ - len(part.dock.panes) == 1 and part.dock.panes[0].IsFixed(): - - return False - - if part.pane: - - # panes that may not be resized should be ignored here - minPix, maxPix = self.CalculatePaneSizerLimits(part.dock, part.pane) - - if minPix == maxPix: - return False - - return True - - - def PaneFromTabEvent(self, event): - """ - Returns a L{AuiPaneInfo} from a L{AuiNotebookEvent} event. - - :param `event`: a L{AuiNotebookEvent} event. - """ - - obj = event.GetEventObject() - - if obj and isinstance(obj, auibook.AuiTabCtrl): - - page_idx = obj.GetActivePage() - - if page_idx >= 0: - page = obj.GetPage(page_idx) - window = page.window - if window: - return self.GetPane(window) - - elif obj and isinstance(obj, auibook.AuiNotebook): - - page_idx = event.GetSelection() - - if page_idx >= 0: - window = obj.GetPage(page_idx) - if window: - return self.GetPane(window) - - return NonePaneInfo - - - def OnTabBeginDrag(self, event): - """ - Handles the ``EVT_AUINOTEBOOK_BEGIN_DRAG`` event. - - :param `event`: a L{AuiNotebookEvent} event to be processed. - """ - - if self._masterManager: - self._masterManager.OnTabBeginDrag(event) - - else: - paneInfo = self.PaneFromTabEvent(event) - - if paneInfo.IsOk(): - - # It's one of ours! - self._action = actionDragFloatingPane - mouse = wx.GetMousePosition() - - # set initial float position - may have to think about this - # offset a bit more later ... - self._action_offset = wx.Point(20, 10) - self._toolbar_action_offset = wx.Point(20, 10) - - paneInfo.floating_pos = mouse - self._action_offset - paneInfo.dock_pos = AUI_DOCK_NONE - paneInfo.notebook_id = -1 - - tab = event.GetEventObject() - - if tab.HasCapture(): - tab.ReleaseMouse() - - # float the window - if paneInfo.IsMaximized(): - self.RestorePane(paneInfo) - paneInfo.Float() - self.Update() - - self._action_window = paneInfo.window - - self._frame.CaptureMouse() - event.SetDispatched(True) - - else: - - # not our window - event.Skip() - - - def OnTabPageClose(self, event): - """ - Handles the ``EVT_AUINOTEBOOK_PAGE_CLOSE`` event. - - :param `event`: a L{AuiNotebookEvent} event to be processed. - """ - - if self._masterManager: - self._masterManager.OnTabPageClose(event) - - else: - - p = self.PaneFromTabEvent(event) - if p.IsOk(): - - # veto it because we will call "RemovePage" ourselves - event.Veto() - - # Now ask the app if they really want to close... - # fire pane close event - e = AuiManagerEvent(wxEVT_AUI_PANE_CLOSE) - e.SetPane(p) - e.SetCanVeto(True) - self.ProcessMgrEvent(e) - - if e.GetVeto(): - return - - self.ClosePane(p) - self.Update() - else: - event.Skip() - - - def OnTabSelected(self, event): - """ - Handles the ``EVT_AUINOTEBOOK_PAGE_CHANGED`` event. - - :param `event`: a L{AuiNotebookEvent} event to be processed. - """ - - if self._masterManager: - self._masterManager.OnTabSelected(event) - return - - obj = event.GetEventObject() - - if obj and isinstance(obj, auibook.AuiNotebook): - - notebook = obj - page = notebook.GetPage(event.GetSelection()) - paneInfo = self.GetPane(page) - - if paneInfo.IsOk(): - notebookRoot = GetNotebookRoot(self._panes, paneInfo.notebook_id) - if notebookRoot: - - notebookRoot.Caption(paneInfo.caption) - self.RefreshCaptions() - - event.Skip() - - - def GetNotebooks(self): - """ Returns all the automatic L{AuiNotebook} in the L{AuiManager}. """ - - if self._masterManager: - return self._masterManager.GetNotebooks() - - return self._notebooks - - - def SetMasterManager(self, manager): - """ - Sets the master manager for an automatic L{AuiNotebook}. - - :param `manager`: an instance of L{AuiManager}. - """ - - self._masterManager = manager - - - def ProcessDockResult(self, target, new_pos): - """ - This is a utility function used by L{DoDrop} - it checks - if a dock operation is allowed, the new dock position is copied into - the target info. If the operation was allowed, the function returns ``True``. - - :param `target`: the L{AuiPaneInfo} instance to be docked; - :param `new_pos`: the new docking position if the docking operation is allowed. - """ - - allowed = False - direction = new_pos.dock_direction - - if direction == AUI_DOCK_TOP: - allowed = target.IsTopDockable() - elif direction == AUI_DOCK_BOTTOM: - allowed = target.IsBottomDockable() - elif direction == AUI_DOCK_LEFT: - allowed = target.IsLeftDockable() - elif direction == AUI_DOCK_RIGHT: - allowed = target.IsRightDockable() - - if allowed: - target = new_pos - - if target.IsToolbar(): - self.SwitchToolBarOrientation(target) - - return allowed, target - - - def SwitchToolBarOrientation(self, pane): - """ - Switches the toolbar orientation from vertical to horizontal and vice-versa. - This is especially useful for vertical docked toolbars once they float. - - :param `pane`: an instance of L{AuiPaneInfo}, which may have a L{AuiToolBar} - window associated with it. - """ - - if not isinstance(pane.window, auibar.AuiToolBar): - return pane - - if pane.IsFloating(): - return pane - - toolBar = pane.window - direction = pane.dock_direction - vertical = direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT] - - agwStyle = toolBar.GetAGWWindowStyleFlag() - new_agwStyle = agwStyle - - if vertical: - new_agwStyle |= AUI_TB_VERTICAL - else: - new_agwStyle &= ~(AUI_TB_VERTICAL) - - if agwStyle != new_agwStyle: - toolBar.SetAGWWindowStyleFlag(new_agwStyle) - if not toolBar.GetGripperVisible(): - toolBar.SetGripperVisible(True) - - s = pane.window.GetMinSize() - pane.BestSize(s) - - if new_agwStyle != agwStyle: - toolBar.Realize() - - return pane - - - def DoDrop(self, docks, panes, target, pt, offset=wx.Point(0, 0)): - """ - This is an important function. It basically takes a mouse position, - and determines where the panes new position would be. If the pane is to be - dropped, it performs the drop operation using the specified dock and pane - arrays. By specifying copy dock and pane arrays when calling, a "what-if" - scenario can be performed, giving precise coordinates for drop hints. - - :param `docks`: a list of L{AuiDockInfo} classes; - :param `panes`: a list of L{AuiPaneInfo} instances; - :param `pt`: a mouse position to check for a drop operation; - :param `offset`: a possible offset from the input point `pt`. - """ - - if target.IsToolbar(): - return self.DoDropToolbar(docks, panes, target, pt, offset) - elif target.IsFloating(): - return self.DoDropFloatingPane(docks, panes, target, pt) - else: - return self.DoDropNonFloatingPane(docks, panes, target, pt) - - - def CopyTarget(self, target): - """ - Copies all the attributes of the input `target` into another L{AuiPaneInfo}. - - :param `target`: the source L{AuiPaneInfo} from where to copy attributes. - """ - - drop = AuiPaneInfo() - drop.name = target.name - drop.caption = target.caption - drop.window = target.window - drop.frame = target.frame - drop.state = target.state - drop.dock_direction = target.dock_direction - drop.dock_layer = target.dock_layer - drop.dock_row = target.dock_row - drop.dock_pos = target.dock_pos - drop.best_size = wx.Size(*target.best_size) - drop.min_size = wx.Size(*target.min_size) - drop.max_size = wx.Size(*target.max_size) - drop.floating_pos = wx.Point(*target.floating_pos) - drop.floating_size = wx.Size(*target.floating_size) - drop.dock_proportion = target.dock_proportion - drop.buttons = target.buttons - drop.rect = wx.Rect(*target.rect) - drop.icon = target.icon - drop.notebook_id = target.notebook_id - drop.transparent = target.transparent - drop.snapped = target.snapped - drop.minimize_mode = target.minimize_mode - - return drop - - - def DoDropToolbar(self, docks, panes, target, pt, offset): - """ - Handles the situation in which the dropped pane contains a toolbar. - - :param `docks`: a list of L{AuiDockInfo} classes; - :param `panes`: a list of L{AuiPaneInfo} instances; - :param `target`: the target pane containing the toolbar; - :param `pt`: a mouse position to check for a drop operation; - :param `offset`: a possible offset from the input point `pt`. - """ - - drop = self.CopyTarget(target) - - # The result should always be shown - drop.Show() - - # Check to see if the toolbar has been dragged out of the window - if CheckOutOfWindow(self._frame, pt): - if self._agwFlags & AUI_MGR_ALLOW_FLOATING and drop.IsFloatable(): - drop.Float() - - return self.ProcessDockResult(target, drop) - - # Allow directional change when the cursor leaves this rect - safeRect = wx.Rect(*target.rect) - if target.IsHorizontal(): - safeRect.Inflate(100, 50) - else: - safeRect.Inflate(50, 100) - - # Check to see if the toolbar has been dragged to edge of the frame - dropDir = CheckEdgeDrop(self._frame, docks, pt) - - if dropDir != -1: - - if dropDir == wx.LEFT: - drop.Dock().Left().Layer(auiToolBarLayer).Row(0). \ - Position(pt.y - self.GetDockPixelOffset(drop) - offset.y) - - elif dropDir == wx.RIGHT: - drop.Dock().Right().Layer(auiToolBarLayer).Row(0). \ - Position(pt.y - self.GetDockPixelOffset(drop) - offset.y) - - elif dropDir == wx.TOP: - drop.Dock().Top().Layer(auiToolBarLayer).Row(0). \ - Position(pt.x - self.GetDockPixelOffset(drop) - offset.x) - - elif dropDir == wx.BOTTOM: - drop.Dock().Bottom().Layer(auiToolBarLayer).Row(0). \ - Position(pt.x - self.GetDockPixelOffset(drop) - offset.x) - - if not target.IsFloating() and safeRect.Contains(pt) and \ - target.dock_direction != drop.dock_direction: - return False, target - - return self.ProcessDockResult(target, drop) - - # If the windows is floating and out of the client area, do nothing - if drop.IsFloating() and not self._frame.GetClientRect().Contains(pt): - return False, target - - # Ok, can't drop on edge - check internals ... - - clientSize = self._frame.GetClientSize() - x = Clip(pt.x, 0, clientSize.x - 1) - y = Clip(pt.y, 0, clientSize.y - 1) - part = self.HitTest(x, y) - - if not part or not part.dock: - return False, target - - dock = part.dock - - # toolbars may only be moved in and to fixed-pane docks, - # otherwise we will try to float the pane. Also, the pane - # should float if being dragged over center pane windows - if not dock.fixed or dock.dock_direction == AUI_DOCK_CENTER: - - if (self._agwFlags & AUI_MGR_ALLOW_FLOATING and drop.IsFloatable()) or \ - dock.dock_direction not in [AUI_DOCK_CENTER, AUI_DOCK_NONE]: - if drop.IsFloatable(): - drop.Float() - - return self.ProcessDockResult(target, drop) - - # calculate the offset from where the dock begins - # to the point where the user dropped the pane - dockDropOffset = 0 - if dock.IsHorizontal(): - dockDropOffset = pt.x - dock.rect.x - offset.x - else: - dockDropOffset = pt.y - dock.rect.y - offset.y - - drop.Dock().Direction(dock.dock_direction).Layer(dock.dock_layer). \ - Row(dock.dock_row).Position(dockDropOffset) - - if (pt.y <= dock.rect.GetTop() + 2 and dock.IsHorizontal()) or \ - (pt.x <= dock.rect.GetLeft() + 2 and dock.IsVertical()): - - if dock.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_LEFT]: - row = drop.dock_row - panes = DoInsertDockRow(panes, dock.dock_direction, dock.dock_layer, dock.dock_row) - drop.dock_row = row - - else: - panes = DoInsertDockRow(panes, dock.dock_direction, dock.dock_layer, dock.dock_row+1) - drop.dock_row = dock.dock_row + 1 - - if (pt.y >= dock.rect.GetBottom() - 2 and dock.IsHorizontal()) or \ - (pt.x >= dock.rect.GetRight() - 2 and dock.IsVertical()): - - if dock.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_LEFT]: - panes = DoInsertDockRow(panes, dock.dock_direction, dock.dock_layer, dock.dock_row+1) - drop.dock_row = dock.dock_row+1 - - else: - row = drop.dock_row - panes = DoInsertDockRow(panes, dock.dock_direction, dock.dock_layer, dock.dock_row) - drop.dock_row = row - - if not target.IsFloating() and safeRect.Contains(pt) and \ - target.dock_direction != drop.dock_direction: - return False, target - - return self.ProcessDockResult(target, drop) - - - def DoDropFloatingPane(self, docks, panes, target, pt): - """ - Handles the situation in which the dropped pane contains a normal window. - - :param `docks`: a list of L{AuiDockInfo} classes; - :param `panes`: a list of L{AuiPaneInfo} instances; - :param `target`: the target pane containing the window; - :param `pt`: a mouse position to check for a drop operation. - """ - - screenPt = self._frame.ClientToScreen(pt) - paneInfo = self.PaneHitTest(panes, pt) - - if paneInfo.IsMaximized(): - return False, target - - if paneInfo.window is None: - return False, target - - # search the dock guides. - # reverse order to handle the center first. - for i in xrange(len(self._guides)-1, -1, -1): - guide = self._guides[i] - - # do hit testing on the guide - dir = guide.host.HitTest(screenPt.x, screenPt.y) - - if dir == -1: # point was outside of the dock guide - continue - - if dir == wx.ALL: # target is a single dock guide - return self.DoDropLayer(docks, target, guide.dock_direction) - - elif dir == wx.CENTER: - - if not target.IsNotebookDockable(): - continue - if not paneInfo.IsNotebookDockable() and not paneInfo.IsNotebookControl(): - continue - - if not paneInfo.HasNotebook(): - - # Add a new notebook pane with the original as a tab... - self.CreateNotebookBase(panes, paneInfo) - - # Add new item to notebook - target.NotebookPage(paneInfo.notebook_id) - - else: - - drop_pane = False - drop_row = False - - insert_dir = paneInfo.dock_direction - insert_layer = paneInfo.dock_layer - insert_row = paneInfo.dock_row - insert_pos = paneInfo.dock_pos - - if insert_dir == AUI_DOCK_CENTER: - - insert_layer = 0 - if dir == wx.LEFT: - insert_dir = AUI_DOCK_LEFT - elif dir == wx.UP: - insert_dir = AUI_DOCK_TOP - elif dir == wx.RIGHT: - insert_dir = AUI_DOCK_RIGHT - elif dir == wx.DOWN: - insert_dir = AUI_DOCK_BOTTOM - - if insert_dir == AUI_DOCK_LEFT: - - drop_pane = (dir == wx.UP or dir == wx.DOWN) - drop_row = (dir == wx.LEFT or dir == wx.RIGHT) - if dir == wx.RIGHT: - insert_row += 1 - elif dir == wx.DOWN: - insert_pos += 1 - - elif insert_dir == AUI_DOCK_RIGHT: - - drop_pane = (dir == wx.UP or dir == wx.DOWN) - drop_row = (dir == wx.LEFT or dir == wx.RIGHT) - if dir == wx.LEFT: - insert_row += 1 - elif dir == wx.DOWN: - insert_pos += 1 - - elif insert_dir == AUI_DOCK_TOP: - - drop_pane = (dir == wx.LEFT or dir == wx.RIGHT) - drop_row = (dir == wx.UP or dir == wx.DOWN) - if dir == wx.DOWN: - insert_row += 1 - elif dir == wx.RIGHT: - insert_pos += 1 - - elif insert_dir == AUI_DOCK_BOTTOM: - - drop_pane = (dir == wx.LEFT or dir == wx.RIGHT) - drop_row = (dir == wx.UP or dir == wx.DOWN) - if dir == wx.UP: - insert_row += 1 - elif dir == wx.RIGHT: - insert_pos += 1 - - if paneInfo.dock_direction == AUI_DOCK_CENTER: - insert_row = GetMaxRow(panes, insert_dir, insert_layer) + 1 - - if drop_pane: - return self.DoDropPane(panes, target, insert_dir, insert_layer, insert_row, insert_pos) - - if drop_row: - return self.DoDropRow(panes, target, insert_dir, insert_layer, insert_row) - - return True, target - - return False, target - - - def DoDropNonFloatingPane(self, docks, panes, target, pt): - """ - Handles the situation in which the dropped pane is not floating. - - :param `docks`: a list of L{AuiDockInfo} classes; - :param `panes`: a list of L{AuiPaneInfo} instances; - :param `target`: the target pane containing the toolbar; - :param `pt`: a mouse position to check for a drop operation. - """ - - screenPt = self._frame.ClientToScreen(pt) - clientSize = self._frame.GetClientSize() - frameRect = GetInternalFrameRect(self._frame, self._docks) - - drop = self.CopyTarget(target) - - # The result should always be shown - drop.Show() - - part = self.HitTest(pt.x, pt.y) - - if not part: - return False, target - - if part.type == AuiDockUIPart.typeDockSizer: - - if len(part.dock.panes) != 1: - return False, target - - part = self.GetPanePart(part.dock.panes[0].window) - if not part: - return False, target - - if not part.pane: - return False, target - - part = self.GetPanePart(part.pane.window) - if not part: - return False, target - - insert_dock_row = False - insert_row = part.pane.dock_row - insert_dir = part.pane.dock_direction - insert_layer = part.pane.dock_layer - - direction = part.pane.dock_direction - - if direction == AUI_DOCK_TOP: - if pt.y >= part.rect.y and pt.y < part.rect.y+auiInsertRowPixels: - insert_dock_row = True - - elif direction == AUI_DOCK_BOTTOM: - if pt.y > part.rect.y+part.rect.height-auiInsertRowPixels and \ - pt.y <= part.rect.y + part.rect.height: - insert_dock_row = True - - elif direction == AUI_DOCK_LEFT: - if pt.x >= part.rect.x and pt.x < part.rect.x+auiInsertRowPixels: - insert_dock_row = True - - elif direction == AUI_DOCK_RIGHT: - if pt.x > part.rect.x+part.rect.width-auiInsertRowPixels and \ - pt.x <= part.rect.x+part.rect.width: - insert_dock_row = True - - elif direction == AUI_DOCK_CENTER: - - # "new row pixels" will be set to the default, but - # must never exceed 20% of the window size - new_row_pixels_x = auiNewRowPixels - new_row_pixels_y = auiNewRowPixels - - if new_row_pixels_x > (part.rect.width*20)/100: - new_row_pixels_x = (part.rect.width*20)/100 - - if new_row_pixels_y > (part.rect.height*20)/100: - new_row_pixels_y = (part.rect.height*20)/100 - - # determine if the mouse pointer is in a location that - # will cause a new row to be inserted. The hot spot positions - # are along the borders of the center pane - - insert_layer = 0 - insert_dock_row = True - pr = part.rect - - if pt.x >= pr.x and pt.x < pr.x + new_row_pixels_x: - insert_dir = AUI_DOCK_LEFT - elif pt.y >= pr.y and pt.y < pr.y + new_row_pixels_y: - insert_dir = AUI_DOCK_TOP - elif pt.x >= pr.x + pr.width - new_row_pixels_x and pt.x < pr.x + pr.width: - insert_dir = AUI_DOCK_RIGHT - elif pt.y >= pr.y+ pr.height - new_row_pixels_y and pt.y < pr.y + pr.height: - insert_dir = AUI_DOCK_BOTTOM - else: - return False, target - - insert_row = GetMaxRow(panes, insert_dir, insert_layer) + 1 - - if insert_dock_row: - - panes = DoInsertDockRow(panes, insert_dir, insert_layer, insert_row) - drop.Dock().Direction(insert_dir).Layer(insert_layer). \ - Row(insert_row).Position(0) - - return self.ProcessDockResult(target, drop) - - # determine the mouse offset and the pane size, both in the - # direction of the dock itself, and perpendicular to the dock - - if part.orientation == wx.VERTICAL: - - offset = pt.y - part.rect.y - size = part.rect.GetHeight() - - else: - - offset = pt.x - part.rect.x - size = part.rect.GetWidth() - - drop_position = part.pane.dock_pos - - # if we are in the top/left part of the pane, - # insert the pane before the pane being hovered over - if offset <= size/2: - - drop_position = part.pane.dock_pos - panes = DoInsertPane(panes, - part.pane.dock_direction, - part.pane.dock_layer, - part.pane.dock_row, - part.pane.dock_pos) - - # if we are in the bottom/right part of the pane, - # insert the pane before the pane being hovered over - if offset > size/2: - - drop_position = part.pane.dock_pos+1 - panes = DoInsertPane(panes, - part.pane.dock_direction, - part.pane.dock_layer, - part.pane.dock_row, - part.pane.dock_pos+1) - - - drop.Dock(). \ - Direction(part.dock.dock_direction). \ - Layer(part.dock.dock_layer).Row(part.dock.dock_row). \ - Position(drop_position) - - return self.ProcessDockResult(target, drop) - - - def DoDropLayer(self, docks, target, dock_direction): - """ - Handles the situation in which `target` is a single dock guide. - - :param `docks`: a list of L{AuiDockInfo} classes; - :param `target`: the target pane; - :param `dock_direction`: the docking direction. - """ - - drop = self.CopyTarget(target) - - if dock_direction == AUI_DOCK_LEFT: - drop.Dock().Left() - drop_new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_LEFT), - GetMaxLayer(docks, AUI_DOCK_BOTTOM)), - GetMaxLayer(docks, AUI_DOCK_TOP)) + 1 - - elif dock_direction == AUI_DOCK_TOP: - drop.Dock().Top() - drop_new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_TOP), - GetMaxLayer(docks, AUI_DOCK_LEFT)), - GetMaxLayer(docks, AUI_DOCK_RIGHT)) + 1 - - elif dock_direction == AUI_DOCK_RIGHT: - drop.Dock().Right() - drop_new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_RIGHT), - GetMaxLayer(docks, AUI_DOCK_TOP)), - GetMaxLayer(docks, AUI_DOCK_BOTTOM)) + 1 - - elif dock_direction == AUI_DOCK_BOTTOM: - drop.Dock().Bottom() - drop_new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_BOTTOM), - GetMaxLayer(docks, AUI_DOCK_LEFT)), - GetMaxLayer(docks, AUI_DOCK_RIGHT)) + 1 - - else: - return False, target - - - drop.Dock().Layer(drop_new_layer) - return self.ProcessDockResult(target, drop) - - - def DoDropPane(self, panes, target, dock_direction, dock_layer, dock_row, dock_pos): - """ - Drop a pane in the interface. - - :param `panes`: a list of L{AuiPaneInfo} classes; - :param `target`: the target pane; - :param `dock_direction`: the docking direction; - :param `dock_layer`: the docking layer; - :param `dock_row`: the docking row; - :param `dock_pos`: the docking position. - """ - - drop = self.CopyTarget(target) - panes = DoInsertPane(panes, dock_direction, dock_layer, dock_row, dock_pos) - - drop.Dock().Direction(dock_direction).Layer(dock_layer).Row(dock_row).Position(dock_pos) - return self.ProcessDockResult(target, drop) - - - def DoDropRow(self, panes, target, dock_direction, dock_layer, dock_row): - """ - Insert a row in the interface before dropping. - - :param `panes`: a list of L{AuiPaneInfo} classes; - :param `target`: the target pane; - :param `dock_direction`: the docking direction; - :param `dock_layer`: the docking layer; - :param `dock_row`: the docking row. - """ - - drop = self.CopyTarget(target) - panes = DoInsertDockRow(panes, dock_direction, dock_layer, dock_row) - - drop.Dock().Direction(dock_direction).Layer(dock_layer).Row(dock_row).Position(0) - return self.ProcessDockResult(target, drop) - - - def ShowHint(self, rect): - """ - Shows the AUI hint window. - - :param `rect`: the hint rect calculated in advance. - """ - - if rect == self._last_hint: - return - - if self._agwFlags & AUI_MGR_RECTANGLE_HINT and wx.Platform != "__WXMAC__": - - if self._last_hint != rect: - # remove the last hint rectangle - self._last_hint = wx.Rect(*rect) - self._frame.Refresh() - self._frame.Update() - - screendc = wx.ScreenDC() - clip = wx.Region(1, 1, 10000, 10000) - - # clip all floating windows, so we don't draw over them - for pane in self._panes: - if pane.IsFloating() and pane.frame.IsShown(): - - rect2 = wx.Rect(*pane.frame.GetRect()) - if wx.Platform == "__WXGTK__": - # wxGTK returns the client size, not the whole frame size - rect2.width += 15 - rect2.height += 35 - rect2.Inflate(5, 5) - - clip.SubtractRect(rect2) - - # As we can only hide the hint by redrawing the managed window, we - # need to clip the region to the managed window too or we get - # nasty redrawn problems. - clip.IntersectRect(self._frame.GetRect()) - screendc.SetClippingRegionAsRegion(clip) - - stipple = PaneCreateStippleBitmap() - brush = wx.BrushFromBitmap(stipple) - screendc.SetBrush(brush) - screendc.SetPen(wx.TRANSPARENT_PEN) - screendc.DrawRectangle(rect.x, rect.y, 5, rect.height) - screendc.DrawRectangle(rect.x+5, rect.y, rect.width-10, 5) - screendc.DrawRectangle(rect.x+rect.width-5, rect.y, 5, rect.height) - screendc.DrawRectangle(rect.x+5, rect.y+rect.height-5, rect.width-10, 5) - RefreshDockingGuides(self._guides) - - return - - if not self._hint_window: - self.CreateHintWindow() - - if self._hint_window: - self._hint_window.SetRect(rect) - self._hint_window.Show() - - self._hint_fadeamt = self._hint_fademax - - if self._agwFlags & AUI_MGR_HINT_FADE: - self._hint_fadeamt = 0 - self._hint_window.SetTransparent(self._hint_fadeamt) - - if self._action == actionDragFloatingPane and self._action_window: - self._action_window.SetFocus() - - if self._hint_fadeamt != self._hint_fademax: # Only fade if we need to - # start fade in timer - self._hint_fadetimer.Start(5) - - self._last_hint = wx.Rect(*rect) - - - def HideHint(self): - """ Hides a transparent window hint if there is one. """ - - # hides a transparent window hint if there is one - if self._hint_window: - self._hint_window.Hide() - - self._hint_fadetimer.Stop() - self._last_hint = wx.Rect() - - - def IsPaneButtonVisible(self, part): - """ - Returns whether a pane button in the pane caption is visible. - - :param `part`: the UI part to analyze. - """ - - captionRect = wx.Rect() - - for temp_part in self._uiparts: - if temp_part.pane == part.pane and \ - temp_part.type == AuiDockUIPart.typeCaption: - captionRect = temp_part.rect - break - - return captionRect.ContainsRect(part.rect) - - - def DrawPaneButton(self, dc, part, pt): - """ - Draws a pane button in the caption (convenience function). - - :param `dc`: a `wx.DC` device context object; - :param `part`: the UI part to analyze; - :param `pt`: a `wx.Point` object, specifying the mouse location. - """ - - if not self.IsPaneButtonVisible(part): - return - - state = AUI_BUTTON_STATE_NORMAL - - if part.rect.Contains(pt): - - if _VERSION_STRING < "2.9": - leftDown = wx.GetMouseState().LeftDown() - else: - leftDown = wx.GetMouseState().LeftIsDown() - - if leftDown: - state = AUI_BUTTON_STATE_PRESSED - else: - state = AUI_BUTTON_STATE_HOVER - - self._art.DrawPaneButton(dc, self._frame, part.button.button_id, - state, part.rect, part.pane) - - - def RefreshButton(self, part): - """ - Refreshes a pane button in the caption. - - :param `part`: the UI part to analyze. - """ - - rect = wx.Rect(*part.rect) - rect.Inflate(2, 2) - self._frame.Refresh(True, rect) - self._frame.Update() - - - def RefreshCaptions(self): - """ Refreshes all pane captions. """ - - for part in self._uiparts: - if part.type == AuiDockUIPart.typeCaption: - self._frame.Refresh(True, part.rect) - self._frame.Update() - - - def CalculateHintRect(self, pane_window, pt, offset): - """ - Calculates the drop hint rectangle. - - The method first calls L{DoDrop} to determine the exact position the pane would - be at were if dropped. If the pane would indeed become docked at the - specified drop point, the the rectangle hint will be returned in - screen coordinates. Otherwise, an empty rectangle is returned. - - :param `pane_window`: it is the window pointer of the pane being dragged; - :param `pt`: is the mouse position, in client coordinates; - :param `offset`: describes the offset that the mouse is from the upper-left - corner of the item being dragged. - """ - - # we need to paint a hint rectangle to find out the exact hint rectangle, - # we will create a new temporary layout and then measure the resulting - # rectangle we will create a copy of the docking structures (self._docks) - # so that we don't modify the real thing on screen - - rect = wx.Rect() - pane = self.GetPane(pane_window) - - attrs = self.GetAttributes(pane) - hint = AuiPaneInfo() - hint = self.SetAttributes(hint, attrs) - - if hint.name != "__HINT__": - self._oldname = hint.name - - hint.name = "__HINT__" - hint.PaneBorder(True) - hint.Show() - - if not hint.IsOk(): - hint.name = self._oldname - return rect - - docks, panes = CopyDocksAndPanes2(self._docks, self._panes) - - # remove any pane already there which bears the same window - # this happens when you are moving a pane around in a dock - for ii in xrange(len(panes)): - if panes[ii].window == pane_window: - docks = RemovePaneFromDocks(docks, panes[ii]) - panes.pop(ii) - break - - # find out where the new pane would be - allow, hint = self.DoDrop(docks, panes, hint, pt, offset) - - if not allow: - return rect - - panes.append(hint) - - sizer, panes, docks, uiparts = self.LayoutAll(panes, docks, [], True, False) - - client_size = self._frame.GetClientSize() - sizer.SetDimension(0, 0, client_size.x, client_size.y) - sizer.Layout() - - sought = "__HINT__" - - # For a notebook page, actually look for the noteboot itself. - if hint.IsNotebookPage(): - id = hint.notebook_id - for pane in panes: - if pane.IsNotebookControl() and pane.notebook_id==id: - sought = pane.name - break - - for part in uiparts: - if part.pane and part.pane.name == sought: - rect.Union(wx.RectPS(part.sizer_item.GetPosition(), - part.sizer_item.GetSize())) - - sizer.Destroy() - - # check for floating frame ... - if rect.IsEmpty(): - for p in panes: - if p.name == sought and p.IsFloating(): - return wx.RectPS(p.floating_pos, p.floating_size) - - if rect.IsEmpty(): - return rect - - # actually show the hint rectangle on the screen - rect.x, rect.y = self._frame.ClientToScreen((rect.x, rect.y)) - if self._frame.GetLayoutDirection() == wx.Layout_RightToLeft: - # Mirror rectangle in RTL mode - rect.x -= rect.GetWidth() - - return rect - - - def DrawHintRect(self, pane_window, pt, offset): - """ - Calculates the hint rectangle by calling - L{CalculateHintRect}. If there is a rectangle, it shows it - by calling L{ShowHint}, otherwise it hides any hint - rectangle currently shown. - - :param `pane_window`: it is the window pointer of the pane being dragged; - :param `pt`: is the mouse position, in client coordinates; - :param `offset`: describes the offset that the mouse is from the upper-left - corner of the item being dragged. - """ - - rect = self.CalculateHintRect(pane_window, pt, offset) - - if rect.IsEmpty(): - self.HideHint() - self._hint_rect = wx.Rect() - else: - self.ShowHint(rect) - self._hint_rect = wx.Rect(*rect) - - - def GetPartSizerRect(self, uiparts): - """ - Returns the rectangle surrounding the specified UI parts. - - :param `uiparts`: UI parts. - """ - - rect = wx.Rect() - - for part in self._uiparts: - if part.pane and part.pane.name == "__HINT__": - rect.Union(wx.RectPS(part.sizer_item.GetPosition(), - part.sizer_item.GetSize())) - - return rect - - - def GetAttributes(self, pane): - """ - Returns all the attributes of a L{AuiPaneInfo}. - - :param `pane`: a L{AuiPaneInfo} instance. - """ - - attrs = [] - attrs.extend([pane.window, pane.frame, pane.state, pane.dock_direction, - pane.dock_layer, pane.dock_pos, pane.dock_row, pane.dock_proportion, - pane.floating_pos, pane.floating_size, pane.best_size, - pane.min_size, pane.max_size, pane.caption, pane.name, - pane.buttons, pane.rect, pane.icon, pane.notebook_id, - pane.transparent, pane.snapped, pane.minimize_mode]) - - return attrs - - - def SetAttributes(self, pane, attrs): - """ - Sets all the attributes contained in `attrs` to a L{AuiPaneInfo}. - - :param `pane`: a L{AuiPaneInfo} instance; - :param `attrs`: a list of attributes. - """ - - pane.window = attrs[0] - pane.frame = attrs[1] - pane.state = attrs[2] - pane.dock_direction = attrs[3] - pane.dock_layer = attrs[4] - pane.dock_pos = attrs[5] - pane.dock_row = attrs[6] - pane.dock_proportion = attrs[7] - pane.floating_pos = attrs[8] - pane.floating_size = attrs[9] - pane.best_size = attrs[10] - pane.min_size = attrs[11] - pane.max_size = attrs[12] - pane.caption = attrs[13] - pane.name = attrs[14] - pane.buttons = attrs[15] - pane.rect = attrs[16] - pane.icon = attrs[17] - pane.notebook_id = attrs[18] - pane.transparent = attrs[19] - pane.snapped = attrs[20] - pane.minimize_mode = attrs[21] - - return pane - - - def OnFloatingPaneResized(self, wnd, size): - """ - Handles the resizing of a floating pane. - - :param `wnd`: a `wx.Window` derived window, managed by the pane; - :param `size`: a `wx.Size` object, specifying the new pane floating size. - """ - - # try to find the pane - pane = self.GetPane(wnd) - if not pane.IsOk(): - raise Exception("Pane window not found") - - if pane.frame: - indx = self._panes.index(pane) - pane.floating_pos = pane.frame.GetPosition() - pane.floating_size = size - self._panes[indx] = pane - if pane.IsSnappable(): - self.SnapPane(pane, pane.floating_pos, pane.floating_size, True) - - - def OnFloatingPaneClosed(self, wnd, event): - """ - Handles the close event of a floating pane. - - :param `wnd`: a `wx.Window` derived window, managed by the pane; - :param `event`: a `wx.CloseEvent` to be processed. - """ - - # try to find the pane - pane = self.GetPane(wnd) - if not pane.IsOk(): - raise Exception("Pane window not found") - - # fire pane close event - e = AuiManagerEvent(wxEVT_AUI_PANE_CLOSE) - e.SetPane(pane) - e.SetCanVeto(event.CanVeto()) - self.ProcessMgrEvent(e) - - if e.GetVeto(): - event.Veto() - return - else: - # close the pane, but check that it - # still exists in our pane array first - # (the event handler above might have removed it) - - check = self.GetPane(wnd) - if check.IsOk(): - self.ClosePane(pane) - - - def OnFloatingPaneActivated(self, wnd): - """ - Handles the activation event of a floating pane. - - :param `wnd`: a `wx.Window` derived window, managed by the pane. - """ - - pane = self.GetPane(wnd) - if not pane.IsOk(): - raise Exception("Pane window not found") - - if self.GetAGWFlags() & AUI_MGR_ALLOW_ACTIVE_PANE: - ret, self._panes = SetActivePane(self._panes, wnd) - self.RefreshCaptions() - self.FireEvent(wxEVT_AUI_PANE_ACTIVATED, wnd, canVeto=False) - - - def OnFloatingPaneMoved(self, wnd, eventOrPt): - """ - Handles the move event of a floating pane. - - :param `wnd`: a `wx.Window` derived window, managed by the pane; - :param `eventOrPt`: a `wx.MoveEvent` to be processed or an instance of `wx.Point`. - """ - - pane = self.GetPane(wnd) - if not pane.IsOk(): - raise Exception("Pane window not found") - - if not pane.IsSnappable(): - return - - if isinstance(eventOrPt, wx.Point): - pane_pos = wx.Point(*eventOrPt) - else: - pane_pos = eventOrPt.GetPosition() - - pane_size = pane.floating_size - - self.SnapPane(pane, pane_pos, pane_size, False) - - - def SnapPane(self, pane, pane_pos, pane_size, toSnap=False): - """ - Snaps a floating pane to one of the main frame sides. - - :param `pane`: a L{AuiPaneInfo} instance; - :param `pane_pos`: the new pane floating position; - :param `pane_size`: the new pane floating size; - :param `toSnap`: a bool variable to check if L{SnapPane} was called from - a move event. - """ - - if self._from_move: - return - - managed_window = self.GetManagedWindow() - wnd_pos = managed_window.GetPosition() - wnd_size = managed_window.GetSize() - snapX, snapY = self._snap_limits - - if not toSnap: - pane.snapped = 0 - if pane.IsLeftSnappable(): - # Check if we can snap to the left - diff = wnd_pos.x - (pane_pos.x + pane_size.x) - if -snapX <= diff <= snapX: - pane.snapped = wx.LEFT - pane.floating_pos = wx.Point(wnd_pos.x-pane_size.x, pane_pos.y) - elif pane.IsTopSnappable(): - # Check if we can snap to the top - diff = wnd_pos.y - (pane_pos.y + pane_size.y) - if -snapY <= diff <= snapY: - pane.snapped = wx.TOP - pane.floating_pos = wx.Point(pane_pos.x, wnd_pos.y-pane_size.y) - elif pane.IsRightSnappable(): - # Check if we can snap to the right - diff = pane_pos.x - (wnd_pos.x + wnd_size.x) - if -snapX <= diff <= snapX: - pane.snapped = wx.RIGHT - pane.floating_pos = wx.Point(wnd_pos.x + wnd_size.x, pane_pos.y) - elif pane.IsBottomSnappable(): - # Check if we can snap to the bottom - diff = pane_pos.y - (wnd_pos.y + wnd_size.y) - if -snapY <= diff <= snapY: - pane.snapped = wx.BOTTOM - pane.floating_pos = wx.Point(pane_pos.x, wnd_pos.y + wnd_size.y) - - self.RepositionPane(pane, wnd_pos, wnd_size) - - - def RepositionPane(self, pane, wnd_pos, wnd_size): - """ - Repositions a pane after the main frame has been moved/resized. - - :param `pane`: a L{AuiPaneInfo} instance; - :param `wnd_pos`: the main frame position; - :param `wnd_size`: the main frame size. - """ - - pane_pos = pane.floating_pos - pane_size = pane.floating_size - - snap = pane.snapped - if snap == wx.LEFT: - floating_pos = wx.Point(wnd_pos.x - pane_size.x, pane_pos.y) - elif snap == wx.TOP: - floating_pos = wx.Point(pane_pos.x, wnd_pos.y - pane_size.y) - elif snap == wx.RIGHT: - floating_pos = wx.Point(wnd_pos.x + wnd_size.x, pane_pos.y) - elif snap == wx.BOTTOM: - floating_pos = wx.Point(pane_pos.x, wnd_pos.y + wnd_size.y) - - if snap: - if pane_pos != floating_pos: - pane.floating_pos = floating_pos - self._from_move = True - pane.frame.SetPosition(pane.floating_pos) - self._from_move = False - - - def OnGripperClicked(self, pane_window, start, offset): - """ - Handles the mouse click on the pane gripper. - - :param `pane_window`: a `wx.Window` derived window, managed by the pane; - :param `start`: a `wx.Point` object, specifying the clicking position; - :param `offset`: an offset point from the `start` position. - """ - - # try to find the pane - paneInfo = self.GetPane(pane_window) - - if not paneInfo.IsOk(): - raise Exception("Pane window not found") - - if self.GetAGWFlags() & AUI_MGR_ALLOW_ACTIVE_PANE: - # set the caption as active - ret, self._panes = SetActivePane(self._panes, pane_window) - self.RefreshCaptions() - self.FireEvent(wxEVT_AUI_PANE_ACTIVATED, pane_window, canVeto=False) - - self._action_part = None - self._action_pane = paneInfo - self._action_window = pane_window - self._action_start = start - self._action_offset = offset - self._toolbar_action_offset = wx.Point(*self._action_offset) - - self._frame.CaptureMouse() - - if paneInfo.IsDocked(): - self._action = actionClickCaption - else: - if paneInfo.IsToolbar(): - self._action = actionDragToolbarPane - else: - self._action = actionDragFloatingPane - - if paneInfo.frame: - - windowPt = paneInfo.frame.GetRect().GetTopLeft() - originPt = paneInfo.frame.ClientToScreen(wx.Point()) - self._action_offset += originPt - windowPt - self._toolbar_action_offset = wx.Point(*self._action_offset) - - if self._agwFlags & AUI_MGR_TRANSPARENT_DRAG: - paneInfo.frame.SetTransparent(150) - - if paneInfo.IsToolbar(): - self._frame.SetCursor(wx.StockCursor(wx.CURSOR_SIZING)) - - - def OnRender(self, event): - """ - Draws all of the pane captions, sashes, - backgrounds, captions, grippers, pane borders and buttons. - It renders the entire user interface. It binds the ``EVT_AUI_RENDER`` event. - - :param `event`: an instance of L{AuiManagerEvent}. - """ - - # if the frame is about to be deleted, don't bother - if not self._frame or self._frame.IsBeingDeleted(): - return - - if not self._frame.GetSizer(): - return - - mouse = wx.GetMouseState() - mousePos = wx.Point(mouse.GetX(), mouse.GetY()) - point = self._frame.ScreenToClient(mousePos) - art = self._art - - dc = event.GetDC() - - for part in self._uiparts: - - # don't draw hidden pane items or items that aren't windows - if part.sizer_item and ((not part.sizer_item.IsWindow() and \ - not part.sizer_item.IsSpacer() and \ - not part.sizer_item.IsSizer()) or \ - not part.sizer_item.IsShown()): - - continue - - ptype = part.type - - if ptype in [AuiDockUIPart.typeDockSizer, AuiDockUIPart.typePaneSizer]: - art.DrawSash(dc, self._frame, part.orientation, part.rect) - - elif ptype == AuiDockUIPart.typeBackground: - art.DrawBackground(dc, self._frame, part.orientation, part.rect) - - elif ptype == AuiDockUIPart.typeCaption: - art.DrawCaption(dc, self._frame, part.pane.caption, part.rect, part.pane) - - elif ptype == AuiDockUIPart.typeGripper: - art.DrawGripper(dc, self._frame, part.rect, part.pane) - - elif ptype == AuiDockUIPart.typePaneBorder: - art.DrawBorder(dc, self._frame, part.rect, part.pane) - - elif ptype == AuiDockUIPart.typePaneButton: - self.DrawPaneButton(dc, part, point) - - - def Repaint(self, dc=None): - """ - Repaints the entire frame decorations (sashes, borders, buttons and so on). - It renders the entire user interface. - - :param `dc`: if not ``None``, an instance of `wx.PaintDC`. - """ - - w, h = self._frame.GetClientSize() - - # Figure out which dc to use; if one - # has been specified, use it, otherwise - # make a client dc - if dc is None: - client_dc = wx.ClientDC(self._frame) - dc = client_dc - - # If the frame has a toolbar, the client area - # origin will not be (0, 0). - pt = self._frame.GetClientAreaOrigin() - if pt.x != 0 or pt.y != 0: - dc.SetDeviceOrigin(pt.x, pt.y) - - # Render all the items - self.Render(dc) - - - def Render(self, dc): - """ - Fires a render event, which is normally handled by - L{OnRender}. This allows the render function to - be overridden via the render event. - - This can be useful for painting custom graphics in the main window. - Default behavior can be invoked in the overridden function by calling - L{OnRender}. - - :param `dc`: a `wx.DC` device context object. - """ - - e = AuiManagerEvent(wxEVT_AUI_RENDER) - e.SetManager(self) - e.SetDC(dc) - self.ProcessMgrEvent(e) - - - def OnCaptionDoubleClicked(self, pane_window): - """ - Handles the mouse double click on the pane caption. - - :param `pane_window`: a `wx.Window` derived window, managed by the pane. - """ - - # try to find the pane - paneInfo = self.GetPane(pane_window) - if not paneInfo.IsOk(): - raise Exception("Pane window not found") - - if not paneInfo.IsFloatable() or not paneInfo.IsDockable() or \ - self._agwFlags & AUI_MGR_ALLOW_FLOATING == 0: - return - - indx = self._panes.index(paneInfo) - win_rect = None - - if paneInfo.IsFloating(): - if paneInfo.name.startswith("__floating__"): - # It's a floating tab from a AuiNotebook - notebook = paneInfo.window.__aui_notebook__ - notebook.ReDockPage(paneInfo) - self.Update() - return - else: - - e = self.FireEvent(wxEVT_AUI_PANE_DOCKING, paneInfo, canVeto=True) - if e.GetVeto(): - self.HideHint() - ShowDockingGuides(self._guides, False) - return - - win_rect = paneInfo.frame.GetRect() - paneInfo.Dock() - if paneInfo.IsToolbar(): - paneInfo = self.SwitchToolBarOrientation(paneInfo) - - e = self.FireEvent(wxEVT_AUI_PANE_DOCKED, paneInfo, canVeto=False) - - else: - - e = self.FireEvent(wxEVT_AUI_PANE_FLOATING, paneInfo, canVeto=True) - if e.GetVeto(): - return - - # float the window - if paneInfo.IsMaximized(): - self.RestorePane(paneInfo) - - if paneInfo.floating_pos == wx.Point(-1, -1): - captionSize = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) - paneInfo.floating_pos = pane_window.GetScreenPosition() - paneInfo.floating_pos.y -= captionSize - - paneInfo.Float() - e = self.FireEvent(wxEVT_AUI_PANE_FLOATED, paneInfo, canVeto=False) - - self._panes[indx] = paneInfo - self.Update() - - if win_rect and self._agwFlags & AUI_MGR_ANIMATE_FRAMES: - paneInfo = self.GetPane(pane_window) - pane_rect = paneInfo.window.GetScreenRect() - self.AnimateDocking(win_rect, pane_rect) - - - def OnPaint(self, event): - """ - Handles the ``wx.EVT_PAINT`` event for L{AuiManager}. - - :param `event`: an instance of `wx.PaintEvent` to be processed. - """ - - dc = wx.PaintDC(self._frame) - self.Repaint(dc) - - - def OnEraseBackground(self, event): - """ - Handles the ``wx.EVT_ERASE_BACKGROUND`` event for L{AuiManager}. - - :param `event`: `wx.EraseEvent` to be processed. - - :note: This is intentionally empty (excluding wxMAC) to reduce - flickering while drawing. - """ - - if wx.Platform == "__WXMAC__": - event.Skip() - - - def OnSize(self, event): - """ - Handles the ``wx.EVT_SIZE`` event for L{AuiManager}. - - :param `event`: a `wx.SizeEvent` to be processed. - """ - - skipped = False - if isinstance(self._frame, AuiFloatingFrame) and self._frame.IsShownOnScreen(): - skipped = True - event.Skip() - - if self._frame: - - self.DoFrameLayout() - if wx.Platform == "__WXMAC__": - self._frame.Refresh() - else: - self.Repaint() - - if isinstance(self._frame, wx.MDIParentFrame) or isinstance(self._frame, tabmdi.AuiMDIClientWindow) \ - or isinstance(self._frame, tabmdi.AuiMDIParentFrame): - # for MDI parent frames, this event must not - # be "skipped". In other words, the parent frame - # must not be allowed to resize the client window - # after we are finished processing sizing changes - return - - if not skipped: - event.Skip() - - # For the snap to screen... - self.OnMove(None) - - - def OnFindManager(self, event): - """ - Handles the ``EVT_AUI_FIND_MANAGER`` event for L{AuiManager}. - - :param `event`: a L{AuiManagerEvent} event to be processed. - """ - - # Initialize to None - event.SetManager(None) - - if not self._frame: - return - - # See it this window wants to overwrite - self._frame.ProcessEvent(event) - - # if no, it must be us - if not event.GetManager(): - event.SetManager(self) - - - def OnSetCursor(self, event): - """ - Handles the ``wx.EVT_SET_CURSOR`` event for L{AuiManager}. - - :param `event`: a `wx.SetCursorEvent` to be processed. - """ - - # determine cursor - part = self.HitTest(event.GetX(), event.GetY()) - cursor = wx.NullCursor - - if part: - if part.type in [AuiDockUIPart.typeDockSizer, AuiDockUIPart.typePaneSizer]: - - if not self.CheckMovableSizer(part): - return - - if part.orientation == wx.VERTICAL: - cursor = wx.StockCursor(wx.CURSOR_SIZEWE) - else: - cursor = wx.StockCursor(wx.CURSOR_SIZENS) - - elif part.type == AuiDockUIPart.typeGripper: - cursor = wx.StockCursor(wx.CURSOR_SIZING) - - event.SetCursor(cursor) - - - def UpdateButtonOnScreen(self, button_ui_part, event): - """ - Updates/redraws the UI part containing a pane button. - - :param `button_ui_part`: the UI part the button belongs to; - :param `event`: a `wx.MouseEvent` to be processed. - """ - - hit_test = self.HitTest(*event.GetPosition()) - - if not hit_test or not button_ui_part: - return - - state = AUI_BUTTON_STATE_NORMAL - - if hit_test == button_ui_part: - if event.LeftDown(): - state = AUI_BUTTON_STATE_PRESSED - else: - state = AUI_BUTTON_STATE_HOVER - else: - if event.LeftDown(): - state = AUI_BUTTON_STATE_HOVER - - # now repaint the button with hover state - cdc = wx.ClientDC(self._frame) - - # if the frame has a toolbar, the client area - # origin will not be (0,0). - pt = self._frame.GetClientAreaOrigin() - if pt.x != 0 or pt.y != 0: - cdc.SetDeviceOrigin(pt.x, pt.y) - - if hit_test.pane: - self._art.DrawPaneButton(cdc, self._frame, - button_ui_part.button.button_id, - state, - button_ui_part.rect, hit_test.pane) - - - def OnLeftDown(self, event): - """ - Handles the ``wx.EVT_LEFT_DOWN`` event for L{AuiManager}. - - :param `event`: a `wx.MouseEvent` to be processed. - """ - - part = self.HitTest(*event.GetPosition()) - - if not part: - event.Skip() - return - - self._currentDragItem = -1 - - if part.type in [AuiDockUIPart.typeDockSizer, AuiDockUIPart.typePaneSizer]: - - if not self.CheckMovableSizer(part): - return - - self._action = actionResize - self._action_part = part - self._action_pane = None - self._action_rect = wx.Rect() - self._action_start = wx.Point(event.GetX(), event.GetY()) - self._action_offset = wx.Point(event.GetX() - part.rect.x, - event.GetY() - part.rect.y) - - # draw the resize hint - rect = wx.RectPS(self._frame.ClientToScreen(part.rect.GetPosition()), - part.rect.GetSize()) - - self._action_rect = wx.Rect(*rect) - - if not AuiManager_HasLiveResize(self): - if wx.Platform == "__WXMAC__": - dc = wx.ClientDC(self._frame) - else: - dc = wx.ScreenDC() - - DrawResizeHint(dc, rect) - - self._frame.CaptureMouse() - - elif part.type == AuiDockUIPart.typePaneButton: - if self.IsPaneButtonVisible(part): - self._action = actionClickButton - self._action_part = part - self._action_pane = None - self._action_start = wx.Point(*event.GetPosition()) - self._frame.CaptureMouse() - - self.RefreshButton(part) - - elif part.type in [AuiDockUIPart.typeCaption, AuiDockUIPart.typeGripper]: - - # if we are managing a AuiFloatingFrame window, then - # we are an embedded AuiManager inside the AuiFloatingFrame. - # We want to initiate a toolbar drag in our owner manager - if isinstance(part.pane.window.GetParent(), AuiFloatingFrame): - rootManager = GetManager(part.pane.window) - else: - rootManager = self - - offset = wx.Point(event.GetX() - part.rect.x, event.GetY() - part.rect.y) - rootManager.OnGripperClicked(part.pane.window, event.GetPosition(), offset) - - if wx.Platform != "__WXMAC__": - event.Skip() - - - def OnLeftDClick(self, event): - """ - Handles the ``wx.EVT_LEFT_DCLICK`` event for L{AuiManager}. - - :param `event`: a `wx.MouseEvent` to be processed. - """ - - part = self.HitTest(event.GetX(), event.GetY()) - - if part and part.type == AuiDockUIPart.typeCaption: - if isinstance(part.pane.window.GetParent(), AuiFloatingFrame): - rootManager = GetManager(part.pane.window) - else: - rootManager = self - - rootManager.OnCaptionDoubleClicked(part.pane.window) - - elif part and part.type in [AuiDockUIPart.typeDockSizer, AuiDockUIPart.typePaneSizer]: - # Handles double click on AuiNotebook sashes to unsplit - sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE) - for child in part.cont_sizer.GetChildren(): - if child.IsSizer(): - win = child.GetSizer().GetContainingWindow() - if isinstance(win, auibook.AuiNotebook): - win.UnsplitDClick(part, sash_size, event.GetPosition()) - break - - event.Skip() - - - def DoEndResizeAction(self, event): - """ - Ends a resize action, or for live update, resizes the sash. - - :param `event`: a `wx.MouseEvent` to be processed. - """ - - clientPt = event.GetPosition() - screenPt = self._frame.ClientToScreen(clientPt) - - return self.RestrictResize(clientPt, screenPt, createDC=False) - - - def RestrictResize(self, clientPt, screenPt, createDC): - """ Common method between L{DoEndResizeAction} and L{OnLeftUp_Resize}. """ - - dock = self._action_part.dock - pane = self._action_part.pane - - if createDC: - if wx.Platform == "__WXMAC__": - dc = wx.ClientDC(self._frame) - else: - dc = wx.ScreenDC() - - DrawResizeHint(dc, self._action_rect) - self._action_rect = wx.Rect() - - newPos = clientPt - self._action_offset - - if self._action_part.type == AuiDockUIPart.typeDockSizer: - minPix, maxPix = self.CalculateDockSizerLimits(dock) - else: - if not self._action_part.pane: - return - minPix, maxPix = self.CalculatePaneSizerLimits(dock, pane) - - if self._action_part.orientation == wx.HORIZONTAL: - newPos.y = Clip(newPos.y, minPix, maxPix) - else: - newPos.x = Clip(newPos.x, minPix, maxPix) - - if self._action_part.type == AuiDockUIPart.typeDockSizer: - - partnerDock = self.GetPartnerDock(dock) - sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE) - new_dock_size = 0 - direction = dock.dock_direction - - if direction == AUI_DOCK_LEFT: - new_dock_size = newPos.x - dock.rect.x - - elif direction == AUI_DOCK_TOP: - new_dock_size = newPos.y - dock.rect.y - - elif direction == AUI_DOCK_RIGHT: - new_dock_size = dock.rect.x + dock.rect.width - newPos.x - sash_size - - elif direction == AUI_DOCK_BOTTOM: - new_dock_size = dock.rect.y + dock.rect.height - newPos.y - sash_size - - deltaDockSize = new_dock_size - dock.size - - if partnerDock: - if deltaDockSize > partnerDock.size - sash_size: - deltaDockSize = partnerDock.size - sash_size - - partnerDock.size -= deltaDockSize - - dock.size += deltaDockSize - self.Update() - - else: - - # determine the new pixel size that the user wants - # this will help us recalculate the pane's proportion - if dock.IsHorizontal(): - oldPixsize = pane.rect.width - newPixsize = oldPixsize + newPos.x - self._action_part.rect.x - - else: - oldPixsize = pane.rect.height - newPixsize = oldPixsize + newPos.y - self._action_part.rect.y - - totalPixsize, totalProportion = self.GetTotalPixSizeAndProportion(dock) - partnerPane = self.GetPartnerPane(dock, pane) - - # prevent division by zero - if totalPixsize <= 0 or totalProportion <= 0 or not partnerPane: - return - - # adjust for the surplus - while (oldPixsize > 0 and totalPixsize > 10 and \ - oldPixsize*totalProportion/totalPixsize < pane.dock_proportion): - - totalPixsize -= 1 - - # calculate the new proportion of the pane - - newProportion = newPixsize*totalProportion/totalPixsize - newProportion = Clip(newProportion, 1, totalProportion) - deltaProp = newProportion - pane.dock_proportion - - if partnerPane.dock_proportion - deltaProp < 1: - deltaProp = partnerPane.dock_proportion - 1 - newProportion = pane.dock_proportion + deltaProp - - # borrow the space from our neighbor pane to the - # right or bottom (depending on orientation) - partnerPane.dock_proportion -= deltaProp - pane.dock_proportion = newProportion - - self.Update() - - return True - - - def OnLeftUp(self, event): - """ - Handles the ``wx.EVT_LEFT_UP`` event for L{AuiManager}. - - :param `event`: a `wx.MouseEvent` to be processed. - """ - - if self._action == actionResize: -## self._frame.Freeze() - self.OnLeftUp_Resize(event) -## self._frame.Thaw() - - elif self._action == actionClickButton: - self.OnLeftUp_ClickButton(event) - - elif self._action == actionDragFloatingPane: - self.OnLeftUp_DragFloatingPane(event) - - elif self._action == actionDragToolbarPane: - self.OnLeftUp_DragToolbarPane(event) - - else: - event.Skip() - - if self._frame.HasCapture(): - self._frame.ReleaseMouse() - - self._action = actionNone - - - def OnMotion(self, event): - """ - Handles the ``wx.EVT_MOTION`` event for L{AuiManager}. - - :param `event`: a `wx.MouseEvent` to be processed. - """ - - if self._action == actionResize: - self.OnMotion_Resize(event) - - elif self._action == actionClickCaption: - self.OnMotion_ClickCaption(event) - - elif self._action == actionDragFloatingPane: - self.OnMotion_DragFloatingPane(event) - - elif self._action == actionDragToolbarPane: - self.OnMotion_DragToolbarPane(event) - - else: - self.OnMotion_Other(event) - - - def OnLeaveWindow(self, event): - """ - Handles the ``wx.EVT_LEAVE_WINDOW`` event for L{AuiManager}. - - :param `event`: a `wx.MouseEvent` to be processed. - """ - - if self._hover_button: - self.RefreshButton(self._hover_button) - self._hover_button = None - - - def OnCaptureLost(self, event): - """ - Handles the ``wx.EVT_MOUSE_CAPTURE_LOST`` event for L{AuiManager}. - - :param `event`: a `wx.MouseCaptureLostEvent` to be processed. - """ - - # cancel the operation in progress, if any - if self._action != actionNone: - self._action = actionNone - self.HideHint() - - - def OnHintFadeTimer(self, event): - """ - Handles the ``wx.EVT_TIMER`` event for L{AuiManager}. - - :param `event`: a `wx.TimerEvent` to be processed. - """ - - if not self._hint_window or self._hint_fadeamt >= self._hint_fademax: - self._hint_fadetimer.Stop() - return - - self._hint_fadeamt += 4 - self._hint_window.SetTransparent(self._hint_fadeamt) - - - def OnMove(self, event): - """ - Handles the ``wx.EVT_MOVE`` event for L{AuiManager}. - - :param `event`: a `wx.MoveEvent` to be processed. - """ - - if event is not None: - event.Skip() - - if isinstance(self._frame, AuiFloatingFrame) and self._frame.IsShownOnScreen(): - return - - docked, hAlign, vAlign, monitor = self._is_docked - if docked: - self.Snap() - - for pane in self._panes: - if pane.IsSnappable(): - if pane.IsFloating() and pane.IsShown(): - self.SnapPane(pane, pane.floating_pos, pane.floating_size, True) - - - def OnSysColourChanged(self, event): - """ - Handles the ``wx.EVT_SYS_COLOUR_CHANGED`` event for L{AuiManager}. - - :param `event`: a `wx.SysColourChangedEvent` to be processed. - """ - - # This event is probably triggered by a theme change - # so we have to re-init the art provider. - if self._art: - self._art.Init() - - if self._frame: - self.Update() - self._frame.Refresh() - - - def OnChildFocus(self, event): - """ - Handles the ``wx.EVT_CHILD_FOCUS`` event for L{AuiManager}. - - :param `event`: a `wx.ChildFocusEvent` to be processed. - """ - - # when a child pane has it's focus set, we should change the - # pane's active state to reflect this. (this is only true if - # active panes are allowed by the owner) - - window = event.GetWindow() - if isinstance(window, wx.Dialog): - # Ignore EVT_CHILD_FOCUS events originating from dialogs not - # managed by AUI - rootManager = None - elif isinstance(window.GetParent(), AuiFloatingFrame): - rootManager = GetManager(window) - else: - rootManager = self - - if rootManager: - rootManager.ActivatePane(window) - - event.Skip() - - - def OnMotion_ClickCaption(self, event): - """ - Sub-handler for the L{OnMotion} event. - - :param `event`: a `wx.MouseEvent` to be processed. - """ - - clientPt = event.GetPosition() - screenPt = self._frame.ClientToScreen(clientPt) - - drag_x_threshold = wx.SystemSettings.GetMetric(wx.SYS_DRAG_X) - drag_y_threshold = wx.SystemSettings.GetMetric(wx.SYS_DRAG_Y) - - if not self._action_pane: - return - - # we need to check if the mouse is now being dragged - if not (abs(clientPt.x - self._action_start.x) > drag_x_threshold or \ - abs(clientPt.y - self._action_start.y) > drag_y_threshold): - - return - - # dragged -- we need to change the mouse action to 'drag' - if self._action_pane.IsToolbar(): - self._action = actionDragToolbarPane - self._action_window = self._action_pane.window - - elif self._action_pane.IsFloatable() and self._agwFlags & AUI_MGR_ALLOW_FLOATING: - - e = self.FireEvent(wxEVT_AUI_PANE_FLOATING, self._action_pane, canVeto=True) - if e.GetVeto(): - return - - self._action = actionDragFloatingPane - - # set initial float position - self._action_pane.floating_pos = screenPt - self._action_offset - - # float the window - if self._action_pane.IsMaximized(): - self.RestorePane(self._action_pane) - - self._action_pane.Hide() - self._action_pane.Float() - if wx.Platform == "__WXGTK__": - self._action_pane.Show() - - e = self.FireEvent(wxEVT_AUI_PANE_FLOATED, self._action_pane, canVeto=False) - - if not self._action_pane.frame: - self.Update() - - self._action_window = self._action_pane.window - - # adjust action offset for window frame - windowPt = self._action_pane.frame.GetRect().GetTopLeft() - originPt = self._action_pane.frame.ClientToScreen(wx.Point()) - self._toolbar_action_offset = originPt - windowPt - - if self._agwFlags & AUI_MGR_USE_NATIVE_MINIFRAMES: - originPt = windowPt + wx.Point(3, 3) - - self._action_offset += originPt - windowPt - - # action offset is used here to make it feel "natural" to the user - # to drag a docked pane and suddenly have it become a floating frame. - # Sometimes, however, the offset where the user clicked on the docked - # caption is bigger than the width of the floating frame itself, so - # in that case we need to set the action offset to a sensible value - frame_size = self._action_pane.frame.GetSize() - if self._action_offset.x > frame_size.x * 2 / 3: - self._action_offset.x = frame_size.x / 2 - if self._action_offset.y > frame_size.y * 2 / 3: - self._action_offset.y = frame_size.y / 2 - - self.OnMotion_DragFloatingPane(event) - if wx.Platform != "__WXGTK__": - self._action_pane.Show() - - self.Update() - - - def OnMotion_Resize(self, event): - """ - Sub-handler for the L{OnMotion} event. - - :param `event`: a `wx.MouseEvent` to be processed. - """ - - if AuiManager_HasLiveResize(self): - if self._currentDragItem != -1: - self._action_part = self._uiparts[self._currentDragItem] - else: - self._currentDragItem = self._uiparts.index(self._action_part) - - if self._frame.HasCapture(): - self._frame.ReleaseMouse() - - self.DoEndResizeAction(event) - self._frame.CaptureMouse() - return - - if not self._action_part or not self._action_part.dock or not self._action_part.orientation: - return - - clientPt = event.GetPosition() - screenPt = self._frame.ClientToScreen(clientPt) - - dock = self._action_part.dock - pos = self._action_part.rect.GetPosition() - - if self._action_part.type == AuiDockUIPart.typeDockSizer: - minPix, maxPix = self.CalculateDockSizerLimits(dock) - else: - if not self._action_part.pane: - return - - pane = self._action_part.pane - minPix, maxPix = self.CalculatePaneSizerLimits(dock, pane) - - if self._action_part.orientation == wx.HORIZONTAL: - pos.y = Clip(clientPt.y - self._action_offset.y, minPix, maxPix) - else: - pos.x = Clip(clientPt.x - self._action_offset.x, minPix, maxPix) - - hintrect = wx.RectPS(self._frame.ClientToScreen(pos), self._action_part.rect.GetSize()) - - if hintrect != self._action_rect: - - if wx.Platform == "__WXMAC__": - dc = wx.ClientDC(self._frame) - else: - dc = wx.ScreenDC() - - DrawResizeHint(dc, self._action_rect) - DrawResizeHint(dc, hintrect) - self._action_rect = wx.Rect(*hintrect) - - - def OnLeftUp_Resize(self, event): - """ - Sub-handler for the L{OnLeftUp} event. - - :param `event`: a `wx.MouseEvent` to be processed. - """ - - if self._currentDragItem != -1 and AuiManager_HasLiveResize(self): - self._action_part = self._uiparts[self._currentDragItem] - - if self._frame.HasCapture(): - self._frame.ReleaseMouse() - - self.DoEndResizeAction(event) - self._currentDragItem = -1 - return - - if not self._action_part or not self._action_part.dock: - return - - clientPt = event.GetPosition() - screenPt = self._frame.ClientToScreen(clientPt) - - return self.RestrictResize(clientPt, screenPt, createDC=True) - - - def OnLeftUp_ClickButton(self, event): - """ - Sub-handler for the L{OnLeftUp} event. - - :param `event`: a `wx.MouseEvent` to be processed. - """ - - self._hover_button = None - - if self._action_part: - self.RefreshButton(self._action_part) - - # make sure we're still over the item that was originally clicked - if self._action_part == self.HitTest(*event.GetPosition()): - - # fire button-click event - e = AuiManagerEvent(wxEVT_AUI_PANE_BUTTON) - e.SetManager(self) - e.SetPane(self._action_part.pane) - e.SetButton(self._action_part.button.button_id) - self.ProcessMgrEvent(e) - - - def CheckPaneMove(self, pane): - """ - Checks if a pane has moved by a visible amount. - - :param `pane`: an instance of L{AuiPaneInfo}. - """ - - win_rect = pane.frame.GetRect() - win_rect.x, win_rect.y = pane.floating_pos - - if win_rect == self._last_rect: - return False - - # skip the first move event - if self._last_rect.IsEmpty(): - self._last_rect = wx.Rect(*win_rect) - return False - - # skip if moving too fast to avoid massive redraws and - # jumping hint windows - if abs(win_rect.x - self._last_rect.x) > 10 or \ - abs(win_rect.y - self._last_rect.y) > 10: - self._last_rect = wx.Rect(*win_rect) - return False - - return True - - - def OnMotion_DragFloatingPane(self, eventOrPt): - """ - Sub-handler for the L{OnMotion} event. - - :param `event`: a `wx.MouseEvent` to be processed. - """ - - isPoint = False - if isinstance(eventOrPt, wx.Point): - clientPt = self._frame.ScreenToClient(eventOrPt) - screenPt = wx.Point(*eventOrPt) - isPoint = True - else: - clientPt = eventOrPt.GetPosition() - screenPt = self._frame.ClientToScreen(clientPt) - - framePos = wx.Point() - - # try to find the pane - pane = self.GetPane(self._action_window) - if not pane.IsOk(): - raise Exception("Pane window not found") - - # update floating position - if pane.IsFloating(): - diff = pane.floating_pos - (screenPt - self._action_offset) - pane.floating_pos = screenPt - self._action_offset - - framePos = pane.floating_pos - - # Move the pane window - if pane.frame: - - if diff.x != 0 or diff.y != 0: - if wx.Platform == "__WXMSW__" and (self._agwFlags & AUI_MGR_TRANSPARENT_DRAG) == 0: # and not self.CheckPaneMove(pane): - # return - # HACK: Terrible hack on wxMSW (!) - pane.frame.SetTransparent(254) - - self._from_move = True - pane.frame.Move(pane.floating_pos) - self._from_move = False - - if self._agwFlags & AUI_MGR_TRANSPARENT_DRAG: - pane.frame.SetTransparent(150) - - # calculate the offset from the upper left-hand corner - # of the frame to the mouse pointer - action_offset = screenPt - framePos - - # is the pane dockable? - if not self.CanDockPanel(pane): - self.HideHint() - ShowDockingGuides(self._guides, False) - return - - for paneInfo in self._panes: - - if not paneInfo.IsDocked() or not paneInfo.IsShown(): - continue - if paneInfo.IsToolbar() or paneInfo.IsNotebookControl(): - continue - if paneInfo.IsMaximized(): - continue - - if paneInfo.IsNotebookPage(): - - notebookRoot = GetNotebookRoot(self._panes, paneInfo.notebook_id) - - if not notebookRoot or not notebookRoot.IsDocked(): - continue - - rc = paneInfo.window.GetScreenRect() - if rc.Contains(screenPt): - if rc.height < 20 or rc.width < 20: - return - - self.UpdateDockingGuides(paneInfo) - ShowDockingGuides(self._guides, True) - break - - self.DrawHintRect(pane.window, clientPt, action_offset) - - - def OnLeftUp_DragFloatingPane(self, eventOrPt): - """ - Sub-handler for the L{OnLeftUp} event. - - :param `event`: a `wx.MouseEvent` to be processed. - """ - - if isinstance(eventOrPt, wx.Point): - clientPt = self._frame.ScreenToClient(eventOrPt) - screenPt = wx.Point(*eventOrPt) - else: - clientPt = eventOrPt.GetPosition() - screenPt = self._frame.ClientToScreen(clientPt) - - # try to find the pane - paneInfo = self.GetPane(self._action_window) - if not paneInfo.IsOk(): - raise Exception("Pane window not found") - - ret = False - - if paneInfo.frame: - - # calculate the offset from the upper left-hand corner - # of the frame to the mouse pointer - framePos = paneInfo.frame.GetPosition() - action_offset = screenPt - framePos - - # is the pane dockable? - if self.CanDockPanel(paneInfo): - # do the drop calculation - indx = self._panes.index(paneInfo) - ret, paneInfo = self.DoDrop(self._docks, self._panes, paneInfo, clientPt, action_offset) - - if ret: - e = self.FireEvent(wxEVT_AUI_PANE_DOCKING, paneInfo, canVeto=True) - if e.GetVeto(): - self.HideHint() - ShowDockingGuides(self._guides, False) - return - - e = self.FireEvent(wxEVT_AUI_PANE_DOCKED, paneInfo, canVeto=False) - - if self._agwFlags & AUI_MGR_SMOOTH_DOCKING: - self.SmoothDock(paneInfo) - - self._panes[indx] = paneInfo - - # if the pane is still floating, update it's floating - # position (that we store) - if paneInfo.IsFloating(): - paneInfo.floating_pos = paneInfo.frame.GetPosition() - if paneInfo.frame._transparent != paneInfo.transparent or self._agwFlags & AUI_MGR_TRANSPARENT_DRAG: - paneInfo.frame.SetTransparent(paneInfo.transparent) - paneInfo.frame._transparent = paneInfo.transparent - - elif self._has_maximized: - self.RestoreMaximizedPane() - - # reorder for dropping to a new notebook - # (caution: this code breaks the reference!) - tempPaneInfo = self.CopyTarget(paneInfo) - self._panes.remove(paneInfo) - self._panes.append(tempPaneInfo) - - if ret: - self.Update() - - self.HideHint() - ShowDockingGuides(self._guides, False) - - - def OnMotion_DragToolbarPane(self, eventOrPt): - """ - Sub-handler for the L{OnMotion} event. - - :param `event`: a `wx.MouseEvent` to be processed. - """ - - isPoint = False - if isinstance(eventOrPt, wx.Point): - clientPt = self._frame.ScreenToClient(eventOrPt) - screenPt = wx.Point(*eventOrPt) - isPoint = True - else: - clientPt = eventOrPt.GetPosition() - screenPt = self._frame.ClientToScreen(clientPt) - - pane = self.GetPane(self._action_window) - if not pane.IsOk(): - raise Exception("Pane window not found") - - pane.state |= AuiPaneInfo.actionPane - indx = self._panes.index(pane) - - ret = False - wasFloating = pane.IsFloating() - # is the pane dockable? - if self.CanDockPanel(pane): - # do the drop calculation - ret, pane = self.DoDrop(self._docks, self._panes, pane, clientPt, self._action_offset) - - # update floating position - if pane.IsFloating(): - pane.floating_pos = screenPt - self._toolbar_action_offset - - # move the pane window - if pane.frame: - if wx.Platform == "__WXMSW__" and (self._agwFlags & AUI_MGR_TRANSPARENT_DRAG) == 0: # and not self.CheckPaneMove(pane): - # return - # HACK: Terrible hack on wxMSW (!) - pane.frame.SetTransparent(254) - - self._from_move = True - pane.frame.Move(pane.floating_pos) - self._from_move = False - - if self._agwFlags & AUI_MGR_TRANSPARENT_DRAG: - pane.frame.SetTransparent(150) - - self._panes[indx] = pane - if ret and wasFloating != pane.IsFloating() or (ret and not wasFloating): - wx.CallAfter(self.Update) - - # when release the button out of the window. - # TODO: a better fix is needed. - - if _VERSION_STRING < "2.9": - leftDown = wx.GetMouseState().LeftDown() - else: - leftDown = wx.GetMouseState().LeftIsDown() - - if not leftDown: - self._action = actionNone - self.OnLeftUp_DragToolbarPane(eventOrPt) - - - def OnMotion_Other(self, event): - """ - Sub-handler for the L{OnMotion} event. - - :param `event`: a `wx.MouseEvent` to be processed. - """ - - part = self.HitTest(*event.GetPosition()) - - if part and part.type == AuiDockUIPart.typePaneButton \ - and self.IsPaneButtonVisible(part): - if part != self._hover_button: - - if self._hover_button: - self.RefreshButton(self._hover_button) - - self._hover_button = part - self.RefreshButton(part) - - else: - - if self._hover_button: - self.RefreshButton(self._hover_button) - else: - event.Skip() - - self._hover_button = None - - - def OnLeftUp_DragToolbarPane(self, eventOrPt): - """ - Sub-handler for the L{OnLeftUp} event. - - :param `event`: a `wx.MouseEvent` to be processed. - """ - - isPoint = False - if isinstance(eventOrPt, wx.Point): - clientPt = self._frame.ScreenToClient(eventOrPt) - screenPt = wx.Point(*eventOrPt) - isPoint = True - else: - clientPt = eventOrPt.GetPosition() - screenPt = self._frame.ClientToScreen(clientPt) - - # try to find the pane - pane = self.GetPane(self._action_window) - if not pane.IsOk(): - raise Exception("Pane window not found") - - if pane.IsFloating(): - pane.floating_pos = pane.frame.GetPosition() - if pane.frame._transparent != pane.transparent or self._agwFlags & AUI_MGR_TRANSPARENT_DRAG: - pane.frame.SetTransparent(pane.transparent) - pane.frame._transparent = pane.transparent - - # save the new positions - docks = FindDocks(self._docks, pane.dock_direction, pane.dock_layer, pane.dock_row) - if len(docks) == 1: - dock = docks[0] - pane_positions, pane_sizes = self.GetPanePositionsAndSizes(dock) - - for i in xrange(len(dock.panes)): - dock.panes[i].dock_pos = pane_positions[i] - - pane.state &= ~AuiPaneInfo.actionPane - self.Update() - - - def OnPaneButton(self, event): - """ - Handles the ``EVT_AUI_PANE_BUTTON`` event for L{AuiManager}. - - :param `event`: a L{AuiManagerEvent} event to be processed. - """ - - if not event.pane: - raise Exception("Pane Info passed to AuiManager.OnPaneButton must be non-null") - - pane = event.pane - - if event.button == AUI_BUTTON_CLOSE: - - if isinstance(pane.window.GetParent(), AuiFloatingFrame): - rootManager = GetManager(pane.window) - else: - rootManager = self - - if rootManager != self: - self._frame.Close() - return - - # fire pane close event - e = AuiManagerEvent(wxEVT_AUI_PANE_CLOSE) - e.SetManager(self) - e.SetPane(event.pane) - self.ProcessMgrEvent(e) - - if not e.GetVeto(): - - # close the pane, but check that it - # still exists in our pane array first - # (the event handler above might have removed it) - - check = self.GetPane(pane.window) - if check.IsOk(): - self.ClosePane(pane) - - self.Update() - - # mn this performs the minimizing of a pane - elif event.button == AUI_BUTTON_MINIMIZE: - e = AuiManagerEvent(wxEVT_AUI_PANE_MINIMIZE) - e.SetManager(self) - e.SetPane(event.pane) - self.ProcessMgrEvent(e) - - if not e.GetVeto(): - self.MinimizePane(pane) - - elif event.button == AUI_BUTTON_MAXIMIZE_RESTORE and not pane.IsMaximized(): - - # fire pane close event - e = AuiManagerEvent(wxEVT_AUI_PANE_MAXIMIZE) - e.SetManager(self) - e.SetPane(event.pane) - self.ProcessMgrEvent(e) - - if not e.GetVeto(): - - self.MaximizePane(pane) - self.Update() - - elif event.button == AUI_BUTTON_MAXIMIZE_RESTORE and pane.IsMaximized(): - - # fire pane close event - e = AuiManagerEvent(wxEVT_AUI_PANE_RESTORE) - e.SetManager(self) - e.SetPane(event.pane) - self.ProcessMgrEvent(e) - - if not e.GetVeto(): - - self.RestorePane(pane) - self.Update() - - elif event.button == AUI_BUTTON_PIN: - - if self._agwFlags & AUI_MGR_ALLOW_FLOATING and pane.IsFloatable(): - e = self.FireEvent(wxEVT_AUI_PANE_FLOATING, pane, canVeto=True) - if e.GetVeto(): - return - - pane.Float() - e = self.FireEvent(wxEVT_AUI_PANE_FLOATED, pane, canVeto=False) - - self.Update() - - - def MinimizePane(self, paneInfo): - """ - Minimizes a pane in a newly and automatically created L{AuiToolBar}. - - Clicking on the minimize button causes a new L{AuiToolBar} to be created - and added to the frame manager (currently the implementation is such that - panes at West will have a toolbar at the right, panes at South will have - toolbars at the bottom etc...) and the pane is hidden in the manager. - - Clicking on the restore button on the newly created toolbar will result in the - toolbar being removed and the original pane being restored. - - :param `paneInfo`: a L{AuiPaneInfo} instance for the pane to be minimized. - """ - - if not paneInfo.IsToolbar(): - - if paneInfo.IsMinimized(): - # We are already minimized - return - - # Basically the idea is this. - # - # 1) create a toolbar, with a restore button - # - # 2) place the new toolbar in the toolbar area representative of the location of the pane - # (NORTH/SOUTH/EAST/WEST, central area always to the right) - # - # 3) Hide the minimizing pane - - - # personalize the toolbar style - tbStyle = AUI_TB_DEFAULT_STYLE - posMask = paneInfo.minimize_mode & AUI_MINIMIZE_POS_MASK - captMask = paneInfo.minimize_mode & AUI_MINIMIZE_CAPT_MASK - dockDirection = paneInfo.dock_direction - if captMask != 0: - tbStyle |= AUI_TB_TEXT - if posMask == AUI_MINIMIZE_POS_SMART: - if paneInfo.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]: - tbStyle |= AUI_TB_HORZ_LAYOUT - - elif paneInfo.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT, AUI_DOCK_CENTER]: - tbStyle |= AUI_TB_VERTICAL - if captMask == AUI_MINIMIZE_CAPT_SMART: - tbStyle |= AUI_TB_CLOCKWISE - - elif posMask in [AUI_MINIMIZE_POS_TOP, AUI_MINIMIZE_POS_BOTTOM]: - tbStyle |= AUI_TB_HORZ_LAYOUT - if posMask == AUI_MINIMIZE_POS_TOP: - dockDirection = AUI_DOCK_TOP - else: - dockDirection = AUI_DOCK_BOTTOM - - else: - tbStyle |= AUI_TB_VERTICAL - if captMask == AUI_MINIMIZE_CAPT_SMART: - tbStyle |= AUI_TB_CLOCKWISE - if posMask == AUI_MINIMIZE_POS_LEFT: - dockDirection = AUI_DOCK_LEFT - elif posMask == AUI_MINIMIZE_POS_RIGHT: - dockDirection = AUI_DOCK_RIGHT - elif posMask == AUI_MINIMIZE_POS_BOTTOM: - dockDirection = AUI_DOCK_BOTTOM - - # Create a new toolbar - # give it the same name as the minimized pane with _min appended - - win_rect = paneInfo.window.GetScreenRect() - - minimize_toolbar = auibar.AuiToolBar(self.GetManagedWindow(), agwStyle=tbStyle) - minimize_toolbar.Hide() - minimize_toolbar.SetToolBitmapSize(wx.Size(16, 16)) - - if paneInfo.icon and paneInfo.icon.IsOk(): - restore_bitmap = paneInfo.icon - else: - restore_bitmap = self._art._restore_bitmap - - minimize_toolbar.AddSimpleTool(ID_RESTORE_FRAME, paneInfo.caption, restore_bitmap, "Restore " + paneInfo.caption) - minimize_toolbar.SetAuiManager(self) - minimize_toolbar.Realize() - toolpanelname = paneInfo.name + "_min" - - if paneInfo.IsMaximized(): - paneInfo.SetFlag(paneInfo.wasMaximized, True) - - if dockDirection == AUI_DOCK_TOP: - self.AddPane(minimize_toolbar, AuiPaneInfo(). \ - Name(toolpanelname).Caption(paneInfo.caption). \ - ToolbarPane().Top().BottomDockable(False). \ - LeftDockable(False).RightDockable(False).DestroyOnClose()) - - elif dockDirection == AUI_DOCK_BOTTOM: - self.AddPane(minimize_toolbar, AuiPaneInfo(). \ - Name(toolpanelname).Caption(paneInfo.caption). \ - ToolbarPane().Bottom().TopDockable(False). \ - LeftDockable(False).RightDockable(False).DestroyOnClose()) - - elif dockDirection == AUI_DOCK_LEFT: - self.AddPane(minimize_toolbar, AuiPaneInfo(). \ - Name(toolpanelname).Caption(paneInfo.caption). \ - ToolbarPane().Left().TopDockable(False). \ - BottomDockable(False).RightDockable(False).DestroyOnClose()) - - elif dockDirection in [AUI_DOCK_RIGHT, AUI_DOCK_CENTER]: - self.AddPane(minimize_toolbar, AuiPaneInfo(). \ - Name(toolpanelname).Caption(paneInfo.caption). \ - ToolbarPane().Right().TopDockable(False). \ - LeftDockable(False).BottomDockable(False).DestroyOnClose()) - - arr = FindDocks(self._docks, paneInfo.dock_direction, paneInfo.dock_layer, paneInfo.dock_row) - - if arr: - dock = arr[0] - paneInfo.previousDockSize = dock.size - - paneInfo.previousDockPos = paneInfo.dock_pos - - # mark ourselves minimized - paneInfo.Minimize() - paneInfo.Show(False) - self._has_minimized = True - # last, hide the window - if paneInfo.window and paneInfo.window.IsShown(): - paneInfo.window.Show(False) - - minimize_toolbar.Show() - self.Update() - if self._agwFlags & AUI_MGR_ANIMATE_FRAMES: - self.AnimateDocking(win_rect, minimize_toolbar.GetScreenRect()) - - - def OnRestoreMinimizedPane(self, event): - """ - Handles the ``EVT_AUI_PANE_MIN_RESTORE`` event for L{AuiManager}. - - :param `event`: an instance of L{AuiManagerEvent} to be processed. - """ - - self.RestoreMinimizedPane(event.pane) - - - def OnPaneDocked(self, event): - """ - Handles the ``EVT_AUI_PANE_DOCKED`` event for L{AuiManager}. - - :param `event`: an instance of L{AuiManagerEvent} to be processed. - """ - - event.Skip() - self.RemoveAutoNBCaption(event.GetPane()) - - - def CreateNotebookBase(self, panes, paneInfo): - """ - Creates an auto-notebook base from a pane, and then add that pane as a page. - - :param `panes`: Set of panes to append new notebook base pane to - :param `paneInfo`: L{AuiPaneInfo} instance to convert to new notebook. - """ - - # Create base notebook pane ... - nbid = len(self._notebooks) - - baseInfo = AuiPaneInfo() - baseInfo.SetDockPos(paneInfo).NotebookControl(nbid). \ - CloseButton(False).SetNameFromNotebookId(). \ - NotebookDockable(False).Floatable(paneInfo.IsFloatable()) - baseInfo.best_size = paneInfo.best_size - panes.append(baseInfo) - - # add original pane as tab ... - paneInfo.NotebookPage(nbid) - - def RemoveAutoNBCaption(self, pane): - """ - Removes the caption on newly created automatic notebooks. - - :param `pane`: an instance of L{AuiPaneInfo} (the target notebook). - """ - - if self._agwFlags & AUI_MGR_AUTONB_NO_CAPTION == 0: - return False - - def RemoveCaption(): - """ Sub-function used to remove the pane caption on automatic notebooks. """ - - if pane.HasNotebook(): - notebook = self._notebooks[pane.notebook_id] - self.GetPane(notebook).CaptionVisible(False).PaneBorder(False) - self.Update() - - # it seems the notebook isnt created by this stage, so remove - # the caption a moment later - wx.CallAfter(RemoveCaption) - return True - - - def RestoreMinimizedPane(self, paneInfo): - """ - Restores a previously minimized pane. - - :param `paneInfo`: a L{AuiPaneInfo} instance for the pane to be restored. - """ - - panename = paneInfo.name - panename = panename[0:-4] - pane = self.GetPane(panename) - - pane.SetFlag(pane.needsRestore, True) - - if not pane.IsOk(): - panename = paneInfo.name - pane = self.GetPane(panename) - paneInfo = self.GetPane(panename + "_min") - if not paneInfo.IsOk(): - # Already minimized - return - - if pane.IsOk(): - if not pane.IsMinimized(): - return - - - if pane.HasFlag(pane.wasMaximized): - - self.SavePreviousDockSizes(pane) - - - self.ShowPane(pane.window, True) - pane.Show(True) - self._has_minimized = False - pane.SetFlag(pane.optionMinimized, False) - paneInfo.window.Show(False) - self.DetachPane(paneInfo.window) - paneInfo.Show(False) - paneInfo.Hide() - - self.Update() - - - def AnimateDocking(self, win_rect, pane_rect): - """ - Animates the minimization/docking of a pane a la Eclipse, using a `wx.ScreenDC` - to draw a "moving docking rectangle" on the screen. - - :param `win_rect`: the original pane screen rectangle; - :param `pane_rect`: the newly created toolbar/pane screen rectangle. - - :note: This functionality is not available on wxMAC as this platform doesn't have - the ability to use `wx.ScreenDC` to draw on-screen and on Windows > Vista. - """ - - if wx.Platform == "__WXMAC__": - # No wx.ScreenDC on the Mac... - return - if wx.Platform == "__WXMSW__" and wx.GetOsVersion()[1] > 5: - # No easy way to handle this on Vista... - return - - xstart, ystart = win_rect.x, win_rect.y - xend, yend = pane_rect.x, pane_rect.y - - step = self.GetAnimationStep() - - wstep = int(abs(win_rect.width - pane_rect.width)/step) - hstep = int(abs(win_rect.height - pane_rect.height)/step) - xstep = int(win_rect.x - pane_rect.x)/step - ystep = int(win_rect.y - pane_rect.y)/step - - dc = wx.ScreenDC() - dc.SetLogicalFunction(wx.INVERT) - dc.SetBrush(wx.TRANSPARENT_BRUSH) - dc.SetPen(wx.LIGHT_GREY_PEN) - - for i in xrange(int(step)): - width, height = win_rect.width - i*wstep, win_rect.height - i*hstep - x, y = xstart - i*xstep, ystart - i*ystep - new_rect = wx.Rect(x, y, width, height) - dc.DrawRoundedRectangleRect(new_rect, 3) - wx.SafeYield() - wx.MilliSleep(10) - dc.DrawRoundedRectangleRect(new_rect, 3) - - - def SmoothDock(self, paneInfo): - """ - This method implements a smooth docking effect for floating panes, similar to - what the PyQT library does with its floating windows. - - :param `paneInfo`: an instance of L{AuiPaneInfo}. - - :note: The smooth docking effect can only be used if you set the ``AUI_MGR_SMOOTH_DOCKING`` - style to L{AuiManager}. - """ - - if paneInfo.IsToolbar(): - return - - if not paneInfo.frame or self._hint_rect.IsEmpty(): - return - - hint_rect = self._hint_rect - win_rect = paneInfo.frame.GetScreenRect() - - xstart, ystart = win_rect.x, win_rect.y - xend, yend = hint_rect.x, hint_rect.y - - step = self.GetAnimationStep()/3 - - wstep = int((win_rect.width - hint_rect.width)/step) - hstep = int((win_rect.height - hint_rect.height)/step) - xstep = int((win_rect.x - hint_rect.x))/step - ystep = int((win_rect.y - hint_rect.y))/step - - for i in xrange(int(step)): - width, height = win_rect.width - i*wstep, win_rect.height - i*hstep - x, y = xstart - i*xstep, ystart - i*ystep - new_rect = wx.Rect(x, y, width, height) - paneInfo.frame.SetRect(new_rect) - wx.MilliSleep(10) - - - def SetSnapLimits(self, x, y): - """ - Modifies the snap limits used when snapping the `managed_window` to the screen - (using L{SnapToScreen}) or when snapping the floating panes to one side of the - `managed_window` (using L{SnapPane}). - - To change the limit after which the `managed_window` or the floating panes are - automatically stickled to the screen border (or to the `managed_window` side), - set these two variables. Default values are 15 pixels. - - :param `x`: the minimum horizontal distance below which the snap occurs; - :param `y`: the minimum vertical distance below which the snap occurs. - """ - - self._snap_limits = (x, y) - self.Snap() - - - def Snap(self): - """ - Snaps the main frame to specified position on the screen. - - :see: L{SnapToScreen} - """ - - snap, hAlign, vAlign, monitor = self._is_docked - if not snap: - return - - managed_window = self.GetManagedWindow() - snap_pos = self.GetSnapPosition() - wnd_pos = managed_window.GetPosition() - snapX, snapY = self._snap_limits - - if abs(snap_pos.x - wnd_pos.x) < snapX and abs(snap_pos.y - wnd_pos.y) < snapY: - managed_window.SetPosition(snap_pos) - - - def SnapToScreen(self, snap=True, monitor=0, hAlign=wx.RIGHT, vAlign=wx.TOP): - """ - Snaps the main frame to specified position on the screen. - - :param `snap`: whether to snap the main frame or not; - :param `monitor`: the monitor display in which snapping the window; - :param `hAlign`: the horizontal alignment of the snapping position; - :param `vAlign`: the vertical alignment of the snapping position. - """ - - if not snap: - self._is_docked = (False, wx.RIGHT, wx.TOP, 0) - return - - displayCount = wx.Display.GetCount() - if monitor > displayCount: - raise Exception("Invalid monitor selected: you only have %d monitors"%displayCount) - - self._is_docked = (True, hAlign, vAlign, monitor) - self.GetManagedWindow().SetPosition(self.GetSnapPosition()) - - - def GetSnapPosition(self): - """ Returns the main frame snapping position. """ - - snap, hAlign, vAlign, monitor = self._is_docked - - display = wx.Display(monitor) - area = display.GetClientArea() - size = self.GetManagedWindow().GetSize() - - pos = wx.Point() - if hAlign == wx.LEFT: - pos.x = area.x - elif hAlign == wx.CENTER: - pos.x = area.x + (area.width - size.x)/2 - else: - pos.x = area.x + area.width - size.x - - if vAlign == wx.TOP: - pos.y = area.y - elif vAlign == wx.CENTER: - pos.y = area.y + (area.height - size.y)/2 - else: - pos.y = area.y + area.height - size.y - - return pos - - - def GetAnimationStep(self): - """ Returns the animation step speed (a float) to use in L{AnimateDocking}. """ - - return self._animation_step - - - def SetAnimationStep(self, step): - """ - Sets the animation step speed (a float) to use in L{AnimateDocking}. - - :param `step`: a floating point value for the animation speed. - """ - - self._animation_step = float(step) - - - def RequestUserAttention(self, pane_window): - """ - Requests the user attention by intermittently highlighting the pane caption. - - :param `pane_window`: a `wx.Window` derived window, managed by the pane. - """ - - # try to find the pane - paneInfo = self.GetPane(pane_window) - if not paneInfo.IsOk(): - raise Exception("Pane window not found") - - dc = wx.ClientDC(self._frame) - - # if the frame is about to be deleted, don't bother - if not self._frame or self._frame.IsBeingDeleted(): - return - - if not self._frame.GetSizer(): - return - - for part in self._uiparts: - if part.pane == paneInfo: - self._art.RequestUserAttention(dc, self._frame, part.pane.caption, part.rect, part.pane) - self._frame.RefreshRect(part.rect, True) - break - - - def StartPreviewTimer(self, toolbar): - """ - Starts a timer for sliding in and out a minimized pane. - - :param `toolbar`: the L{AuiToolBar} containing the minimized pane tool. - """ - - toolbar_pane = self.GetPane(toolbar) - toolbar_name = toolbar_pane.name - - pane_name = toolbar_name[0:-4] - - self._sliding_pane = self.GetPane(pane_name) - self._sliding_rect = toolbar.GetScreenRect() - self._sliding_direction = toolbar_pane.dock_direction - self._sliding_frame = None - - self._preview_timer.Start(1000, wx.TIMER_ONE_SHOT) - - - def StopPreviewTimer(self): - """ Stops a timer for sliding in and out a minimized pane. """ - - if self._preview_timer.IsRunning(): - self._preview_timer.Stop() - - self.SlideOut() - self._sliding_pane = None - - - def SlideIn(self, event): - """ - Handles the ``wx.EVT_TIMER`` event for L{AuiManager}. - - :param `event`: a `wx.TimerEvent` to be processed. - - :note: This is used solely for sliding in and out minimized panes. - """ - - window = self._sliding_pane.window - self._sliding_frame = wx.MiniFrame(None, -1, title=_("Pane Preview"), - style=wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP | - wx.FRAME_NO_TASKBAR | wx.CAPTION) - window.Reparent(self._sliding_frame) - self._sliding_frame.SetSize((0, 0)) - window.Show() - self._sliding_frame.Show() - - size = window.GetBestSize() - - startX, startY, stopX, stopY = GetSlidingPoints(self._sliding_rect, size, self._sliding_direction) - - step = stopX/10 - window_size = 0 - - for i in xrange(0, stopX, step): - window_size = i - self._sliding_frame.SetDimensions(startX, startY, window_size, stopY) - self._sliding_frame.Refresh() - self._sliding_frame.Update() - wx.MilliSleep(10) - - self._sliding_frame.SetDimensions(startX, startY, stopX, stopY) - self._sliding_frame.Refresh() - self._sliding_frame.Update() - - - def SlideOut(self): - """ - Slides out a preview of a minimized pane. - - :note: This is used solely for sliding in and out minimized panes. - """ - - if not self._sliding_frame: - return - - window = self._sliding_frame.GetChildren()[0] - size = window.GetBestSize() - - startX, startY, stopX, stopY = GetSlidingPoints(self._sliding_rect, size, self._sliding_direction) - - step = stopX/10 - window_size = 0 - - for i in xrange(stopX, 0, -step): - window_size = i - self._sliding_frame.SetDimensions(startX, startY, window_size, stopY) - self._sliding_frame.Refresh() - self._sliding_frame.Update() - self._frame.RefreshRect(wx.Rect(startX+window_size, startY, step, stopY)) - self._frame.Update() - wx.MilliSleep(10) - - self._sliding_frame.SetDimensions(startX, startY, 0, stopY) - - window.Hide() - window.Reparent(self._frame) - - self._sliding_frame.Hide() - self._sliding_frame.Destroy() - self._sliding_frame = None - self._sliding_pane = None - - -class AuiManager_DCP(AuiManager): - """ - A class similar to L{AuiManager} but with a Dummy Center Pane (**DCP**). - The code for this class is still flickery due to the call to `wx.CallAfter` - and the double-update call. - """ - - def __init__(self, *args, **keys): - - AuiManager.__init__(self, *args, **keys) - self.hasDummyPane = False - - - def _createDummyPane(self): - """ Creates a Dummy Center Pane (**DCP**). """ - - if self.hasDummyPane: - return - - self.hasDummyPane = True - dummy = wx.Panel(self.GetManagedWindow()) - info = AuiPaneInfo().CenterPane().NotebookDockable(True).Name('dummyCenterPane').DestroyOnClose(True) - self.AddPane(dummy, info) - - - def _destroyDummyPane(self): - """ Destroys the Dummy Center Pane (**DCP**). """ - - if not self.hasDummyPane: - return - - self.hasDummyPane = False - self.ClosePane(self.GetPane('dummyCenterPane')) - - - def Update(self): - """ - This method is called after any number of changes are made to any of the - managed panes. L{Update} must be invoked after L{AuiManager.AddPane} or L{AuiManager.InsertPane} are - called in order to "realize" or "commit" the changes. - - In addition, any number of changes may be made to L{AuiPaneInfo} structures - (retrieved with L{AuiManager.GetPane}), but to realize the changes, L{Update} - must be called. This construction allows pane flicker to be avoided by updating - the whole layout at one time. - """ - - AuiManager.Update(self) - - # check if there's already a center pane (except our dummy pane) - dummyCenterPane = self.GetPane('dummyCenterPane') - haveCenterPane = any((pane != dummyCenterPane) and (pane.dock_direction == AUI_DOCK_CENTER) and - not pane.IsFloating() and pane.IsShown() for pane in self.GetAllPanes()) - if haveCenterPane: - if self.hasDummyPane: - # there's our dummy pane and also another center pane, therefor let's remove our dummy - def do(): - self._destroyDummyPane() - self.Update() - wx.CallAfter(do) - else: - # if we get here, there's no center pane, create our dummy - if not self.hasDummyPane: - self._createDummyPane() - - diff --git a/agw/aui/tabart.py b/agw/aui/tabart.py deleted file mode 100644 index 60b8e01..0000000 --- a/agw/aui/tabart.py +++ /dev/null @@ -1,2777 +0,0 @@ -""" -Tab art provider code - a tab provider provides all drawing functionality to -the L{AuiNotebook}. This allows the L{AuiNotebook} to have a plugable look-and-feel. - -By default, a L{AuiNotebook} uses an instance of this class called L{AuiDefaultTabArt} -which provides bitmap art and a colour scheme that is adapted to the major platforms' -look. You can either derive from that class to alter its behaviour or write a -completely new tab art class. Call L{AuiNotebook.SetArtProvider} to make use this -new tab art. -""" - -__author__ = "Andrea Gavana " -__date__ = "31 March 2009" - - -import wx - -if wx.Platform == '__WXMAC__': - import Carbon.Appearance - -from aui_utilities import BitmapFromBits, StepColour, IndentPressedBitmap, ChopText -from aui_utilities import GetBaseColour, DrawMACCloseButton, LightColour, TakeScreenShot -from aui_utilities import CopyAttributes - -from aui_constants import * - - -# -- GUI helper classes and functions -- -class AuiCommandCapture(wx.PyEvtHandler): - """ A class to handle the dropdown window menu. """ - - def __init__(self): - """ Default class constructor. """ - - wx.PyEvtHandler.__init__(self) - self._last_id = 0 - - - def GetCommandId(self): - """ Returns the event command identifier. """ - - return self._last_id - - - def ProcessEvent(self, event): - """ - Processes an event, searching event tables and calling zero or more suitable - event handler function(s). - - :param `event`: the event to process. - - :note: Normally, your application would not call this function: it is called - in the wxPython implementation to dispatch incoming user interface events - to the framework (and application). - However, you might need to call it if implementing new functionality (such as - a new control) where you define new event types, as opposed to allowing the - user to override functions. - - An instance where you might actually override the L{ProcessEvent} function is where - you want to direct event processing to event handlers not normally noticed by - wxPython. For example, in the document/view architecture, documents and views - are potential event handlers. When an event reaches a frame, L{ProcessEvent} will - need to be called on the associated document and view in case event handler - functions are associated with these objects. - - The normal order of event table searching is as follows: - - 1. If the object is disabled (via a call to `SetEvtHandlerEnabled`) the function - skips to step (6). - 2. If the object is a `wx.Window`, L{ProcessEvent} is recursively called on the window's - `wx.Validator`. If this returns ``True``, the function exits. - 3. wxWidgets `SearchEventTable` is called for this event handler. If this fails, the - base class table is tried, and so on until no more tables exist or an appropriate - function was found, in which case the function exits. - 4. The search is applied down the entire chain of event handlers (usually the chain - has a length of one). If this succeeds, the function exits. - 5. If the object is a `wx.Window` and the event is a `wx.CommandEvent`, L{ProcessEvent} is - recursively applied to the parent window's event handler. If this returns ``True``, - the function exits. - 6. Finally, L{ProcessEvent} is called on the `wx.App` object. - """ - - if event.GetEventType() == wx.wxEVT_COMMAND_MENU_SELECTED: - self._last_id = event.GetId() - return True - - if self.GetNextHandler(): - return self.GetNextHandler().ProcessEvent(event) - - return False - - -class AuiDefaultTabArt(object): - """ - Tab art provider code - a tab provider provides all drawing functionality to - the L{AuiNotebook}. This allows the L{AuiNotebook} to have a plugable look-and-feel. - - By default, a L{AuiNotebook} uses an instance of this class called L{AuiDefaultTabArt} - which provides bitmap art and a colour scheme that is adapted to the major platforms' - look. You can either derive from that class to alter its behaviour or write a - completely new tab art class. Call L{AuiNotebook.SetArtProvider} to make use this - new tab art. - """ - - def __init__(self): - """ Default class constructor. """ - - self._normal_font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) - self._selected_font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) - self._selected_font.SetWeight(wx.BOLD) - self._measuring_font = self._selected_font - - self._fixed_tab_width = 100 - self._tab_ctrl_height = 0 - self._buttonRect = wx.Rect() - - self.SetDefaultColours() - - if wx.Platform == "__WXMAC__": - bmp_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DDKSHADOW) - self._active_close_bmp = DrawMACCloseButton(bmp_colour) - self._disabled_close_bmp = DrawMACCloseButton(wx.Colour(128, 128, 128)) - else: - self._active_close_bmp = BitmapFromBits(nb_close_bits, 16, 16, wx.BLACK) - self._disabled_close_bmp = BitmapFromBits(nb_close_bits, 16, 16, wx.Colour(128, 128, 128)) - - self._hover_close_bmp = self._active_close_bmp - self._pressed_close_bmp = self._active_close_bmp - - self._active_left_bmp = BitmapFromBits(nb_left_bits, 16, 16, wx.BLACK) - self._disabled_left_bmp = BitmapFromBits(nb_left_bits, 16, 16, wx.Colour(128, 128, 128)) - - self._active_right_bmp = BitmapFromBits(nb_right_bits, 16, 16, wx.BLACK) - self._disabled_right_bmp = BitmapFromBits(nb_right_bits, 16, 16, wx.Colour(128, 128, 128)) - - self._active_windowlist_bmp = BitmapFromBits(nb_list_bits, 16, 16, wx.BLACK) - self._disabled_windowlist_bmp = BitmapFromBits(nb_list_bits, 16, 16, wx.Colour(128, 128, 128)) - - if wx.Platform == "__WXMAC__": - # Get proper highlight colour for focus rectangle from the - # current Mac theme. kThemeBrushFocusHighlight is - # available on Mac OS 8.5 and higher - if hasattr(wx, 'MacThemeColour'): - c = wx.MacThemeColour(Carbon.Appearance.kThemeBrushFocusHighlight) - else: - brush = wx.Brush(wx.BLACK) - brush.MacSetTheme(Carbon.Appearance.kThemeBrushFocusHighlight) - c = brush.GetColour() - self._focusPen = wx.Pen(c, 2, wx.SOLID) - else: - self._focusPen = wx.Pen(wx.BLACK, 1, wx.USER_DASH) - self._focusPen.SetDashes([1, 1]) - self._focusPen.SetCap(wx.CAP_BUTT) - - - def SetBaseColour(self, base_colour): - """ - Sets a new base colour. - - :param `base_colour`: an instance of `wx.Colour`. - """ - - self._base_colour = base_colour - self._base_colour_pen = wx.Pen(self._base_colour) - self._base_colour_brush = wx.Brush(self._base_colour) - - - def SetDefaultColours(self, base_colour=None): - """ - Sets the default colours, which are calculated from the given base colour. - - :param `base_colour`: an instance of `wx.Colour`. If defaulted to ``None``, a colour - is generated accordingly to the platform and theme. - """ - - if base_colour is None: - base_colour = GetBaseColour() - - self.SetBaseColour( base_colour ) - self._border_colour = StepColour(base_colour, 75) - self._border_pen = wx.Pen(self._border_colour) - - self._background_top_colour = StepColour(self._base_colour, 90) - self._background_bottom_colour = StepColour(self._base_colour, 170) - - self._tab_top_colour = self._base_colour - self._tab_bottom_colour = wx.WHITE - self._tab_gradient_highlight_colour = wx.WHITE - - self._tab_inactive_top_colour = self._base_colour - self._tab_inactive_bottom_colour = StepColour(self._tab_inactive_top_colour, 160) - - self._tab_text_colour = lambda page: page.text_colour - self._tab_disabled_text_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT) - - - def Clone(self): - """ Clones the art object. """ - - art = type(self)() - art.SetNormalFont(self.GetNormalFont()) - art.SetSelectedFont(self.GetSelectedFont()) - art.SetMeasuringFont(self.GetMeasuringFont()) - - art = CopyAttributes(art, self) - return art - - - def SetAGWFlags(self, agwFlags): - """ - Sets the tab art flags. - - :param `agwFlags`: a combination of the following values: - - ==================================== ================================== - Flag name Description - ==================================== ================================== - ``AUI_NB_TOP`` With this style, tabs are drawn along the top of the notebook - ``AUI_NB_LEFT`` With this style, tabs are drawn along the left of the notebook. Not implemented yet. - ``AUI_NB_RIGHT`` With this style, tabs are drawn along the right of the notebook. Not implemented yet. - ``AUI_NB_BOTTOM`` With this style, tabs are drawn along the bottom of the notebook - ``AUI_NB_TAB_SPLIT`` Allows the tab control to be split by dragging a tab - ``AUI_NB_TAB_MOVE`` Allows a tab to be moved horizontally by dragging - ``AUI_NB_TAB_EXTERNAL_MOVE`` Allows a tab to be moved to another tab control - ``AUI_NB_TAB_FIXED_WIDTH`` With this style, all tabs have the same width - ``AUI_NB_SCROLL_BUTTONS`` With this style, left and right scroll buttons are displayed - ``AUI_NB_WINDOWLIST_BUTTON`` With this style, a drop-down list of windows is available - ``AUI_NB_CLOSE_BUTTON`` With this style, a close button is available on the tab bar - ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` With this style, a close button is available on the active tab - ``AUI_NB_CLOSE_ON_ALL_TABS`` With this style, a close button is available on all tabs - ``AUI_NB_MIDDLE_CLICK_CLOSE`` Allows to close L{AuiNotebook} tabs by mouse middle button click - ``AUI_NB_SUB_NOTEBOOK`` This style is used by L{AuiManager} to create automatic AuiNotebooks - ``AUI_NB_HIDE_ON_SINGLE_TAB`` Hides the tab window if only one tab is present - ``AUI_NB_SMART_TABS`` Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows - ``AUI_NB_USE_IMAGES_DROPDOWN`` Uses images on dropdown window list menu instead of check items - ``AUI_NB_CLOSE_ON_TAB_LEFT`` Draws the tab close button on the left instead of on the right (a la Camino browser) - ``AUI_NB_TAB_FLOAT`` Allows the floating of single tabs. Known limitation: when the notebook is more or less full screen, tabs cannot be dragged far enough outside of the notebook to become floating pages - ``AUI_NB_DRAW_DND_TAB`` Draws an image representation of a tab while dragging (on by default) - ``AUI_NB_ORDER_BY_ACCESS`` Tab navigation order by last access time for the tabs - ``AUI_NB_NO_TAB_FOCUS`` Don't draw tab focus rectangle - ==================================== ================================== - - """ - - self._agwFlags = agwFlags - - - def GetAGWFlags(self): - """ - Returns the tab art flags. - - :see: L{SetAGWFlags} for a list of possible return values. - """ - - return self._agwFlags - - - def SetSizingInfo(self, tab_ctrl_size, tab_count, minMaxTabWidth): - """ - Sets the tab sizing information. - - :param `tab_ctrl_size`: the size of the tab control area; - :param `tab_count`: the number of tabs; - :param `minMaxTabWidth`: a tuple containing the minimum and maximum tab widths - to be used when the ``AUI_NB_TAB_FIXED_WIDTH`` style is active. - """ - - self._fixed_tab_width = 100 - minTabWidth, maxTabWidth = minMaxTabWidth - - tot_width = tab_ctrl_size.x - self.GetIndentSize() - 4 - agwFlags = self.GetAGWFlags() - - if agwFlags & AUI_NB_CLOSE_BUTTON: - tot_width -= self._active_close_bmp.GetWidth() - if agwFlags & AUI_NB_WINDOWLIST_BUTTON: - tot_width -= self._active_windowlist_bmp.GetWidth() - - if tab_count > 0: - self._fixed_tab_width = tot_width/tab_count - - if self._fixed_tab_width < 100: - self._fixed_tab_width = 100 - - if self._fixed_tab_width > tot_width/2: - self._fixed_tab_width = tot_width/2 - - if self._fixed_tab_width > 220: - self._fixed_tab_width = 220 - - if minTabWidth > -1: - self._fixed_tab_width = max(self._fixed_tab_width, minTabWidth) - if maxTabWidth > -1: - self._fixed_tab_width = min(self._fixed_tab_width, maxTabWidth) - - self._tab_ctrl_height = tab_ctrl_size.y - - - def DrawBackground(self, dc, wnd, rect): - """ - Draws the tab area background. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` instance object; - :param `rect`: the tab control rectangle. - """ - - self._buttonRect = wx.Rect() - - # draw background - agwFlags = self.GetAGWFlags() - if agwFlags & AUI_NB_BOTTOM: - r = wx.Rect(rect.x, rect.y, rect.width+2, rect.height) - - # TODO: else if (agwFlags & AUI_NB_LEFT) - # TODO: else if (agwFlags & AUI_NB_RIGHT) - else: #for AUI_NB_TOP - r = wx.Rect(rect.x, rect.y, rect.width+2, rect.height-3) - - dc.GradientFillLinear(r, self._background_top_colour, self._background_bottom_colour, wx.SOUTH) - - # draw base lines - - dc.SetPen(self._border_pen) - y = rect.GetHeight() - w = rect.GetWidth() - - if agwFlags & AUI_NB_BOTTOM: - dc.SetBrush(wx.Brush(self._background_bottom_colour)) - dc.DrawRectangle(-1, 0, w+2, 4) - - # TODO: else if (agwFlags & AUI_NB_LEFT) - # TODO: else if (agwFlags & AUI_NB_RIGHT) - - else: # for AUI_NB_TOP - dc.SetBrush(self._base_colour_brush) - dc.DrawRectangle(-1, y-4, w+2, 4) - - - def DrawTab(self, dc, wnd, page, in_rect, close_button_state, paint_control=False): - """ - Draws a single tab. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` instance object; - :param `page`: the tab control page associated with the tab; - :param `in_rect`: rectangle the tab should be confined to; - :param `close_button_state`: the state of the close button on the tab; - :param `paint_control`: whether to draw the control inside a tab (if any) on a `wx.MemoryDC`. - """ - - # if the caption is empty, measure some temporary text - caption = page.caption - if not caption: - caption = "Xj" - - dc.SetFont(self._selected_font) - selected_textx, selected_texty, dummy = dc.GetMultiLineTextExtent(caption) - - dc.SetFont(self._normal_font) - normal_textx, normal_texty, dummy = dc.GetMultiLineTextExtent(caption) - - control = page.control - - # figure out the size of the tab - tab_size, x_extent = self.GetTabSize(dc, wnd, page.caption, page.bitmap, - page.active, close_button_state, control) - - tab_height = self._tab_ctrl_height - 3 - tab_width = tab_size[0] - tab_x = in_rect.x - tab_y = in_rect.y + in_rect.height - tab_height - - caption = page.caption - - # select pen, brush and font for the tab to be drawn - - if page.active: - - dc.SetFont(self._selected_font) - textx, texty = selected_textx, selected_texty - - else: - - dc.SetFont(self._normal_font) - textx, texty = normal_textx, normal_texty - - if not page.enabled: - dc.SetTextForeground(self._tab_disabled_text_colour) - pagebitmap = page.dis_bitmap - else: - dc.SetTextForeground(self._tab_text_colour(page)) - pagebitmap = page.bitmap - - # create points that will make the tab outline - - clip_width = tab_width - if tab_x + clip_width > in_rect.x + in_rect.width: - clip_width = in_rect.x + in_rect.width - tab_x - - # since the above code above doesn't play well with WXDFB or WXCOCOA, - # we'll just use a rectangle for the clipping region for now -- - dc.SetClippingRegion(tab_x, tab_y, clip_width+1, tab_height-3) - - border_points = [wx.Point() for i in xrange(6)] - agwFlags = self.GetAGWFlags() - - if agwFlags & AUI_NB_BOTTOM: - - border_points[0] = wx.Point(tab_x, tab_y) - border_points[1] = wx.Point(tab_x, tab_y+tab_height-6) - border_points[2] = wx.Point(tab_x+2, tab_y+tab_height-4) - border_points[3] = wx.Point(tab_x+tab_width-2, tab_y+tab_height-4) - border_points[4] = wx.Point(tab_x+tab_width, tab_y+tab_height-6) - border_points[5] = wx.Point(tab_x+tab_width, tab_y) - - else: #if (agwFlags & AUI_NB_TOP) - - border_points[0] = wx.Point(tab_x, tab_y+tab_height-4) - border_points[1] = wx.Point(tab_x, tab_y+2) - border_points[2] = wx.Point(tab_x+2, tab_y) - border_points[3] = wx.Point(tab_x+tab_width-2, tab_y) - border_points[4] = wx.Point(tab_x+tab_width, tab_y+2) - border_points[5] = wx.Point(tab_x+tab_width, tab_y+tab_height-4) - - # TODO: else if (agwFlags & AUI_NB_LEFT) - # TODO: else if (agwFlags & AUI_NB_RIGHT) - - drawn_tab_yoff = border_points[1].y - drawn_tab_height = border_points[0].y - border_points[1].y - - if page.active: - - # draw active tab - - # draw base background colour - r = wx.Rect(tab_x, tab_y, tab_width, tab_height) - dc.SetPen(self._base_colour_pen) - dc.SetBrush(self._base_colour_brush) - dc.DrawRectangle(r.x+1, r.y+1, r.width-1, r.height-4) - - # this white helps fill out the gradient at the top of the tab - dc.SetPen( wx.Pen(self._tab_gradient_highlight_colour) ) - dc.SetBrush( wx.Brush(self._tab_gradient_highlight_colour) ) - dc.DrawRectangle(r.x+2, r.y+1, r.width-3, r.height-4) - - # these two points help the rounded corners appear more antialiased - dc.SetPen(self._base_colour_pen) - dc.DrawPoint(r.x+2, r.y+1) - dc.DrawPoint(r.x+r.width-2, r.y+1) - - # set rectangle down a bit for gradient drawing - r.SetHeight(r.GetHeight()/2) - r.x += 2 - r.width -= 2 - r.y += r.height - r.y -= 2 - - # draw gradient background - top_colour = self._tab_bottom_colour - bottom_colour = self._tab_top_colour - dc.GradientFillLinear(r, bottom_colour, top_colour, wx.NORTH) - - else: - - # draw inactive tab - - r = wx.Rect(tab_x, tab_y+1, tab_width, tab_height-3) - - # start the gradent up a bit and leave the inside border inset - # by a pixel for a 3D look. Only the top half of the inactive - # tab will have a slight gradient - r.x += 3 - r.y += 1 - r.width -= 4 - r.height /= 2 - r.height -= 1 - - # -- draw top gradient fill for glossy look - top_colour = self._tab_inactive_top_colour - bottom_colour = self._tab_inactive_bottom_colour - dc.GradientFillLinear(r, bottom_colour, top_colour, wx.NORTH) - - r.y += r.height - r.y -= 1 - - # -- draw bottom fill for glossy look - top_colour = self._tab_inactive_bottom_colour - bottom_colour = self._tab_inactive_bottom_colour - dc.GradientFillLinear(r, top_colour, bottom_colour, wx.SOUTH) - - # draw tab outline - dc.SetPen(self._border_pen) - dc.SetBrush(wx.TRANSPARENT_BRUSH) - dc.DrawPolygon(border_points) - - # there are two horizontal grey lines at the bottom of the tab control, - # this gets rid of the top one of those lines in the tab control - if page.active: - - if agwFlags & AUI_NB_BOTTOM: - dc.SetPen(wx.Pen(self._background_bottom_colour)) - - # TODO: else if (agwFlags & AUI_NB_LEFT) - # TODO: else if (agwFlags & AUI_NB_RIGHT) - else: # for AUI_NB_TOP - dc.SetPen(self._base_colour_pen) - - dc.DrawLine(border_points[0].x+1, - border_points[0].y, - border_points[5].x, - border_points[5].y) - - text_offset = tab_x + 8 - close_button_width = 0 - - if close_button_state != AUI_BUTTON_STATE_HIDDEN: - close_button_width = self._active_close_bmp.GetWidth() - - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - text_offset += close_button_width - 5 - - bitmap_offset = 0 - - if pagebitmap.IsOk(): - - bitmap_offset = tab_x + 8 - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT and close_button_width: - bitmap_offset += close_button_width - 5 - - # draw bitmap - dc.DrawBitmap(pagebitmap, - bitmap_offset, - drawn_tab_yoff + (drawn_tab_height/2) - (pagebitmap.GetHeight()/2), - True) - - text_offset = bitmap_offset + pagebitmap.GetWidth() - text_offset += 3 # bitmap padding - - else: - - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT == 0 or not close_button_width: - text_offset = tab_x + 8 - - draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x) - close_button_width) - - ypos = drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2) - 1 - - offset_focus = text_offset - if control is not None: - if control.GetPosition() != wx.Point(text_offset+1, ypos): - control.SetPosition(wx.Point(text_offset+1, ypos)) - - if not control.IsShown(): - control.Show() - - if paint_control: - bmp = TakeScreenShot(control.GetScreenRect()) - dc.DrawBitmap(bmp, text_offset+1, ypos, True) - - controlW, controlH = control.GetSize() - text_offset += controlW + 4 - textx += controlW + 4 - - # draw tab text - rectx, recty, dummy = dc.GetMultiLineTextExtent(draw_text) - dc.DrawLabel(draw_text, wx.Rect(text_offset, ypos, rectx, recty)) - - # draw focus rectangle - if (agwFlags & AUI_NB_NO_TAB_FOCUS) == 0: - self.DrawFocusRectangle(dc, page, wnd, draw_text, offset_focus, bitmap_offset, drawn_tab_yoff, drawn_tab_height, rectx, recty) - - out_button_rect = wx.Rect() - - # draw close button if necessary - if close_button_state != AUI_BUTTON_STATE_HIDDEN: - - bmp = self._disabled_close_bmp - - if close_button_state == AUI_BUTTON_STATE_HOVER: - bmp = self._hover_close_bmp - elif close_button_state == AUI_BUTTON_STATE_PRESSED: - bmp = self._pressed_close_bmp - - shift = (agwFlags & AUI_NB_BOTTOM and [1] or [0])[0] - - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - rect = wx.Rect(tab_x + 4, tab_y + (tab_height - bmp.GetHeight())/2 - shift, - close_button_width, tab_height) - else: - rect = wx.Rect(tab_x + tab_width - close_button_width - 1, - tab_y + (tab_height - bmp.GetHeight())/2 - shift, - close_button_width, tab_height) - - rect = IndentPressedBitmap(rect, close_button_state) - dc.DrawBitmap(bmp, rect.x, rect.y, True) - - out_button_rect = rect - - out_tab_rect = wx.Rect(tab_x, tab_y, tab_width, tab_height) - - dc.DestroyClippingRegion() - - return out_tab_rect, out_button_rect, x_extent - - - def SetCustomButton(self, bitmap_id, button_state, bmp): - """ - Sets a custom bitmap for the close, left, right and window list - buttons. - - :param `bitmap_id`: the button identifier; - :param `button_state`: the button state; - :param `bmp`: the custom bitmap to use for the button. - """ - - if bitmap_id == AUI_BUTTON_CLOSE: - if button_state == AUI_BUTTON_STATE_NORMAL: - self._active_close_bmp = bmp - self._hover_close_bmp = self._active_close_bmp - self._pressed_close_bmp = self._active_close_bmp - self._disabled_close_bmp = self._active_close_bmp - - elif button_state == AUI_BUTTON_STATE_HOVER: - self._hover_close_bmp = bmp - elif button_state == AUI_BUTTON_STATE_PRESSED: - self._pressed_close_bmp = bmp - else: - self._disabled_close_bmp = bmp - - elif bitmap_id == AUI_BUTTON_LEFT: - if button_state & AUI_BUTTON_STATE_DISABLED: - self._disabled_left_bmp = bmp - else: - self._active_left_bmp = bmp - - elif bitmap_id == AUI_BUTTON_RIGHT: - if button_state & AUI_BUTTON_STATE_DISABLED: - self._disabled_right_bmp = bmp - else: - self._active_right_bmp = bmp - - elif bitmap_id == AUI_BUTTON_WINDOWLIST: - if button_state & AUI_BUTTON_STATE_DISABLED: - self._disabled_windowlist_bmp = bmp - else: - self._active_windowlist_bmp = bmp - - - def GetIndentSize(self): - """ Returns the tabs indent size. """ - - return 5 - - - def GetTabSize(self, dc, wnd, caption, bitmap, active, close_button_state, control=None): - """ - Returns the tab size for the given caption, bitmap and button state. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` instance object; - :param `caption`: the tab text caption; - :param `bitmap`: the bitmap displayed on the tab; - :param `active`: whether the tab is selected or not; - :param `close_button_state`: the state of the close button on the tab; - :param `control`: a `wx.Window` instance inside a tab (or ``None``). - """ - - dc.SetFont(self._measuring_font) - measured_textx, measured_texty, dummy = dc.GetMultiLineTextExtent(caption) - - # add padding around the text - tab_width = measured_textx - tab_height = measured_texty - - # if the close button is showing, add space for it - if close_button_state != AUI_BUTTON_STATE_HIDDEN: - tab_width += self._active_close_bmp.GetWidth() + 3 - - # if there's a bitmap, add space for it - if bitmap.IsOk(): - tab_width += bitmap.GetWidth() - tab_width += 3 # right side bitmap padding - tab_height = max(tab_height, bitmap.GetHeight()) - - # add padding - tab_width += 16 - tab_height += 10 - - agwFlags = self.GetAGWFlags() - if agwFlags & AUI_NB_TAB_FIXED_WIDTH: - tab_width = self._fixed_tab_width - - if control is not None: - tab_width += control.GetSize().GetWidth() + 4 - - x_extent = tab_width - - return (tab_width, tab_height), x_extent - - - def DrawButton(self, dc, wnd, in_rect, button, orientation): - """ - Draws a button on the tab or on the tab area, depending on the button identifier. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` instance object; - :param `in_rect`: rectangle the tab should be confined to; - :param `button`: an instance of the button class; - :param `orientation`: the tab orientation. - """ - - bitmap_id, button_state = button.id, button.cur_state - - if bitmap_id == AUI_BUTTON_CLOSE: - if button_state & AUI_BUTTON_STATE_DISABLED: - bmp = self._disabled_close_bmp - elif button_state & AUI_BUTTON_STATE_HOVER: - bmp = self._hover_close_bmp - elif button_state & AUI_BUTTON_STATE_PRESSED: - bmp = self._pressed_close_bmp - else: - bmp = self._active_close_bmp - - elif bitmap_id == AUI_BUTTON_LEFT: - if button_state & AUI_BUTTON_STATE_DISABLED: - bmp = self._disabled_left_bmp - else: - bmp = self._active_left_bmp - - elif bitmap_id == AUI_BUTTON_RIGHT: - if button_state & AUI_BUTTON_STATE_DISABLED: - bmp = self._disabled_right_bmp - else: - bmp = self._active_right_bmp - - elif bitmap_id == AUI_BUTTON_WINDOWLIST: - if button_state & AUI_BUTTON_STATE_DISABLED: - bmp = self._disabled_windowlist_bmp - else: - bmp = self._active_windowlist_bmp - - else: - if button_state & AUI_BUTTON_STATE_DISABLED: - bmp = button.dis_bitmap - else: - bmp = button.bitmap - - if not bmp.IsOk(): - return - - rect = wx.Rect(*in_rect) - - if orientation == wx.LEFT: - - rect.SetX(in_rect.x) - rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2)) - rect.SetWidth(bmp.GetWidth()) - rect.SetHeight(bmp.GetHeight()) - - else: - - rect = wx.Rect(in_rect.x + in_rect.width - bmp.GetWidth(), - ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2), - bmp.GetWidth(), bmp.GetHeight()) - - rect = IndentPressedBitmap(rect, button_state) - dc.DrawBitmap(bmp, rect.x, rect.y, True) - - out_rect = rect - - if bitmap_id == AUI_BUTTON_RIGHT: - self._buttonRect = wx.Rect(rect.x, rect.y, 30, rect.height) - - return out_rect - - - def DrawFocusRectangle(self, dc, page, wnd, draw_text, text_offset, bitmap_offset, drawn_tab_yoff, drawn_tab_height, textx, texty): - """ - Draws the focus rectangle on a tab. - - :param `dc`: a `wx.DC` device context; - :param `page`: the page associated with the tab; - :param `wnd`: a `wx.Window` instance object; - :param `draw_text`: the text that has been drawn on the tab; - :param `text_offset`: the text offset on the tab; - :param `bitmap_offset`: the bitmap offset on the tab; - :param `drawn_tab_yoff`: the y offset of the tab text; - :param `drawn_tab_height`: the height of the tab; - :param `textx`: the x text extent; - :param `texty`: the y text extent. - """ - - if self.GetAGWFlags() & AUI_NB_NO_TAB_FOCUS: - return - - if page.active and wx.Window.FindFocus() == wnd: - - focusRectText = wx.Rect(text_offset, (drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2)), - textx, texty) - - if page.bitmap.IsOk(): - focusRectBitmap = wx.Rect(bitmap_offset, drawn_tab_yoff + (drawn_tab_height/2) - (page.bitmap.GetHeight()/2), - page.bitmap.GetWidth(), page.bitmap.GetHeight()) - - if page.bitmap.IsOk() and draw_text == "": - focusRect = wx.Rect(*focusRectBitmap) - elif not page.bitmap.IsOk() and draw_text != "": - focusRect = wx.Rect(*focusRectText) - elif page.bitmap.IsOk() and draw_text != "": - focusRect = focusRectText.Union(focusRectBitmap) - - focusRect.Inflate(2, 2) - - dc.SetBrush(wx.TRANSPARENT_BRUSH) - dc.SetPen(self._focusPen) - dc.DrawRoundedRectangleRect(focusRect, 2) - - - def GetBestTabCtrlSize(self, wnd, pages, required_bmp_size): - """ - Returns the best tab control size. - - :param `wnd`: a `wx.Window` instance object; - :param `pages`: the pages associated with the tabs; - :param `required_bmp_size`: the size of the bitmap on the tabs. - """ - - dc = wx.ClientDC(wnd) - dc.SetFont(self._measuring_font) - - # sometimes a standard bitmap size needs to be enforced, especially - # if some tabs have bitmaps and others don't. This is important because - # it prevents the tab control from resizing when tabs are added. - - measure_bmp = wx.NullBitmap - - if required_bmp_size.IsFullySpecified(): - measure_bmp = wx.EmptyBitmap(required_bmp_size.x, - required_bmp_size.y) - - max_y = 0 - - for page in pages: - - if measure_bmp.IsOk(): - bmp = measure_bmp - else: - bmp = page.bitmap - - # we don't use the caption text because we don't - # want tab heights to be different in the case - # of a very short piece of text on one tab and a very - # tall piece of text on another tab - s, x_ext = self.GetTabSize(dc, wnd, page.caption, bmp, True, AUI_BUTTON_STATE_HIDDEN, None) - max_y = max(max_y, s[1]) - - if page.control: - controlW, controlH = page.control.GetSize() - max_y = max(max_y, controlH+4) - - return max_y + 2 - - - def SetNormalFont(self, font): - """ - Sets the normal font for drawing tab labels. - - :param `font`: a `wx.Font` object. - """ - - self._normal_font = font - - - def SetSelectedFont(self, font): - """ - Sets the selected tab font for drawing tab labels. - - :param `font`: a `wx.Font` object. - """ - - self._selected_font = font - - - def SetMeasuringFont(self, font): - """ - Sets the font for calculating text measurements. - - :param `font`: a `wx.Font` object. - """ - - self._measuring_font = font - - - def GetNormalFont(self): - """ Returns the normal font for drawing tab labels. """ - - return self._normal_font - - - def GetSelectedFont(self): - """ Returns the selected tab font for drawing tab labels. """ - - return self._selected_font - - - def GetMeasuringFont(self): - """ Returns the font for calculating text measurements. """ - - return self._measuring_font - - - def ShowDropDown(self, wnd, pages, active_idx): - """ - Shows the drop-down window menu on the tab area. - - :param `wnd`: a `wx.Window` derived window instance; - :param `pages`: the pages associated with the tabs; - :param `active_idx`: the active tab index. - """ - - useImages = self.GetAGWFlags() & AUI_NB_USE_IMAGES_DROPDOWN - menuPopup = wx.Menu() - - longest = 0 - for i, page in enumerate(pages): - - caption = page.caption - - # if there is no caption, make it a space. This will prevent - # an assert in the menu code. - if caption == "": - caption = " " - - # Save longest caption width for calculating menu width with - width = wnd.GetTextExtent(caption)[0] - if width > longest: - longest = width - - if useImages: - menuItem = wx.MenuItem(menuPopup, 1000+i, caption) - if page.bitmap: - menuItem.SetBitmap(page.bitmap) - - menuPopup.AppendItem(menuItem) - - else: - - menuPopup.AppendCheckItem(1000+i, caption) - - menuPopup.Enable(1000+i, page.enabled) - - if active_idx != -1 and not useImages: - - menuPopup.Check(1000+active_idx, True) - - # find out the screen coordinate at the bottom of the tab ctrl - cli_rect = wnd.GetClientRect() - - # Calculate the approximate size of the popupmenu for setting the - # position of the menu when its shown. - # Account for extra padding on left/right of text on mac menus - if wx.Platform in ['__WXMAC__', '__WXMSW__']: - longest += 32 - - # Bitmap/Checkmark width + padding - longest += 20 - - if self.GetAGWFlags() & AUI_NB_CLOSE_BUTTON: - longest += 16 - - pt = wx.Point(cli_rect.x + cli_rect.GetWidth() - longest, - cli_rect.y + cli_rect.height) - - cc = AuiCommandCapture() - wnd.PushEventHandler(cc) - wnd.PopupMenu(menuPopup, pt) - command = cc.GetCommandId() - wnd.PopEventHandler(True) - - if command >= 1000: - return command - 1000 - - return -1 - - -class AuiSimpleTabArt(object): - """ A simple-looking implementation of a tab art. """ - - def __init__(self): - """ Default class constructor. """ - - self._normal_font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) - self._selected_font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) - self._selected_font.SetWeight(wx.BOLD) - self._measuring_font = self._selected_font - - self._agwFlags = 0 - self._fixed_tab_width = 100 - - base_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE) - - background_colour = base_colour - normaltab_colour = base_colour - selectedtab_colour = wx.WHITE - - self._bkbrush = wx.Brush(background_colour) - self._normal_bkbrush = wx.Brush(normaltab_colour) - self._normal_bkpen = wx.Pen(normaltab_colour) - self._selected_bkbrush = wx.Brush(selectedtab_colour) - self._selected_bkpen = wx.Pen(selectedtab_colour) - - self._active_close_bmp = BitmapFromBits(nb_close_bits, 16, 16, wx.BLACK) - self._disabled_close_bmp = BitmapFromBits(nb_close_bits, 16, 16, wx.Colour(128, 128, 128)) - - self._active_left_bmp = BitmapFromBits(nb_left_bits, 16, 16, wx.BLACK) - self._disabled_left_bmp = BitmapFromBits(nb_left_bits, 16, 16, wx.Colour(128, 128, 128)) - - self._active_right_bmp = BitmapFromBits(nb_right_bits, 16, 16, wx.BLACK) - self._disabled_right_bmp = BitmapFromBits(nb_right_bits, 16, 16, wx.Colour(128, 128, 128)) - - self._active_windowlist_bmp = BitmapFromBits(nb_list_bits, 16, 16, wx.BLACK) - self._disabled_windowlist_bmp = BitmapFromBits(nb_list_bits, 16, 16, wx.Colour(128, 128, 128)) - - - def Clone(self): - """ Clones the art object. """ - - art = type(self)() - art.SetNormalFont(self.GetNormalFont()) - art.SetSelectedFont(self.GetSelectedFont()) - art.SetMeasuringFont(self.GetMeasuringFont()) - - art = CopyAttributes(art, self) - return art - - - def SetAGWFlags(self, agwFlags): - """ - Sets the tab art flags. - - :param `agwFlags`: a combination of the following values: - - ==================================== ================================== - Flag name Description - ==================================== ================================== - ``AUI_NB_TOP`` With this style, tabs are drawn along the top of the notebook - ``AUI_NB_LEFT`` With this style, tabs are drawn along the left of the notebook. Not implemented yet. - ``AUI_NB_RIGHT`` With this style, tabs are drawn along the right of the notebook. Not implemented yet. - ``AUI_NB_BOTTOM`` With this style, tabs are drawn along the bottom of the notebook - ``AUI_NB_TAB_SPLIT`` Allows the tab control to be split by dragging a tab - ``AUI_NB_TAB_MOVE`` Allows a tab to be moved horizontally by dragging - ``AUI_NB_TAB_EXTERNAL_MOVE`` Allows a tab to be moved to another tab control - ``AUI_NB_TAB_FIXED_WIDTH`` With this style, all tabs have the same width - ``AUI_NB_SCROLL_BUTTONS`` With this style, left and right scroll buttons are displayed - ``AUI_NB_WINDOWLIST_BUTTON`` With this style, a drop-down list of windows is available - ``AUI_NB_CLOSE_BUTTON`` With this style, a close button is available on the tab bar - ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` With this style, a close button is available on the active tab - ``AUI_NB_CLOSE_ON_ALL_TABS`` With this style, a close button is available on all tabs - ``AUI_NB_MIDDLE_CLICK_CLOSE`` Allows to close L{AuiNotebook} tabs by mouse middle button click - ``AUI_NB_SUB_NOTEBOOK`` This style is used by L{AuiManager} to create automatic AuiNotebooks - ``AUI_NB_HIDE_ON_SINGLE_TAB`` Hides the tab window if only one tab is present - ``AUI_NB_SMART_TABS`` Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows - ``AUI_NB_USE_IMAGES_DROPDOWN`` Uses images on dropdown window list menu instead of check items - ``AUI_NB_CLOSE_ON_TAB_LEFT`` Draws the tab close button on the left instead of on the right (a la Camino browser) - ``AUI_NB_TAB_FLOAT`` Allows the floating of single tabs. Known limitation: when the notebook is more or less full screen, tabs cannot be dragged far enough outside of the notebook to become floating pages - ``AUI_NB_DRAW_DND_TAB`` Draws an image representation of a tab while dragging (on by default) - ``AUI_NB_ORDER_BY_ACCESS`` Tab navigation order by last access time for the tabs - ``AUI_NB_NO_TAB_FOCUS`` Don't draw tab focus rectangle - ==================================== ================================== - - """ - - self._agwFlags = agwFlags - - - def GetAGWFlags(self): - """ - Returns the tab art flags. - - :see: L{SetAGWFlags} for a list of possible return values. - """ - - return self._agwFlags - - - def SetSizingInfo(self, tab_ctrl_size, tab_count, minMaxTabWidth): - """ - Sets the tab sizing information. - - :param `tab_ctrl_size`: the size of the tab control area; - :param `tab_count`: the number of tabs; - :param `minMaxTabWidth`: a tuple containing the minimum and maximum tab widths - to be used when the ``AUI_NB_TAB_FIXED_WIDTH`` style is active. - """ - - self._fixed_tab_width = 100 - minTabWidth, maxTabWidth = minMaxTabWidth - - tot_width = tab_ctrl_size.x - self.GetIndentSize() - 4 - - if self._agwFlags & AUI_NB_CLOSE_BUTTON: - tot_width -= self._active_close_bmp.GetWidth() - if self._agwFlags & AUI_NB_WINDOWLIST_BUTTON: - tot_width -= self._active_windowlist_bmp.GetWidth() - - if tab_count > 0: - self._fixed_tab_width = tot_width/tab_count - - if self._fixed_tab_width < 100: - self._fixed_tab_width = 100 - - if self._fixed_tab_width > tot_width/2: - self._fixed_tab_width = tot_width/2 - - if self._fixed_tab_width > 220: - self._fixed_tab_width = 220 - - if minTabWidth > -1: - self._fixed_tab_width = max(self._fixed_tab_width, minTabWidth) - if maxTabWidth > -1: - self._fixed_tab_width = min(self._fixed_tab_width, maxTabWidth) - - self._tab_ctrl_height = tab_ctrl_size.y - - - def DrawBackground(self, dc, wnd, rect): - """ - Draws the tab area background. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` instance object; - :param `rect`: the tab control rectangle. - """ - - # draw background - dc.SetBrush(self._bkbrush) - dc.SetPen(wx.TRANSPARENT_PEN) - dc.DrawRectangle(-1, -1, rect.GetWidth()+2, rect.GetHeight()+2) - - # draw base line - dc.SetPen(wx.GREY_PEN) - dc.DrawLine(0, rect.GetHeight()-1, rect.GetWidth(), rect.GetHeight()-1) - - - def DrawTab(self, dc, wnd, page, in_rect, close_button_state, paint_control=False): - """ - Draws a single tab. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` instance object; - :param `page`: the tab control page associated with the tab; - :param `in_rect`: rectangle the tab should be confined to; - :param `close_button_state`: the state of the close button on the tab; - :param `paint_control`: whether to draw the control inside a tab (if any) on a `wx.MemoryDC`. - """ - - # if the caption is empty, measure some temporary text - caption = page.caption - if caption == "": - caption = "Xj" - - agwFlags = self.GetAGWFlags() - - dc.SetFont(self._selected_font) - selected_textx, selected_texty, dummy = dc.GetMultiLineTextExtent(caption) - - dc.SetFont(self._normal_font) - normal_textx, normal_texty, dummy = dc.GetMultiLineTextExtent(caption) - - control = page.control - - # figure out the size of the tab - tab_size, x_extent = self.GetTabSize(dc, wnd, page.caption, page.bitmap, - page.active, close_button_state, control) - - tab_height = tab_size[1] - tab_width = tab_size[0] - tab_x = in_rect.x - tab_y = in_rect.y + in_rect.height - tab_height - - caption = page.caption - # select pen, brush and font for the tab to be drawn - - if page.active: - - dc.SetPen(self._selected_bkpen) - dc.SetBrush(self._selected_bkbrush) - dc.SetFont(self._selected_font) - textx = selected_textx - texty = selected_texty - - else: - - dc.SetPen(self._normal_bkpen) - dc.SetBrush(self._normal_bkbrush) - dc.SetFont(self._normal_font) - textx = normal_textx - texty = normal_texty - - if not page.enabled: - dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) - else: - dc.SetTextForeground(page.text_colour) - - # -- draw line -- - - points = [wx.Point() for i in xrange(7)] - points[0].x = tab_x - points[0].y = tab_y + tab_height - 1 - points[1].x = tab_x + tab_height - 3 - points[1].y = tab_y + 2 - points[2].x = tab_x + tab_height + 3 - points[2].y = tab_y - points[3].x = tab_x + tab_width - 2 - points[3].y = tab_y - points[4].x = tab_x + tab_width - points[4].y = tab_y + 2 - points[5].x = tab_x + tab_width - points[5].y = tab_y + tab_height - 1 - points[6] = points[0] - - dc.SetClippingRect(in_rect) - dc.DrawPolygon(points) - - dc.SetPen(wx.GREY_PEN) - dc.DrawLines(points) - - close_button_width = 0 - - if close_button_state != AUI_BUTTON_STATE_HIDDEN: - - close_button_width = self._active_close_bmp.GetWidth() - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - if control: - text_offset = tab_x + (tab_height/2) + close_button_width - (textx/2) - 2 - else: - text_offset = tab_x + (tab_height/2) + ((tab_width+close_button_width)/2) - (textx/2) - 2 - else: - if control: - text_offset = tab_x + (tab_height/2) + close_button_width - (textx/2) - else: - text_offset = tab_x + (tab_height/2) + ((tab_width-close_button_width)/2) - (textx/2) - - else: - - text_offset = tab_x + (tab_height/3) + (tab_width/2) - (textx/2) - if control: - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - text_offset = tab_x + (tab_height/3) - (textx/2) + close_button_width + 2 - else: - text_offset = tab_x + (tab_height/3) - (textx/2) - - # set minimum text offset - if text_offset < tab_x + tab_height: - text_offset = tab_x + tab_height - - # chop text if necessary - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x)) - else: - draw_text = ChopText(dc, caption, - tab_width - (text_offset-tab_x) - close_button_width) - - ypos = (tab_y + tab_height)/2 - (texty/2) + 1 - - if control is not None: - if control.GetPosition() != wx.Point(text_offset+1, ypos): - control.SetPosition(wx.Point(text_offset+1, ypos)) - - if not control.IsShown(): - control.Show() - - if paint_control: - bmp = TakeScreenShot(control.GetScreenRect()) - dc.DrawBitmap(bmp, text_offset+1, ypos, True) - - controlW, controlH = control.GetSize() - text_offset += controlW + 4 - - # draw tab text - rectx, recty, dummy = dc.GetMultiLineTextExtent(draw_text) - dc.DrawLabel(draw_text, wx.Rect(text_offset, ypos, rectx, recty)) - - # draw focus rectangle - if page.active and wx.Window.FindFocus() == wnd and (agwFlags & AUI_NB_NO_TAB_FOCUS) == 0: - - focusRect = wx.Rect(text_offset, ((tab_y + tab_height)/2 - (texty/2) + 1), - selected_textx, selected_texty) - - focusRect.Inflate(2, 2) - # TODO: - # This should be uncommented when DrawFocusRect will become - # available in wxPython - # wx.RendererNative.Get().DrawFocusRect(wnd, dc, focusRect, 0) - - out_button_rect = wx.Rect() - # draw close button if necessary - if close_button_state != AUI_BUTTON_STATE_HIDDEN: - - if page.active: - bmp = self._active_close_bmp - else: - bmp = self._disabled_close_bmp - - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - rect = wx.Rect(tab_x + tab_height - 2, - tab_y + (tab_height/2) - (bmp.GetHeight()/2) + 1, - close_button_width, tab_height - 1) - else: - rect = wx.Rect(tab_x + tab_width - close_button_width - 1, - tab_y + (tab_height/2) - (bmp.GetHeight()/2) + 1, - close_button_width, tab_height - 1) - - self.DrawButtons(dc, rect, bmp, wx.WHITE, close_button_state) - out_button_rect = wx.Rect(*rect) - - out_tab_rect = wx.Rect(tab_x, tab_y, tab_width, tab_height) - dc.DestroyClippingRegion() - - return out_tab_rect, out_button_rect, x_extent - - - def DrawButtons(self, dc, _rect, bmp, bkcolour, button_state): - """ - Convenience method to draw tab buttons. - - :param `dc`: a `wx.DC` device context; - :param `_rect`: the tab rectangle; - :param `bmp`: the tab bitmap; - :param `bkcolour`: the tab background colour; - :param `button_state`: the state of the tab button. - """ - - rect = wx.Rect(*_rect) - - if button_state == AUI_BUTTON_STATE_PRESSED: - rect.x += 1 - rect.y += 1 - - if button_state in [AUI_BUTTON_STATE_HOVER, AUI_BUTTON_STATE_PRESSED]: - dc.SetBrush(wx.Brush(StepColour(bkcolour, 120))) - dc.SetPen(wx.Pen(StepColour(bkcolour, 75))) - - # draw the background behind the button - dc.DrawRectangle(rect.x, rect.y, 15, 15) - - # draw the button itself - dc.DrawBitmap(bmp, rect.x, rect.y, True) - - - def GetIndentSize(self): - """ Returns the tabs indent size. """ - - return 0 - - - def GetTabSize(self, dc, wnd, caption, bitmap, active, close_button_state, control=None): - """ - Returns the tab size for the given caption, bitmap and button state. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` instance object; - :param `caption`: the tab text caption; - :param `bitmap`: the bitmap displayed on the tab; - :param `active`: whether the tab is selected or not; - :param `close_button_state`: the state of the close button on the tab; - :param `control`: a `wx.Window` instance inside a tab (or ``None``). - """ - - dc.SetFont(self._measuring_font) - measured_textx, measured_texty, dummy = dc.GetMultiLineTextExtent(caption) - - tab_height = measured_texty + 4 - tab_width = measured_textx + tab_height + 5 - - if close_button_state != AUI_BUTTON_STATE_HIDDEN: - tab_width += self._active_close_bmp.GetWidth() - - if self._agwFlags & AUI_NB_TAB_FIXED_WIDTH: - tab_width = self._fixed_tab_width - - if control is not None: - controlW, controlH = control.GetSize() - tab_width += controlW + 4 - - x_extent = tab_width - (tab_height/2) - 1 - - return (tab_width, tab_height), x_extent - - - def DrawButton(self, dc, wnd, in_rect, button, orientation): - """ - Draws a button on the tab or on the tab area, depending on the button identifier. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` instance object; - :param `in_rect`: rectangle the tab should be confined to; - :param `button`: an instance of the button class; - :param `orientation`: the tab orientation. - """ - - bitmap_id, button_state = button.id, button.cur_state - - if bitmap_id == AUI_BUTTON_CLOSE: - if button_state & AUI_BUTTON_STATE_DISABLED: - bmp = self._disabled_close_bmp - else: - bmp = self._active_close_bmp - - elif bitmap_id == AUI_BUTTON_LEFT: - if button_state & AUI_BUTTON_STATE_DISABLED: - bmp = self._disabled_left_bmp - else: - bmp = self._active_left_bmp - - elif bitmap_id == AUI_BUTTON_RIGHT: - if button_state & AUI_BUTTON_STATE_DISABLED: - bmp = self._disabled_right_bmp - else: - bmp = self._active_right_bmp - - elif bitmap_id == AUI_BUTTON_WINDOWLIST: - if button_state & AUI_BUTTON_STATE_DISABLED: - bmp = self._disabled_windowlist_bmp - else: - bmp = self._active_windowlist_bmp - - else: - if button_state & AUI_BUTTON_STATE_DISABLED: - bmp = button.dis_bitmap - else: - bmp = button.bitmap - - if not bmp.IsOk(): - return - - rect = wx.Rect(*in_rect) - - if orientation == wx.LEFT: - - rect.SetX(in_rect.x) - rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2)) - rect.SetWidth(bmp.GetWidth()) - rect.SetHeight(bmp.GetHeight()) - - else: - - rect = wx.Rect(in_rect.x + in_rect.width - bmp.GetWidth(), - ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2), - bmp.GetWidth(), bmp.GetHeight()) - - self.DrawButtons(dc, rect, bmp, wx.WHITE, button_state) - - out_rect = wx.Rect(*rect) - return out_rect - - - def ShowDropDown(self, wnd, pages, active_idx): - """ - Shows the drop-down window menu on the tab area. - - :param `wnd`: a `wx.Window` derived window instance; - :param `pages`: the pages associated with the tabs; - :param `active_idx`: the active tab index. - """ - - menuPopup = wx.Menu() - useImages = self.GetAGWFlags() & AUI_NB_USE_IMAGES_DROPDOWN - - for i, page in enumerate(pages): - - if useImages: - menuItem = wx.MenuItem(menuPopup, 1000+i, page.caption) - if page.bitmap: - menuItem.SetBitmap(page.bitmap) - - menuPopup.AppendItem(menuItem) - - else: - - menuPopup.AppendCheckItem(1000+i, page.caption) - - menuPopup.Enable(1000+i, page.enabled) - - if active_idx != -1 and not useImages: - menuPopup.Check(1000+active_idx, True) - - # find out where to put the popup menu of window - # items. Subtract 100 for now to center the menu - # a bit, until a better mechanism can be implemented - pt = wx.GetMousePosition() - pt = wnd.ScreenToClient(pt) - - if pt.x < 100: - pt.x = 0 - else: - pt.x -= 100 - - # find out the screen coordinate at the bottom of the tab ctrl - cli_rect = wnd.GetClientRect() - pt.y = cli_rect.y + cli_rect.height - - cc = AuiCommandCapture() - wnd.PushEventHandler(cc) - wnd.PopupMenu(menuPopup, pt) - command = cc.GetCommandId() - wnd.PopEventHandler(True) - - if command >= 1000: - return command-1000 - - return -1 - - - def GetBestTabCtrlSize(self, wnd, pages, required_bmp_size): - """ - Returns the best tab control size. - - :param `wnd`: a `wx.Window` instance object; - :param `pages`: the pages associated with the tabs; - :param `required_bmp_size`: the size of the bitmap on the tabs. - """ - - dc = wx.ClientDC(wnd) - dc.SetFont(self._measuring_font) - s, x_extent = self.GetTabSize(dc, wnd, "ABCDEFGHIj", wx.NullBitmap, True, - AUI_BUTTON_STATE_HIDDEN, None) - - max_y = s[1] - - for page in pages: - if page.control: - controlW, controlH = page.control.GetSize() - max_y = max(max_y, controlH+4) - - textx, texty, dummy = dc.GetMultiLineTextExtent(page.caption) - max_y = max(max_y, texty) - - return max_y + 3 - - - def SetNormalFont(self, font): - """ - Sets the normal font for drawing tab labels. - - :param `font`: a `wx.Font` object. - """ - - self._normal_font = font - - - def SetSelectedFont(self, font): - """ - Sets the selected tab font for drawing tab labels. - - :param `font`: a `wx.Font` object. - """ - - self._selected_font = font - - - def SetMeasuringFont(self, font): - """ - Sets the font for calculating text measurements. - - :param `font`: a `wx.Font` object. - """ - - self._measuring_font = font - - - def GetNormalFont(self): - """ Returns the normal font for drawing tab labels. """ - - return self._normal_font - - - def GetSelectedFont(self): - """ Returns the selected tab font for drawing tab labels. """ - - return self._selected_font - - - def GetMeasuringFont(self): - """ Returns the font for calculating text measurements. """ - - return self._measuring_font - - - def SetCustomButton(self, bitmap_id, button_state, bmp): - """ - Sets a custom bitmap for the close, left, right and window list - buttons. - - :param `bitmap_id`: the button identifier; - :param `button_state`: the button state; - :param `bmp`: the custom bitmap to use for the button. - """ - - if bitmap_id == AUI_BUTTON_CLOSE: - if button_state == AUI_BUTTON_STATE_NORMAL: - self._active_close_bmp = bmp - self._hover_close_bmp = self._active_close_bmp - self._pressed_close_bmp = self._active_close_bmp - self._disabled_close_bmp = self._active_close_bmp - - elif button_state == AUI_BUTTON_STATE_HOVER: - self._hover_close_bmp = bmp - elif button_state == AUI_BUTTON_STATE_PRESSED: - self._pressed_close_bmp = bmp - else: - self._disabled_close_bmp = bmp - - elif bitmap_id == AUI_BUTTON_LEFT: - if button_state & AUI_BUTTON_STATE_DISABLED: - self._disabled_left_bmp = bmp - else: - self._active_left_bmp = bmp - - elif bitmap_id == AUI_BUTTON_RIGHT: - if button_state & AUI_BUTTON_STATE_DISABLED: - self._disabled_right_bmp = bmp - else: - self._active_right_bmp = bmp - - elif bitmap_id == AUI_BUTTON_WINDOWLIST: - if button_state & AUI_BUTTON_STATE_DISABLED: - self._disabled_windowlist_bmp = bmp - else: - self._active_windowlist_bmp = bmp - - -class VC71TabArt(AuiDefaultTabArt): - """ A class to draw tabs using the Visual Studio 2003 (VC71) style. """ - - def __init__(self): - """ Default class constructor. """ - - AuiDefaultTabArt.__init__(self) - - - def Clone(self): - """ Clones the art object. """ - - art = type(self)() - art.SetNormalFont(self.GetNormalFont()) - art.SetSelectedFont(self.GetSelectedFont()) - art.SetMeasuringFont(self.GetMeasuringFont()) - - art = CopyAttributes(art, self) - return art - - - def DrawTab(self, dc, wnd, page, in_rect, close_button_state, paint_control=False): - """ - Draws a single tab. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` instance object; - :param `page`: the tab control page associated with the tab; - :param `in_rect`: rectangle the tab should be confined to; - :param `close_button_state`: the state of the close button on the tab; - :param `paint_control`: whether to draw the control inside a tab (if any) on a `wx.MemoryDC`. - """ - - # Visual studio 7.1 style - # This code is based on the renderer included in FlatNotebook - - # figure out the size of the tab - - control = page.control - tab_size, x_extent = self.GetTabSize(dc, wnd, page.caption, page.bitmap, page.active, - close_button_state, control) - - tab_height = self._tab_ctrl_height - 3 - tab_width = tab_size[0] - tab_x = in_rect.x - tab_y = in_rect.y + in_rect.height - tab_height - clip_width = tab_width - - if tab_x + clip_width > in_rect.x + in_rect.width - 4: - clip_width = (in_rect.x + in_rect.width) - tab_x - 4 - - dc.SetClippingRegion(tab_x, tab_y, clip_width + 1, tab_height - 3) - agwFlags = self.GetAGWFlags() - - if agwFlags & AUI_NB_BOTTOM: - tab_y -= 1 - - dc.SetPen((page.active and [wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DHIGHLIGHT))] or \ - [wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DSHADOW))])[0]) - dc.SetBrush((page.active and [wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE))] or \ - [wx.TRANSPARENT_BRUSH])[0]) - - if page.active: - - tabH = tab_height - 2 - dc.DrawRectangle(tab_x, tab_y, tab_width, tabH) - - rightLineY1 = (agwFlags & AUI_NB_BOTTOM and [vertical_border_padding - 2] or \ - [vertical_border_padding - 1])[0] - rightLineY2 = tabH + 3 - dc.SetPen(wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DSHADOW))) - dc.DrawLine(tab_x + tab_width - 1, rightLineY1 + 1, tab_x + tab_width - 1, rightLineY2) - - if agwFlags & AUI_NB_BOTTOM: - dc.DrawLine(tab_x + 1, rightLineY2 - 3 , tab_x + tab_width - 1, rightLineY2 - 3) - - dc.SetPen(wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DDKSHADOW))) - dc.DrawLine(tab_x + tab_width, rightLineY1, tab_x + tab_width, rightLineY2) - - if agwFlags & AUI_NB_BOTTOM: - dc.DrawLine(tab_x, rightLineY2 - 2, tab_x + tab_width, rightLineY2 - 2) - - else: - - # We dont draw a rectangle for non selected tabs, but only - # vertical line on the right - blackLineY1 = (agwFlags & AUI_NB_BOTTOM and [vertical_border_padding + 2] or \ - [vertical_border_padding + 1])[0] - blackLineY2 = tab_height - 5 - dc.DrawLine(tab_x + tab_width, blackLineY1, tab_x + tab_width, blackLineY2) - - border_points = [0, 0] - - if agwFlags & AUI_NB_BOTTOM: - - border_points[0] = wx.Point(tab_x, tab_y) - border_points[1] = wx.Point(tab_x, tab_y + tab_height - 6) - - else: # if (agwFlags & AUI_NB_TOP) - - border_points[0] = wx.Point(tab_x, tab_y + tab_height - 4) - border_points[1] = wx.Point(tab_x, tab_y + 2) - - drawn_tab_yoff = border_points[1].y - drawn_tab_height = border_points[0].y - border_points[1].y - - text_offset = tab_x + 8 - close_button_width = 0 - - if close_button_state != AUI_BUTTON_STATE_HIDDEN: - close_button_width = self._active_close_bmp.GetWidth() - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - text_offset += close_button_width - 5 - - if not page.enabled: - dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) - pagebitmap = page.dis_bitmap - else: - dc.SetTextForeground(page.text_colour) - pagebitmap = page.bitmap - - shift = 0 - if agwFlags & AUI_NB_BOTTOM: - shift = (page.active and [1] or [2])[0] - - bitmap_offset = 0 - if pagebitmap.IsOk(): - bitmap_offset = tab_x + 8 - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT and close_button_width: - bitmap_offset += close_button_width - 5 - - # draw bitmap - dc.DrawBitmap(pagebitmap, bitmap_offset, - drawn_tab_yoff + (drawn_tab_height/2) - (pagebitmap.GetHeight()/2) + shift, - True) - - text_offset = bitmap_offset + pagebitmap.GetWidth() - text_offset += 3 # bitmap padding - - else: - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT == 0 or not close_button_width: - text_offset = tab_x + 8 - - # if the caption is empty, measure some temporary text - caption = page.caption - - if caption == "": - caption = "Xj" - - if page.active: - dc.SetFont(self._selected_font) - textx, texty, dummy = dc.GetMultiLineTextExtent(caption) - else: - dc.SetFont(self._normal_font) - textx, texty, dummy = dc.GetMultiLineTextExtent(caption) - - draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x) - close_button_width) - - ypos = drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2) - 1 + shift - - offset_focus = text_offset - - if control is not None: - if control.GetPosition() != wx.Point(text_offset+1, ypos): - control.SetPosition(wx.Point(text_offset+1, ypos)) - - if not control.IsShown(): - control.Show() - - if paint_control: - bmp = TakeScreenShot(control.GetScreenRect()) - dc.DrawBitmap(bmp, text_offset+1, ypos, True) - - controlW, controlH = control.GetSize() - text_offset += controlW + 4 - textx += controlW + 4 - - # draw tab text - rectx, recty, dummy = dc.GetMultiLineTextExtent(draw_text) - dc.DrawLabel(draw_text, wx.Rect(text_offset, ypos, rectx, recty)) - - out_button_rect = wx.Rect() - - # draw focus rectangle - if (agwFlags & AUI_NB_NO_TAB_FOCUS) == 0: - self.DrawFocusRectangle(dc, page, wnd, draw_text, offset_focus, bitmap_offset, drawn_tab_yoff+shift, - drawn_tab_height+shift, rectx, recty) - - # draw 'x' on tab (if enabled) - if close_button_state != AUI_BUTTON_STATE_HIDDEN: - close_button_width = self._active_close_bmp.GetWidth() - - bmp = self._disabled_close_bmp - - if close_button_state == AUI_BUTTON_STATE_HOVER: - bmp = self._hover_close_bmp - elif close_button_state == AUI_BUTTON_STATE_PRESSED: - bmp = self._pressed_close_bmp - - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - rect = wx.Rect(tab_x + 4, - drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2) + shift, - close_button_width, tab_height) - else: - rect = wx.Rect(tab_x + tab_width - close_button_width - 3, - drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2) + shift, - close_button_width, tab_height) - - # Indent the button if it is pressed down: - rect = IndentPressedBitmap(rect, close_button_state) - dc.DrawBitmap(bmp, rect.x, rect.y, True) - - out_button_rect = rect - - out_tab_rect = wx.Rect(tab_x, tab_y, tab_width, tab_height) - dc.DestroyClippingRegion() - - return out_tab_rect, out_button_rect, x_extent - - -class FF2TabArt(AuiDefaultTabArt): - """ A class to draw tabs using the Firefox 2 (FF2) style. """ - - def __init__(self): - """ Default class constructor. """ - - AuiDefaultTabArt.__init__(self) - - - def Clone(self): - """ Clones the art object. """ - - art = type(self)() - art.SetNormalFont(self.GetNormalFont()) - art.SetSelectedFont(self.GetSelectedFont()) - art.SetMeasuringFont(self.GetMeasuringFont()) - - art = CopyAttributes(art, self) - return art - - - def GetTabSize(self, dc, wnd, caption, bitmap, active, close_button_state, control): - """ - Returns the tab size for the given caption, bitmap and button state. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` instance object; - :param `caption`: the tab text caption; - :param `bitmap`: the bitmap displayed on the tab; - :param `active`: whether the tab is selected or not; - :param `close_button_state`: the state of the close button on the tab; - :param `control`: a `wx.Window` instance inside a tab (or ``None``). - """ - - tab_size, x_extent = AuiDefaultTabArt.GetTabSize(self, dc, wnd, caption, bitmap, - active, close_button_state, control) - - tab_width, tab_height = tab_size - - # add some vertical padding - tab_height += 2 - - return (tab_width, tab_height), x_extent - - - def DrawTab(self, dc, wnd, page, in_rect, close_button_state, paint_control=False): - """ - Draws a single tab. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` instance object; - :param `page`: the tab control page associated with the tab; - :param `in_rect`: rectangle the tab should be confined to; - :param `close_button_state`: the state of the close button on the tab; - :param `paint_control`: whether to draw the control inside a tab (if any) on a `wx.MemoryDC`. - """ - - # Firefox 2 style - - control = page.control - - # figure out the size of the tab - tab_size, x_extent = self.GetTabSize(dc, wnd, page.caption, page.bitmap, - page.active, close_button_state, control) - - tab_height = self._tab_ctrl_height - 2 - tab_width = tab_size[0] - tab_x = in_rect.x - tab_y = in_rect.y + in_rect.height - tab_height - - clip_width = tab_width - if tab_x + clip_width > in_rect.x + in_rect.width - 4: - clip_width = (in_rect.x + in_rect.width) - tab_x - 4 - - dc.SetClippingRegion(tab_x, tab_y, clip_width + 1, tab_height - 3) - - tabPoints = [wx.Point() for i in xrange(7)] - - adjust = 0 - if not page.active: - adjust = 1 - - agwFlags = self.GetAGWFlags() - - tabPoints[0].x = tab_x + 3 - tabPoints[0].y = (agwFlags & AUI_NB_BOTTOM and [3] or [tab_height - 2])[0] - - tabPoints[1].x = tabPoints[0].x - tabPoints[1].y = (agwFlags & AUI_NB_BOTTOM and [tab_height - (vertical_border_padding + 2) - adjust] or \ - [(vertical_border_padding + 2) + adjust])[0] - - tabPoints[2].x = tabPoints[1].x+2 - tabPoints[2].y = (agwFlags & AUI_NB_BOTTOM and [tab_height - vertical_border_padding - adjust] or \ - [vertical_border_padding + adjust])[0] - - tabPoints[3].x = tab_x + tab_width - 2 - tabPoints[3].y = tabPoints[2].y - - tabPoints[4].x = tabPoints[3].x + 2 - tabPoints[4].y = tabPoints[1].y - - tabPoints[5].x = tabPoints[4].x - tabPoints[5].y = tabPoints[0].y - - tabPoints[6].x = tabPoints[0].x - tabPoints[6].y = tabPoints[0].y - - rr = wx.RectPP(tabPoints[2], tabPoints[5]) - self.DrawTabBackground(dc, rr, page.active, (agwFlags & AUI_NB_BOTTOM) == 0) - - dc.SetBrush(wx.TRANSPARENT_BRUSH) - dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))) - - # Draw the tab as rounded rectangle - dc.DrawPolygon(tabPoints) - - if page.active: - dc.DrawLine(tabPoints[0].x + 1, tabPoints[0].y, tabPoints[5].x , tabPoints[0].y) - - drawn_tab_yoff = tabPoints[1].y - drawn_tab_height = tabPoints[0].y - tabPoints[2].y - - text_offset = tab_x + 8 - close_button_width = 0 - if close_button_state != AUI_BUTTON_STATE_HIDDEN: - close_button_width = self._active_close_bmp.GetWidth() - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - text_offset += close_button_width - 4 - - if not page.enabled: - dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) - pagebitmap = page.dis_bitmap - else: - dc.SetTextForeground(page.text_colour) - pagebitmap = page.bitmap - - shift = -1 - if agwFlags & AUI_NB_BOTTOM: - shift = 2 - - bitmap_offset = 0 - if pagebitmap.IsOk(): - bitmap_offset = tab_x + 8 - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT and close_button_width: - bitmap_offset += close_button_width - 4 - - # draw bitmap - dc.DrawBitmap(pagebitmap, bitmap_offset, - drawn_tab_yoff + (drawn_tab_height/2) - (pagebitmap.GetHeight()/2) + shift, - True) - - text_offset = bitmap_offset + pagebitmap.GetWidth() - text_offset += 3 # bitmap padding - - else: - - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT == 0 or not close_button_width: - text_offset = tab_x + 8 - - # if the caption is empty, measure some temporary text - caption = page.caption - if caption == "": - caption = "Xj" - - if page.active: - dc.SetFont(self._selected_font) - textx, texty, dummy = dc.GetMultiLineTextExtent(caption) - else: - dc.SetFont(self._normal_font) - textx, texty, dummy = dc.GetMultiLineTextExtent(caption) - - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x) - close_button_width + 1) - else: - draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x) - close_button_width) - - ypos = drawn_tab_yoff + drawn_tab_height/2 - texty/2 - 1 + shift - - offset_focus = text_offset - - if control is not None: - if control.GetPosition() != wx.Point(text_offset+1, ypos): - control.SetPosition(wx.Point(text_offset+1, ypos)) - - if not control.IsShown(): - control.Show() - - if paint_control: - bmp = TakeScreenShot(control.GetScreenRect()) - dc.DrawBitmap(bmp, text_offset+1, ypos, True) - - controlW, controlH = control.GetSize() - text_offset += controlW + 4 - textx += controlW + 4 - - # draw tab text - rectx, recty, dummy = dc.GetMultiLineTextExtent(draw_text) - dc.DrawLabel(draw_text, wx.Rect(text_offset, ypos, rectx, recty)) - - # draw focus rectangle - if (agwFlags & AUI_NB_NO_TAB_FOCUS) == 0: - self.DrawFocusRectangle(dc, page, wnd, draw_text, offset_focus, bitmap_offset, drawn_tab_yoff+shift, - drawn_tab_height, rectx, recty) - - out_button_rect = wx.Rect() - # draw 'x' on tab (if enabled) - if close_button_state != AUI_BUTTON_STATE_HIDDEN: - - close_button_width = self._active_close_bmp.GetWidth() - bmp = self._disabled_close_bmp - - if close_button_state == AUI_BUTTON_STATE_HOVER: - bmp = self._hover_close_bmp - elif close_button_state == AUI_BUTTON_STATE_PRESSED: - bmp = self._pressed_close_bmp - - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - rect = wx.Rect(tab_x + 5, - drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2) + shift, - close_button_width, tab_height) - else: - rect = wx.Rect(tab_x + tab_width - close_button_width - 3, - drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2) + shift, - close_button_width, tab_height) - - # Indent the button if it is pressed down: - rect = IndentPressedBitmap(rect, close_button_state) - dc.DrawBitmap(bmp, rect.x, rect.y, True) - out_button_rect = rect - - out_tab_rect = wx.Rect(tab_x, tab_y, tab_width, tab_height) - dc.DestroyClippingRegion() - - return out_tab_rect, out_button_rect, x_extent - - - def DrawTabBackground(self, dc, rect, focus, upperTabs): - """ - Draws the tab background for the Firefox 2 style. - This is more consistent with L{FlatNotebook} than before. - - :param `dc`: a `wx.DC` device context; - :param `rect`: rectangle the tab should be confined to; - :param `focus`: whether the tab has focus or not; - :param `upperTabs`: whether the style is ``AUI_NB_TOP`` or ``AUI_NB_BOTTOM``. - """ - - # Define the rounded rectangle base on the given rect - # we need an array of 9 points for it - regPts = [wx.Point() for indx in xrange(9)] - - if focus: - if upperTabs: - leftPt = wx.Point(rect.x, rect.y + (rect.height / 10)*8) - rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 10)*8) - else: - leftPt = wx.Point(rect.x, rect.y + (rect.height / 10)*5) - rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 10)*5) - else: - leftPt = wx.Point(rect.x, rect.y + (rect.height / 2)) - rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 2)) - - # Define the top region - top = wx.RectPP(rect.GetTopLeft(), rightPt) - bottom = wx.RectPP(leftPt, rect.GetBottomRight()) - - topStartColour = wx.WHITE - - if not focus: - topStartColour = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 50) - - topEndColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE) - bottomStartColour = topEndColour - bottomEndColour = topEndColour - - # Incase we use bottom tabs, switch the colours - if upperTabs: - if focus: - dc.GradientFillLinear(top, topStartColour, topEndColour, wx.SOUTH) - dc.GradientFillLinear(bottom, bottomStartColour, bottomEndColour, wx.SOUTH) - else: - dc.GradientFillLinear(top, topEndColour , topStartColour, wx.SOUTH) - dc.GradientFillLinear(bottom, bottomStartColour, bottomEndColour, wx.SOUTH) - - else: - if focus: - dc.GradientFillLinear(bottom, topEndColour, bottomEndColour, wx.SOUTH) - dc.GradientFillLinear(top, topStartColour, topStartColour, wx.SOUTH) - else: - dc.GradientFillLinear(bottom, bottomStartColour, bottomEndColour, wx.SOUTH) - dc.GradientFillLinear(top, topEndColour, topStartColour, wx.SOUTH) - - dc.SetBrush(wx.TRANSPARENT_BRUSH) - - -class VC8TabArt(AuiDefaultTabArt): - """ A class to draw tabs using the Visual Studio 2005 (VC8) style. """ - - def __init__(self): - """ Default class constructor. """ - - AuiDefaultTabArt.__init__(self) - - - def Clone(self): - """ Clones the art object. """ - - art = type(self)() - art.SetNormalFont(self.GetNormalFont()) - art.SetSelectedFont(self.GetSelectedFont()) - art.SetMeasuringFont(self.GetMeasuringFont()) - - art = CopyAttributes(art, self) - return art - - - def SetSizingInfo(self, tab_ctrl_size, tab_count, minMaxTabWidth): - """ - Sets the tab sizing information. - - :param `tab_ctrl_size`: the size of the tab control area; - :param `tab_count`: the number of tabs; - :param `minMaxTabWidth`: a tuple containing the minimum and maximum tab widths - to be used when the ``AUI_NB_TAB_FIXED_WIDTH`` style is active. - """ - - AuiDefaultTabArt.SetSizingInfo(self, tab_ctrl_size, tab_count, minMaxTabWidth) - - minTabWidth, maxTabWidth = minMaxTabWidth - if minTabWidth > -1: - self._fixed_tab_width = max(self._fixed_tab_width, minTabWidth) - if maxTabWidth > -1: - self._fixed_tab_width = min(self._fixed_tab_width, maxTabWidth) - - self._fixed_tab_width -= 5 - - - def GetTabSize(self, dc, wnd, caption, bitmap, active, close_button_state, control=None): - """ - Returns the tab size for the given caption, bitmap and button state. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` instance object; - :param `caption`: the tab text caption; - :param `bitmap`: the bitmap displayed on the tab; - :param `active`: whether the tab is selected or not; - :param `close_button_state`: the state of the close button on the tab; - :param `control`: a `wx.Window` instance inside a tab (or ``None``). - """ - - tab_size, x_extent = AuiDefaultTabArt.GetTabSize(self, dc, wnd, caption, bitmap, - active, close_button_state, control) - - tab_width, tab_height = tab_size - - # add some padding - tab_width += 10 - tab_height += 2 - - return (tab_width, tab_height), x_extent - - - def DrawTab(self, dc, wnd, page, in_rect, close_button_state, paint_control=False): - """ - Draws a single tab. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` instance object; - :param `page`: the tab control page associated with the tab; - :param `in_rect`: rectangle the tab should be confined to; - :param `close_button_state`: the state of the close button on the tab; - :param `paint_control`: whether to draw the control inside a tab (if any) on a `wx.MemoryDC`. - """ - - # Visual Studio 8 style - - control = page.control - - # figure out the size of the tab - tab_size, x_extent = self.GetTabSize(dc, wnd, page.caption, page.bitmap, - page.active, close_button_state, control) - - tab_height = self._tab_ctrl_height - 1 - tab_width = tab_size[0] - tab_x = in_rect.x - tab_y = in_rect.y + in_rect.height - tab_height - - clip_width = tab_width + 3 - if tab_x + clip_width > in_rect.x + in_rect.width - 4: - clip_width = (in_rect.x + in_rect.width) - tab_x - 4 - - tabPoints = [wx.Point() for i in xrange(8)] - - # If we draw the first tab or the active tab, - # we draw a full tab, else we draw a truncated tab - # - # X(2) X(3) - # X(1) X(4) - # - # X(5) - # - # X(0),(7) X(6) - # - # - - adjust = 0 - if not page.active: - adjust = 1 - - agwFlags = self.GetAGWFlags() - tabPoints[0].x = (agwFlags & AUI_NB_BOTTOM and [tab_x] or [tab_x + adjust])[0] - tabPoints[0].y = (agwFlags & AUI_NB_BOTTOM and [2] or [tab_height - 3])[0] - - tabPoints[1].x = tabPoints[0].x + tab_height - vertical_border_padding - 3 - adjust - tabPoints[1].y = (agwFlags & AUI_NB_BOTTOM and [tab_height - (vertical_border_padding+2)] or \ - [(vertical_border_padding+2)])[0] - - tabPoints[2].x = tabPoints[1].x + 4 - tabPoints[2].y = (agwFlags & AUI_NB_BOTTOM and [tab_height - vertical_border_padding] or \ - [vertical_border_padding])[0] - - tabPoints[3].x = tabPoints[2].x + tab_width - tab_height + vertical_border_padding - tabPoints[3].y = (agwFlags & AUI_NB_BOTTOM and [tab_height - vertical_border_padding] or \ - [vertical_border_padding])[0] - - tabPoints[4].x = tabPoints[3].x + 1 - tabPoints[4].y = (agwFlags & AUI_NB_BOTTOM and [tabPoints[3].y - 1] or [tabPoints[3].y + 1])[0] - - tabPoints[5].x = tabPoints[4].x + 1 - tabPoints[5].y = (agwFlags & AUI_NB_BOTTOM and [(tabPoints[4].y - 1)] or [tabPoints[4].y + 1])[0] - - tabPoints[6].x = tabPoints[2].x + tab_width - tab_height + 2 + vertical_border_padding - tabPoints[6].y = tabPoints[0].y - - tabPoints[7].x = tabPoints[0].x - tabPoints[7].y = tabPoints[0].y - - self.FillVC8GradientColour(dc, tabPoints, page.active) - - dc.SetBrush(wx.TRANSPARENT_BRUSH) - - dc.SetPen(wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNSHADOW))) - dc.DrawPolygon(tabPoints) - - if page.active: - # Delete the bottom line (or the upper one, incase we use wxBOTTOM) - dc.SetPen(wx.WHITE_PEN) - dc.DrawLine(tabPoints[0].x, tabPoints[0].y, tabPoints[6].x, tabPoints[6].y) - - dc.SetClippingRegion(tab_x, tab_y, clip_width + 2, tab_height - 3) - - drawn_tab_yoff = tabPoints[1].y - drawn_tab_height = tabPoints[0].y - tabPoints[2].y - - text_offset = tab_x + 20 - close_button_width = 0 - if close_button_state != AUI_BUTTON_STATE_HIDDEN: - close_button_width = self._active_close_bmp.GetWidth() - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - text_offset += close_button_width - - if not page.enabled: - dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) - pagebitmap = page.dis_bitmap - else: - dc.SetTextForeground(page.text_colour) - pagebitmap = page.bitmap - - shift = 0 - if agwFlags & AUI_NB_BOTTOM: - shift = (page.active and [1] or [2])[0] - - bitmap_offset = 0 - if pagebitmap.IsOk(): - bitmap_offset = tab_x + 20 - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT and close_button_width: - bitmap_offset += close_button_width - - # draw bitmap - dc.DrawBitmap(pagebitmap, bitmap_offset, - drawn_tab_yoff + (drawn_tab_height/2) - (pagebitmap.GetHeight()/2) + shift, - True) - - text_offset = bitmap_offset + pagebitmap.GetWidth() - text_offset += 3 # bitmap padding - - else: - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT == 0 or not close_button_width: - text_offset = tab_x + tab_height - - # if the caption is empty, measure some temporary text - caption = page.caption - if caption == "": - caption = "Xj" - - if page.active: - dc.SetFont(self._selected_font) - textx, texty, dummy = dc.GetMultiLineTextExtent(caption) - else: - dc.SetFont(self._normal_font) - textx, texty, dummy = dc.GetMultiLineTextExtent(caption) - - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x)) - else: - draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x) - close_button_width) - - ypos = drawn_tab_yoff + drawn_tab_height/2 - texty/2 - 1 + shift - - offset_focus = text_offset - - if control is not None: - if control.GetPosition() != wx.Point(text_offset+1, ypos): - control.SetPosition(wx.Point(text_offset+1, ypos)) - - if not control.IsShown(): - control.Show() - - if paint_control: - bmp = TakeScreenShot(control.GetScreenRect()) - dc.DrawBitmap(bmp, text_offset+1, ypos, True) - - controlW, controlH = control.GetSize() - text_offset += controlW + 4 - textx += controlW + 4 - - # draw tab text - rectx, recty, dummy = dc.GetMultiLineTextExtent(draw_text) - dc.DrawLabel(draw_text, wx.Rect(text_offset, ypos, rectx, recty)) - - # draw focus rectangle - if (agwFlags & AUI_NB_NO_TAB_FOCUS) == 0: - self.DrawFocusRectangle(dc, page, wnd, draw_text, offset_focus, bitmap_offset, drawn_tab_yoff+shift, - drawn_tab_height+shift, rectx, recty) - - out_button_rect = wx.Rect() - # draw 'x' on tab (if enabled) - if close_button_state != AUI_BUTTON_STATE_HIDDEN: - - close_button_width = self._active_close_bmp.GetWidth() - bmp = self._disabled_close_bmp - - if close_button_state == AUI_BUTTON_STATE_HOVER: - bmp = self._hover_close_bmp - elif close_button_state == AUI_BUTTON_STATE_PRESSED: - bmp = self._pressed_close_bmp - - if page.active: - xpos = tab_x + tab_width - close_button_width + 3 - else: - xpos = tab_x + tab_width - close_button_width - 5 - - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - rect = wx.Rect(tab_x + 20, - drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2) + shift, - close_button_width, tab_height) - else: - rect = wx.Rect(xpos, - drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2) + shift, - close_button_width, tab_height) - - # Indent the button if it is pressed down: - rect = IndentPressedBitmap(rect, close_button_state) - dc.DrawBitmap(bmp, rect.x, rect.y, True) - out_button_rect = rect - - out_tab_rect = wx.Rect(tab_x, tab_y, x_extent, tab_height) - dc.DestroyClippingRegion() - - return out_tab_rect, out_button_rect, x_extent - - - def FillVC8GradientColour(self, dc, tabPoints, active): - """ - Fills the tab with the Visual Studio 2005 gradient background. - - :param `dc`: a `wx.DC` device context; - :param `tabPoints`: a list of `wx.Point` objects describing the tab shape; - :param `active`: whether the tab is selected or not. - """ - - xList = [pt.x for pt in tabPoints] - yList = [pt.y for pt in tabPoints] - - minx, maxx = min(xList), max(xList) - miny, maxy = min(yList), max(yList) - - rect = wx.Rect(minx, maxy, maxx-minx, miny-maxy+1) - region = wx.RegionFromPoints(tabPoints) - - if self._buttonRect.width > 0: - buttonRegion = wx.Region(*self._buttonRect) - region.XorRegion(buttonRegion) - - dc.SetClippingRegionAsRegion(region) - - if active: - bottom_colour = top_colour = wx.WHITE - else: - bottom_colour = StepColour(self._base_colour, 90) - top_colour = StepColour(self._base_colour, 170) - - dc.GradientFillLinear(rect, top_colour, bottom_colour, wx.SOUTH) - dc.DestroyClippingRegion() - - -class ChromeTabArt(AuiDefaultTabArt): - """ - A class to draw tabs using the Google Chrome browser style. - It uses custom bitmap to render the tabs, so that the look and feel is as close - as possible to the Chrome style. - """ - - def __init__(self): - """ Default class constructor. """ - - AuiDefaultTabArt.__init__(self) - - self.SetBitmaps(mirror=False) - - closeBmp = tab_close.GetBitmap() - closeHBmp = tab_close_h.GetBitmap() - closePBmp = tab_close_p.GetBitmap() - - self.SetCustomButton(AUI_BUTTON_CLOSE, AUI_BUTTON_STATE_NORMAL, closeBmp) - self.SetCustomButton(AUI_BUTTON_CLOSE, AUI_BUTTON_STATE_HOVER, closeHBmp) - self.SetCustomButton(AUI_BUTTON_CLOSE, AUI_BUTTON_STATE_PRESSED, closePBmp) - - - def SetAGWFlags(self, agwFlags): - """ - Sets the tab art flags. - - :param `agwFlags`: a combination of the following values: - - ==================================== ================================== - Flag name Description - ==================================== ================================== - ``AUI_NB_TOP`` With this style, tabs are drawn along the top of the notebook - ``AUI_NB_LEFT`` With this style, tabs are drawn along the left of the notebook. Not implemented yet. - ``AUI_NB_RIGHT`` With this style, tabs are drawn along the right of the notebook. Not implemented yet. - ``AUI_NB_BOTTOM`` With this style, tabs are drawn along the bottom of the notebook - ``AUI_NB_TAB_SPLIT`` Allows the tab control to be split by dragging a tab - ``AUI_NB_TAB_MOVE`` Allows a tab to be moved horizontally by dragging - ``AUI_NB_TAB_EXTERNAL_MOVE`` Allows a tab to be moved to another tab control - ``AUI_NB_TAB_FIXED_WIDTH`` With this style, all tabs have the same width - ``AUI_NB_SCROLL_BUTTONS`` With this style, left and right scroll buttons are displayed - ``AUI_NB_WINDOWLIST_BUTTON`` With this style, a drop-down list of windows is available - ``AUI_NB_CLOSE_BUTTON`` With this style, a close button is available on the tab bar - ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` With this style, a close button is available on the active tab - ``AUI_NB_CLOSE_ON_ALL_TABS`` With this style, a close button is available on all tabs - ``AUI_NB_MIDDLE_CLICK_CLOSE`` Allows to close L{AuiNotebook} tabs by mouse middle button click - ``AUI_NB_SUB_NOTEBOOK`` This style is used by L{AuiManager} to create automatic AuiNotebooks - ``AUI_NB_HIDE_ON_SINGLE_TAB`` Hides the tab window if only one tab is present - ``AUI_NB_SMART_TABS`` Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows - ``AUI_NB_USE_IMAGES_DROPDOWN`` Uses images on dropdown window list menu instead of check items - ``AUI_NB_CLOSE_ON_TAB_LEFT`` Draws the tab close button on the left instead of on the right (a la Camino browser) - ``AUI_NB_TAB_FLOAT`` Allows the floating of single tabs. Known limitation: when the notebook is more or less full screen, tabs cannot be dragged far enough outside of the notebook to become floating pages - ``AUI_NB_DRAW_DND_TAB`` Draws an image representation of a tab while dragging (on by default) - ``AUI_NB_ORDER_BY_ACCESS`` Tab navigation order by last access time for the tabs - ``AUI_NB_NO_TAB_FOCUS`` Don't draw tab focus rectangle - ==================================== ================================== - - :note: Overridden from L{AuiDefaultTabArt}. - """ - - if agwFlags & AUI_NB_TOP: - self.SetBitmaps(mirror=False) - elif agwFlags & AUI_NB_BOTTOM: - self.SetBitmaps(mirror=True) - - AuiDefaultTabArt.SetAGWFlags(self, agwFlags) - - - def SetBitmaps(self, mirror): - """ - Assigns the tab custom bitmaps - - :param `mirror`: whether to vertically mirror the bitmap or not. - """ - - bmps = [tab_active_left.GetBitmap(), tab_active_center.GetBitmap(), - tab_active_right.GetBitmap(), tab_inactive_left.GetBitmap(), - tab_inactive_center.GetBitmap(), tab_inactive_right.GetBitmap()] - - if mirror: - for indx, bmp in enumerate(bmps): - img = bmp.ConvertToImage() - img = img.Mirror(horizontally=False) - bmps[indx] = img.ConvertToBitmap() - - self._leftActiveBmp = bmps[0] - self._centerActiveBmp = bmps[1] - self._rightActiveBmp = bmps[2] - self._leftInactiveBmp = bmps[3] - self._centerInactiveBmp = bmps[4] - self._rightInactiveBmp = bmps[5] - - - def Clone(self): - """ Clones the art object. """ - - art = type(self)() - art.SetNormalFont(self.GetNormalFont()) - art.SetSelectedFont(self.GetSelectedFont()) - art.SetMeasuringFont(self.GetMeasuringFont()) - - art = CopyAttributes(art, self) - return art - - - def SetSizingInfo(self, tab_ctrl_size, tab_count, minMaxTabWidth): - """ - Sets the tab sizing information. - - :param `tab_ctrl_size`: the size of the tab control area; - :param `tab_count`: the number of tabs; - :param `minMaxTabWidth`: a tuple containing the minimum and maximum tab widths - to be used when the ``AUI_NB_TAB_FIXED_WIDTH`` style is active. - """ - - AuiDefaultTabArt.SetSizingInfo(self, tab_ctrl_size, tab_count, minMaxTabWidth) - - minTabWidth, maxTabWidth = minMaxTabWidth - if minTabWidth > -1: - self._fixed_tab_width = max(self._fixed_tab_width, minTabWidth) - if maxTabWidth > -1: - self._fixed_tab_width = min(self._fixed_tab_width, maxTabWidth) - - self._fixed_tab_width -= 5 - - - def GetTabSize(self, dc, wnd, caption, bitmap, active, close_button_state, control=None): - """ - Returns the tab size for the given caption, bitmap and button state. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` instance object; - :param `caption`: the tab text caption; - :param `bitmap`: the bitmap displayed on the tab; - :param `active`: whether the tab is selected or not; - :param `close_button_state`: the state of the close button on the tab; - :param `control`: a `wx.Window` instance inside a tab (or ``None``). - """ - - tab_size, x_extent = AuiDefaultTabArt.GetTabSize(self, dc, wnd, caption, bitmap, - active, close_button_state, control) - - tab_width, tab_height = tab_size - - # add some padding - tab_width += self._leftActiveBmp.GetWidth() - tab_height += 2 - - tab_height = max(tab_height, self._centerActiveBmp.GetHeight()) - - return (tab_width, tab_height), x_extent - - - def DrawTab(self, dc, wnd, page, in_rect, close_button_state, paint_control=False): - """ - Draws a single tab. - - :param `dc`: a `wx.DC` device context; - :param `wnd`: a `wx.Window` instance object; - :param `page`: the tab control page associated with the tab; - :param `in_rect`: rectangle the tab should be confined to; - :param `close_button_state`: the state of the close button on the tab; - :param `paint_control`: whether to draw the control inside a tab (if any) on a `wx.MemoryDC`. - """ - - # Chrome tab style - - control = page.control - # figure out the size of the tab - tab_size, x_extent = self.GetTabSize(dc, wnd, page.caption, page.bitmap, page.active, - close_button_state, control) - - agwFlags = self.GetAGWFlags() - - tab_height = self._tab_ctrl_height - 1 - tab_width = tab_size[0] - tab_x = in_rect.x - tab_y = in_rect.y + in_rect.height - tab_height - clip_width = tab_width - - if tab_x + clip_width > in_rect.x + in_rect.width - 4: - clip_width = (in_rect.x + in_rect.width) - tab_x - 4 - - dc.SetClippingRegion(tab_x, tab_y, clip_width + 1, tab_height - 3) - drawn_tab_yoff = 1 - - if page.active: - left = self._leftActiveBmp - center = self._centerActiveBmp - right = self._rightActiveBmp - else: - left = self._leftInactiveBmp - center = self._centerInactiveBmp - right = self._rightInactiveBmp - - dc.DrawBitmap(left, tab_x, tab_y) - leftw = left.GetWidth() - centerw = center.GetWidth() - rightw = right.GetWidth() - - available = tab_x + tab_width - rightw - posx = tab_x + leftw - - while 1: - if posx >= available: - break - dc.DrawBitmap(center, posx, tab_y) - posx += centerw - - dc.DrawBitmap(right, posx, tab_y) - - drawn_tab_height = center.GetHeight() - text_offset = tab_x + leftw - - close_button_width = 0 - if close_button_state != AUI_BUTTON_STATE_HIDDEN: - close_button_width = self._active_close_bmp.GetWidth() - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - text_offset += close_button_width - - if not page.enabled: - dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) - pagebitmap = page.dis_bitmap - else: - dc.SetTextForeground(page.text_colour) - pagebitmap = page.bitmap - - bitmap_offset = 0 - if pagebitmap.IsOk(): - bitmap_offset = tab_x + leftw - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT and close_button_width: - bitmap_offset += close_button_width - - # draw bitmap - dc.DrawBitmap(pagebitmap, bitmap_offset, - drawn_tab_yoff + (drawn_tab_height/2) - (pagebitmap.GetHeight()/2), - True) - - text_offset = bitmap_offset + pagebitmap.GetWidth() - text_offset += 3 # bitmap padding - - else: - - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT == 0 or not close_button_width: - text_offset = tab_x + leftw - - # if the caption is empty, measure some temporary text - caption = page.caption - if caption == "": - caption = "Xj" - - if page.active: - dc.SetFont(self._selected_font) - textx, texty, dummy = dc.GetMultiLineTextExtent(caption) - else: - dc.SetFont(self._normal_font) - textx, texty, dummy = dc.GetMultiLineTextExtent(caption) - - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x) - leftw) - else: - draw_text = ChopText(dc, caption, tab_width - (text_offset-tab_x) - close_button_width - leftw) - - ypos = drawn_tab_yoff + drawn_tab_height/2 - texty/2 - 1 - - if control is not None: - if control.GetPosition() != wx.Point(text_offset+1, ypos): - control.SetPosition(wx.Point(text_offset+1, ypos)) - - if not control.IsShown(): - control.Show() - - if paint_control: - bmp = TakeScreenShot(control.GetScreenRect()) - dc.DrawBitmap(bmp, text_offset+1, ypos, True) - - controlW, controlH = control.GetSize() - text_offset += controlW + 4 - - # draw tab text - rectx, recty, dummy = dc.GetMultiLineTextExtent(draw_text) - dc.DrawLabel(draw_text, wx.Rect(text_offset, ypos, rectx, recty)) - - out_button_rect = wx.Rect() - # draw 'x' on tab (if enabled) - if close_button_state != AUI_BUTTON_STATE_HIDDEN: - - close_button_width = self._active_close_bmp.GetWidth() - bmp = self._disabled_close_bmp - - if close_button_state == AUI_BUTTON_STATE_HOVER: - bmp = self._hover_close_bmp - elif close_button_state == AUI_BUTTON_STATE_PRESSED: - bmp = self._pressed_close_bmp - - if agwFlags & AUI_NB_CLOSE_ON_TAB_LEFT: - rect = wx.Rect(tab_x + leftw - 2, - drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2) + 1, - close_button_width, tab_height) - else: - rect = wx.Rect(tab_x + tab_width - close_button_width - rightw + 2, - drawn_tab_yoff + (drawn_tab_height / 2) - (bmp.GetHeight() / 2) + 1, - close_button_width, tab_height) - - if agwFlags & AUI_NB_BOTTOM: - rect.y -= 1 - - # Indent the button if it is pressed down: - rect = IndentPressedBitmap(rect, close_button_state) - dc.DrawBitmap(bmp, rect.x, rect.y, True) - out_button_rect = rect - - out_tab_rect = wx.Rect(tab_x, tab_y, tab_width, tab_height) - dc.DestroyClippingRegion() - - return out_tab_rect, out_button_rect, x_extent - - diff --git a/agw/aui/tabmdi.py b/agw/aui/tabmdi.py deleted file mode 100644 index ef09e9f..0000000 --- a/agw/aui/tabmdi.py +++ /dev/null @@ -1,666 +0,0 @@ -__author__ = "Andrea Gavana " -__date__ = "31 March 2009" - - -import wx - -import auibook -from aui_constants import * - -_ = wx.GetTranslation - -#----------------------------------------------------------------------------- -# AuiMDIParentFrame -#----------------------------------------------------------------------------- - -class AuiMDIParentFrame(wx.Frame): - - def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition, - size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE|wx.VSCROLL|wx.HSCROLL, - name="AuiMDIParentFrame"): - - wx.Frame.__init__(self, parent, id, title, pos, size, style, name=name) - self.Init() - - self.Bind(wx.EVT_MENU, self.DoHandleMenu, id=wx.ID_ANY) - - # this style can be used to prevent a window from having the standard MDI - # "Window" menu - if not style & wx.FRAME_NO_WINDOW_MENU: - - self._pWindowMenu = wx.Menu() - self._pWindowMenu.Append(wxWINDOWCLOSE, _("Cl&ose")) - self._pWindowMenu.Append(wxWINDOWCLOSEALL, _("Close All")) - self._pWindowMenu.AppendSeparator() - self._pWindowMenu.Append(wxWINDOWNEXT, _("&Next")) - self._pWindowMenu.Append(wxWINDOWPREV, _("&Previous")) - - self._pClientWindow = self.OnCreateClient() - - - def SetArtProvider(self, provider): - - if self._pClientWindow: - self._pClientWindow.SetArtProvider(provider) - - - def GetArtProvider(self): - - if not self._pClientWindow: - return None - - return self._pClientWindow.GetArtProvider() - - - def GetNotebook(self): - - return self._pClientWindow - - - def SetWindowMenu(self, pMenu): - - # Replace the window menu from the currently loaded menu bar. - pMenuBar = self.GetMenuBar() - - if self._pWindowMenu: - self.RemoveWindowMenu(pMenuBar) - del self._pWindowMenu - self._pWindowMenu = None - - if pMenu: - self._pWindowMenu = pMenu - self.AddWindowMenu(pMenuBar) - - - def GetWindowMenu(self): - - return self._pWindowMenu - - - def SetMenuBar(self, pMenuBar): - - # Remove the Window menu from the old menu bar - self.RemoveWindowMenu(self.GetMenuBar()) - - # Add the Window menu to the new menu bar. - self.AddWindowMenu(pMenuBar) - - wx.Frame.SetMenuBar(self, pMenuBar) - - - def SetChildMenuBar(self, pChild): - - if not pChild: - - # No Child, set Our menu bar back. - if self._pMyMenuBar: - self.SetMenuBar(self._pMyMenuBar) - else: - self.SetMenuBar(self.GetMenuBar()) - - # Make sure we know our menu bar is in use - self._pMyMenuBar = None - - else: - - if pChild.GetMenuBar() == None: - return - - # Do we need to save the current bar? - if self._pMyMenuBar == None: - self._pMyMenuBar = self.GetMenuBar() - - self.SetMenuBar(pChild.GetMenuBar()) - - - def ProcessEvent(self, event): - - # stops the same event being processed repeatedly - if self._pLastEvt == event: - return False - - self._pLastEvt = event - - # let the active child (if any) process the event first. - res = False - if self._pActiveChild and event.IsCommandEvent() and \ - event.GetEventObject() != self._pClientWindow and \ - event.GetEventType() not in [wx.wxEVT_ACTIVATE, wx.wxEVT_SET_FOCUS, - wx.wxEVT_KILL_FOCUS, wx.wxEVT_CHILD_FOCUS, - wx.wxEVT_COMMAND_SET_FOCUS, wx.wxEVT_COMMAND_KILL_FOCUS]: - - res = self._pActiveChild.GetEventHandler().ProcessEvent(event) - - if not res: - - # if the event was not handled this frame will handle it, - # which is why we need the protection code at the beginning - # of this method - res = self.GetEventHandler().ProcessEvent(event) - - self._pLastEvt = None - - return res - - - def GetActiveChild(self): - - return self._pActiveChild - - - def SetActiveChild(self, pChildFrame): - - self._pActiveChild = pChildFrame - - - def GetClientWindow(self): - - return self._pClientWindow - - - def OnCreateClient(self): - - return AuiMDIClientWindow(self) - - - def ActivateNext(self): - - if self._pClientWindow and self._pClientWindow.GetSelection() != wx.NOT_FOUND: - - active = self._pClientWindow.GetSelection() + 1 - if active >= self._pClientWindow.GetPageCount(): - active = 0 - - self._pClientWindow.SetSelection(active) - - - def ActivatePrevious(self): - - if self._pClientWindow and self._pClientWindow.GetSelection() != wx.NOT_FOUND: - - active = self._pClientWindow.GetSelection() - 1 - if active < 0: - active = self._pClientWindow.GetPageCount() - 1 - - self._pClientWindow.SetSelection(active) - - - def Init(self): - - self._pLastEvt = None - - self._pClientWindow = None - self._pActiveChild = None - self._pWindowMenu = None - self._pMyMenuBar = None - - - def RemoveWindowMenu(self, pMenuBar): - - if pMenuBar and self._pWindowMenu: - - # Remove old window menu - pos = pMenuBar.FindMenu(_("&Window")) - if pos != wx.NOT_FOUND: - pMenuBar.Remove(pos) - - - def AddWindowMenu(self, pMenuBar): - - if pMenuBar and self._pWindowMenu: - - pos = pMenuBar.FindMenu(wx.GetStockLabel(wx.ID_HELP, wx.STOCK_NOFLAGS)) - if pos == wx.NOT_FOUND: - pMenuBar.Append(self._pWindowMenu, _("&Window")) - else: - pMenuBar.Insert(pos, self._pWindowMenu, _("&Window")) - - - def DoHandleMenu(self, event): - - evId = event.GetId() - - if evId == wxWINDOWCLOSE: - if self._pActiveChild: - self._pActiveChild.Close() - - elif evId == wxWINDOWCLOSEALL: - - while self._pActiveChild: - if not self._pActiveChild.Close(): - return # failure - - elif evId == wxWINDOWNEXT: - self.ActivateNext() - - elif evId == wxWINDOWPREV: - self.ActivatePrevious() - - else: - event.Skip() - - - def Tile(self, orient=wx.HORIZONTAL): - - client_window = self.GetClientWindow() - if not client_window: - raise Exception("Missing MDI Client Window") - - cur_idx = client_window.GetSelection() - if cur_idx == -1: - return - - if orient == wx.VERTICAL: - - client_window.Split(cur_idx, wx.LEFT) - - elif orient == wx.HORIZONTAL: - - client_window.Split(cur_idx, wx.TOP) - - -#----------------------------------------------------------------------------- -# AuiMDIChildFrame -#----------------------------------------------------------------------------- - -class AuiMDIChildFrame(wx.PyPanel): - - def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition, - size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="AuiMDIChildFrame"): - - pClientWindow = parent.GetClientWindow() - if pClientWindow is None: - raise Exception("Missing MDI client window.") - - self.Init() - - # see comment in constructor - if style & wx.MINIMIZE: - self._activate_on_create = False - - cli_size = pClientWindow.GetClientSize() - - # create the window off-screen to prevent flicker - wx.PyPanel.__init__(self, pClientWindow, id, wx.Point(cli_size.x+1, cli_size.y+1), - size, wx.NO_BORDER, name=name) - - self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) - self.Show(False) - self.SetMDIParentFrame(parent) - - # this is the currently active child - parent.SetActiveChild(self) - self._title = title - - pClientWindow.AddPage(self, title, self._activate_on_create) - pClientWindow.Refresh() - - self.Bind(wx.EVT_MENU_HIGHLIGHT_ALL, self.OnMenuHighlight) - self.Bind(wx.EVT_ACTIVATE, self.OnActivate) - self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) - - - def Init(self): - - # There are two ways to create an tabbed mdi child fram without - # making it the active document. Either Show(False) can be called - # before Create() (as is customary on some ports with wxFrame-type - # windows), or wx.MINIMIZE can be passed in the style flags. Note that - # AuiMDIChildFrame is not really derived from wxFrame, as MDIChildFrame - # is, but those are the expected symantics. No style flag is passed - # onto the panel underneath. - - self._activate_on_create = True - - self._pMDIParentFrame = None - self._pMenuBar = None - - self._mdi_currect = None - self._mdi_newrect = wx.Rect() - self._icon = None - self._icon_bundle = None - - - def Destroy(self): - - pParentFrame = self.GetMDIParentFrame() - if not pParentFrame: - raise Exception("Missing MDI Parent Frame") - - pClientWindow = pParentFrame.GetClientWindow() - if not pClientWindow: - raise Exception("Missing MDI Client Window") - - if pParentFrame.GetActiveChild() == self: - - # deactivate ourself - event = wx.ActivateEvent(wx.wxEVT_ACTIVATE, False, self.GetId()) - event.SetEventObject(self) - self.GetEventHandler().ProcessEvent(event) - - pParentFrame.SetActiveChild(None) - pParentFrame.SetChildMenuBar(None) - - for pos in xrange(pClientWindow.GetPageCount()): - if pClientWindow.GetPage(pos) == self: - return pClientWindow.DeletePage(pos) - - return False - - - def SetMenuBar(self, menu_bar): - - pOldMenuBar = self._pMenuBar - self._pMenuBar = menu_bar - - if self._pMenuBar: - - pParentFrame = self.GetMDIParentFrame() - if not pParentFrame: - raise Exception("Missing MDI Parent Frame") - - self._pMenuBar.Reparent(pParentFrame) - if pParentFrame.GetActiveChild() == self: - - # replace current menu bars - if pOldMenuBar: - pParentFrame.SetChildMenuBar(None) - - pParentFrame.SetChildMenuBar(self) - - - def GetMenuBar(self): - - return self._pMenuBar - - - def SetTitle(self, title): - - self._title = title - - pParentFrame = self.GetMDIParentFrame() - if not pParentFrame: - raise Exception("Missing MDI Parent Frame") - - pClientWindow = pParentFrame.GetClientWindow() - if pClientWindow is not None: - - for pos in xrange(pClientWindow.GetPageCount()): - if pClientWindow.GetPage(pos) == self: - pClientWindow.SetPageText(pos, self._title) - break - - - def GetTitle(self): - - return self._title - - - def SetIcons(self, icons): - - # get icon with the system icon size - self.SetIcon(icons.GetIcon(-1)) - self._icon_bundle = icons - - - def GetIcons(self): - - return self._icon_bundle - - - def SetIcon(self, icon): - - pParentFrame = self.GetMDIParentFrame() - if not pParentFrame: - raise Exception("Missing MDI Parent Frame") - - self._icon = icon - - bmp = wx.BitmapFromIcon(self._icon) - - pClientWindow = pParentFrame.GetClientWindow() - if pClientWindow is not None: - idx = pClientWindow.GetPageIndex(self) - if idx != -1: - pClientWindow.SetPageBitmap(idx, bmp) - - - def GetIcon(self): - - return self._icon - - - def Activate(self): - - pParentFrame = self.GetMDIParentFrame() - if not pParentFrame: - raise Exception("Missing MDI Parent Frame") - - pClientWindow = pParentFrame.GetClientWindow() - if pClientWindow is not None: - - for pos in xrange(pClientWindow.GetPageCount()): - if pClientWindow.GetPage(pos) == self: - pClientWindow.SetSelection(pos) - break - - - def OnMenuHighlight(self, event): - - if self._pMDIParentFrame: - - # we don't have any help text for this item, - # but may be the MDI frame does? - self._pMDIParentFrame.OnMenuHighlight(event) - - - def OnActivate(self, event): - - # do nothing - pass - - - def OnCloseWindow(self, event): - - pParentFrame = self.GetMDIParentFrame() - if pParentFrame: - if pParentFrame.GetActiveChild() == self: - - pParentFrame.SetActiveChild(None) - pParentFrame.SetChildMenuBar(None) - - pClientWindow = pParentFrame.GetClientWindow() - idx = pClientWindow.GetPageIndex(self) - - if idx != wx.NOT_FOUND: - pClientWindow.RemovePage(idx) - - self.Destroy() - - - def SetMDIParentFrame(self, parentFrame): - - self._pMDIParentFrame = parentFrame - - - def GetMDIParentFrame(self): - - return self._pMDIParentFrame - - - def CreateStatusBar(self, number=1, style=1, winid=1, name=""): - - return None - - - def GetStatusBar(self): - - return None - - - def SetStatusText(self, text, number=0): - - pass - - - def SetStatusWidths(self, widths_field): - - pass - - - # no toolbar bars - def CreateToolBar(self, style=1, winid=-1, name=""): - - return None - - - def GetToolBar(self): - - return None - - - # no maximize etc - def Maximize(self, maximize=True): - - pass - - - def Restore(self): - - pass - - - def Iconize(self, iconize=True): - - pass - - - def IsMaximized(self): - - return True - - - def IsIconized(self): - - return False - - - def ShowFullScreen(self, show=True, style=0): - - return False - - - def IsFullScreen(self): - - return False - - - def IsTopLevel(self): - - return False - - - # renamed from Show(). - def ActivateOnCreate(self, activate_on_create): - - self._activate_on_create = activate_on_create - return True - - - def Show(self, show=True): - - wx.PyPanel.Show(self, show) - - - def ApplyMDIChildFrameRect(self): - - if self._mdi_currect != self._mdi_newrect: - self.SetDimensions(*self._mdi_newrect) - self._mdi_currect = wx.Rect(*self._mdi_newrect) - - -#----------------------------------------------------------------------------- -# AuiMDIClientWindow -#----------------------------------------------------------------------------- - -class AuiMDIClientWindow(auibook.AuiNotebook): - - def __init__(self, parent, agwStyle=0): - - auibook.AuiNotebook.__init__(self, parent, wx.ID_ANY, wx.Point(0, 0), wx.Size(100, 100), - agwStyle=AUI_NB_DEFAULT_STYLE|wx.NO_BORDER) - - caption_icon_size = wx.Size(wx.SystemSettings.GetMetric(wx.SYS_SMALLICON_X), - wx.SystemSettings.GetMetric(wx.SYS_SMALLICON_Y)) - self.SetUniformBitmapSize(caption_icon_size) - - bkcolour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_APPWORKSPACE) - self.SetOwnBackgroundColour(bkcolour) - - self._mgr.GetArtProvider().SetColour(AUI_DOCKART_BACKGROUND_COLOUR, bkcolour) - - self.Bind(auibook.EVT_AUINOTEBOOK_PAGE_CHANGED, self.OnPageChanged) - self.Bind(auibook.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnPageClose) - self.Bind(wx.EVT_SIZE, self.OnSize) - - - def SetSelection(self, nPage): - - return auibook.AuiNotebook.SetSelection(self, nPage) - - - def PageChanged(self, old_selection, new_selection): - - # don't do anything if the page doesn't actually change - if old_selection == new_selection: - return - - # notify old active child that it has been deactivated - if old_selection != -1 and old_selection < self.GetPageCount(): - - old_child = self.GetPage(old_selection) - if not old_child: - raise Exception("AuiMDIClientWindow.PageChanged - null page pointer") - - event = wx.ActivateEvent(wx.wxEVT_ACTIVATE, False, old_child.GetId()) - event.SetEventObject(old_child) - old_child.GetEventHandler().ProcessEvent(event) - - # notify new active child that it has been activated - if new_selection != -1: - - active_child = self.GetPage(new_selection) - if not active_child: - raise Exception("AuiMDIClientWindow.PageChanged - null page pointer") - - event = wx.ActivateEvent(wx.wxEVT_ACTIVATE, True, active_child.GetId()) - event.SetEventObject(active_child) - active_child.GetEventHandler().ProcessEvent(event) - - if active_child.GetMDIParentFrame(): - active_child.GetMDIParentFrame().SetActiveChild(active_child) - active_child.GetMDIParentFrame().SetChildMenuBar(active_child) - - - def OnPageClose(self, event): - - wnd = self.GetPage(event.GetSelection()) - wnd.Close() - - # regardless of the result of wnd.Close(), we've - # already taken care of the close operations, so - # suppress further processing - event.Veto() - - - def OnPageChanged(self, event): - - self.PageChanged(event.GetOldSelection(), event.GetSelection()) - - - def OnSize(self, event): - - auibook.AuiNotebook.OnSize(self, event) - - for pos in xrange(self.GetPageCount()): - self.GetPage(pos).ApplyMDIChildFrameRect() diff --git a/iramuteq.py b/iramuteq.py index 42b8fa8..aad2ebd 100644 --- a/iramuteq.py +++ b/iramuteq.py @@ -28,8 +28,8 @@ import logging #------------------------------------ import wx #import wx.aui -#import wx.lib.agw.aui as aui -import agw.aui as aui +import wx.lib.agw.aui as aui +#import agw.aui as aui import wx.html import wx.grid import wx.lib.hyperlink as hl diff --git a/layout.py b/layout.py index 3e30c62..0e2d5a9 100644 --- a/layout.py +++ b/layout.py @@ -7,7 +7,8 @@ import os import wx import wx.lib.hyperlink as hl -import agw.aui as aui +#import agw.aui as aui +import wx.lib.agw.aui as aui from chemins import ConstructPathOut, ChdTxtPathOut, FFF, ffr, PathOut, StatTxtPathOut, simipath from ConfigParser import ConfigParser from functions import ReadProfileAsDico, GetTxtProfile, read_list_file, ReadList, exec_rcode, print_liste, BugReport, DoConf, indices_simi, check_Rresult, progressbar diff --git a/profile_segment.py b/profile_segment.py index 3973d84..9a89195 100644 --- a/profile_segment.py +++ b/profile_segment.py @@ -6,7 +6,8 @@ import tempfile from ProfList import * -import agw.aui as aui +#import agw.aui as aui +import wx.lib.agw.aui as aui from functions import exec_rcode, check_Rresult, ReadProfileAsDico, ReadList from listlex import * from dialog import PrefSegProf, PrefProfTypes -- 2.7.4