File: gui.py

package info (click to toggle)
enthought-traits-ui 2.0.5-1
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 15,204 kB
  • ctags: 9,623
  • sloc: python: 45,547; sh: 32; makefile: 19
file content (243 lines) | stat: -rw-r--r-- 7,390 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#------------------------------------------------------------------------------
# Copyright (c) 2005, Enthought, Inc.
# All rights reserved.
# 
# This software is provided without warranty under the terms of the BSD
# license included in enthought/LICENSE.txt and may be redistributed only
# under the conditions described in the aforementioned license.  The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
# Thanks for using Enthought open source!
# 
# Author: Enthought, Inc.
# Description: <Enthought pyface package component>
#------------------------------------------------------------------------------
""" The GUI for a Pyface application. """


# Standard library imports.
import sys
import logging

# Major package imports.
import wx

# Enthought library imports.
from enthought.traits.api import HasTraits, Bool

# Local imports.
from system_metrics import SystemMetrics


# Create a logger for this module.
logger = logging.getLogger(__name__)


# fixme: Shouldn't this use delegation instead of inheriting from a wx class?
class GUI(wx.PySimpleApp, HasTraits):
    """ The GUI for a Pyface application. """

    #### 'GUI' interface ######################################################

    # Is the GUI busy? (i.e., should the busy cursor (often an hourglass) be
    # displayed.
    busy = Bool(False)

    # Has the GUI's event loop been started?
    started = Bool(False)

    ###########################################################################
    # 'GUI' CLASS interface.
    ###########################################################################

    def invoke_after(cls, millisecs, callable, *args, **kw):
        """ Invokes a callable after a specific delay in the main GUI thread.
        
        Returns the instance using which one can obtain the return value of the
        callable.

        fixme: This returns a wx-specific object!
        
        """
        
        return wx.FutureCall(millisecs, callable, *args, **kw)

    invoke_after = classmethod(invoke_after)

    def invoke_later(cls, callable, *args, **kw):
        """ Invokes a callable in the main GUI thread. """
        
        wx.CallAfter(callable, *args, **kw)

        return

    invoke_later = classmethod(invoke_later)

    def set_trait_after(cls, millisecs, obj, trait_name, new):
        """ Sets a trait after a specific delay in the main GUI thread.

        fixme: This returns a wx-specific object!

        """

        return wx.FutureCall(millisecs, setattr, obj, trait_name, new)

    set_trait_after = classmethod(set_trait_after)
    
    def set_trait_later(cls, obj, trait_name, new):
        """ Sets a trait in the main GUI thread. """

        wx.CallAfter(setattr, obj, trait_name, new)
        
        return

    set_trait_later = classmethod(set_trait_later)

    def process_events(allow_user_events=True):
        """ Process any pending GUI events. If allow_user_events is False then
        user generated events are not processed.

        """
        if allow_user_events:
            wx.Yield()
        else:
            wx.SafeYield()

    process_events = staticmethod(process_events)

    def set_busy(busy=True):
        """Specify if the GUI is busy.  If `True` is passed, the
        cursor is set to a 'busy' cursor.  Passing `False` will reset
        the cursor to the default.
        """
        if busy:
            GUI._cursor = wx.BusyCursor()
        else:
            GUI._cursor = None

    set_busy = staticmethod(set_busy)

    ###########################################################################
    # 'object' interface.
    ###########################################################################

    def __init__(self, splash_screen=None, redirect=False, filename=None):
        """ Creates a new GUI. """

        # The (optional) splash screen.
        #
        # fixme: For now, we have disabled splash screens on non-Windows
        # platforms as on Linux they cause the application to hang when they
        # are supposed to close (allegedly, this is for applications that use
        # the workbench plugin).
        if sys.platform == 'win32':
            self._splash_screen = splash_screen

        else:
            logger.warn('splash screen disabled on non-Windows platforms')
            self._splash_screen = None
            
        # The system metrics.
        self.system_metrics = SystemMetrics()
        
        # Base-class constructor.
        wx.PySimpleApp.__init__(self, redirect=redirect, filename=filename)

        return
    
    ###########################################################################
    # 'Wx.App' interface.
    ###########################################################################

    def OnInit(self):
        """ wx application initialization. """

        logger.debug("---------- starting GUI ---------- ")

        # Before we can load any images we have to initialize wxPython's image
        # handlers.
        wx.InitAllImageHandlers()

        # Show the (optional) splash screen.
        if self._splash_screen is not None:
            self._splash_screen.open()

        return True

    def OnExit(self):
        """ Called when the user wants to exit the application.

        OnExit() is called after destroying all application windows and
        controls, but before wxWindows cleanup.

        """

        logger.debug("---------- exiting GUI ---------- ")

        return

    ###########################################################################
    # 'GUI' interface.
    ###########################################################################

    def start_event_loop(self):
        """ Start the GUI event loop. """

        if self._splash_screen is not None:
            self._splash_screen.close()

        logger.debug("---------- starting GUI event loop ---------- ")

        # Make sure that we only set the 'started' trait after the main loop
        # has really started.
        self.invoke_after(10, setattr, self, "started", True)

        # A hack to force menus to appear for applications run on Mac
        # OS X.
        if sys.platform == 'darwin':
            def _mac_os_x_hack():
                f = wx.Frame(None, -1)
                f.Show(True)
                f.Close()
            self.invoke_later(_mac_os_x_hack)
        
        self.MainLoop()
        self.started = False

        return

    def stop_event_loop(self):
        """ Stop the GUI event loop. """

        self.ExitMainLoop()

        return

    #### Deprecated ###########################################################
    
    def event_loop(self):
        """ Start the GUI event loop. """

        logger.debug('DEPRECATED: Use GUI.start_event_loop')

        self.start_event_loop()
        
        return

    ###########################################################################
    # Private 'GUI' interface.
    ###########################################################################

    #### Trait change handlers ################################################

    def _busy_changed(self):
        """ Static trait change handler. """

        if self.busy:
            self._cursor = wx.BusyCursor()

        else:
            del self._cursor

        return
    
#### EOF ######################################################################