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