mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-04 11:00:07 +01:00
Adding missing close for open. If the "close()" call is missing after a "open(filename)" call, the filename isn't guaranteed to be closed before the interpreter exits. This is generally a bad practice as explained here: https://stackoverflow.com/questions/7395542/is-explicitly-closing-files-important Also replaced "fid=open(filename) fid.close()" statements for files with the safer "with open(filename) as fid:" blocks. See https://www.python.org/dev/peps/pep-0343/
398 lines
14 KiB
Python
398 lines
14 KiB
Python
#!/usr/bin/env python
|
|
|
|
import wx
|
|
|
|
import os
|
|
import sys
|
|
import string
|
|
import random
|
|
|
|
from images import catalog
|
|
import images
|
|
|
|
from wx.lib.embeddedimage import PyEmbeddedImage
|
|
|
|
try:
|
|
dirName = os.path.dirname(os.path.abspath(__file__))
|
|
except:
|
|
dirName = os.path.dirname(os.path.abspath(sys.argv[0]))
|
|
|
|
sys.path.append(os.path.split(dirName)[0])
|
|
|
|
try:
|
|
from agw import shortcuteditor as SE
|
|
except ImportError: # if it's not there locally, try the wxPython lib.
|
|
import wx.lib.agw.shortcuteditor as SE
|
|
|
|
|
|
SE_DIR = os.path.split(SE.__file__)[0]
|
|
HTML_HELP = os.path.join(SE_DIR, 'data', 'default_help_text.html')
|
|
|
|
TOP_MENUS = ['File', 'Edit', 'View', 'Options', 'Window', 'Help']
|
|
|
|
COMBINATIONS = string.ascii_uppercase + string.digits
|
|
COMBINATIONS = [c for c in COMBINATIONS] + list(SE.KEYMAP.values())
|
|
|
|
ACCEL_IDS = wx.NewIdRef(6)
|
|
|
|
_ = wx.GetTranslation
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
_accelerators = PyEmbeddedImage(
|
|
b"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
|
|
b"ZSBJbWFnZVJlYWR5ccllPAAAAUNJREFUeNqkkrFqg1AUho+idLKCEgSnvoBkUiwBoU4tGXyJ"
|
|
b"Lpmy+QI+gUuzFbK5OhSKQzZBfIlACCEiplAHkQj2XFNDaYOJ6YHPH7n85z/ncqm6ruE/xZDP"
|
|
b"eDzu66ORELmnrwy+Q9K2U9+6RZ6Rt+MKvw6nyCNy09HkHXk91cBGPpAn5PPiS/wuFnlATKS8"
|
|
b"dB9qPp+/oE6uvMwZU1XVxDRNyLIMBEGA3W53VkmJogiLxWJC7/d7WK/XMBwOYbVanVVFURqI"
|
|
b"h3gp13VrXdchTdNesw8GA4iiCOiyLIHneSiKAgzD6NTRaASqqgIJ3G63QLyU4zi1pmmQJEln"
|
|
b"IsdxkOf58V+SJIjjGBjShZgtywLP8xolu/0slmXB9/3mrNUgCA4T2LbdTLDZbP6knJqgVVmW"
|
|
b"DxNg2iwMw97vYLlcNu/gS4ABALx5qLfCRWM1AAAAAElFTkSuQmCC")
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
_edit = PyEmbeddedImage(
|
|
b"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABmJLR0QAAAAAAAD5Q7t/AAAA"
|
|
b"CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1QsOEh8bQbXRcgAAAhxJREFUKM91ks1rE1EU"
|
|
b"xc99H5l8m2lolKRuqtamKohFChahYF0IfoBSF4IbwY1/gv+DK/cuXLgTxaWIXSjSjWKEFgm4"
|
|
b"aGvaJo1NJpm0eTPvzXPRmrZgz+7C+d3DPVz6WvmVTMTwT9tKK2W9le8Ta08VTXei0fL9R8nC"
|
|
b"iYFBJJPO2VPFwRyEkbLMazwrnvvJTM5frP3+MDz24PHAwGAtDohLZpt113nHNoH5he6nL+mx"
|
|
b"8wcNDIdFAG++imMVLaCFbzT+vtrdanWOBEyny9sveQjssLUa712aq7e9xaXqkQC8ea4r6Mds"
|
|
b"nTZKV07O3iu4KSJ7JGCXn8tMAn685WX98dtDI0UOwxj9HzAbCzxeRS+NjrOVnnBn5hJWZdOZ"
|
|
b"Rr0BIAiCw4Ax0doLFmdQWb+dbo3ccIslwRhx8trtMAybzT+9Xk/shikLbFSEs0zaBZzGjjN8"
|
|
b"92Hgt8NAdbyOUkprDaDb9cXu9igCTB9RCfGMv15r5qfjEVebTUYUGUNEAIhICM4G9euQuJw1"
|
|
b"+nplyQ3PzGirTWSFFAQCkRAilzuWz+f3EiTHcn37x8fPpUSKrj5JjZZ1fxuwXLBkKiV4KKWU"
|
|
b"Uu4dvVtyf0evV9fl5J38hSkE/ZiQrpstFI4LyYul0v7zEWcEcKA8OXX64mWeG9L9MMxlpBOL"
|
|
b"jI3FOOeCs/0yxepK7c3rt1wwYhJEkQlguYWxFjayjJHndW/dvDYA/gKtTuQVCWY6EAAAAABJ"
|
|
b"RU5ErkJgggo=")
|
|
|
|
#----------------------------------------------------------------------
|
|
_file = PyEmbeddedImage(
|
|
b"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAB3RJTUUH0AwNAR44FPFuJQAA"
|
|
b"AAlwSFlzAAAK8AAACvABQqw0mAAAADBQTFRFAP8Af39/UFBQz8/P4ODg////8PDw///wn5+f"
|
|
b"MDAwgICAAAAAAAAAAAAAAAAAAAAAZbZ2KAAAAAF0Uk5TAEDm2GYAAABRSURBVHjaY2BcBQQL"
|
|
b"GBgYGEOBoAnECC8vL29XgDI0Z0IY6RZCYEZZmXMTRCTFxQjMSHeBMNLdoIySFCgDKABmhKVB"
|
|
b"GS4uUIYxCIAYSmDAAAcA0SwdEWLFwocAAAAASUVORK5CYII=")
|
|
|
|
#----------------------------------------------------------------------
|
|
_help = PyEmbeddedImage(
|
|
b"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC+ElEQVR4nGWTP2xbVRjFf9+9"
|
|
b"9/01TgwJCQkMbkMKqCkEKGoXBpiQEqkpZUL8y8BeRqYwMMBQRMWMGtQgJCSKYWCohARIVCCo"
|
|
b"MJUgLbSipVERTuzYcexn+713L4OlirafdLZzznC+c4TbbnZxrSTIEkoeQ9S8iICob0WkevHM"
|
|
b"C5Xb+XKLeOH08WIxXnloZqoUhSFRFDHIcmr1XerNDts7navWuTfWPz1SucNgduH0qfm58mt7"
|
|
b"y/ezfq1LrZmR2SHFaAg9QTtLo1WnnybLv3+yuHrTYHZh7a1DT8ysFEfH+eVyh73TEa8vTvL0"
|
|
b"o0WsdXzz6w6nzm5x5cYALdDtNMgG3aO/ffxcRWYX18pTE6W/Dj7+CN9daDM17lN5+2GsteS5"
|
|
b"w1qLc44b9ZSXTlxHRHDOkrRqTWvzPXp837GVw0/OHl7fyOiljt2eJQ4U9VbGiTM1HLBn0iP2"
|
|
b"hR8v92n1QGmNaB3m6eCS8QNvSZmI7XYXRECED76skTshs6C18OyBGOccm7uOTjrMLNQRottH"
|
|
b"zOhIoVxrpsM0BPqpo9vJEa15YMLnzWNjWGs590efRg/8yABQUJB0dclYB71BjnWwvZORI3i+"
|
|
b"RnuKd16ZIA6EK/9mnPy6QxB7KDV8XDFw1BsGM0hzBMfmdooTwfgKZRQLB+9iZtJgrePD7xNS"
|
|
b"ZQgChdIKgJGCRZRGdZJBpd1OsM4hSlB6iKl7DM45nHNc2nQEoSGIPMLYY2TEIwxAtKkaRH3R"
|
|
b"au8uFcNRulZQaojKzwn7pn22EjC+xgs0fuhhfE15DP5cbyFKf6Qufvb8atJPqpHOMQKIIEo4"
|
|
b"+lTMoRmfhTmfuWmD9jReqJm+10ORs/FPv3L+/QNVBeBwy4O01QzE3uz2hesp3QFs7MDfTYdR"
|
|
b"cN+oUPIyzv3QqIrSy7dsYf+LX82jzOe5GS3rsEgcGeKCR6FouLvkMVYybDV6XNtIqoNMnvnp"
|
|
b"3Qebd6xx7uWzJZQ6Ltp71XhBOS7EhJEhzS27SV4VbU6ef2//6v81/wH6bjI8fK9HXAAAAABJ"
|
|
b"RU5ErkJggg==")
|
|
|
|
#----------------------------------------------------------------------
|
|
_options = PyEmbeddedImage(
|
|
b"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAA"
|
|
b"CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1QkaDBM5i2PCSAAAAfBJREFUOMulkktoE2EU"
|
|
b"hb+Z+EyKTRQKgkqwzMaFtt1FrC40FGJm60JwIVSkqLUtElICFQNDQqBrQXRlQIriwomN0GJX"
|
|
b"gtI2iUkXFYJVadOXhiBERDozbmaGMR3rwrP7ueece++5P/wnBOcjnVGigArI8Vgi9xdNNJ1R"
|
|
b"bI7YUlT7r/YDqKaZq/j6tQHNbLQd6YxiNBp1I51RDPdaw6pFAcR0RolaZKur19vmZhwFePDw"
|
|
b"PvFYQgZyACKgDt4cMp4+mzAA9fatETbX15A6Jer1r/das4ndGRUsMYBgFW8MDBqatiXoum7o"
|
|
b"ukZhfk4ovC8CyDsFK7R0sBHpu0i5UmG59gUgGY8l7v7zjE68yr80SpUS3Sd7KJYLmBNMArqr"
|
|
b"QTCSOgzUrPeVkE7XCYmjR47RbDZ5N/cWtzU8TvH4cJi+UCcdAS/ZmU2Ot39LLn1eOtd9qoeA"
|
|
b"P8BKbfnyhfD5+emp11XAABCDkVQXUHs0JjNbXmS2vEjHQR8A5t5yLv8CSZI4e7rX+mR2HiJQ"
|
|
b"HB8OM/WmxJamI+7zs1Fv2iOaI8vZJ4850O7nTKgXYMxpAMDuXR72+A7x88cvsvkFgHCrSS6v"
|
|
b"Uv1Y/SNsEWBl4zv7fQHa9np4PvMBIPxpcnTaSTRNkmvrqwtA0r5CMJK6BEw4uNvEO+E3N+LV"
|
|
b"9uq8VLwAAAAASUVORK5CYII=")
|
|
|
|
#----------------------------------------------------------------------
|
|
_view = PyEmbeddedImage(
|
|
b"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAB3RJTUUH2QMSDgcQHD2pKgAA"
|
|
b"AAlwSFlzAAALEgAACxIB0t1+/AAAAARnQU1BAACxjwv8YQUAAACWUExURb7Dxvz8/ObXxs+0"
|
|
b"mK6UZb6JXMGZf9rBpezn39PT07unkOq0iuvBotSdZ/7+/trZ2eng1uvr5O7u7v///ubMsNDe"
|
|
b"7ae+23Og32aX3Y+z58va6vHx8fT09Nzm8Zm66nql4+Dg3/j4+LXN8IOs5vf39/v7+6fE7g8U"
|
|
b"G8iUWdXGwMqldOvUtr/Jzunp6ayfnaSps5qhs9/NuBN0LcUAAAABdFJOUwBA5thmAAAAqUlE"
|
|
b"QVR42o2PSxaCMBAEx4kQZIKGGAQEE8NXRUHufzkRL2Dt6vWmGuAfXIzzrLWW7ucKh2HgjAsh"
|
|
b"gq+/cGDhOE3v0SfCdQ+fXWdMXlecKACp723Vmb6vbd0iPUDLpu1M3vc2tW0jb3BVpavy2to0"
|
|
b"M65UDFAW5cUsmtmkLJAg1hio5JRm+bmIdcQADlygjNUCUuQfl5BdSLRECYo8tl9TN8i2nuf5"
|
|
b"PPjr6Qc/LA45I8MgVQAAAABJRU5ErkJggg==")
|
|
|
|
#----------------------------------------------------------------------
|
|
_window = PyEmbeddedImage(
|
|
b"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAKnRFWHRDcmVhdGlvbiBUaW1l"
|
|
b"AERpIDQgTXJ6IDIwMDMgMDA6MjQ6MDQgKzAxMDDdSQ6OAAAAB3RJTUUH0woGFAwIjuRPzgAA"
|
|
b"AAlwSFlzAAAK8AAACvABQqw0mAAAAARnQU1BAACxjwv8YQUAAAEVSURBVHjaY2SY/tuDgYll"
|
|
b"OwMp4OqOKIZJntuArM+MDDP//59pTLzeJQ8ZGA6/ATLSGT2A5AkWkGD6WSDx5g1xJvDwMDBw"
|
|
b"cIBYlkB8C2zANdvrKGr+/mVg+P0bQv/5g8AgsT9/XjN4PdYEKRMEYjawAZqamigGgBT/+gXR"
|
|
b"AKORMcNjsDJGEMFEUuBhAdQ34N8/VEwIsMD8jGwAiA8KQBgbn6FgA0ABhWwAsub//xF8nAaA"
|
|
b"QxbNCzBXwFwAYoMMA2G8LoB5CaQQZggMwwzD6wJ0b6C7AoSh4D/EgGu7IqUZ3JaTFHcdFkuA"
|
|
b"5HuQ40GpiR+ILRggaRuUPBkJaP8P1XwciE8wQtMCLxALAzErkW4AefotEH8GAEJMrcAWjkHy"
|
|
b"AAAAAElFTkSuQmCC")
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
def GetValidMenuImages():
|
|
|
|
valid_images = []
|
|
counter = 0
|
|
|
|
for key in catalog:
|
|
bmp = catalog[key].GetBitmap()
|
|
if bmp.GetWidth() == 16 and bmp.GetHeight() == 16:
|
|
valid_images.append(bmp)
|
|
|
|
return valid_images
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
class ShortcutEditorDemo(wx.Frame):
|
|
|
|
def __init__(self, parent, log):
|
|
|
|
wx.Frame.__init__(self, parent, -1, 'ShortcutEditor wxPython Demo :-D', size=(900, 800))
|
|
|
|
self.log = log
|
|
|
|
self.valid_images = GetValidMenuImages()
|
|
self.used_shortcuts = []
|
|
|
|
self.SetIcon(images.Mondrian.GetIcon())
|
|
|
|
self.MakeMenuBar()
|
|
self.MakeAcceleratorTable()
|
|
|
|
dlg = SE.ShortcutEditor(self)
|
|
dlg.FromMenuBar(self)
|
|
dlg.FromAcceleratorTable(self.accelTable)
|
|
|
|
self.AddTopMenuBitmaps(dlg)
|
|
|
|
dlg.Bind(SE.EVT_SHORTCUT_CHANGING, self.OnShortcutChanging)
|
|
dlg.Bind(SE.EVT_SHORTCUT_CHANGED, self.OnShortcutChanged)
|
|
|
|
self.CenterOnScreen()
|
|
self.Show()
|
|
self.Raise()
|
|
|
|
wx.CallAfter(self.ShowDialog, dlg)
|
|
|
|
|
|
def MakeMenuBar(self):
|
|
|
|
bar = wx.MenuBar()
|
|
top_menus = []
|
|
|
|
for title in TOP_MENUS:
|
|
menu = wx.Menu()
|
|
|
|
self.AppendMenus(menu, title)
|
|
|
|
bar.Append(menu, title)
|
|
top_menus.append(menu)
|
|
|
|
self.SetMenuBar(bar)
|
|
|
|
|
|
def MakeAcceleratorTable(self):
|
|
|
|
table = []
|
|
saved_table = []
|
|
|
|
for i in range(6):
|
|
name = 'Accelerator %d'%(i+1)
|
|
choice = random.choice(list(SE.ACCELERATORS))
|
|
|
|
if choice == wx.ACCEL_ALT:
|
|
letter = random.choice(COMBINATIONS)
|
|
|
|
if len(letter) > 1:
|
|
inv_keyMap = dict(zip(SE.KEYMAP.values(), SE.KEYMAP.keys()))
|
|
wxk = inv_keyMap[letter]
|
|
else:
|
|
wxk = ord(letter)
|
|
|
|
else:
|
|
wxk = random.choice(list(SE.KEYMAP))
|
|
|
|
accel = (choice, wxk, ACCEL_IDS[i])
|
|
saved_accel = (name, choice, wxk, ACCEL_IDS[i])
|
|
|
|
self.Bind(wx.EVT_MENU, self.OnAcceleratorShortcuts, id=ACCEL_IDS[i])
|
|
|
|
table.append(accel)
|
|
saved_table.append(saved_accel)
|
|
|
|
self.accelTable = saved_table
|
|
self.SetAcceleratorTable(wx.AcceleratorTable(table))
|
|
|
|
|
|
def AppendMenus(self, top_menu, title, recursive=''):
|
|
|
|
num_menus = random.randint(2, 7)
|
|
|
|
for index in range(num_menus):
|
|
shortcut = self.CreateShortcut()
|
|
|
|
sub_menu = wx.MenuItem(top_menu, -1, '%s%sItem %d%s'%(recursive, title, index+1, shortcut),
|
|
'Help for %s%sItem %d'%(recursive, title, index+1))
|
|
|
|
if random.randint(0, 1) == 1:
|
|
# Get a random image for the menu
|
|
bmp = random.choice(self.valid_images)
|
|
sub_menu.SetBitmap(bmp)
|
|
|
|
self.Bind(wx.EVT_MENU, self.OnMenuShortcuts, id=sub_menu.GetId())
|
|
|
|
if random.randint(0, 10) == 5 and not recursive:
|
|
# Append a sub-sub-menu
|
|
dummy_menu = wx.Menu()
|
|
|
|
recursive = 'Sub-'
|
|
self.AppendMenus(dummy_menu, title, recursive)
|
|
dummy_item = top_menu.AppendSubMenu(dummy_menu, 'Sub ' + title)
|
|
|
|
if random.randint(0, 1) == 1:
|
|
# Get a random image for the menu
|
|
bmp = random.choice(self.valid_images)
|
|
dummy_item.SetBitmap(bmp)
|
|
|
|
recursive = ''
|
|
|
|
top_menu.Append(sub_menu)
|
|
|
|
if random.randint(0, 1) == 1 and index < num_menus - 1:
|
|
# Append a separator
|
|
top_menu.AppendSeparator()
|
|
|
|
|
|
def CreateShortcut(self):
|
|
|
|
rand = random.randint(0, 3)
|
|
|
|
if rand == 0:
|
|
# No shortcut
|
|
return ''
|
|
|
|
letter = random.choice(COMBINATIONS)
|
|
shortcut = '\t%s+' + letter
|
|
|
|
if rand == 1:
|
|
# Ctrl + character
|
|
modifier = 'Ctrl'
|
|
|
|
elif rand == 2:
|
|
# Shift + character
|
|
modifier = 'Shift'
|
|
|
|
else:
|
|
# Ctrl + Shift + character
|
|
modifier = 'Ctrl+Shift'
|
|
|
|
shortcut = shortcut % modifier
|
|
|
|
if shortcut in self.used_shortcuts:
|
|
return self.CreateShortcut()
|
|
|
|
self.used_shortcuts.append(shortcut)
|
|
return shortcut
|
|
|
|
|
|
def AddTopMenuBitmaps(self, dlg):
|
|
|
|
manager = dlg.GetShortcutManager()
|
|
|
|
for child in manager.children:
|
|
name = child.label.lower()
|
|
bitmap = eval('_%s'%name).GetBitmap()
|
|
child.SetBitmap(bitmap)
|
|
|
|
|
|
def ShowDialog(self, dlg):
|
|
|
|
answer = dlg.ShowModal()
|
|
|
|
if answer == wx.ID_CANCEL:
|
|
dlg.Destroy()
|
|
return
|
|
|
|
dlg.ToMenuBar(self)
|
|
dlg.ToAcceleratorTable(self)
|
|
|
|
dlg.Destroy()
|
|
|
|
|
|
def OnMenuShortcuts(self, event):
|
|
|
|
itemId = event.GetId()
|
|
menu = event.GetEventObject().GetMenuBar()
|
|
menuItem = menu.FindItemById(itemId)
|
|
|
|
label = menuItem.GetItemLabel()
|
|
label, accel = label.split('\t')
|
|
|
|
self.log.write('You have selected the shortcut for %s (%s)'%(label, accel))
|
|
|
|
|
|
def OnAcceleratorShortcuts(self, event):
|
|
|
|
itemId = event.GetId()
|
|
|
|
for label, choice, accel, ids in self.accelTable:
|
|
if ids == itemId:
|
|
self.log.write('You have selected the accelerator for %s (%s)'%(label, accel))
|
|
break
|
|
|
|
|
|
def OnShortcutChanging(self, event):
|
|
|
|
shortcut = event.GetShortcut()
|
|
oldAccel = event.GetOldAccelerator()
|
|
newAccel = event.GetAccelerator()
|
|
|
|
self.log.write('Shortcut for "%s" changing from "%s" to "%s"'%(shortcut.label, oldAccel, newAccel))
|
|
event.Skip()
|
|
|
|
|
|
def OnShortcutChanged(self, event):
|
|
|
|
shortcut = event.GetShortcut()
|
|
newAccel = event.GetAccelerator()
|
|
|
|
self.log.write('Shortcut for "%s" changed to "%s"'%(shortcut.label, newAccel))
|
|
|
|
|
|
#---------------------------------------------------------------------------
|
|
|
|
class TestPanel(wx.Panel):
|
|
def __init__(self, parent, log):
|
|
self.log = log
|
|
wx.Panel.__init__(self, parent, -1)
|
|
|
|
b1 = wx.Button(self, -1, " Run ShortcutEditor ", (50, 50))
|
|
self.Bind(wx.EVT_BUTTON, self.OnButton1, b1)
|
|
|
|
|
|
def OnButton1(self, event):
|
|
self.win = ShortcutEditorDemo(self, self.log)
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
def runTest(frame, nb, log):
|
|
|
|
win = TestPanel(nb, log)
|
|
return win
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
with open(HTML_HELP, 'rt') as fid:
|
|
overview = fid.read()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
import run
|
|
run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
|
|
|