~ubuntu-branches/ubuntu/utopic/python-traitsui/utopic

« back to all changes in this revision

Viewing changes to traitsui/wx/themed_window.py

  • Committer: Bazaar Package Importer
  • Author(s): Varun Hiremath
  • Date: 2011-07-09 13:57:39 UTC
  • Revision ID: james.westby@ubuntu.com-20110709135739-x5u20q86huissmn1
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#-------------------------------------------------------------------------------
 
2
#
 
3
#  Copyright (c) 2007, Enthought, Inc.
 
4
#  All rights reserved.
 
5
#
 
6
#  This software is provided without warranty under the terms of the BSD
 
7
#  license included in enthought/LICENSE.txt and may be redistributed only
 
8
#  under the conditions described in the aforementioned license.  The license
 
9
#  is also available online at http://www.enthought.com/licenses/BSD.txt
 
10
#
 
11
#  Thanks for using Enthought open source!
 
12
#
 
13
#  Author: David C. Morrill
 
14
#  Date:   07/09/2007
 
15
#
 
16
#-------------------------------------------------------------------------------
 
17
 
 
18
""" Defines a ThemedWindow base class for creating themed windows.
 
19
"""
 
20
 
 
21
#-------------------------------------------------------------------------------
 
22
#  Imports:
 
23
#-------------------------------------------------------------------------------
 
24
 
 
25
import wx
 
26
 
 
27
from traits.api \
 
28
    import HasPrivateTraits, HasTraits, Instance, Str, Enum, Any, Bool
 
29
 
 
30
from traitsui.ui_traits \
 
31
    import ATheme
 
32
 
 
33
from helper \
 
34
    import init_wx_handlers, BufferDC
 
35
 
 
36
#-------------------------------------------------------------------------------
 
37
#  'ThemedWindow' class:
 
38
#-------------------------------------------------------------------------------
 
39
 
 
40
class ThemedWindow ( HasPrivateTraits ):
 
41
 
 
42
    #-- Public Traits ----------------------------------------------------------
 
43
 
 
44
    # The theme associated with this window:
 
45
    theme = ATheme
 
46
 
 
47
    # The default alignment to use:
 
48
    default_alignment = Enum( 'left', 'center', 'right' )
 
49
 
 
50
    # The current mouse event state:
 
51
    state = Str( 'normal' )
 
52
 
 
53
    # Optional controller used for overriding event handling:
 
54
    controller = Instance( HasTraits )
 
55
 
 
56
    # Should debugging information be overlaid on the theme?
 
57
    debug = Bool( False )
 
58
 
 
59
    #-- Public Methods ---------------------------------------------------------
 
60
 
 
61
    def init_control ( self ):
 
62
        """ Initializes the underlying wx.Window object.
 
63
        """
 
64
        init_wx_handlers( self.control, self )
 
65
 
 
66
    def in_control ( self, x, y ):
 
67
        """ Returns whether a specified (x,y) coordinate is inside the control
 
68
            or not.
 
69
        """
 
70
        wdx, wdy = self.control.GetClientSize()
 
71
        return ((0 <= x < wdx) and (0 <= y < wdy))
 
72
 
 
73
    def refresh ( self ):
 
74
        """ Refreshes the contents of the control.
 
75
        """
 
76
        if self.control is not None:
 
77
            self.control.Refresh()
 
78
 
 
79
    def capture_mouse ( self ):
 
80
        """ Grab control of the mouse and indicate that we are controlling it.
 
81
        """
 
82
        if not self._has_capture:
 
83
            self._has_capture = True
 
84
            self.control.CaptureMouse()
 
85
 
 
86
    def release_mouse ( self ):
 
87
        """ Grab control of the mouse and indicate that we are controlling it.
 
88
        """
 
89
        if self._has_capture:
 
90
            self._has_capture = False
 
91
            self.control.ReleaseMouse()
 
92
 
 
93
    #-- Trait Event Handlers ---------------------------------------------------
 
94
 
 
95
    def _theme_changed ( self ):
 
96
        """ Handles the 'theme' trait being changed.
 
97
        """
 
98
        self.refresh()
 
99
 
 
100
    #-- wxPython Event Handlers ------------------------------------------------
 
101
 
 
102
    def _erase_background ( self, event ):
 
103
        """ Do not erase the background here (do it in the 'on_paint' handler).
 
104
        """
 
105
        pass
 
106
 
 
107
    def _paint ( self, event ):
 
108
        """ Paint the background using the associated ImageSlice object.
 
109
        """
 
110
        dc = BufferDC( self.control )
 
111
        self._paint_bg( dc )
 
112
        self._paint_fg( dc )
 
113
        dc.copy()
 
114
 
 
115
    def _paint_bg ( self, dc ):
 
116
        """ Paints the background into the supplied device context using the
 
117
            associated ImageSlice object and returns the image slice used (if
 
118
            any).
 
119
        """
 
120
        from image_slice import paint_parent
 
121
 
 
122
        # Repaint the parent's theme (if necessary):
 
123
        paint_parent( dc, self.control )
 
124
 
 
125
        # Draw the background theme (if any):
 
126
        if self.theme is not None:
 
127
            slice = self.theme.image_slice
 
128
            if slice is not None:
 
129
                wdx, wdy = self.control.GetClientSize()
 
130
                slice.fill( dc, 0, 0, wdx, wdy, True )
 
131
 
 
132
                if self.debug:
 
133
                    dc.SetPen( wx.Pen( wx.RED ) )
 
134
                    dc.SetBrush( wx.TRANSPARENT_BRUSH )
 
135
                    theme  = self.theme
 
136
                    border = theme.border
 
137
                    dc.DrawRectangle( border.left, border.top,
 
138
                                      wdx - border.right  - border.left,
 
139
                                      wdy - border.bottom - border.top )
 
140
                    dc.DrawRectangle( border.left + 3, border.top + 3,
 
141
                                      wdx - border.right  - border.left - 6,
 
142
                                      wdy - border.bottom - border.top  - 6 )
 
143
                    content = theme.content
 
144
                    x = slice.xleft + content.left
 
145
                    y = slice.xtop  + content.top
 
146
                    dc.DrawRectangle( x - 1, y - 1,
 
147
                           wdx - slice.xright  - content.right  - x + 2,
 
148
                           wdy - slice.xbottom - content.bottom - y + 2 )
 
149
 
 
150
                    label = theme.label
 
151
                    if slice.xtop >= slice.xbottom:
 
152
                        y, dy = 0, slice.xtop
 
153
                    else:
 
154
                        y, dy = wdy - slice.xbottom, slice.xbottom
 
155
 
 
156
                    if dy >= 13:
 
157
                        x  = slice.xleft + label.left
 
158
                        y += label.top
 
159
                        dc.DrawRectangle( x - 1, y - 1,
 
160
                            wdx - slice.xright - label.right - x + 2,
 
161
                            dy - label.bottom - label.top + 2 )
 
162
 
 
163
    def _paint_fg ( self, dc ):
 
164
        """ Paints the foreground of the window into the supplied device
 
165
            context.
 
166
        """
 
167
        pass
 
168
 
 
169
    def _size ( self, event ):
 
170
        """ Handles the control being resized.
 
171
        """
 
172
        control = self.control
 
173
        if control is not None:
 
174
            control.Layout()
 
175
            control.Refresh()
 
176
 
 
177
    def _left_down ( self, event ):
 
178
        """ Handles a left mouse button down event.
 
179
        """
 
180
        self.control.SetFocus()
 
181
        self.capture_mouse()
 
182
        self._mouse_event( 'left_down', event )
 
183
 
 
184
    def _left_up ( self, event ):
 
185
        """ Handles a left mouse button up event.
 
186
        """
 
187
        if self._has_capture:
 
188
            self._has_capture = False
 
189
            self.control.ReleaseMouse()
 
190
            self._mouse_event( 'left_up', event )
 
191
 
 
192
    def _left_dclick ( self, event ):
 
193
        """ Handles a left mouse button double click event.
 
194
        """
 
195
        self.capture_mouse()
 
196
        self._mouse_event( 'left_dclick', event )
 
197
 
 
198
    def _middle_down ( self, event ):
 
199
        """ Handles a middle mouse button down event.
 
200
        """
 
201
        self.capture_mouse()
 
202
        self._mouse_event( 'middle_down', event )
 
203
 
 
204
    def _middle_up ( self, event ):
 
205
        """ Handles a middle mouse button up event.
 
206
        """
 
207
        self.release_mouse()
 
208
        self._mouse_event( 'middle_up', event )
 
209
 
 
210
    def _middle_dclick ( self, event ):
 
211
        """ Handles a middle mouse button double click event.
 
212
        """
 
213
        self.capture_mouse()
 
214
        self._mouse_event( 'middle_dclick', event )
 
215
 
 
216
    def _right_down ( self, event ):
 
217
        """ Handles a right mouse button down event.
 
218
        """
 
219
        self.capture_mouse()
 
220
        self._mouse_event( 'right_down', event )
 
221
 
 
222
    def _right_up ( self, event ):
 
223
        """ Handles a right mouse button up event.
 
224
        """
 
225
        self.release_mouse()
 
226
        self._mouse_event( 'right_up', event )
 
227
 
 
228
    def _right_dclick ( self, event ):
 
229
        """ Handles a right mouse button double click event.
 
230
        """
 
231
        self.capture_mouse()
 
232
        self._mouse_event( 'right_dclick', event )
 
233
 
 
234
    def _motion ( self, event ):
 
235
        """ Handles a mouse move event.
 
236
        """
 
237
        self._mouse_event( 'motion', event )
 
238
 
 
239
    def _enter ( self, event ):
 
240
        """ Handles the mouse entering the window event.
 
241
        """
 
242
        self._mouse_event( 'enter', event )
 
243
 
 
244
    def _leave ( self, event ):
 
245
        """ Handles the mouse leaving the window event.
 
246
        """
 
247
        self._mouse_event( 'leave', event )
 
248
 
 
249
    def _wheel ( self, event ):
 
250
        """ Handles a mouse wheel event.
 
251
        """
 
252
        self._mouse_event( 'wheel', event )
 
253
 
 
254
    #-- Private Methods --------------------------------------------------------
 
255
 
 
256
    def _mouse_event ( self, name, event ):
 
257
        """ Routes a mouse event to the proper handler (if any).
 
258
        """
 
259
        method_name = '%s_%s' % ( self.state, name )
 
260
        method      = None
 
261
 
 
262
        if self.controller is not None:
 
263
            method = getattr( self.controller, method_name, None )
 
264
 
 
265
        if method is None:
 
266
            method = getattr( self, method_name, None )
 
267
 
 
268
        if method is not None:
 
269
            method( event.GetX(), event.GetY(), event )
 
270