1# (C) Copyright 2005-2020 Enthought, Inc., Austin, TX
2# All rights reserved.
3#
4# This software is provided without warranty under the terms of the BSD
5# license included in LICENSE.txt and may be redistributed only under
6# the conditions described in the aforementioned license. The license
7# is also available online at http://www.enthought.com/licenses/BSD.txt
8#
9# Thanks for using Enthought open source!
10
11
12""" Enthought pyface package component
13"""
14
15
16import sys
17
18
19import wx
20from pyface.wx.aui import aui, PyfaceAuiManager
21
22
23from pyface.action.api import MenuBarManager, StatusBarManager
24from pyface.action.api import ToolBarManager
25from traits.api import Instance, List, on_trait_change, provides, Str
26from pyface.i_application_window import IApplicationWindow
27from pyface.i_application_window import MApplicationWindow
28from pyface.image_resource import ImageResource
29
30
31from .window import Window
32
33
34@provides(IApplicationWindow)
35class ApplicationWindow(MApplicationWindow, Window):
36    """ The toolkit specific implementation of an ApplicationWindow.  See the
37    IApplicationWindow interface for the API documentation.
38    """
39
40    # 'IApplicationWindow' interface ---------------------------------------
41
42    icon = Instance(ImageResource)
43
44    menu_bar_manager = Instance(MenuBarManager)
45
46    status_bar_manager = Instance(StatusBarManager)
47
48    tool_bar_manager = Instance(ToolBarManager)
49
50    # If the underlying toolkit supports multiple toolbars then you can use
51    # this list instead.
52    tool_bar_managers = List(ToolBarManager)
53
54    # 'IWindow' interface -------------------------------------------------#
55
56    # fixme: We can't set the default value of the actual 'size' trait here as
57    # in the toolkit-specific event handlers for window size and position
58    # changes, we set the value of the shadow '_size' trait. The problem is
59    # that by doing that traits never knows that the trait has been set and
60    # hence always returns the default value! Using a trait initializer method
61    # seems to work however (e.g. 'def _size_default'). Hmmmm....
62    ##     size = (800, 600)
63
64    title = Str("Pyface")
65
66    # ------------------------------------------------------------------------
67    # Protected 'IApplicationWindow' interface.
68    # ------------------------------------------------------------------------
69
70    def _create_contents(self, parent):
71        panel = wx.Panel(parent, -1, name="ApplicationWindow")
72        panel.SetBackgroundColour("blue")
73        return panel
74
75    def _create_menu_bar(self, parent):
76        if self.menu_bar_manager is not None:
77            menu_bar = self.menu_bar_manager.create_menu_bar(parent)
78            self.control.SetMenuBar(menu_bar)
79
80    def _create_status_bar(self, parent):
81        if self.status_bar_manager is not None:
82            status_bar = self.status_bar_manager.create_status_bar(parent)
83            self.control.SetStatusBar(status_bar)
84
85    def _create_tool_bar(self, parent):
86        tool_bar_managers = self._get_tool_bar_managers()
87        if len(tool_bar_managers) > 0:
88            for tool_bar_manager in reversed(tool_bar_managers):
89                tool_bar = tool_bar_manager.create_tool_bar(parent, aui=True)
90                self._add_toolbar_to_aui_manager(tool_bar)
91            self._aui_manager.Update()
92
93    def _set_window_icon(self):
94        if self.icon is None:
95            icon = ImageResource("application.ico")
96        else:
97            icon = self.icon
98
99        if self.control is not None:
100            self.control.SetIcon(icon.create_icon())
101
102    # ------------------------------------------------------------------------
103    # 'Window' interface.
104    # ------------------------------------------------------------------------
105
106    def _size_default(self):
107        """ Trait initialiser. """
108        return (800, 600)
109
110    # ------------------------------------------------------------------------
111    # Protected 'IWidget' interface.
112    # ------------------------------------------------------------------------
113
114    def _create(self):
115
116        super(ApplicationWindow, self)._create()
117
118        self._aui_manager = PyfaceAuiManager()
119        self._aui_manager.SetManagedWindow(self.control)
120
121        # Keep a reference to the AUI Manager in the control because Panes
122        # will need to access it in order to lay themselves out
123        self.control._aui_manager = self._aui_manager
124
125        contents = self._create_contents(self.control)
126        self._aui_manager.AddPane(contents, aui.AuiPaneInfo().CenterPane())
127
128        self._create_trim_widgets(self.control)
129
130        # Updating the AUI manager actually commits all of the pane's added
131        # to it (this allows batch updates).
132        self._aui_manager.Update()
133
134    def _create_control(self, parent):
135
136        style = (
137            wx.DEFAULT_FRAME_STYLE | wx.FRAME_NO_WINDOW_MENU | wx.CLIP_CHILDREN
138        )
139
140        control = wx.Frame(
141            parent,
142            -1,
143            self.title,
144            style=style,
145            size=self.size,
146            pos=self.position,
147        )
148
149        # Mac/Win needs this, otherwise background color is black
150        attr = control.GetDefaultAttributes()
151        control.SetBackgroundColour(attr.colBg)
152
153        return control
154
155    def destroy(self):
156        if self.control:
157            self._aui_manager.UnInit()
158        super(ApplicationWindow, self).destroy()
159
160    # ------------------------------------------------------------------------
161    # Private interface.
162    # ------------------------------------------------------------------------
163
164    def _add_toolbar_to_aui_manager(self, tool_bar):
165        """ Add a toolbar to the AUI manager. """
166
167        info = self._get_tool_bar_pane_info(tool_bar)
168        self._aui_manager.AddPane(tool_bar, info)
169
170    def _get_tool_bar_pane_info(self, tool_bar):
171        info = aui.AuiPaneInfo()
172        info.Caption(tool_bar.tool_bar_manager.name)
173        info.LeftDockable(False)
174        info.Name(tool_bar.tool_bar_manager.id)
175        info.RightDockable(False)
176        info.ToolbarPane()
177        info.Top()
178
179        return info
180
181    def _get_tool_bar_managers(self):
182        """ Return all tool bar managers specified for the window. """
183
184        # fixme: V3 remove the old-style single toolbar option!
185        if self.tool_bar_manager is not None:
186            tool_bar_managers = [self.tool_bar_manager]
187
188        else:
189            tool_bar_managers = self.tool_bar_managers
190
191        return tool_bar_managers
192
193    def _wx_enable_tool_bar(self, tool_bar, enabled):
194        """ Enable/Disablea tool bar. """
195
196        # AUI toolbars cannot be enabled/disabled.
197
198    def _wx_show_tool_bar(self, tool_bar, visible):
199        """ Hide/Show a tool bar. """
200
201        pane = self._aui_manager.GetPane(tool_bar.tool_bar_manager.id)
202
203        if visible:
204            pane.Show()
205
206        else:
207            # Without this workaround, toolbars know the sizes of other
208            # hidden toolbars and leave gaps in the toolbar dock
209            pane.window.Show(False)
210            self._aui_manager.DetachPane(pane.window)
211            info = self._get_tool_bar_pane_info(pane.window)
212            info.Hide()
213            self._aui_manager.AddPane(pane.window, info)
214
215        self._aui_manager.Update()
216
217        return
218
219    # Trait change handlers ------------------------------------------------
220
221    def _menu_bar_manager_changed(self):
222        if self.control is not None:
223            self._create_menu_bar(self.control)
224
225    def _status_bar_manager_changed(self, old, new):
226        if self.control is not None:
227            if old is not None:
228                self.control.SetStatusBar(None)
229                old.remove_status_bar(self.control)
230            self._create_status_bar(self.control)
231
232    @on_trait_change("tool_bar_manager, tool_bar_managers")
233    def _update_tool_bar_managers(self):
234        if self.control is not None:
235            self._create_tool_bar(self.control)
236
237    def _icon_changed(self):
238        self._set_window_icon()
239