Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/contributed/sumopy/agilepy/lib_wx/wxmisc.py
169689 views
1
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
2
# Copyright (C) 2016-2025 German Aerospace Center (DLR) and others.
3
# SUMOPy module
4
# Copyright (C) 2012-2021 University of Bologna - DICAM
5
# This program and the accompanying materials are made available under the
6
# terms of the Eclipse Public License 2.0 which is available at
7
# https://www.eclipse.org/legal/epl-2.0/
8
# This Source Code may also be made available under the following Secondary
9
# Licenses when the conditions for such availability set forth in the Eclipse
10
# Public License 2.0 are satisfied: GNU General Public License, version 2
11
# or later which is available at
12
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
13
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
14
15
# @file wxmisc.py
16
# @author Joerg Schweizer
17
# @date 2012
18
19
20
import zlib
21
import cPickle
22
import sys
23
import os
24
import types
25
#AGILEDIR = os.path.join(os.path.dirname(__file__),"..")
26
# sys.path.append(os.path.join(AGILEDIR,"lib_base"))
27
#IMAGEDIR = os.path.join(os.path.dirname(__file__),"images")
28
29
30
import wx
31
32
import time
33
import string
34
35
# def OnOpen(self,e):
36
## """ Open a file"""
37
## self.dirname = ''
38
## dlg = wx.FileDialog(self, "Choose a file", self.dirname, "", "*.*", wx.OPEN)
39
# if dlg.ShowModal() == wx.ID_OK:
40
## self.filename = dlg.GetFilename()
41
## self.dirname = dlg.GetDirectory()
42
## f = open(os.path.join(self.dirname, self.filename), 'r')
43
# self.control.SetValue(f.read())
44
# f.close()
45
# dlg.Destroy()
46
47
# alternating colors in tables "light blue" 'WHEAT'
48
#TABLECOLORS=[wx.NamedColour('grey85'),wx.NamedColour("light blue")]
49
50
51
def get_tablecolors():
52
cs = [wx.NamedColour('grey85'), wx.NamedColour("light blue")]
53
# cs = [wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW ) ,\
54
# wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNHIGHLIGHT)]
55
# print 'resources.get_tablecolors',cs
56
return cs
57
58
59
class AgileToolbarMixin:
60
"""
61
Easy to use toolbar where strings can be used to identify tools.
62
Mixin for frames.
63
"""
64
65
def init_toolbar(self, orientation='horizontal', size=(16, 16), separation=5):
66
"""
67
This initialization works for panels and windows.
68
For frames use the AgileToolbar frames mixin class
69
"""
70
if orientation == 'horizontal':
71
self.toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL | wx.TB_NODIVIDER
72
| wx.NO_BORDER
73
| wx.TB_FLAT
74
| wx.TB_TEXT
75
)
76
else:
77
self.toolbar = wx.ToolBar(self, -1, style=wx.TB_VERTICAL | wx.TB_NODIVIDER
78
| wx.NO_BORDER
79
| wx.TB_FLAT
80
| wx.TB_TEXT
81
)
82
83
self.toolbar.SetToolBitmapSize(size)
84
self.toolbar.SetToolSeparation(separation)
85
86
self._tools = {}
87
self.toolbar.Realize()
88
S = self.toolbar.GetSize()
89
self.toolbar.SetSizeHints(S[0], S[1])
90
91
def get_size_toolbaricons(self):
92
"""
93
Returns tuple with width and height of toolbar icons.
94
This is required to create them.
95
"""
96
return self.toolbar.GetToolBitmapSize()
97
98
def disable_tools(self):
99
pass
100
# GetToolEnabled
101
102
def restore_tools(self):
103
pass
104
# GetToolEnabled
105
106
def add_tool(self, key, func=None, bitmap=None, info='', widget=None, **args):
107
"""
108
Add a tool to the tool bar
109
"""
110
# print 'add_tool',self,key,func
111
112
id = wx.NewId()
113
if not args.has_key('name'):
114
name = string.capitalize(key)
115
else:
116
name = args['name']
117
118
if widget is not None:
119
# tool is a widget
120
self.toolbar.AddControl(widget)
121
else:
122
# tools is a simple button
123
if not bitmap:
124
bitmap = wx.NullBitmap
125
126
# print 'bitmap=',name,bitmap
127
self.toolbar.AddSimpleTool(id, bitmap, name, info)
128
#self.toolbar.AddTool(id,name, bitmap, shortHelpString=info)
129
130
wx.EVT_TOOL(self, id, func)
131
# if args.has_key('func_rclick'):
132
# wx.EVT_TOOL_RCLICKED(self.parent, id, args['func_rclick'])
133
134
self._tools[key] = id
135
# Final thing to do for a toolbar is call the Realize() method. This
136
# causes it to render (more or less, that is).
137
self.toolbar.Realize()
138
S = self.toolbar.GetSize()
139
self.toolbar.SetSizeHints(S[0], S[1])
140
return id
141
142
def enable_tool(self, key, enable=True):
143
if self._tools.has_key(key):
144
# self._tools[key].Show(False)
145
self.toolbar.EnableTool(self._tools[key], enable)
146
147
else:
148
print 'enable_tool: no tool named:', key
149
150
def del_tool(self, key):
151
if self._tools.has_key(key):
152
# self._tools[key].Show(False)
153
self.toolbar.RemoveTool(self._tools[key])
154
del self._tools[key]
155
156
# Final thing to do for a toolbar is call the Realize() method. This
157
# causes it to render (more or less, that is).
158
self.toolbar.Realize()
159
else:
160
print 'del_tool: no tool named:', key
161
162
163
class AgileToolbarFrameMixin(AgileToolbarMixin):
164
"""
165
Easy to use toolbar where strings can be used to identify tools.
166
Mixin for frames only.
167
"""
168
169
def init_toolbar(self, orientation='horizontal', size=(16, 16), separation=5):
170
"""
171
Only this initialization is specific to frames.
172
"""
173
# Use the wxFrame internals to create the toolbar and associate it all
174
# in one tidy method call.
175
if orientation == 'horizontal':
176
self.toolbar = self.CreateToolBar(wx.TB_HORIZONTAL
177
| wx.NO_BORDER
178
| wx.TB_FLAT
179
| wx.TB_TEXT
180
)
181
else:
182
self.toolbar = self.CreateToolBar(wx.TB_VERTICAL
183
| wx.NO_BORDER
184
| wx.TB_FLAT
185
| wx.TB_TEXT
186
)
187
188
self.toolbar.SetToolBitmapSize(size)
189
self.toolbar.SetToolSeparation(separation)
190
191
self._tools = {}
192
193
194
class AgileMenuMixin:
195
"""
196
Easy to use menue mixin for main menu and popup
197
"""
198
199
def init_menu(self, parent):
200
"""
201
Initialize internal variables.
202
"""
203
self.parent = parent
204
self.__tree = {}
205
206
def get_menu(self, path):
207
items = self.__tree
208
val = (None, None, -1)
209
# print 'get_menu',path
210
for key in path:
211
# print ' ',key,items
212
if items.has_key(key):
213
val = items[key]
214
# print val
215
if len(val) == 3:
216
items = val[1]
217
else:
218
return None, None, -1
219
else:
220
print 'WARNING in get_menu: invalid menu key', key, 'in path'
221
return None, None, -1
222
223
return val[0], val[1], val[2]
224
225
def get_menuitem(self, path):
226
menupath = string.split(path, '/')[:-1]
227
key = string.split(path, '/')[-1]
228
229
# print '\nget_menuitem',self.__tree
230
if len(menupath) == 0:
231
# print " *create toplevel menu",key
232
menuitem, id = self.__tree[key]
233
234
else:
235
# print " *create submenu",key
236
menu, tree, id = self.get_menu(menupath)
237
menuitem, id = tree[key]
238
239
# print ' menuitem,id',menuitem,id
240
return menuitem
241
242
def append_menu(self, path, **args):
243
"""
244
"""
245
# print 'append_menu',path,args
246
if path == '.':
247
# print " use '.' as root for popups"
248
# create an entry for database but do not append a menue
249
250
key = '.'
251
# create special menu as direct root
252
id = wx.NewId()
253
self.__tree[key] = (self, {}, id)
254
# print ' ROOTMENU ATTRS: self,dir(self)',self,dir(self)
255
256
else:
257
# print " normal menu"
258
menupath = string.split(path, '/')[:-1]
259
key = string.split(path, '/')[-1]
260
261
if len(menupath) == 0:
262
# print " *create toplevel menu",key
263
menu, id = self._create_menu(self, key, **args)
264
self.__tree[key] = (menu, {}, id)
265
266
else:
267
# print " *create submenu",key
268
parentmenu, parentmenu_dict, parentid = self.get_menu(menupath)
269
# print ' PARENTMENU ATTRS: self,dir(parentmenu)',parentmenu,dir(parentmenu)
270
# print ' parentmenu,key,parentmenu_dict,parentid',parentmenu,key,parentmenu_dict,parentid
271
menu, id = self._create_menu(parentmenu, key, **args)
272
parentmenu_dict[key] = (menu, {}, id)
273
274
def _create_menu(self, parentmenu, key, menu=None, **args):
275
# print '\n\n_create_menu key',key
276
# default menu/submenu item
277
data = {'alt': True}
278
# print ' PARENTMENU ATTRS: self,dir(parentmenu)',parentmenu,dir(parentmenu)
279
# overwrite with args
280
data.update(args)
281
282
if not data.has_key('name'):
283
data['name'] = string.capitalize(key)
284
285
if data['alt']:
286
alt = '&'
287
else:
288
alt = ''
289
290
id = wx.NewId()
291
if menu is None:
292
menu = wx.Menu()
293
294
if parentmenu == self:
295
id = -1
296
if data.get('popup', False):
297
298
# !! this is the way to append a menue to toplevel
299
# popup menu which is a menu itself
300
self.AppendMenu(id, data['name'], menu)
301
302
else:
303
# !! this is the way to append a menue to toplevel
304
# which is a menubar !!
305
self.Append(menu, alt+data['name'])
306
307
else:
308
# attach menu to a submenu
309
# print ' make submenu'
310
311
item, id = self._create_item(key, parentmenu, function=None, **args)
312
item.SetSubMenu(menu)
313
parentmenu.AppendItem(item)
314
# parentmenu.AppendMenu(id,alt+data['name'],menu)
315
316
return menu, id
317
318
def append_item(self, path, function, **args):
319
320
# print 'append_item',path,function
321
menupath = string.split(path, '/')[:-1]
322
key = string.split(path, '/')[-1]
323
324
menu, menu_dict, menuid = self.get_menu(menupath)
325
326
# print ' key=',key
327
328
if menu:
329
# create item and append to menu instance
330
item, id = self._create_item(key, menu, function, **args)
331
332
# append item
333
# print ' menu',menu,type(menu),dir(menu)
334
menu.AppendItem(item)
335
if args.has_key('check'):
336
menu.Check(item.GetId(), args['check'])
337
# if (args.has_key('check'))&(args.has_key('checked')):
338
# menu.Check(item.GetId(), args['checked'])
339
340
menu_dict[key] = (item, id)
341
return item, id
342
else:
343
print 'WARNING: in append_item: invalid menu path', menupath
344
return None, None
345
346
def _create_item(self, key, menu, function=None, **args):
347
# default item
348
data = {'alt': True,
349
'shortkey': '',
350
# 'info':'',
351
}
352
353
# overwrite with args
354
data.update(args)
355
356
if not data.has_key('name'):
357
data['name'] = string.capitalize(key)
358
359
if not data.has_key('info'):
360
if function.__doc__ is not None:
361
data['info'] = function.__doc__.replace('\n', ' ').strip()
362
else:
363
data['info'] = data['name']
364
365
# print '_create_item',data
366
367
# create item
368
id = wx.NewId()
369
if data['alt']:
370
alt = '&'
371
else:
372
alt = ''
373
itemtext = alt+data['name']
374
if data['shortkey'] != '':
375
itemtext += '\t'+data['shortkey']
376
377
if data.has_key('radio'):
378
379
item = wx.MenuItem(menu, id, itemtext, data['info'], wx.ITEM_RADIO)
380
# print ' radio item'
381
382
elif data.has_key('check'):
383
item = wx.MenuItem(menu, id, itemtext, data['info'], wx.ITEM_CHECK)
384
# check boxes AFTER append
385
386
else:
387
item = wx.MenuItem(menu, id, itemtext, data['info'], wx.ITEM_NORMAL)
388
# print ' normal item'
389
390
if data.has_key('bitmap'):
391
# print '_create_item bitmap',data['bitmap']
392
# TODO: allow more image formats in menuitem
393
# item.SetBitmap(images.getSmilesBitmap())
394
item.SetBitmap(data['bitmap'])
395
396
# define callback function
397
if function is not None: # None for submenueitem
398
# wx.EVT_MENU(self.parent,id,function)
399
self.parent.Bind(wx.EVT_MENU, function, id=id)
400
401
return item, id
402
403
def del_item(self, path):
404
menupath = string.split(path, '/')[:-1]
405
key = string.split(path, '/')[-1]
406
407
menu, menu_dict, menuid = self.get_menu(menupath)
408
if menu:
409
if menu_dict.has_key(key):
410
menu.RemoveItem(menu_dict[key][0])
411
# menu_dict[key][0].Remove()
412
del menu_dict[key]
413
414
def del_menu(self, path):
415
menupath = string.split(path, '/')[:-1]
416
key = string.split(path, '/')[-1]
417
allpath = string.split(path, '/')
418
parentmenu, parentmenu_dict, parentmenuid = self.get_menu(menupath)
419
menu, menu_dict, menuid = self.get_menu(allpath)
420
421
if menu:
422
if menuid > -1:
423
parentmenu.Remove(menuid) # works
424
del parentmenu_dict[key]
425
else:
426
self.Remove(menu)
427
del parentmenu_dict[key]
428
429
def __setitem__(self, menupath, **data):
430
# print 'set menue',menupath,'to',data
431
432
if type(name) != types.TupleType:
433
# create main menue entry, if necessary
434
if not self.menus.has_key(name):
435
newmenue = wx.Menu()
436
self.Append(newmenue, '&'+name)
437
self.menus[name] = (-1, {})
438
439
elif len(name) == 2:
440
# create submenu entry, if necessary
441
name1, name2 = name
442
if not self.menus.has_key(name1):
443
newmenue = wx.Menu()
444
self.Append(newmenue, '&'+name1)
445
self.menus[name] = (-1, {})
446
447
menuid, submenus = self.menus[name1]
448
449
if not submenus.has_key(name2):
450
id = wx.NewId()
451
get_menu_item()
452
newmenue = wx.Menu()
453
self.Append(newmenue, '&'+name1)
454
self.menus[name] = {}
455
456
submenu = self.menus
457
parentmenu = None
458
for m in menu:
459
if not submenu.has_key(m):
460
newmenue = wx.Menu()
461
462
def get_menu_item(self, id):
463
item = self.FindItemById(id)
464
menu = item.GetMenu()
465
return menu, item
466
467
def get_menuitem_from_id(self, id):
468
menu, item = self.get_menu_item(id)
469
return item
470
471
472
class AgilePopupMenu(wx.Menu, AgileMenuMixin):
473
"""
474
Easy to use popup
475
"""
476
477
def __init__(self, parent):
478
wx.Menu.__init__(self)
479
self.init_menu(parent)
480
481
# append special root menu
482
AgileMenuMixin.append_menu(self, '.')
483
484
def append_menu(self, path, **args):
485
AgileMenuMixin.append_menu(self, './'+path, popup=True, **args)
486
487
def append_item(self, path, function, **args):
488
return AgileMenuMixin.append_item(self, './'+path, function, **args)
489
490
def get_menuitem(self, path):
491
return AgileMenuMixin.get_menuitem(self, './'+path)
492
493
# -------------------------------------------------------------------------------
494
# the folling methods are used with contect<sebitive menus
495
# on a grid based widget.
496
# When initializing the menu the row and column of its location can
497
# be stored for later retrival during an event:
498
# event.GetEventObject().get_row() event.GetEventObject().get_row()
499
500
def set_row(self, row):
501
self.row = row
502
503
def set_col(self, col):
504
self.col = col
505
506
def get_row(self):
507
return self.row
508
509
def get_col(self):
510
return self.col
511
512
513
KEYMAP = {
514
wx.WXK_BACK: "BACK",
515
wx.WXK_TAB: "TAB",
516
wx.WXK_RETURN: "RETURN",
517
wx.WXK_ESCAPE: "ESCAPE",
518
wx.WXK_SPACE: "SPACE",
519
wx.WXK_DELETE: "DELETE",
520
wx.WXK_START: "START",
521
wx.WXK_LBUTTON: "LBUTTON",
522
wx.WXK_RBUTTON: "RBUTTON",
523
wx.WXK_CANCEL: "CANCEL",
524
wx.WXK_MBUTTON: "MBUTTON",
525
wx.WXK_CLEAR: "CLEAR",
526
wx.WXK_SHIFT: "SHIFT",
527
wx.WXK_ALT: "ALT",
528
wx.WXK_CONTROL: "CONTROL",
529
wx.WXK_MENU: "MENU",
530
wx.WXK_PAUSE: "PAUSE",
531
wx.WXK_CAPITAL: "CAPITAL",
532
wx.WXK_PRIOR: "PRIOR",
533
wx.WXK_NEXT: "NEXT",
534
wx.WXK_END: "END",
535
wx.WXK_HOME: "HOME",
536
wx.WXK_LEFT: "LEFT",
537
wx.WXK_UP: "UP",
538
wx.WXK_RIGHT: "RIGHT",
539
wx.WXK_DOWN: "DOWN",
540
wx.WXK_SELECT: "SELECT",
541
wx.WXK_PRINT: "PRINT",
542
wx.WXK_EXECUTE: "EXECUTE",
543
wx.WXK_SNAPSHOT: "SNAPSHOT",
544
wx.WXK_INSERT: "INSERT",
545
wx.WXK_HELP: "HELP",
546
wx.WXK_NUMPAD0: "NUMPAD0",
547
wx.WXK_NUMPAD1: "NUMPAD1",
548
wx.WXK_NUMPAD2: "NUMPAD2",
549
wx.WXK_NUMPAD3: "NUMPAD3",
550
wx.WXK_NUMPAD4: "NUMPAD4",
551
wx.WXK_NUMPAD5: "NUMPAD5",
552
wx.WXK_NUMPAD6: "NUMPAD6",
553
wx.WXK_NUMPAD7: "NUMPAD7",
554
wx.WXK_NUMPAD8: "NUMPAD8",
555
wx.WXK_NUMPAD9: "NUMPAD9",
556
wx.WXK_MULTIPLY: "MULTIPLY",
557
wx.WXK_ADD: "ADD",
558
wx.WXK_SEPARATOR: "SEPARATOR",
559
wx.WXK_SUBTRACT: "SUBTRACT",
560
wx.WXK_DECIMAL: "DECIMAL",
561
wx.WXK_DIVIDE: "DIVIDE",
562
wx.WXK_F1: "F1",
563
wx.WXK_F2: "F2",
564
wx.WXK_F3: "F3",
565
wx.WXK_F4: "F4",
566
wx.WXK_F5: "F5",
567
wx.WXK_F6: "F6",
568
wx.WXK_F7: "F7",
569
wx.WXK_F8: "F8",
570
wx.WXK_F9: "F9",
571
wx.WXK_F10: "F10",
572
wx.WXK_F11: "F11",
573
wx.WXK_F12: "F12",
574
wx.WXK_F13: "F13",
575
wx.WXK_F14: "F14",
576
wx.WXK_F15: "F15",
577
wx.WXK_F16: "F16",
578
wx.WXK_F17: "F17",
579
wx.WXK_F18: "F18",
580
wx.WXK_F19: "F19",
581
wx.WXK_F20: "F20",
582
wx.WXK_F21: "F21",
583
wx.WXK_F22: "F22",
584
wx.WXK_F23: "F23",
585
wx.WXK_F24: "F24",
586
wx.WXK_NUMLOCK: "NUMLOCK",
587
wx.WXK_SCROLL: "SCROLL",
588
wx.WXK_PAGEUP: "PAGEUP",
589
wx.WXK_PAGEDOWN: "PAGEDOWN",
590
wx.WXK_NUMPAD_SPACE: "NUMPAD_SPACE",
591
wx.WXK_NUMPAD_TAB: "NUMPAD_TAB",
592
wx.WXK_NUMPAD_ENTER: "NUMPAD_ENTER",
593
wx.WXK_NUMPAD_F1: "NUMPAD_F1",
594
wx.WXK_NUMPAD_F2: "NUMPAD_F2",
595
wx.WXK_NUMPAD_F3: "NUMPAD_F3",
596
wx.WXK_NUMPAD_F4: "NUMPAD_F4",
597
wx.WXK_NUMPAD_HOME: "NUMPAD_HOME",
598
wx.WXK_NUMPAD_LEFT: "NUMPAD_LEFT",
599
wx.WXK_NUMPAD_UP: "NUMPAD_UP",
600
wx.WXK_NUMPAD_RIGHT: "NUMPAD_RIGHT",
601
wx.WXK_NUMPAD_DOWN: "NUMPAD_DOWN",
602
wx.WXK_NUMPAD_PRIOR: "NUMPAD_PRIOR",
603
wx.WXK_NUMPAD_PAGEUP: "NUMPAD_PAGEUP",
604
wx.WXK_NUMPAD_NEXT: "NUMPAD_NEXT",
605
wx.WXK_NUMPAD_PAGEDOWN: "NUMPAD_PAGEDOWN",
606
wx.WXK_NUMPAD_END: "NUMPAD_END",
607
wx.WXK_NUMPAD_BEGIN: "NUMPAD_BEGIN",
608
wx.WXK_NUMPAD_INSERT: "NUMPAD_INSERT",
609
wx.WXK_NUMPAD_DELETE: "NUMPAD_DELETE",
610
wx.WXK_NUMPAD_EQUAL: "NUMPAD_EQUAL",
611
wx.WXK_NUMPAD_MULTIPLY: "NUMPAD_MULTIPLY",
612
wx.WXK_NUMPAD_ADD: "NUMPAD_ADD",
613
wx.WXK_NUMPAD_SEPARATOR: "NUMPAD_SEPARATOR",
614
wx.WXK_NUMPAD_SUBTRACT: "NUMPAD_SUBTRACT",
615
wx.WXK_NUMPAD_DECIMAL: "NUMPAD_DECIMAL",
616
wx.WXK_NUMPAD_DIVIDE: "NUMPAD_DIVIDE",
617
}
618
619
620
class KeyHandler:
621
"""
622
Mixin for handling key events in wx
623
"""
624
625
def init_keys(self, parent=None):
626
"""
627
Sets events and variables for parent.
628
If no parent is defined then self is assumed to be parent.
629
"""
630
if parent is None:
631
parent = self
632
633
self.key_pressed = '' # string code of currently pressed key
634
wx.EVT_ENTER_WINDOW(self, self.on_enter_window)
635
wx.EVT_KEY_DOWN(self, self.on_key_down)
636
wx.EVT_KEY_UP(self, self.on_key_up)
637
638
def on_enter_window(self, evt):
639
# print 'on_enter_window'
640
self.SetFocus()
641
#self.haveFocus = False
642
# self.Refresh()
643
644
def on_key_down(self, event):
645
"""
646
A key has been pressed down...
647
"""
648
if self.GUIMode is None:
649
# try custom tool of metacanvas
650
input = self.set_keypress(event)
651
# print 'on_key_down',input
652
self.metacanvas.make_transition(input, self)
653
654
def on_key_up(self, event):
655
"""
656
A key has been pressed down...
657
"""
658
# print 'on_key_up'
659
self.del_keypress()
660
print ' key_pressed', self.key_pressed
661
662
def del_keypress(self):
663
"""
664
Empties self.key_pressed string
665
"""
666
self.key_pressed = ''
667
668
def set_keypress(self, evt, ignore_specials=False):
669
"""
670
This method analyses the event and sets the self.key_pressed string.
671
Method returns a string with the key.
672
673
674
"""
675
keycode = evt.GetKeyCode()
676
keyname = KEYMAP.get(keycode, None)
677
if keyname is None:
678
# regular character key
679
if keycode < 256:
680
if keycode == 0:
681
keyname = "NUL"
682
elif (keycode < 27) & (not ignore_specials):
683
# keycode is a special control key
684
keyname = "Ctrl-%s" % chr(ord('A') + keycode-1)
685
elif (keycode < 27):
686
keyname = ''
687
else:
688
keyname = "\"%s\"" % chr(keycode)
689
else:
690
keyname = '' # ignore
691
692
elif ignore_specials: # keycode is a special key
693
keyname = '' # ignore
694
695
self.key_pressed = keyname
696
697
return keyname
698
699
def get_code_special_keys(self, event, sep='+'):
700
"""
701
This method analyses the special keypress and returns a string
702
that codes SHIFT, ALT, CONTROL
703
"""
704
code = ''
705
706
if event.ControlDown():
707
code += 'CONTROL'+sep
708
709
if event.ShiftDown():
710
code += 'SHIFT'+sep
711
712
if event.AltDown():
713
code += 'ALT'+sep
714
715
return code
716
717
# class ToolMixin(AgileToolbarMixin):
718
719
720
class OptionsFrame(wx.Frame):
721
"""
722
Simple wx frame with some special features.
723
"""
724
725
def __init__(self, parent, mainframe=None, id=-1, title='testframe', pos=wx.DefaultPosition,
726
size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE,
727
name='frame'):
728
729
if mainframe is None:
730
self._mainframe = parent
731
else:
732
self._mainframe = mainframe
733
734
# Forcing a specific style on the window.
735
# Should this include styles passed?
736
style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE
737
wx.Frame.__init__(self, parent, id, title, pos, size, style, name)
738
#super(GLFrame, self).__init__(parent, id, title, pos, size, style, name)
739
740
def get_metacanvas(self):
741
return metacanvas
742
743
744
class OptionsPanel(AgileToolbarMixin, wx.Panel):
745
"""
746
UNUSED
747
Simple wx panele with some special features.
748
"""
749
750
def __init__(self, parent, mainframe=None):
751
752
wx.Panel.__init__(self, parent, -1, wx.DefaultPosition,
753
wx.DefaultSize, wx.SUNKEN_BORDER | wx.WANTS_CHARS)
754
if mainframe is None:
755
self._mainframe = parent
756
else:
757
self._mainframe = mainframe
758
759
def get_metacanvas(self):
760
return metacanvas
761
762
763
class AgileStatusbar(wx.StatusBar):
764
def __init__(self, parent, fields=[('action', -4),
765
('message', -4),
766
# ('coords',-1),
767
# ('zoom',-1),
768
('progress', -1),
769
('status', -1),
770
# ('coords',-1),
771
]):
772
773
wx.StatusBar.__init__(self, parent, -1, wx.ST_SIZEGRIP)
774
775
self.set_fields(fields)
776
777
self.sizeChanged = False
778
self.Bind(wx.EVT_SIZE, self.OnSize)
779
#self.Bind(wx.EVT_IDLE, self.OnIdle)
780
781
# Field 0 ... just text
782
# self['message']=""
783
784
# create a progrss bar
785
self.progressbar = wx.Gauge(self, -1, 100)
786
self.progressbar.SetBezelFace(4)
787
self.progressbar.SetShadowWidth(4)
788
# self.progressbar.SetValue(50)
789
790
# put into position all status bar fields and elements
791
self.Reposition()
792
793
def write_action(self, text):
794
self['action'] = text
795
796
def write_message(self, text):
797
self['message'] = text
798
799
# def write_coords(self,text):
800
# self['coords'] = text
801
802
def set_progress(self, percent):
803
"""
804
Set bar of progressbar in percent
805
"""
806
# print 'set_progress',percent
807
self.progressbar.SetValue(int(percent))
808
self.Update()
809
810
def set_fields(self, fields):
811
"""
812
Sets basic data of fields in status bar.
813
Argument field is a list with the following format:
814
[(name1,width1),(name2,width2),...]
815
"""
816
self._ind_fields = {}
817
widths = []
818
ind = 0
819
for name, width in fields:
820
widths.append(width)
821
self._ind_fields[name] = ind
822
ind += 1
823
self.SetFieldsCount(ind)
824
self.SetStatusWidths(widths)
825
826
def __setitem__(self, key, message):
827
828
ind_field = self._ind_fields[key]
829
# print 'AgileStatusbar.__setitem__',key,ind_field
830
self.SetStatusText(message, ind_field)
831
self.Update()
832
833
def has_key(self, key):
834
return self._ind_fields.has_key(key)
835
836
def OnSize(self, evt):
837
self.Reposition() # for normal size events
838
839
# Set a flag so the idle time handler will also do the repositioning.
840
# It is done this way to get around a buglet where GetFieldRect is not
841
# accurate during the EVT_SIZE resulting from a frame maximize.
842
self.sizeChanged = True
843
844
def OnIdle(self, evt):
845
if self.sizeChanged:
846
self.Reposition()
847
848
# reposition the checkbox
849
850
def Reposition(self):
851
# print 1,rect
852
rect = self.GetFieldRect(self._ind_fields['progress'])
853
self.progressbar.SetPosition(rect.GetPosition())
854
self.progressbar.SetSize(rect.GetSize())
855
856
self.sizeChanged = False
857
858
859
class AgileMenubar(AgileMenuMixin, wx.MenuBar):
860
"""
861
Easy to use main menu bar
862
"""
863
864
def __init__(self, parent):
865
wx.MenuBar.__init__(self)
866
self.init_menu(parent)
867
868
869
def get_bitmap(name, size=22):
870
"""Return bitmap of right size from imgImages library"""
871
name = name + "_"+str(size)
872
try:
873
return imgImages.catalog[name].getBitmap()
874
except:
875
print 'WARNING in get_bitmap: failed to return image', name
876
return wx.NullBitmap
877
878
879
# These are some functions for bitmaps of icons.
880
881
882
def GetHandData():
883
return cPickle.loads(zlib.decompress(
884
'x\xda\xd3\xc8)0\xe4\nV72T\x00!\x05Cu\xae\xc4`u=\x85d\x05\xa7\x9c\xc4\xe4l0O\
885
\x01\xc8S\xb6t\x06A(\x1f\x0b\xa0\xa9\x8c\x9e\x1e6\x19\xa0\xa8\x1e\x88\xd4C\
886
\x97\xd1\x83\xe8\x80 \x9c2zh\xa6\xc1\x11X\n\xab\x8c\x02\x8a\x0cD!\x92\x12\
887
\x98\x8c\x1e\x8a\x8b\xd1d\x14\xf4\x90%\x90LC\xf6\xbf\x1e\xba\xab\x91%\xd0\
888
\xdc\x86C\x06\xd9m\xe8!\xaa\x87S\x86\x1a1\xa7\x07\x00v\x0f[\x17'))
889
890
891
def GetHandBitmap():
892
return wx.BitmapFromXPMData(GetHandData())
893
894
# ----------------------------------------------------------------------
895
896
897
def GetPlusData():
898
return cPickle.loads(zlib.decompress(
899
'x\xda\xd3\xc8)0\xe4\nV72T\x00!\x05Cu\xae\xc4`u=\x85d\x05\xa7\x9c\xc4\xe4l0O\
900
\x01\xc8S\xb6t\x06A(\x1f\x0b RF\x0f\x08\xb0\xc9@D\xe1r\x08\x19\xb8j=l2`\r\
901
\xe82HF\xe9a\xc8\xe8\xe9A\x9c@\x8a\x0c\x0e\xd3p\xbb\x00\x8f\xab\xe1>\xd5\xd3\
902
\xc3\x15:P)l!\n\x91\xc2\x1a\xd6`)\xec\xb1\x00\x92\xc2\x11?\xb8e\x88\x8fSt\
903
\x19=\x00\x82\x16[\xf7'))
904
905
906
def GetPlusBitmap():
907
return wx.BitmapFromXPMData(GetPlusData())
908
909
# ----------------------------------------------------------------------
910
911
912
def GetMinusData():
913
return cPickle.loads(zlib.decompress(
914
'x\xda\xd3\xc8)0\xe4\nV72T\x00!\x05Cu\xae\xc4`u=\x85d\x05\xa7\x9c\xc4\xe4l0O\
915
\x01\xc8S\xb6t\x06A(\x1f\x0b RF\x0f\x08\xb0\xc9@D\xe1r\x08\x19\xb8j=\xa2e\
916
\x10\x16@\x99\xc82zz\x10\'\x90"\x83\xc34r\xdc\x86\xf0\xa9\x9e\x1e\xae\xd0\
917
\x81Ja\x0bQ\x88\x14\xd6\xb0\x06Ka\x8f\x05\x90\x14\x8e\xf8\xc1-C|\x9c\xa2\xcb\
918
\xe8\x01\x00\xed\x0f[\x87'))
919
920
921
def GetMinusBitmap():
922
return wx.BitmapFromXPMData(GetMinusData())
923
924