1
#-------------------------------------------------------------------------------
3
# Copyright (c) 2007, Enthought, Inc.
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
11
# Thanks for using Enthought open source!
13
# Author: David C. Morrill
16
#-------------------------------------------------------------------------------
18
""" Defines a ThemedWindow base class for creating themed windows.
21
#-------------------------------------------------------------------------------
23
#-------------------------------------------------------------------------------
28
import HasPrivateTraits, HasTraits, Instance, Str, Enum, Any, Bool
30
from traitsui.ui_traits \
34
import init_wx_handlers, BufferDC
36
#-------------------------------------------------------------------------------
37
# 'ThemedWindow' class:
38
#-------------------------------------------------------------------------------
40
class ThemedWindow ( HasPrivateTraits ):
42
#-- Public Traits ----------------------------------------------------------
44
# The theme associated with this window:
47
# The default alignment to use:
48
default_alignment = Enum( 'left', 'center', 'right' )
50
# The current mouse event state:
51
state = Str( 'normal' )
53
# Optional controller used for overriding event handling:
54
controller = Instance( HasTraits )
56
# Should debugging information be overlaid on the theme?
59
#-- Public Methods ---------------------------------------------------------
61
def init_control ( self ):
62
""" Initializes the underlying wx.Window object.
64
init_wx_handlers( self.control, self )
66
def in_control ( self, x, y ):
67
""" Returns whether a specified (x,y) coordinate is inside the control
70
wdx, wdy = self.control.GetClientSize()
71
return ((0 <= x < wdx) and (0 <= y < wdy))
74
""" Refreshes the contents of the control.
76
if self.control is not None:
77
self.control.Refresh()
79
def capture_mouse ( self ):
80
""" Grab control of the mouse and indicate that we are controlling it.
82
if not self._has_capture:
83
self._has_capture = True
84
self.control.CaptureMouse()
86
def release_mouse ( self ):
87
""" Grab control of the mouse and indicate that we are controlling it.
90
self._has_capture = False
91
self.control.ReleaseMouse()
93
#-- Trait Event Handlers ---------------------------------------------------
95
def _theme_changed ( self ):
96
""" Handles the 'theme' trait being changed.
100
#-- wxPython Event Handlers ------------------------------------------------
102
def _erase_background ( self, event ):
103
""" Do not erase the background here (do it in the 'on_paint' handler).
107
def _paint ( self, event ):
108
""" Paint the background using the associated ImageSlice object.
110
dc = BufferDC( self.control )
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
120
from image_slice import paint_parent
122
# Repaint the parent's theme (if necessary):
123
paint_parent( dc, self.control )
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 )
133
dc.SetPen( wx.Pen( wx.RED ) )
134
dc.SetBrush( wx.TRANSPARENT_BRUSH )
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 )
151
if slice.xtop >= slice.xbottom:
152
y, dy = 0, slice.xtop
154
y, dy = wdy - slice.xbottom, slice.xbottom
157
x = slice.xleft + label.left
159
dc.DrawRectangle( x - 1, y - 1,
160
wdx - slice.xright - label.right - x + 2,
161
dy - label.bottom - label.top + 2 )
163
def _paint_fg ( self, dc ):
164
""" Paints the foreground of the window into the supplied device
169
def _size ( self, event ):
170
""" Handles the control being resized.
172
control = self.control
173
if control is not None:
177
def _left_down ( self, event ):
178
""" Handles a left mouse button down event.
180
self.control.SetFocus()
182
self._mouse_event( 'left_down', event )
184
def _left_up ( self, event ):
185
""" Handles a left mouse button up event.
187
if self._has_capture:
188
self._has_capture = False
189
self.control.ReleaseMouse()
190
self._mouse_event( 'left_up', event )
192
def _left_dclick ( self, event ):
193
""" Handles a left mouse button double click event.
196
self._mouse_event( 'left_dclick', event )
198
def _middle_down ( self, event ):
199
""" Handles a middle mouse button down event.
202
self._mouse_event( 'middle_down', event )
204
def _middle_up ( self, event ):
205
""" Handles a middle mouse button up event.
208
self._mouse_event( 'middle_up', event )
210
def _middle_dclick ( self, event ):
211
""" Handles a middle mouse button double click event.
214
self._mouse_event( 'middle_dclick', event )
216
def _right_down ( self, event ):
217
""" Handles a right mouse button down event.
220
self._mouse_event( 'right_down', event )
222
def _right_up ( self, event ):
223
""" Handles a right mouse button up event.
226
self._mouse_event( 'right_up', event )
228
def _right_dclick ( self, event ):
229
""" Handles a right mouse button double click event.
232
self._mouse_event( 'right_dclick', event )
234
def _motion ( self, event ):
235
""" Handles a mouse move event.
237
self._mouse_event( 'motion', event )
239
def _enter ( self, event ):
240
""" Handles the mouse entering the window event.
242
self._mouse_event( 'enter', event )
244
def _leave ( self, event ):
245
""" Handles the mouse leaving the window event.
247
self._mouse_event( 'leave', event )
249
def _wheel ( self, event ):
250
""" Handles a mouse wheel event.
252
self._mouse_event( 'wheel', event )
254
#-- Private Methods --------------------------------------------------------
256
def _mouse_event ( self, name, event ):
257
""" Routes a mouse event to the proper handler (if any).
259
method_name = '%s_%s' % ( self.state, name )
262
if self.controller is not None:
263
method = getattr( self.controller, method_name, None )
266
method = getattr( self, method_name, None )
268
if method is not None:
269
method( event.GetX(), event.GetY(), event )