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