]> git.saurik.com Git - wxWidgets.git/blame - wxPython/demo/EventManager.py
support for fractional characters widths under Mac
[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 66
1e4a197e
RD
67 buttonPanel.SetSizer(sizer)
68 sizer.Fit(buttonPanel)
69
8fa876ca
RD
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.LEFT | wx.BOTTOM | wx.RIGHT, 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)
1e4a197e
RD
79 self.SetSizer(sizer)
80
81
82
78a32590 83class Tile(wx.Window):
1e4a197e
RD
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 """
8fa876ca
RD
89 normal = wx.Colour(150,150,150)
90 active = wx.Colour(250,245,245)
91 hover = wx.Colour(210,220,210)
1e4a197e
RD
92
93 def __init__(self, parent, log, factor=1, thingToWatch=None, bgColor=None, active=1, size=(38,38), borderWidth=3):
78a32590 94 wx.Window.__init__(self, parent, -1, size=size, style=wx.CLIP_CHILDREN)
1e4a197e
RD
95 self.tile = InnerTile(self, log, factor, thingToWatch, bgColor)
96 self.log = log
8fa876ca
RD
97 sizer = wx.BoxSizer(wx.HORIZONTAL)
98 sizer.Add(self.tile, 1, wx.EXPAND | wx.ALL, borderWidth)
1e4a197e
RD
99 self.SetSizer(sizer)
100 self.Layout()
78a32590 101 em.eventManager.Register(self.doLayout, wx.EVT_SIZE, self)
1e4a197e
RD
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.
8fa876ca
RD
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)
1e4a197e
RD
110
111
78a32590
RD
112 def doLayout(self, event):
113 self.Layout()
114
115
1e4a197e
RD
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
78a32590 132class InnerTile(wx.Window):
8fa876ca
RD
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)
1e4a197e
RD
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):
78a32590 146 wx.Window.__init__(self, parent, -1)
1e4a197e
RD
147 self.log=log
148 if bgColor:
149 self.SetBackgroundColour(bgColor)
150 if thingToWatch:
151 self.factor = factor
152 self.thingToWatch = thingToWatch
153 self.state = 0
154 self.toggleOnOff()
155 # Watch for the mouse click to enable/disable myself.
8fa876ca 156 em.eventManager.Register(self.toggleOnOff, wx.EVT_LEFT_UP, self)
1e4a197e
RD
157
158
159 def toggleOnOff(self, event=None):
160 # Implement being on or off by registering and
161 # de-registering self.makeColor() from the event manager.
162 if self.state:
8fa876ca 163 em.eventManager.DeregisterListener(self.makeColor)
1e4a197e 164 else:
8fa876ca 165 em.eventManager.Register(self.makeColor, wx.EVT_MOTION, self.thingToWatch)
1e4a197e
RD
166 self.state = 1 - self.state
167 self.resetColor()
168
169
170 def resetColor(self, event=None):
171 if self.state:
172 self.setColor(InnerTile.IDLE_COLOR)
173 else:
174 self.setColor(InnerTile.OFF_COLOR)
175
176
177 def setColor(self, color):
178 self.SetBackgroundColour(color)
179 self.Refresh()
180
181
182 def makeColor(self, mouseEvent):
183 self.makeColorFromTuple(mouseEvent.GetPositionTuple())
184
185
186 def makeColorFromTuple(self, (x, y)):
187 MAX = 180.0
188 scaled = min((x + y) * self.factor, MAX) # In range [0..MAX]
189 percent = scaled / MAX
190 r = InnerTile.START_COLOR_TUPLE[0] + (InnerTile.DELTAS[0] * percent)
191 g = InnerTile.START_COLOR_TUPLE[1] + (InnerTile.DELTAS[1] * percent)
192 b = InnerTile.START_COLOR_TUPLE[2] + (InnerTile.DELTAS[2] * percent)
8fa876ca 193 self.setColor(wx.Colour(int(r), int(g), int(b)))
1e4a197e
RD
194
195
196
197
198#----------------------------------------------------------------------
199
200def runTest(frame, nb, log):
201 win = TestPanel(nb, log)
202 return win
203
204#----------------------------------------------------------------------
205
206
207
208overview = """<html><body>
209<h2>EventManager</h2>
210
211<p> The goal of the EventManager is to make wxWindows events more
212'Pythonic' (ie. object-oriented) and easier to work with, without
213impacting performance. It offers these features:
214
215<p>
216<ul>
217
218 <li> Allows any number of listeners to register for a single
219 event. (In addition to the standard wxPython feature of a single
220 listener being able to respond to many events.)
221
222 <li> Makes it easy to disconnect and reconnect listeners. This
223 has the effect of reducing the need for case-based branching in
224 application code.
225
226 <li> Has an object-oriented API. Programmers register to get
227 events directly from the objects that generate them, instead of
228 using ID numbers.
229
230</ul>
231
232<h3>Usage</h3>
233
234<p>The EventManager class has three public methods. First get a
235reference to it:
236
237<PRE>
238 from wxPython.lib.evtmgr import eventManager
239</PRE>
240
241<p>...and then invoke any of the following methods. These methods are
242'safe'; duplicate registrations or de-registrations will have no
243effect.
244
245<p><b>Registering a listener:</b>
246
247<PRE>
248 eventManager.Register(listener, event, event-source)
249</PRE>
250
251
252<p><b>De-registering by window:</b>
253
254<PRE>
255 eventManager.DeregisterWindow(event-source)
256</PRE>
257
258
259<p><b>De-registering by listener:</b>
260
261<PRE>
262 eventManager.DeregisterListener(listener)
263</PRE>
264
265<p><b>Simple Example:</b>
266
267<PRE>
268 from wxPython.lib.evtmgr import eventManager
269
270 aButton = wxButton(somePanel, -1, 'Click me')
271 eventManager.Register(self.someMethod, EVT_BUTTON, aButton)
272</PRE>
273
274<p> See the demo code as well as the documentation in the source of
275<tt>wxPython.lib.evtmgr</tt> for more details.
276
277
278<p>
279by Robb Shecter (robb@acm.org)
280</body></html>
281"""
282
283
284
285if __name__ == '__main__':
286 import sys,os
287 import run
8eca4fef 288 run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
1e4a197e 289