easycoder 241218.1__py2.py3-none-any.whl → 241231.1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of easycoder might be problematic. Click here for more details.
- easycoder/README.md +6 -0
- easycoder/__init__.py +2 -2
- easycoder/ec.py +10 -0
- easycoder/ec_classes.py +3 -0
- easycoder/ec_compiler.py +7 -6
- easycoder/ec_core.py +29 -4
- easycoder/ec_graphics.py +275 -222
- easycoder/ec_handler.py +1 -0
- easycoder/ec_program.py +72 -58
- easycoder/ec_renderer.py +235 -325
- easycoder/ec_screenspec.py +77 -0
- easycoder/ec_value.py +10 -10
- {easycoder-241218.1.dist-info → easycoder-241231.1.dist-info}/METADATA +11 -3
- easycoder-241231.1.dist-info/RECORD +19 -0
- easycoder-241218.1.dist-info/RECORD +0 -16
- {easycoder-241218.1.dist-info → easycoder-241231.1.dist-info}/LICENSE +0 -0
- {easycoder-241218.1.dist-info → easycoder-241231.1.dist-info}/WHEEL +0 -0
- {easycoder-241218.1.dist-info → easycoder-241231.1.dist-info}/entry_points.txt +0 -0
easycoder/ec_renderer.py
CHANGED
|
@@ -1,335 +1,245 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
from
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
1
|
+
from kivy.app import App
|
|
2
|
+
from kivy.uix.widget import Widget
|
|
3
|
+
from kivy.uix.label import CoreLabel
|
|
4
|
+
from kivy.uix.image import AsyncImage
|
|
5
|
+
from kivy.core.window import Window
|
|
6
|
+
from kivy.graphics import Color, Ellipse, Rectangle
|
|
7
|
+
from kivy.utils import colormap
|
|
8
|
+
from kivy.clock import Clock
|
|
9
|
+
from kivy.vector import Vector
|
|
10
|
+
import math
|
|
11
|
+
|
|
12
|
+
class Object():
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
class Element():
|
|
16
|
+
|
|
17
|
+
def __init__(self, type, spec):
|
|
18
|
+
self.type = type
|
|
19
|
+
self.spec = spec
|
|
20
|
+
|
|
21
|
+
def getType(self):
|
|
22
|
+
return self.spec.type
|
|
23
|
+
|
|
24
|
+
def getID(self):
|
|
25
|
+
return self.spec.id
|
|
26
|
+
|
|
27
|
+
def getRealPos(self):
|
|
28
|
+
spec = self.spec
|
|
29
|
+
pos = spec.realpos
|
|
30
|
+
if spec.parent != None:
|
|
31
|
+
pos = Vector(pos) + spec.parent.realpos
|
|
32
|
+
return pos
|
|
33
|
+
|
|
34
|
+
def getPos(self):
|
|
35
|
+
spec = self.spec
|
|
36
|
+
pos = spec.pos
|
|
37
|
+
if spec.parent != None:
|
|
38
|
+
pos = Vector(pos) + spec.parent.pos
|
|
39
|
+
return pos
|
|
40
|
+
|
|
41
|
+
def setPos(self, pos):
|
|
42
|
+
self.spec.realpos = pos
|
|
43
|
+
self.spec.item.pos = pos
|
|
44
|
+
|
|
45
|
+
# Called when the parent moves
|
|
46
|
+
def repos(self):
|
|
47
|
+
spec = self.spec
|
|
48
|
+
spec.item.pos = Vector(spec.realpos) + spec.parent.realpos
|
|
49
|
+
|
|
50
|
+
def getRealSize(self):
|
|
51
|
+
return self.spec.realsize
|
|
52
|
+
|
|
53
|
+
def getSize(self):
|
|
54
|
+
return self.spec.size
|
|
55
|
+
|
|
56
|
+
def setSize(self, size):
|
|
57
|
+
self.spec.size = size
|
|
58
|
+
|
|
59
|
+
def getChildren(self):
|
|
60
|
+
return self.spec.children
|
|
28
61
|
|
|
29
|
-
|
|
30
|
-
width = values['width']['content'] if 'width' in values else 600
|
|
31
|
-
height = values['height']['content'] if 'height' in values else 800
|
|
32
|
-
screenLeft = int((screen.winfo_screenwidth() - width) / 2)
|
|
33
|
-
screenTop = int((screen.winfo_screenheight() - height) / 2)
|
|
34
|
-
if 'left' in values:
|
|
35
|
-
screenLeft = values['left']['content']
|
|
36
|
-
if 'top' in values:
|
|
37
|
-
screenTop = values['top']['content']
|
|
62
|
+
class UI(Widget):
|
|
38
63
|
|
|
39
|
-
|
|
40
|
-
|
|
64
|
+
elements = {}
|
|
65
|
+
zlist = []
|
|
41
66
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
67
|
+
def getElement(self, id):
|
|
68
|
+
if id in self.elements.keys():
|
|
69
|
+
return self.elements[id]
|
|
70
|
+
return None
|
|
71
|
+
|
|
72
|
+
def addElement(self, id, spec):
|
|
73
|
+
if id in self.elements.keys():
|
|
74
|
+
raise(Exception(f'Element {id} already exists'))
|
|
75
|
+
element = Element(type, spec)
|
|
76
|
+
element.cb = None
|
|
77
|
+
self.elements[id] = element
|
|
78
|
+
self.zlist.append(element)
|
|
79
|
+
|
|
80
|
+
def createElement(self, spec):
|
|
81
|
+
# Get a real position or size value
|
|
82
|
+
def getReal(val):
|
|
83
|
+
if isinstance(val, str):
|
|
84
|
+
c = val[-1]
|
|
85
|
+
if c in ['w', 'h']:
|
|
86
|
+
val = int(val[0:len(val)-1])
|
|
87
|
+
if spec.parent == None:
|
|
88
|
+
if c == 'w':
|
|
89
|
+
n = Window.width
|
|
90
|
+
else:
|
|
91
|
+
n = Window.height
|
|
92
|
+
else:
|
|
93
|
+
if c == 'w':
|
|
94
|
+
n = spec.parent.realsize[0]
|
|
95
|
+
else:
|
|
96
|
+
n = spec.parent.realsize[1]
|
|
97
|
+
return val * n / 100
|
|
98
|
+
return val
|
|
99
|
+
|
|
100
|
+
with self.canvas:
|
|
101
|
+
if hasattr(spec, 'fill'):
|
|
102
|
+
c = spec.fill
|
|
103
|
+
if isinstance(c, str):
|
|
104
|
+
c = colormap[c]
|
|
105
|
+
Color(c[0], c[1], c[2])
|
|
62
106
|
else:
|
|
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
|
-
if
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
"top": top,
|
|
145
|
-
"width": width,
|
|
146
|
-
"height": height,
|
|
147
|
-
"parent": parent,
|
|
148
|
-
"children": []
|
|
149
|
-
}
|
|
150
|
-
elements[widgetName] = widgetSpec
|
|
151
|
-
zlist.append({widgetName: widgetSpec})
|
|
152
|
-
if '#' in values:
|
|
153
|
-
children = values['#']
|
|
154
|
-
if type(children) == list:
|
|
155
|
-
for item in children:
|
|
156
|
-
if item in values:
|
|
157
|
-
child = values[item]
|
|
158
|
-
childSpec = renderWidget(child, widgetSpec, args)
|
|
159
|
-
widgetSpec['children'].append(childSpec['name'])
|
|
160
|
-
else:
|
|
161
|
-
child = values[children]
|
|
162
|
-
childSpec = renderWidget(child, widgetSpec, args)
|
|
163
|
-
widgetSpec['children'].append(childSpec['name'])
|
|
164
|
-
return widgetSpec
|
|
165
|
-
|
|
166
|
-
def renderText(values, parent, args):
|
|
167
|
-
left = getValue(args, values['left']) if 'left' in values else 10
|
|
168
|
-
screenLeft = left + getScreenLeft(parent)
|
|
169
|
-
top = getValue(args, values['top']) if 'top' in values else 10
|
|
170
|
-
screenTop = top + getScreenTop(parent)
|
|
171
|
-
width = getValue(args, values['width']) if 'width' in values else 100
|
|
172
|
-
height = getValue(args, values['height']) if 'height' in values else 100
|
|
173
|
-
shape = getValue(args, values['shape']) if 'shape' in values else 'rectangle'
|
|
174
|
-
outline = getValue(args, values['outline']) if 'outline' in values else None
|
|
175
|
-
color = getValue(args, values['color']) if 'color' in values else None
|
|
176
|
-
text = getValue(args, values['text']) if 'text' in values else ''
|
|
177
|
-
fontFace = getValue(args, values['fontFace']) if 'fontFace' in values else 'Helvetica'
|
|
178
|
-
fontWeight = getValue(args, values['fontWeight']) if 'fontWeight' in values else 'normal'
|
|
179
|
-
fontTop = int(round(screenTop + height/2))
|
|
180
|
-
if 'fontSize' in values:
|
|
181
|
-
fontSize = getValue(args, values['fontSize'])
|
|
182
|
-
fontTop = int(round(screenTop + height/2 - fontSize/4))
|
|
183
|
-
else:
|
|
184
|
-
fontSize = int(round(height*2/5) if shape == 'ellipse' else round(height*3/5))
|
|
185
|
-
fontTop -= int(round(screenTop + height/2 - fontSize/5))
|
|
186
|
-
adjust = int(round(fontSize/5)) if shape == 'ellipse' else 0
|
|
187
|
-
align = getValue(args, values['align']) if 'align' in values else 'center'
|
|
188
|
-
if align == 'left':
|
|
189
|
-
xoff = int(round(fontSize/5))
|
|
190
|
-
anchor = 'w'
|
|
191
|
-
elif align == 'right':
|
|
192
|
-
xoff = width - int(round(fontSize/5))
|
|
193
|
-
anchor = 'e'
|
|
194
|
-
else:
|
|
195
|
-
xoff = int(round(width/2))
|
|
196
|
-
anchor = 'center'
|
|
197
|
-
if xoff < 3:
|
|
198
|
-
xoff = 3
|
|
199
|
-
xoff -= int(round(fontSize/4))
|
|
200
|
-
textId = canvas.create_text(screenLeft + xoff, fontTop + adjust, fill=color, font=f'"{fontFace}" {fontSize} {fontWeight}', text=text, anchor=anchor)
|
|
201
|
-
if 'name' in values:
|
|
202
|
-
widgetName = getValue(args, values['name'])
|
|
107
|
+
Color(c[0]/255, c[1]/255, c[2]/255)
|
|
108
|
+
pos = (getReal(spec.pos[0]), getReal(spec.pos[1]))
|
|
109
|
+
spec.realpos = pos
|
|
110
|
+
size = (getReal(spec.size[0]), getReal(spec.size[1]))
|
|
111
|
+
spec.realsize = size
|
|
112
|
+
if spec.parent != None:
|
|
113
|
+
pos = Vector(pos) + spec.parent.realpos
|
|
114
|
+
if spec.type == 'ellipse':
|
|
115
|
+
item = Ellipse(pos=pos, size=size)
|
|
116
|
+
elif spec.type == 'rectangle':
|
|
117
|
+
item = Rectangle(pos=pos, size=size)
|
|
118
|
+
elif spec.type == 'text':
|
|
119
|
+
if hasattr(spec, 'color'):
|
|
120
|
+
c = spec.color
|
|
121
|
+
if isinstance(c, str):
|
|
122
|
+
c = colormap[c]
|
|
123
|
+
Color(c[0], c[1], c[2])
|
|
124
|
+
else:
|
|
125
|
+
Color(c[0]/255, c[1]/255, c[2]/255)
|
|
126
|
+
else:
|
|
127
|
+
Color(1, 1, 1, 1)
|
|
128
|
+
label = CoreLabel(text=spec.text, font_size=1000, halign='center', valign='center')
|
|
129
|
+
label.refresh()
|
|
130
|
+
text = label.texture
|
|
131
|
+
item = Rectangle(pos=pos, size=size, texture=text)
|
|
132
|
+
elif spec.type == 'image':
|
|
133
|
+
item = AsyncImage(pos=pos, size=size, source=spec.source)
|
|
134
|
+
spec.item = item
|
|
135
|
+
self.addElement(spec.id, spec)
|
|
136
|
+
|
|
137
|
+
def moveElementBy(self, id, dist):
|
|
138
|
+
element = self.getElement(id)
|
|
139
|
+
if element != None:
|
|
140
|
+
element.setPos(Vector(element.getRealPos()) + dist)
|
|
141
|
+
for id in element.getChildren():
|
|
142
|
+
self.getElement(id).repos()
|
|
143
|
+
return
|
|
144
|
+
|
|
145
|
+
def moveElementTo(self, id, pos):
|
|
146
|
+
element = self.getElement(id)
|
|
147
|
+
if element != None:
|
|
148
|
+
self.moveElementBy(id, Vector(pos) - element.getRealPos())
|
|
149
|
+
return
|
|
150
|
+
|
|
151
|
+
def on_touch_down(self, touch):
|
|
152
|
+
tp = touch.pos
|
|
153
|
+
x = tp[0]
|
|
154
|
+
y = tp[1]
|
|
155
|
+
for element in reversed(self.zlist):
|
|
156
|
+
if element.cb != None:
|
|
157
|
+
spec = element.spec
|
|
158
|
+
pos = self.getRealPos()
|
|
159
|
+
if spec.parent != None:
|
|
160
|
+
pos = Vector(pos) + spec.parent.getRealPos()
|
|
161
|
+
size = spec.size
|
|
162
|
+
if spec.type == 'ellipse':
|
|
163
|
+
a = size[0]/2
|
|
164
|
+
b = size[1]/2
|
|
165
|
+
ctr = (pos[0] + a, pos[1] +b)
|
|
166
|
+
h = ctr[0]
|
|
167
|
+
k = ctr[1]
|
|
168
|
+
if (math.pow((x - h), 2) / math.pow(a, 2)) + (math.pow((y - k), 2) / math.pow(b, 2)) <= 1:
|
|
169
|
+
element.cb()
|
|
170
|
+
break
|
|
171
|
+
elif spec.type in ['rectangle', 'text', 'image']:
|
|
172
|
+
if tp[0] >= pos[0] and tp[0] < pos[0] + size[0] and tp[1] >= pos[1] and tp[1] < pos[1] + size[1]:
|
|
173
|
+
element.cb()
|
|
174
|
+
break
|
|
175
|
+
|
|
176
|
+
def setOnClick(self, id, callback):
|
|
177
|
+
self.getElement(id).cb = callback
|
|
178
|
+
|
|
179
|
+
def getWindowAttribute(self, attribute):
|
|
180
|
+
if attribute == 'left':
|
|
181
|
+
return Window.left
|
|
182
|
+
elif attribute == 'top':
|
|
183
|
+
return Window.top
|
|
184
|
+
elif attribute == 'width':
|
|
185
|
+
return Window.size[0]
|
|
186
|
+
elif attribute == 'height':
|
|
187
|
+
return Window.size[1]
|
|
203
188
|
else:
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
zlist.append({widgetName: widgetSpec})
|
|
217
|
-
return widgetSpec
|
|
218
|
-
|
|
219
|
-
def renderImage(values, parent, args):
|
|
220
|
-
global images
|
|
221
|
-
left = getValue(args, values['left']) if 'left' in values else 10
|
|
222
|
-
screenLeft = left + getScreenLeft(parent)
|
|
223
|
-
top = getValue(args, values['top']) if 'top' in values else 10
|
|
224
|
-
screenTop = top + getScreenTop(parent)
|
|
225
|
-
width = getValue(args, values['width']) if 'width' in values else 100
|
|
226
|
-
source = getValue(args, values['source']) if 'source' in values else None
|
|
227
|
-
if 'name' in values:
|
|
228
|
-
widgetName = values['name']
|
|
189
|
+
raise Exception(f'Unknown attribute: {attribute}')
|
|
190
|
+
|
|
191
|
+
def getAttribute(self, id, attribute):
|
|
192
|
+
spec = self.getElement(id).spec
|
|
193
|
+
if attribute == 'left':
|
|
194
|
+
return spec.realpos[0]
|
|
195
|
+
elif attribute == 'bottom':
|
|
196
|
+
return spec.realpos[1]
|
|
197
|
+
elif attribute == 'width':
|
|
198
|
+
return spec.realsize[0]
|
|
199
|
+
elif attribute == 'height':
|
|
200
|
+
return spec.realsize[1]
|
|
229
201
|
else:
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
"source": source,
|
|
247
|
-
"parent": parent
|
|
248
|
-
}
|
|
249
|
-
elements[widgetName] = widgetSpec
|
|
250
|
-
zlist.append({widgetName: widgetSpec})
|
|
251
|
-
return widgetSpec
|
|
252
|
-
|
|
253
|
-
# Create a canvas or render a widget
|
|
254
|
-
def renderWidget(widget, parent, args):
|
|
255
|
-
widgetType = widget['type']
|
|
256
|
-
if widgetType in ['rectangle', 'ellipse']:
|
|
257
|
-
return renderIntoRectangle(widgetType, widget, parent, args)
|
|
258
|
-
elif widgetType == 'text':
|
|
259
|
-
return renderText(widget, parent, args)
|
|
260
|
-
elif widgetType == 'image':
|
|
261
|
-
return renderImage(widget, parent, args)
|
|
262
|
-
|
|
263
|
-
# Render a complete specification
|
|
264
|
-
def renderSpec(spec, parent, args):
|
|
265
|
-
widgets = spec['#']
|
|
266
|
-
# If a list, iterate it
|
|
267
|
-
if type(widgets) is list:
|
|
268
|
-
for widget in widgets:
|
|
269
|
-
renderWidget(spec[widget], parent, args)
|
|
270
|
-
# Otherwise, process the single widget
|
|
202
|
+
raise Exception(f'Unknown attribute: {attribute}')
|
|
203
|
+
|
|
204
|
+
def setAttribute(self, id, attribute, value):
|
|
205
|
+
spec = self.getElement(id).spec
|
|
206
|
+
if attribute == 'left':
|
|
207
|
+
spec.realpos = (value, spec.realsize[0])
|
|
208
|
+
spec.item.pos = (value, spec.realsize[0])
|
|
209
|
+
elif attribute == 'bottom':
|
|
210
|
+
spec.realpos = (spec.realsize[0], value)
|
|
211
|
+
spec.item.pos = (spec.realsize[0], value)
|
|
212
|
+
elif attribute == 'width':
|
|
213
|
+
spec.realsize = (value, spec.realsize[0])
|
|
214
|
+
spec.item.size = (value, spec.realsize[0])
|
|
215
|
+
elif attribute == 'height':
|
|
216
|
+
spec.realsize = (spec.realsize[0], value)
|
|
217
|
+
spec.item.size = (spec.realsize[0], value)
|
|
271
218
|
else:
|
|
272
|
-
|
|
219
|
+
raise Exception(f'Unknown attribute: {attribute}')
|
|
273
220
|
|
|
274
|
-
|
|
275
|
-
if parent != screen:
|
|
276
|
-
RuntimeError(None, 'Can\'t yet render into parent widget')
|
|
221
|
+
class Renderer(App):
|
|
277
222
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
renderSpec(json.loads(spec), None, {})
|
|
281
|
-
|
|
282
|
-
# If it's a 'dict', extract the spec and the args
|
|
283
|
-
if type(spec) is dict:
|
|
284
|
-
args = spec['args']
|
|
285
|
-
spec = json.loads(spec['spec'])
|
|
286
|
-
renderSpec(spec, None, args)
|
|
287
|
-
|
|
288
|
-
# Get the widget whose name is given
|
|
289
|
-
def getElement(name):
|
|
290
|
-
global elements
|
|
291
|
-
if name in elements:
|
|
292
|
-
return elements[name]
|
|
293
|
-
else:
|
|
294
|
-
RuntimeError(None, f'Element \'{name}\' does not exist')
|
|
295
|
-
|
|
296
|
-
# Set the content of a text widget
|
|
297
|
-
def setText(name, value):
|
|
298
|
-
getCanvas().itemconfig(getElement(name)['id'], text=value)
|
|
299
|
-
|
|
300
|
-
# Set the background of a rectangle or ellipse widget
|
|
301
|
-
def setBackground(name, value):
|
|
302
|
-
id = getElement(name)['id']
|
|
303
|
-
getCanvas().itemconfig(getElement(name)['id'], fill=value)
|
|
223
|
+
def getUI(self):
|
|
224
|
+
return self.ui
|
|
304
225
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
# Get the screen left position of an element
|
|
326
|
-
def getScreenLeft(element):
|
|
327
|
-
if element == None:
|
|
328
|
-
return 0
|
|
329
|
-
return element['left'] + getScreenLeft(element['parent'])
|
|
330
|
-
|
|
331
|
-
# Get the screen top position of an element
|
|
332
|
-
def getScreenTop(element):
|
|
333
|
-
if element == None:
|
|
334
|
-
return 0
|
|
335
|
-
return element['top'] + getScreenTop(element['parent'])
|
|
226
|
+
def request_close(self):
|
|
227
|
+
print('close window')
|
|
228
|
+
Window.close()
|
|
229
|
+
|
|
230
|
+
def flushQueue(self, dt):
|
|
231
|
+
self.flush()
|
|
232
|
+
|
|
233
|
+
def build(self):
|
|
234
|
+
Clock.schedule_interval(self.flushQueue, 0.01)
|
|
235
|
+
self.ui = UI()
|
|
236
|
+
return self.ui
|
|
237
|
+
|
|
238
|
+
def init(self, spec):
|
|
239
|
+
self.title = spec.title
|
|
240
|
+
self.flush = spec.flush
|
|
241
|
+
Window.size = spec.size
|
|
242
|
+
Window.left = spec.pos[0]
|
|
243
|
+
Window.top = spec.pos[1]
|
|
244
|
+
Window.clearcolor = spec.fill
|
|
245
|
+
Window.on_request_close=self.request_close
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# screenspec.py
|
|
2
|
+
|
|
3
|
+
from json import loads
|
|
4
|
+
from .ec_renderer import Object
|
|
5
|
+
|
|
6
|
+
class ScreenSpec():
|
|
7
|
+
|
|
8
|
+
# Get an attribute of an element
|
|
9
|
+
def getAttribute(self, id, attribute):
|
|
10
|
+
element = self.ui.getElement(id)
|
|
11
|
+
return element[attribute]
|
|
12
|
+
|
|
13
|
+
# Render a single widget
|
|
14
|
+
def createWidget(self, widget, parent):
|
|
15
|
+
spec = Object()
|
|
16
|
+
type = widget['type']
|
|
17
|
+
spec.type = type
|
|
18
|
+
spec.id = widget['id']
|
|
19
|
+
spec.pos = (widget['left'], widget['bottom'])
|
|
20
|
+
spec.size = (widget['width'], widget['height'])
|
|
21
|
+
if widget.get('fill') != None:
|
|
22
|
+
spec.fill = widget['fill']
|
|
23
|
+
if widget.get('text') != None:
|
|
24
|
+
spec.text = widget['text']
|
|
25
|
+
if widget.get('fontSize') != None:
|
|
26
|
+
spec.fontSize = widget['fontSize']
|
|
27
|
+
if widget.get('source') != None:
|
|
28
|
+
spec.source = widget['source']
|
|
29
|
+
if widget.get('color') != None:
|
|
30
|
+
spec.color = widget['color']
|
|
31
|
+
spec.parent = parent
|
|
32
|
+
spec.children = []
|
|
33
|
+
self.ui.createElement(spec)
|
|
34
|
+
|
|
35
|
+
if '#' in widget:
|
|
36
|
+
children = widget['#']
|
|
37
|
+
if isinstance(children, list):
|
|
38
|
+
for item in children:
|
|
39
|
+
if item in widget:
|
|
40
|
+
child = widget[item]
|
|
41
|
+
childSpec = self.createWidget(child, spec)
|
|
42
|
+
spec.children.append(childSpec.id)
|
|
43
|
+
else:
|
|
44
|
+
raise Exception(f'Child \'{item}\' is missing')
|
|
45
|
+
else:
|
|
46
|
+
child = widget[children]
|
|
47
|
+
childSpec = self.createWidget(child, spec)
|
|
48
|
+
spec.children.append(childSpec.id)
|
|
49
|
+
|
|
50
|
+
return spec
|
|
51
|
+
|
|
52
|
+
# Render a complete specification
|
|
53
|
+
def renderSpec(self, spec, parent):
|
|
54
|
+
widgets = spec['#']
|
|
55
|
+
# If a list, iterate it
|
|
56
|
+
if isinstance(widgets, list):
|
|
57
|
+
for widget in widgets:
|
|
58
|
+
self.createWidget(spec[widget], parent)
|
|
59
|
+
# Otherwise, process the single widget
|
|
60
|
+
else:
|
|
61
|
+
self.createWidget(spec[widgets], parent)
|
|
62
|
+
|
|
63
|
+
# Render a graphic specification
|
|
64
|
+
def render(self, spec, ui):
|
|
65
|
+
self.ui = ui
|
|
66
|
+
|
|
67
|
+
# If it'a string, process it
|
|
68
|
+
if isinstance(spec, str):
|
|
69
|
+
self.renderSpec(loads(spec), None)
|
|
70
|
+
|
|
71
|
+
# If it's a 'dict', extract the spec and the args
|
|
72
|
+
elif isinstance(spec, dict):
|
|
73
|
+
spec = loads(spec['spec'])
|
|
74
|
+
self.renderSpec(spec, None)
|
|
75
|
+
|
|
76
|
+
else:
|
|
77
|
+
raise Exception('Spec is an unknown type')
|