]> git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/EventManager.py
Aquire the GIL before raising the NotImplementedError exception
[wxWidgets.git] / wxPython / demo / EventManager.py
1 #---------------------------------------------------------------------------
2 # Name: EventManager.py
3 # Purpose: A module to demonstrate wxPython.lib.evtmgr.EventManager.
4 #
5 # Author: Robb Shecter (robb@acm.org)
6 #
7 # Created: 16-December-2002
8 # Copyright: (c) 2002 by Robb Shecter (robb@acm.org)
9 # Licence: wxWindows license
10 #---------------------------------------------------------------------------
11 #
12 # 11/22/2003 - Jeff Grimmett (grimmtooth@softhome.net)
13 #
14 # o Updated for wx namespace
15 #
16 # 11/25/2003 - Jeff Grimmett (grimmtooth@softhome.net)
17 #
18 # o What happened to wx.Color()?
19 #
20
21
22 import wx
23 import wx.lib.evtmgr as em
24
25 #----------------------------------------------------------------------
26
27 class TestPanel(wx.Panel):
28 def __init__(self, parent, log):
29 wx.Panel.__init__(self, parent, -1)
30 self.log = log
31
32 fsize = self.GetFont().GetPointSize()
33 f1 = wx.Font(fsize+0, wx.SWISS, wx.NORMAL, wx.NORMAL)
34 f2 = wx.Font(fsize+2, wx.SWISS, wx.NORMAL, wx.BOLD)
35 f3 = wx.Font(fsize+6, wx.SWISS, wx.NORMAL, wx.BOLD)
36
37 title1 = wx.StaticText(self, -1, 'EventManager')
38 title1.SetFont(f3)
39 txt = """\
40 This demo shows (1) basic uses and features of the EventManager, as well
41 as (2) how it helps with a real-world task: creating independent, object-
42 oriented components."""
43 message0 = wx.StaticText(self, -1, txt)
44 message0.SetFont(f1)
45
46 title2 = wx.StaticText(self, -1, 'Event Listeners')
47 title2.SetFont(f2)
48
49 txt = """\
50 These objects listen to motion events from the target window, using the ability
51 to register one event with multiple listeners. They also register for mouse events
52 on themselves to implement toggle-button functionality."""
53 message1 = wx.StaticText(self, -1, txt)
54 message1.SetFont(f1)
55
56 title3 = wx.StaticText(self, -1, 'Target Window')
57 title3.SetFont(f2)
58
59 txt = """\
60 A passive window that's used as an event generator. Move the mouse over it to
61 send events to the listeners above."""
62 message2 = wx.StaticText(self, -1, txt)
63 message2.SetFont(f1)
64
65 targetPanel = Tile(self, log, bgColor=wx.Colour(80,10,10), active=0)
66 buttonPanel = wx.Panel(self ,-1)
67 sizer = wx.BoxSizer(wx.HORIZONTAL)
68 target = targetPanel.tile
69
70 sizer.Add((0,0), 1)
71 for factor in [0.2, 0.3, 0.4, 0.5, 0.6, 0.7]:
72 sizer.Add(Tile(buttonPanel, log, factor-0.05, target), 0, wx.ALIGN_CENTER)
73 sizer.Add((0,0),1)
74 sizer.Add(Tile(buttonPanel, log, factor, target), 0, wx.ALIGN_CENTER)
75 sizer.Add((0,0),1)
76
77 buttonPanel.SetAutoLayout(1)
78 buttonPanel.SetSizer(sizer)
79 sizer.Fit(buttonPanel)
80
81 sizer = wx.BoxSizer(wx.VERTICAL)
82 sizer.Add(title1, 0, wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM, 6)
83 sizer.Add(message0, 0, wx.ALIGN_CENTER | wx.ALL, 6)
84 sizer.Add(title2, 0, wx.ALIGN_CENTER | wx.LEFT | wx.TOP | wx.RIGHT, 16)
85 sizer.Add(message1, 0, wx.ALIGN_CENTER | wx.ALL, 6)
86 sizer.Add(buttonPanel, 0, wx.EXPAND | wx.LEFT | wx.BOTTOM | wx.RIGHT, 16)
87 sizer.Add(title3, 0, wx.ALIGN_CENTER | wx.LEFT | wx.RIGHT, 16)
88 sizer.Add(message2, 0, wx.ALIGN_CENTER | wx.ALL, 6)
89 sizer.Add(targetPanel, 2, wx.EXPAND | wx.LEFT | wx.BOTTOM | wx.RIGHT, 16)
90 self.SetAutoLayout(1)
91 self.SetSizer(sizer)
92
93
94
95 class Tile(wx.Panel):
96 """
97 This outer class is responsible for changing
98 its border color in response to certain mouse
99 events over its contained 'InnerTile'.
100 """
101 normal = wx.Colour(150,150,150)
102 active = wx.Colour(250,245,245)
103 hover = wx.Colour(210,220,210)
104
105 def __init__(self, parent, log, factor=1, thingToWatch=None, bgColor=None, active=1, size=(38,38), borderWidth=3):
106 wx.Panel.__init__(self, parent, -1, size=size, style=wx.CLIP_CHILDREN)
107 self.tile = InnerTile(self, log, factor, thingToWatch, bgColor)
108 self.log = log
109 sizer = wx.BoxSizer(wx.HORIZONTAL)
110 sizer.Add(self.tile, 1, wx.EXPAND | wx.ALL, borderWidth)
111 self.SetAutoLayout(1)
112 self.SetSizer(sizer)
113 self.Layout()
114 self.SetBackgroundColour(Tile.normal)
115 if active:
116 # Register myself for mouse events over self.tile in order to
117 # create typical button/hyperlink visual effects.
118 em.eventManager.Register(self.setHover, wx.EVT_ENTER_WINDOW, self.tile)
119 em.eventManager.Register(self.setNormal, wx.EVT_LEAVE_WINDOW, self.tile)
120 em.eventManager.Register(self.setActive, wx.EVT_LEFT_DOWN, self.tile)
121 em.eventManager.Register(self.setHover, wx.EVT_LEFT_UP, self.tile)
122
123
124 def setHover(self, event):
125 self.SetBackgroundColour(Tile.hover)
126 self.Refresh()
127
128
129 def setActive(self, event):
130 self.SetBackgroundColour(Tile.active)
131 self.Refresh()
132
133
134 def setNormal(self, event):
135 self.SetBackgroundColour(Tile.normal)
136 self.Refresh()
137
138
139
140 class InnerTile(wx.Panel):
141 IDLE_COLOR = wx.Colour( 80, 10, 10)
142 START_COLOR = wx.Colour(200, 70, 50)
143 FINAL_COLOR = wx.Colour( 20, 80,240)
144 OFF_COLOR = wx.Colour(185,190,185)
145 # Some pre-computation.
146 DELTAS = map(lambda a,b: b-a, START_COLOR.Get(), FINAL_COLOR.Get())
147 START_COLOR_TUPLE = START_COLOR.Get()
148
149 """
150 This inner panel changes its color in reaction to mouse
151 events over the 'thingToWatch'.
152 """
153 def __init__(self, parent, log, factor, thingToWatch=None, bgColor=None):
154 wx.Panel.__init__(self, parent, -1)
155 self.log=log
156 if bgColor:
157 self.SetBackgroundColour(bgColor)
158 if thingToWatch:
159 self.factor = factor
160 self.thingToWatch = thingToWatch
161 self.state = 0
162 self.toggleOnOff()
163 # Watch for the mouse click to enable/disable myself.
164 em.eventManager.Register(self.toggleOnOff, wx.EVT_LEFT_UP, self)
165
166
167 def toggleOnOff(self, event=None):
168 # Implement being on or off by registering and
169 # de-registering self.makeColor() from the event manager.
170 if self.state:
171 em.eventManager.DeregisterListener(self.makeColor)
172 else:
173 em.eventManager.Register(self.makeColor, wx.EVT_MOTION, self.thingToWatch)
174 self.state = 1 - self.state
175 self.resetColor()
176
177
178 def resetColor(self, event=None):
179 if self.state:
180 self.setColor(InnerTile.IDLE_COLOR)
181 else:
182 self.setColor(InnerTile.OFF_COLOR)
183
184
185 def setColor(self, color):
186 self.SetBackgroundColour(color)
187 self.Refresh()
188
189
190 def makeColor(self, mouseEvent):
191 self.makeColorFromTuple(mouseEvent.GetPositionTuple())
192
193
194 def makeColorFromTuple(self, (x, y)):
195 MAX = 180.0
196 scaled = min((x + y) * self.factor, MAX) # In range [0..MAX]
197 percent = scaled / MAX
198 r = InnerTile.START_COLOR_TUPLE[0] + (InnerTile.DELTAS[0] * percent)
199 g = InnerTile.START_COLOR_TUPLE[1] + (InnerTile.DELTAS[1] * percent)
200 b = InnerTile.START_COLOR_TUPLE[2] + (InnerTile.DELTAS[2] * percent)
201 self.setColor(wx.Colour(int(r), int(g), int(b)))
202
203
204
205
206 #----------------------------------------------------------------------
207
208 def runTest(frame, nb, log):
209 win = TestPanel(nb, log)
210 return win
211
212 #----------------------------------------------------------------------
213
214
215
216 overview = """<html><body>
217 <h2>EventManager</h2>
218
219 <p> The goal of the EventManager is to make wxWindows events more
220 'Pythonic' (ie. object-oriented) and easier to work with, without
221 impacting performance. It offers these features:
222
223 <p>
224 <ul>
225
226 <li> Allows any number of listeners to register for a single
227 event. (In addition to the standard wxPython feature of a single
228 listener being able to respond to many events.)
229
230 <li> Makes it easy to disconnect and reconnect listeners. This
231 has the effect of reducing the need for case-based branching in
232 application code.
233
234 <li> Has an object-oriented API. Programmers register to get
235 events directly from the objects that generate them, instead of
236 using ID numbers.
237
238 </ul>
239
240 <h3>Usage</h3>
241
242 <p>The EventManager class has three public methods. First get a
243 reference to it:
244
245 <PRE>
246 from wxPython.lib.evtmgr import eventManager
247 </PRE>
248
249 <p>...and then invoke any of the following methods. These methods are
250 'safe'; duplicate registrations or de-registrations will have no
251 effect.
252
253 <p><b>Registering a listener:</b>
254
255 <PRE>
256 eventManager.Register(listener, event, event-source)
257 </PRE>
258
259
260 <p><b>De-registering by window:</b>
261
262 <PRE>
263 eventManager.DeregisterWindow(event-source)
264 </PRE>
265
266
267 <p><b>De-registering by listener:</b>
268
269 <PRE>
270 eventManager.DeregisterListener(listener)
271 </PRE>
272
273 <p><b>Simple Example:</b>
274
275 <PRE>
276 from wxPython.lib.evtmgr import eventManager
277
278 aButton = wxButton(somePanel, -1, 'Click me')
279 eventManager.Register(self.someMethod, EVT_BUTTON, aButton)
280 </PRE>
281
282 <p> See the demo code as well as the documentation in the source of
283 <tt>wxPython.lib.evtmgr</tt> for more details.
284
285
286 <p>
287 by Robb Shecter (robb@acm.org)
288 </body></html>
289 """
290
291
292
293 if __name__ == '__main__':
294 import sys,os
295 import run
296 run.main(['', os.path.basename(sys.argv[0])])
297