-
Notifications
You must be signed in to change notification settings - Fork 0
/
GUIApplication.py
121 lines (83 loc) · 3.18 KB
/
GUIApplication.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# GUIApplication.py
from abc import ABC, abstractmethod
import re
from TreeNode import TreeNode
from PLLParser import parsePLL
root = None # disallow creating more than one instance
reWidgetDef = re.compile(r'^\s*(\S+)\s*(.*)$')
class GUIApplication(ABC):
def __init__(self, appDesc):
global root
if root:
raise Exception("You can only create one GUIApplication")
self.hWidgets = {} # widgets saved by name
# --- Parse the app description into an appNode, and a hash
# holding any tagged subtrees
(appNode, hSubTrees) = parsePLL(appDesc)
root = self.getMainWindow(appNode, hSubTrees)
self.mainWindow = root
if getattr(self, 'centerWindow', None):
self.centerWindow()
# ---------------------------------------------------------------------------
@abstractmethod
def getMainWindow(self, node, hSubTrees):
assert isinstance(node, TreeNode)
assert isinstance(hSubTrees, dict)
# ---------------------------------------------------------------------------
@abstractmethod
def run(self):
raise Exception("You cannot call super().run()")
# ---------------------------------------------------------------------------
@abstractmethod
def exit(self):
pass
# ------------------------------------------------------------------------
@abstractmethod
def getWidgetConstructor(self, type):
pass
# ---------------------------------------------------------------------------
def widgetFromNode(self, window, node):
global reWidgetDef
hOptions = self.getNodeOptions(node)
# --- Extract widget type and label
result = reWidgetDef.search(node['label'])
if result:
type = result.group(1)
label = hOptions['label'] = result.group(2)
else:
raise Exception(f"Invalid Widget Def: '{traceStr(label)}'")
return self.newWidget(window, type, hOptions)
# ------------------------------------------------------------------------
def getNodeOptions(self, node):
# --- Override this if your options syntax is not 'x = val'
return node.getOptions()
# ------------------------------------------------------------------------
def newWidget(self, parent, type, hOptions={}, *, debug=False):
if debug:
print(f"newWidget('{type}')")
for (key, value) in hOptions.items():
print(f" {key} => '{value}'")
constructor = self.getWidgetConstructor(type)
if not constructor:
raise Exception(f"Unknown widget type: '{type}'")
# --- For some odd reason, in Python, you don't supply a
# self parameter in this case
widget = constructor(parent, hOptions)
if 'name' in hOptions:
self.saveWidget(hOptions['name'], widget)
return widget
# ------------------------------------------------------------------------
def saveWidget(self, name, widget):
# --- This is called for any widget created
# that has a 'name' key
if name in self.hWidgets:
raise Exception(f"saveWidget(): There is already a widget"
f" named '{name}'")
self.hWidgets[name] = widget
# ------------------------------------------------------------------------
def findWidgetByName(self, name):
if name in self.hWidgets:
return self.hWidgets[name]
else:
raise Exception(f"findWidgetByName():"
f" There is no widget named '{name}'")