1 #---------------------------------------------------------------------------
2 # Name: EventManager.py
3 # Purpose: A module to demonstrate wxPython.lib.evtmgr.EventManager.
5 # Author: Robb Shecter (robb@acm.org)
7 # Created: 16-December-2002
8 # Copyright: (c) 2002 by Robb Shecter (robb@acm.org)
9 # Licence: wxWindows license
10 #---------------------------------------------------------------------------
12 from wxPython
.wx
import *
13 from wxPython
.lib
.evtmgr
import eventManager
15 #----------------------------------------------------------------------
17 class TestPanel(wxPanel
):
18 def __init__(self
, parent
, log
):
19 wxPanel
.__init
__(self
, parent
, -1)
22 fsize
= self
.GetFont().GetPointSize()
23 f1
= wxFont(fsize
+0, wxSWISS
, wxNORMAL
, wxNORMAL
)
24 f2
= wxFont(fsize
+2, wxSWISS
, wxNORMAL
, wxBOLD
)
25 f3
= wxFont(fsize
+6, wxSWISS
, wxNORMAL
, wxBOLD
)
27 title1
= wxStaticText(self
, -1, 'EventManager')
30 This demo shows (1) basic uses and features of the EventManager, as well
31 as (2) how it helps with a real-world task: creating independent, object-
32 oriented components."""
33 message0
= wxStaticText(self
, -1, txt
)
36 title2
= wxStaticText(self
, -1, 'Event Listeners')
40 These objects listen to motion events from the target window, using the ability
41 to register one event with multiple listeners. They also register for mouse events
42 on themselves to implement toggle-button functionality."""
43 message1
= wxStaticText(self
, -1, txt
)
46 title3
= wxStaticText(self
, -1, 'Target Window')
50 A passive window that's used as an event generator. Move the mouse over it to
51 send events to the listeners above."""
52 message2
= wxStaticText(self
, -1, txt
)
55 targetPanel
= Tile(self
, log
, bgColor
=wxColor(80,10,10), active
=0)
56 buttonPanel
= wxPanel(self
,-1)
57 sizer
= wxBoxSizer(wxHORIZONTAL
)
58 target
= targetPanel
.tile
61 for factor
in [0.2, 0.3, 0.4, 0.5, 0.6, 0.7]:
62 sizer
.Add(Tile(buttonPanel
, log
, factor
-0.05, target
), 0, wxALIGN_CENTER
)
64 sizer
.Add(Tile(buttonPanel
, log
, factor
, target
), 0, wxALIGN_CENTER
)
67 buttonPanel
.SetAutoLayout(1)
68 buttonPanel
.SetSizer(sizer
)
69 sizer
.Fit(buttonPanel
)
71 sizer
= wxBoxSizer(wxVERTICAL
)
72 sizer
.Add(title1
, 0, wxALIGN_CENTER | wxTOP | wxBOTTOM
, 6)
73 sizer
.Add(message0
, 0, wxALIGN_CENTER | wxALL
, 6)
74 sizer
.Add(title2
, 0, wxALIGN_CENTER | wxLEFT | wxTOP | wxRIGHT
, 16)
75 sizer
.Add(message1
, 0, wxALIGN_CENTER | wxALL
, 6)
76 sizer
.Add(buttonPanel
, 0, wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT
, 16)
77 sizer
.Add(title3
, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT
, 16)
78 sizer
.Add(message2
, 0, wxALIGN_CENTER | wxALL
, 6)
79 sizer
.Add(targetPanel
, 2, wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT
, 16)
87 This outer class is responsible for changing
88 its border color in response to certain mouse
89 events over its contained 'InnerTile'.
91 normal
= wxColor(150,150,150)
92 active
= wxColor(250,245,245)
93 hover
= wxColor(210,220,210)
95 def __init__(self
, parent
, log
, factor
=1, thingToWatch
=None, bgColor
=None, active
=1, size
=(38,38), borderWidth
=3):
96 wxPanel
.__init
__(self
, parent
, -1, size
=size
, style
=wxCLIP_CHILDREN
)
97 self
.tile
= InnerTile(self
, log
, factor
, thingToWatch
, bgColor
)
99 sizer
= wxBoxSizer(wxHORIZONTAL
)
100 sizer
.Add(self
.tile
, 1, wxEXPAND | wxALL
, borderWidth
)
101 self
.SetAutoLayout(1)
104 self
.SetBackgroundColour(Tile
.normal
)
106 # Register myself for mouse events over self.tile in order to
107 # create typical button/hyperlink visual effects.
108 eventManager
.Register(self
.setHover
, EVT_ENTER_WINDOW
, self
.tile
)
109 eventManager
.Register(self
.setNormal
, EVT_LEAVE_WINDOW
, self
.tile
)
110 eventManager
.Register(self
.setActive
, EVT_LEFT_DOWN
, self
.tile
)
111 eventManager
.Register(self
.setHover
, EVT_LEFT_UP
, self
.tile
)
114 def setHover(self
, event
):
115 self
.SetBackgroundColour(Tile
.hover
)
119 def setActive(self
, event
):
120 self
.SetBackgroundColour(Tile
.active
)
124 def setNormal(self
, event
):
125 self
.SetBackgroundColour(Tile
.normal
)
130 class InnerTile(wxPanel
):
131 IDLE_COLOR
= wxColor( 80, 10, 10)
132 START_COLOR
= wxColor(200, 70, 50)
133 FINAL_COLOR
= wxColor( 20, 80,240)
134 OFF_COLOR
= wxColor(185,190,185)
135 # Some pre-computation.
136 DELTAS
= map(lambda a
,b
: b
-a
, START_COLOR
.Get(), FINAL_COLOR
.Get())
137 START_COLOR_TUPLE
= START_COLOR
.Get()
140 This inner panel changes its color in reaction to mouse
141 events over the 'thingToWatch'.
143 def __init__(self
, parent
, log
, factor
, thingToWatch
=None, bgColor
=None):
144 wxPanel
.__init
__(self
, parent
, -1)
147 self
.SetBackgroundColour(bgColor
)
150 self
.thingToWatch
= thingToWatch
153 # Watch for the mouse click to enable/disable myself.
154 eventManager
.Register(self
.toggleOnOff
, EVT_LEFT_UP
, self
)
157 def toggleOnOff(self
, event
=None):
158 # Implement being on or off by registering and
159 # de-registering self.makeColor() from the event manager.
161 eventManager
.DeregisterListener(self
.makeColor
)
163 eventManager
.Register(self
.makeColor
, EVT_MOTION
, self
.thingToWatch
)
164 self
.state
= 1 - self
.state
168 def resetColor(self
, event
=None):
170 self
.setColor(InnerTile
.IDLE_COLOR
)
172 self
.setColor(InnerTile
.OFF_COLOR
)
175 def setColor(self
, color
):
176 self
.SetBackgroundColour(color
)
180 def makeColor(self
, mouseEvent
):
181 self
.makeColorFromTuple(mouseEvent
.GetPositionTuple())
184 def makeColorFromTuple(self
, (x
, y
)):
186 scaled
= min((x
+ y
) * self
.factor
, MAX
) # In range [0..MAX]
187 percent
= scaled
/ MAX
188 r
= InnerTile
.START_COLOR_TUPLE
[0] + (InnerTile
.DELTAS
[0] * percent
)
189 g
= InnerTile
.START_COLOR_TUPLE
[1] + (InnerTile
.DELTAS
[1] * percent
)
190 b
= InnerTile
.START_COLOR_TUPLE
[2] + (InnerTile
.DELTAS
[2] * percent
)
191 self
.setColor(wxColor(r
,g
,b
))
196 #----------------------------------------------------------------------
198 def runTest(frame
, nb
, log
):
199 win
= TestPanel(nb
, log
)
202 #----------------------------------------------------------------------
206 overview
= """<html><body>
207 <h2>EventManager</h2>
209 <p> The goal of the EventManager is to make wxWindows events more
210 'Pythonic' (ie. object-oriented) and easier to work with, without
211 impacting performance. It offers these features:
216 <li> Allows any number of listeners to register for a single
217 event. (In addition to the standard wxPython feature of a single
218 listener being able to respond to many events.)
220 <li> Makes it easy to disconnect and reconnect listeners. This
221 has the effect of reducing the need for case-based branching in
224 <li> Has an object-oriented API. Programmers register to get
225 events directly from the objects that generate them, instead of
232 <p>The EventManager class has three public methods. First get a
236 from wxPython.lib.evtmgr import eventManager
239 <p>...and then invoke any of the following methods. These methods are
240 'safe'; duplicate registrations or de-registrations will have no
243 <p><b>Registering a listener:</b>
246 eventManager.Register(listener, event, event-source)
250 <p><b>De-registering by window:</b>
253 eventManager.DeregisterWindow(event-source)
257 <p><b>De-registering by listener:</b>
260 eventManager.DeregisterListener(listener)
263 <p><b>Simple Example:</b>
266 from wxPython.lib.evtmgr import eventManager
268 aButton = wxButton(somePanel, -1, 'Click me')
269 eventManager.Register(self.someMethod, EVT_BUTTON, aButton)
272 <p> See the demo code as well as the documentation in the source of
273 <tt>wxPython.lib.evtmgr</tt> for more details.
277 by Robb Shecter (robb@acm.org)
283 if __name__
== '__main__':
286 run
.main(['', os
.path
.basename(sys
.argv
[0])])