]>
Commit | Line | Data |
---|---|---|
8fa876ca RD |
1 | |
2 | import wx | |
3 | import wx.lib.mixins.listctrl as listmix | |
3b867149 RD |
4 | |
5 | #---------------------------------------------------------------------- | |
6 | ||
7 | keyMap = { | |
33971536 RD |
8 | wx.WXK_BACK : "WXK_BACK", |
9 | wx.WXK_TAB : "WXK_TAB", | |
10 | wx.WXK_RETURN : "WXK_RETURN", | |
11 | wx.WXK_ESCAPE : "WXK_ESCAPE", | |
12 | wx.WXK_SPACE : "WXK_SPACE", | |
13 | wx.WXK_DELETE : "WXK_DELETE", | |
14 | wx.WXK_START : "WXK_START", | |
15 | wx.WXK_LBUTTON : "WXK_LBUTTON", | |
16 | wx.WXK_RBUTTON : "WXK_RBUTTON", | |
17 | wx.WXK_CANCEL : "WXK_CANCEL", | |
18 | wx.WXK_MBUTTON : "WXK_MBUTTON", | |
19 | wx.WXK_CLEAR : "WXK_CLEAR", | |
20 | wx.WXK_SHIFT : "WXK_SHIFT", | |
21 | wx.WXK_ALT : "WXK_ALT", | |
22 | wx.WXK_CONTROL : "WXK_CONTROL", | |
23 | wx.WXK_MENU : "WXK_MENU", | |
24 | wx.WXK_PAUSE : "WXK_PAUSE", | |
25 | wx.WXK_CAPITAL : "WXK_CAPITAL", | |
26 | wx.WXK_PRIOR : "WXK_PRIOR", | |
27 | wx.WXK_NEXT : "WXK_NEXT", | |
28 | wx.WXK_END : "WXK_END", | |
29 | wx.WXK_HOME : "WXK_HOME", | |
30 | wx.WXK_LEFT : "WXK_LEFT", | |
31 | wx.WXK_UP : "WXK_UP", | |
32 | wx.WXK_RIGHT : "WXK_RIGHT", | |
33 | wx.WXK_DOWN : "WXK_DOWN", | |
34 | wx.WXK_SELECT : "WXK_SELECT", | |
35 | wx.WXK_PRINT : "WXK_PRINT", | |
36 | wx.WXK_EXECUTE : "WXK_EXECUTE", | |
37 | wx.WXK_SNAPSHOT : "WXK_SNAPSHOT", | |
38 | wx.WXK_INSERT : "WXK_INSERT", | |
39 | wx.WXK_HELP : "WXK_HELP", | |
40 | wx.WXK_NUMPAD0 : "WXK_NUMPAD0", | |
41 | wx.WXK_NUMPAD1 : "WXK_NUMPAD1", | |
42 | wx.WXK_NUMPAD2 : "WXK_NUMPAD2", | |
43 | wx.WXK_NUMPAD3 : "WXK_NUMPAD3", | |
44 | wx.WXK_NUMPAD4 : "WXK_NUMPAD4", | |
45 | wx.WXK_NUMPAD5 : "WXK_NUMPAD5", | |
46 | wx.WXK_NUMPAD6 : "WXK_NUMPAD6", | |
47 | wx.WXK_NUMPAD7 : "WXK_NUMPAD7", | |
48 | wx.WXK_NUMPAD8 : "WXK_NUMPAD8", | |
49 | wx.WXK_NUMPAD9 : "WXK_NUMPAD9", | |
50 | wx.WXK_MULTIPLY : "WXK_MULTIPLY", | |
51 | wx.WXK_ADD : "WXK_ADD", | |
52 | wx.WXK_SEPARATOR : "WXK_SEPARATOR", | |
53 | wx.WXK_SUBTRACT : "WXK_SUBTRACT", | |
54 | wx.WXK_DECIMAL : "WXK_DECIMAL", | |
55 | wx.WXK_DIVIDE : "WXK_DIVIDE", | |
56 | wx.WXK_F1 : "WXK_F1", | |
57 | wx.WXK_F2 : "WXK_F2", | |
58 | wx.WXK_F3 : "WXK_F3", | |
59 | wx.WXK_F4 : "WXK_F4", | |
60 | wx.WXK_F5 : "WXK_F5", | |
61 | wx.WXK_F6 : "WXK_F6", | |
62 | wx.WXK_F7 : "WXK_F7", | |
63 | wx.WXK_F8 : "WXK_F8", | |
64 | wx.WXK_F9 : "WXK_F9", | |
65 | wx.WXK_F10 : "WXK_F10", | |
66 | wx.WXK_F11 : "WXK_F11", | |
67 | wx.WXK_F12 : "WXK_F12", | |
68 | wx.WXK_F13 : "WXK_F13", | |
69 | wx.WXK_F14 : "WXK_F14", | |
70 | wx.WXK_F15 : "WXK_F15", | |
71 | wx.WXK_F16 : "WXK_F16", | |
72 | wx.WXK_F17 : "WXK_F17", | |
73 | wx.WXK_F18 : "WXK_F18", | |
74 | wx.WXK_F19 : "WXK_F19", | |
75 | wx.WXK_F20 : "WXK_F20", | |
76 | wx.WXK_F21 : "WXK_F21", | |
77 | wx.WXK_F22 : "WXK_F22", | |
78 | wx.WXK_F23 : "WXK_F23", | |
79 | wx.WXK_F24 : "WXK_F24", | |
80 | wx.WXK_NUMLOCK : "WXK_NUMLOCK", | |
81 | wx.WXK_SCROLL : "WXK_SCROLL", | |
82 | wx.WXK_PAGEUP : "WXK_PAGEUP", | |
83 | wx.WXK_PAGEDOWN : "WXK_PAGEDOWN", | |
84 | wx.WXK_NUMPAD_SPACE : "WXK_NUMPAD_SPACE", | |
85 | wx.WXK_NUMPAD_TAB : "WXK_NUMPAD_TAB", | |
86 | wx.WXK_NUMPAD_ENTER : "WXK_NUMPAD_ENTER", | |
87 | wx.WXK_NUMPAD_F1 : "WXK_NUMPAD_F1", | |
88 | wx.WXK_NUMPAD_F2 : "WXK_NUMPAD_F2", | |
89 | wx.WXK_NUMPAD_F3 : "WXK_NUMPAD_F3", | |
90 | wx.WXK_NUMPAD_F4 : "WXK_NUMPAD_F4", | |
91 | wx.WXK_NUMPAD_HOME : "WXK_NUMPAD_HOME", | |
92 | wx.WXK_NUMPAD_LEFT : "WXK_NUMPAD_LEFT", | |
93 | wx.WXK_NUMPAD_UP : "WXK_NUMPAD_UP", | |
94 | wx.WXK_NUMPAD_RIGHT : "WXK_NUMPAD_RIGHT", | |
95 | wx.WXK_NUMPAD_DOWN : "WXK_NUMPAD_DOWN", | |
96 | wx.WXK_NUMPAD_PRIOR : "WXK_NUMPAD_PRIOR", | |
97 | wx.WXK_NUMPAD_PAGEUP : "WXK_NUMPAD_PAGEUP", | |
98 | wx.WXK_NUMPAD_NEXT : "WXK_NUMPAD_NEXT", | |
99 | wx.WXK_NUMPAD_PAGEDOWN : "WXK_NUMPAD_PAGEDOWN", | |
100 | wx.WXK_NUMPAD_END : "WXK_NUMPAD_END", | |
101 | wx.WXK_NUMPAD_BEGIN : "WXK_NUMPAD_BEGIN", | |
102 | wx.WXK_NUMPAD_INSERT : "WXK_NUMPAD_INSERT", | |
103 | wx.WXK_NUMPAD_DELETE : "WXK_NUMPAD_DELETE", | |
104 | wx.WXK_NUMPAD_EQUAL : "WXK_NUMPAD_EQUAL", | |
105 | wx.WXK_NUMPAD_MULTIPLY : "WXK_NUMPAD_MULTIPLY", | |
106 | wx.WXK_NUMPAD_ADD : "WXK_NUMPAD_ADD", | |
107 | wx.WXK_NUMPAD_SEPARATOR : "WXK_NUMPAD_SEPARATOR", | |
108 | wx.WXK_NUMPAD_SUBTRACT : "WXK_NUMPAD_SUBTRACT", | |
109 | wx.WXK_NUMPAD_DECIMAL : "WXK_NUMPAD_DECIMAL", | |
110 | wx.WXK_NUMPAD_DIVIDE : "WXK_NUMPAD_DIVIDE", | |
3b867149 RD |
111 | } |
112 | ||
113 | ||
114 | #---------------------------------------------------------------------- | |
115 | ||
8fa876ca | 116 | class KeySink(wx.Window): |
3b867149 | 117 | def __init__(self, parent): |
8fa876ca RD |
118 | wx.Window.__init__(self, parent, -1, style=wx.WANTS_CHARS |
119 | #| wx.RAISED_BORDER | |
120 | #| wx.SUNKEN_BORDER | |
33971536 | 121 | , name="sink") |
8fa876ca RD |
122 | |
123 | self.SetBackgroundColour(wx.BLUE) | |
1e4a197e | 124 | self.haveFocus = False |
38f7d801 | 125 | self.callSkip = True |
1e4a197e RD |
126 | self.logKeyDn = True |
127 | self.logKeyUp = True | |
128 | self.logChar = True | |
3b867149 | 129 | |
8fa876ca RD |
130 | self.Bind(wx.EVT_PAINT, self.OnPaint) |
131 | self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) | |
132 | self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) | |
133 | self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse) | |
3b867149 | 134 | |
8fa876ca RD |
135 | self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) |
136 | self.Bind(wx.EVT_KEY_UP, self.OnKeyUp) | |
137 | self.Bind(wx.EVT_CHAR, self.OnChar) | |
3b867149 RD |
138 | |
139 | ||
140 | def SetCallSkip(self, skip): | |
141 | self.callSkip = skip | |
142 | ||
143 | def SetLogKeyUp(self, val): | |
144 | self.logKeyUp = val | |
145 | ||
146 | def SetLogKeyDn(self, val): | |
147 | self.logKeyDn = val | |
148 | ||
149 | def SetLogChar(self, val): | |
150 | self.logChar = val | |
151 | ||
152 | ||
153 | def OnPaint(self, evt): | |
8fa876ca | 154 | dc = wx.PaintDC(self) |
3b867149 | 155 | rect = self.GetClientRect() |
8fa876ca | 156 | dc.SetTextForeground(wx.WHITE) |
3b867149 | 157 | dc.DrawLabel("Click here and then press some keys", |
8fa876ca | 158 | rect, wx.ALIGN_CENTER | wx.ALIGN_TOP) |
3b867149 | 159 | if self.haveFocus: |
8fa876ca RD |
160 | dc.SetTextForeground(wx.GREEN) |
161 | dc.DrawLabel("Have Focus", rect, wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM) | |
3b867149 | 162 | else: |
8fa876ca RD |
163 | dc.SetTextForeground(wx.RED) |
164 | dc.DrawLabel("Need Focus!", rect, wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM) | |
3b867149 RD |
165 | |
166 | ||
167 | def OnSetFocus(self, evt): | |
1e4a197e | 168 | self.haveFocus = True |
3b867149 RD |
169 | self.Refresh() |
170 | ||
171 | def OnKillFocus(self, evt): | |
1e4a197e | 172 | self.haveFocus = False |
3b867149 RD |
173 | self.Refresh() |
174 | ||
175 | def OnMouse(self, evt): | |
176 | if evt.ButtonDown(): | |
177 | self.SetFocus() | |
178 | ||
179 | ||
180 | def OnKeyDown(self, evt): | |
181 | if self.logKeyDn: | |
182 | self.GetParent().keylog.LogKeyEvent("KeyDown", evt) | |
183 | if self.callSkip: | |
184 | evt.Skip() | |
185 | ||
186 | def OnKeyUp(self, evt): | |
187 | if self.logKeyUp: | |
188 | self.GetParent().keylog.LogKeyEvent("KeyUp", evt) | |
189 | if self.callSkip: | |
190 | evt.Skip() | |
191 | ||
192 | def OnChar(self, evt): | |
193 | if self.logChar: | |
194 | self.GetParent().keylog.LogKeyEvent("Char", evt) | |
195 | ||
196 | ||
197 | #---------------------------------------------------------------------- | |
198 | ||
d4b73b1b | 199 | class KeyLog(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin): |
39ac2874 RD |
200 | colHeaders = [ "Event Type", |
201 | "Key Name", | |
202 | "Key Code", | |
203 | "Modifiers", | |
204 | "Unicode", | |
205 | "RawKeyCode", | |
206 | "RawKeyFlags", | |
207 | ] | |
3b867149 RD |
208 | |
209 | def __init__(self, parent): | |
8fa876ca RD |
210 | wx.ListCtrl.__init__(self, parent, -1, |
211 | style = wx.LC_REPORT|wx.LC_VRULES|wx.LC_HRULES) | |
d4b73b1b | 212 | listmix.ListCtrlAutoWidthMixin.__init__(self) |
3b867149 | 213 | |
39ac2874 RD |
214 | for idx, header in enumerate(self.colHeaders): |
215 | self.InsertColumn(idx, header) | |
216 | idx += 1 | |
39ac2874 | 217 | self.InsertColumn(idx, "") |
3b867149 | 218 | |
39ac2874 | 219 | for x in range(idx): |
8fa876ca | 220 | self.SetColumnWidth(x, wx.LIST_AUTOSIZE_USEHEADER) |
3b867149 RD |
221 | |
222 | self.SetColumnWidth(1, 125) | |
223 | ||
224 | ||
225 | def LogKeyEvent(self, evType, evt): | |
226 | keycode = evt.GetKeyCode() | |
227 | keyname = keyMap.get(keycode, None) | |
228 | if keyname is None: | |
d82c2542 RD |
229 | if "unicode" in wx.PlatformInfo: |
230 | keycode = evt.GetUnicodeKey() | |
231 | if keycode <= 127: | |
232 | keycode = evt.GetKeyCode() | |
7db509e2 RD |
233 | keyname = "\"" + unichr(evt.GetUnicodeKey()) + "\"" |
234 | ||
235 | elif keycode < 256: | |
3b867149 RD |
236 | if keycode == 0: |
237 | keyname = "NUL" | |
238 | elif keycode < 27: | |
239 | keyname = "Ctrl-%s" % chr(ord('A') + keycode-1) | |
240 | else: | |
241 | keyname = "\"%s\"" % chr(keycode) | |
242 | else: | |
243 | keyname = "unknown (%s)" % keycode | |
244 | ||
245 | modifiers = "" | |
246 | for mod, ch in [(evt.ControlDown(), 'C'), | |
247 | (evt.AltDown(), 'A'), | |
248 | (evt.ShiftDown(), 'S'), | |
249 | (evt.MetaDown(), 'M')]: | |
250 | if mod: | |
251 | modifiers += ch | |
252 | else: | |
253 | modifiers += '-' | |
254 | ||
f0a0d77e | 255 | id = self.InsertStringItem(self.GetItemCount(), evType) |
3b867149 RD |
256 | self.SetStringItem(id, 1, keyname) |
257 | self.SetStringItem(id, 2, str(keycode)) | |
258 | self.SetStringItem(id, 3, modifiers) | |
d9975a31 RD |
259 | self.SetStringItem(id, 4, str(evt.GetUnicodeKey())) |
260 | self.SetStringItem(id, 5, str(evt.GetRawKeyCode())) | |
261 | self.SetStringItem(id, 6, str(evt.GetRawKeyFlags())) | |
3b867149 RD |
262 | |
263 | #print ( id, evType, keyname, str(keycode), modifiers, str(evt.GetRawKeyCode()), str(evt.GetRawKeyFlags())) | |
264 | ||
265 | self.EnsureVisible(id) | |
266 | ||
267 | ||
268 | def ClearLog(self): | |
269 | self.DeleteAllItems() | |
270 | ||
39ac2874 RD |
271 | def CopyLog(self): |
272 | # build a newline and tab delimited string to put into the clipboard | |
273 | if "unicode" in wx.PlatformInfo: | |
274 | st = u"" | |
275 | else: | |
276 | st = "" | |
277 | for h in self.colHeaders: | |
278 | st += h + "\t" | |
279 | st += "\n" | |
280 | ||
281 | for idx in range(self.GetItemCount()): | |
282 | for col in range(self.GetColumnCount()): | |
283 | item = self.GetItem(idx, col) | |
284 | st += item.GetText() + "\t" | |
285 | st += "\n" | |
286 | ||
287 | data = wx.TextDataObject() | |
288 | data.SetText(st) | |
289 | if wx.TheClipboard.Open(): | |
290 | wx.TheClipboard.SetData(data) | |
291 | wx.TheClipboard.Close() | |
292 | else: | |
293 | wx.MessageBox("Unable to open the clipboard", "Error") | |
294 | ||
295 | ||
296 | ||
3b867149 RD |
297 | |
298 | #---------------------------------------------------------------------- | |
299 | ||
300 | ||
8fa876ca | 301 | class TestPanel(wx.Panel): |
3b867149 RD |
302 | def __init__(self, parent, log): |
303 | self.log = log | |
8fa876ca | 304 | wx.Panel.__init__(self, parent, -1, style=0) |
3b867149 | 305 | self.keysink = KeySink(self) |
5193b348 | 306 | self.keysink.SetMinSize((100, 65)) |
3b867149 RD |
307 | self.keylog = KeyLog(self) |
308 | ||
39ac2874 | 309 | btn = wx.Button(self, -1, "Clear", style=wx.BU_EXACTFIT) |
8fa876ca | 310 | self.Bind(wx.EVT_BUTTON, self.OnClearBtn, btn) |
33971536 RD |
311 | btn.SetToolTipString( |
312 | "Clear the items from the log window") | |
3b867149 | 313 | |
39ac2874 RD |
314 | btn2 = wx.Button(self, -1, "Copy", style=wx.BU_EXACTFIT) |
315 | self.Bind(wx.EVT_BUTTON, self.OnCopyBtn, btn2) | |
33971536 RD |
316 | btn2.SetToolTipString( |
317 | "Copy the contents of the log window to the clipboard") | |
39ac2874 RD |
318 | |
319 | cb1 = wx.CheckBox(self, -1, "Call evt.Skip in Key* events") | |
8fa876ca | 320 | self.Bind(wx.EVT_CHECKBOX, self.OnSkipCB, cb1) |
38f7d801 | 321 | cb1.SetValue(True) |
3b867149 | 322 | |
39ac2874 | 323 | cb2 = wx.CheckBox(self, -1, "KEY_UP") |
8fa876ca | 324 | self.Bind(wx.EVT_CHECKBOX, self.OnKeyUpCB, cb2) |
1e4a197e | 325 | cb2.SetValue(True) |
3b867149 | 326 | |
39ac2874 | 327 | cb3 = wx.CheckBox(self, -1, "KEY_DOWN") |
8fa876ca | 328 | self.Bind(wx.EVT_CHECKBOX, self.OnKeyDnCB, cb3) |
1e4a197e | 329 | cb3.SetValue(True) |
3b867149 | 330 | |
39ac2874 | 331 | cb4 = wx.CheckBox(self, -1, "CHAR") |
8fa876ca | 332 | self.Bind(wx.EVT_CHECKBOX, self.OnCharCB, cb4) |
1e4a197e | 333 | cb4.SetValue(True) |
3b867149 | 334 | |
8fa876ca RD |
335 | buttons = wx.BoxSizer(wx.HORIZONTAL) |
336 | buttons.Add(btn, 0, wx.ALL, 4) | |
39ac2874 | 337 | buttons.Add(btn2, 0, wx.ALL, 4) |
8fa876ca RD |
338 | buttons.Add(cb1, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 6) |
339 | buttons.Add(cb2, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 6) | |
340 | buttons.Add(cb3, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 6) | |
341 | buttons.Add(cb4, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 6) | |
3b867149 | 342 | |
8fa876ca RD |
343 | sizer = wx.BoxSizer(wx.VERTICAL) |
344 | sizer.Add(self.keysink, 0, wx.GROW) | |
3b867149 | 345 | sizer.Add(buttons) |
8fa876ca | 346 | sizer.Add(self.keylog, 1, wx.GROW) |
3b867149 RD |
347 | |
348 | self.SetSizer(sizer) | |
349 | ||
350 | ||
351 | def OnClearBtn(self, evt): | |
352 | self.keylog.ClearLog() | |
353 | ||
39ac2874 RD |
354 | def OnCopyBtn(self, evt): |
355 | self.keylog.CopyLog() | |
356 | ||
3b867149 RD |
357 | def OnSkipCB(self, evt): |
358 | self.keysink.SetCallSkip(evt.GetInt()) | |
359 | ||
360 | def OnKeyUpCB(self, evt): | |
361 | self.keysink.SetLogKeyUp(evt.GetInt()) | |
362 | ||
363 | def OnKeyDnCB(self, evt): | |
364 | self.keysink.SetLogKeyDn(evt.GetInt()) | |
365 | ||
366 | def OnCharCB(self, evt): | |
367 | self.keysink.SetLogChar(evt.GetInt()) | |
368 | ||
369 | ||
370 | #---------------------------------------------------------------------- | |
371 | ||
372 | def runTest(frame, nb, log): | |
373 | win = TestPanel(nb, log) | |
374 | return win | |
375 | ||
376 | #---------------------------------------------------------------------- | |
377 | ||
378 | ||
379 | ||
380 | overview = """<html><body> | |
381 | <h2><center>wxKeyEvents</center></h2> | |
382 | ||
8fa876ca | 383 | This demo simply catches all key events and prints info about them. |
3b867149 RD |
384 | It is meant to be used as a compatibility test for cross platform work. |
385 | ||
386 | </body></html> | |
387 | """ | |
388 | ||
389 | ||
390 | ||
391 | if __name__ == '__main__': | |
392 | import sys,os | |
393 | import run | |
8eca4fef | 394 | run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:]) |
3b867149 | 395 |