easycoder 241227.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 +1 -1
- easycoder/ec_core.py +25 -2
- easycoder/ec_graphics.py +93 -35
- easycoder/ec_program.py +46 -30
- easycoder/ec_renderer.py +78 -18
- easycoder/ec_screenspec.py +0 -1
- {easycoder-241227.1.dist-info → easycoder-241231.1.dist-info}/METADATA +11 -3
- easycoder-241231.1.dist-info/RECORD +19 -0
- easycoder-241227.1.dist-info/RECORD +0 -18
- {easycoder-241227.1.dist-info → easycoder-241231.1.dist-info}/LICENSE +0 -0
- {easycoder-241227.1.dist-info → easycoder-241231.1.dist-info}/WHEEL +0 -0
- {easycoder-241227.1.dist-info → easycoder-241231.1.dist-info}/entry_points.txt +0 -0
easycoder/README.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# EasyCode source code
|
|
2
|
+
These are the Python files that comprise **_EasyCoder_**.
|
|
3
|
+
|
|
4
|
+
**_EasyCoder_** has a small number of third-party dependencies. A minor one is `pytz`, which handles timezones. The biggest one by far is `kivy`, a comprehensive Python graphics library.
|
|
5
|
+
|
|
6
|
+
If an **_EasyCoder_** script filename ends with `.ecs` it's a command-line script. If it ends with `.ecg` it's a script for a graphical application and will cause `kivy` to be imported. Obviously this will only work on a GUI-based system, whereas command-line scripts will run anywhere there is Python.
|
easycoder/__init__.py
CHANGED
easycoder/ec_core.py
CHANGED
|
@@ -696,6 +696,29 @@ class Core(Handler):
|
|
|
696
696
|
self.putSymbolValue(target, value)
|
|
697
697
|
return self.nextPC()
|
|
698
698
|
|
|
699
|
+
# Negate a variable
|
|
700
|
+
def k_negate(self, command):
|
|
701
|
+
if self.nextIsSymbol():
|
|
702
|
+
symbolRecord = self.getSymbolRecord()
|
|
703
|
+
if symbolRecord['valueHolder']:
|
|
704
|
+
command['target'] = self.getToken()
|
|
705
|
+
self.add(command)
|
|
706
|
+
return True
|
|
707
|
+
self.warning(f'Core.negate: Variable "{symbolRecord["name"]}" does not hold a value')
|
|
708
|
+
return False
|
|
709
|
+
|
|
710
|
+
def r_negate(self, command):
|
|
711
|
+
symbolRecord = self.getVariable(command['target'])
|
|
712
|
+
if not symbolRecord['valueHolder']:
|
|
713
|
+
RuntimeError(self.program, f'{symbolRecord["name"]} does not hold a value')
|
|
714
|
+
return None
|
|
715
|
+
value = self.getSymbolValue(symbolRecord)
|
|
716
|
+
if value == None:
|
|
717
|
+
RuntimeError(self.program, f'{symbolRecord["name"]} has not been initialised')
|
|
718
|
+
value['content'] *= -1
|
|
719
|
+
self.putSymbolValue(symbolRecord, value)
|
|
720
|
+
return self.nextPC()
|
|
721
|
+
|
|
699
722
|
# Define an object variable
|
|
700
723
|
def k_object(self, command):
|
|
701
724
|
return self.compileVariable(command)
|
|
@@ -976,7 +999,7 @@ class Core(Handler):
|
|
|
976
999
|
content = self.getSymbolValue(templateRecord)['content']
|
|
977
1000
|
original = self.getRuntimeValue(command['original'])
|
|
978
1001
|
replacement = self.getRuntimeValue(command['replacement'])
|
|
979
|
-
content = content.replace(original, replacement)
|
|
1002
|
+
content = content.replace(original, str(replacement))
|
|
980
1003
|
value = {}
|
|
981
1004
|
value['type'] = 'text'
|
|
982
1005
|
value['numeric'] = False
|
|
@@ -1417,7 +1440,7 @@ class Core(Handler):
|
|
|
1417
1440
|
# Compile a value in this domain
|
|
1418
1441
|
def compileValue(self):
|
|
1419
1442
|
value = {}
|
|
1420
|
-
value['domain'] =
|
|
1443
|
+
value['domain'] = self.getName()
|
|
1421
1444
|
token = self.getToken()
|
|
1422
1445
|
if self.isSymbol():
|
|
1423
1446
|
value['name'] = token
|
easycoder/ec_graphics.py
CHANGED
|
@@ -9,7 +9,7 @@ class Graphics(Handler):
|
|
|
9
9
|
Handler.__init__(self, compiler)
|
|
10
10
|
|
|
11
11
|
def getName(self):
|
|
12
|
-
return '
|
|
12
|
+
return 'graphics'
|
|
13
13
|
|
|
14
14
|
#############################################################################
|
|
15
15
|
# Keyword handlers
|
|
@@ -204,12 +204,47 @@ class Graphics(Handler):
|
|
|
204
204
|
def r_ellipse(self, command):
|
|
205
205
|
return self.nextPC()
|
|
206
206
|
|
|
207
|
+
def r_getui(self, command):
|
|
208
|
+
self.ui = self.renderer.getUI()
|
|
209
|
+
return self.nextPC()
|
|
210
|
+
|
|
207
211
|
def k_image(self, command):
|
|
208
212
|
return self.compileVariable(command)
|
|
209
213
|
|
|
210
214
|
def r_image(self, command):
|
|
211
215
|
return self.nextPC()
|
|
212
216
|
|
|
217
|
+
# move an element
|
|
218
|
+
def k_move(self, command):
|
|
219
|
+
if self.nextIsSymbol():
|
|
220
|
+
record = self.getSymbolRecord()
|
|
221
|
+
type = record['keyword']
|
|
222
|
+
if type in ['ellipse', 'rectangle']:
|
|
223
|
+
command['target'] = record['id']
|
|
224
|
+
token = self.nextToken()
|
|
225
|
+
if token == 'to':
|
|
226
|
+
command['x'] = self.nextValue()
|
|
227
|
+
command['y'] = self.nextValue()
|
|
228
|
+
self.add(command)
|
|
229
|
+
return True
|
|
230
|
+
elif token == 'by':
|
|
231
|
+
command['keyword'] = 'moveBy'
|
|
232
|
+
command['dx'] = self.nextValue()
|
|
233
|
+
command['dy'] = self.nextValue()
|
|
234
|
+
self.add(command)
|
|
235
|
+
return True
|
|
236
|
+
return False
|
|
237
|
+
|
|
238
|
+
def r_move(self, command):
|
|
239
|
+
pos = (self.getRuntimeValue(command['x']), self.getRuntimeValue(command['y']))
|
|
240
|
+
self.ui.moveElementTo(self.getRuntimeValue(command['target']), pos)
|
|
241
|
+
return self.nextPC()
|
|
242
|
+
|
|
243
|
+
def r_moveBy(self, command):
|
|
244
|
+
dist = (self.getRuntimeValue(command['dx']), self.getRuntimeValue(command['dy']))
|
|
245
|
+
self.ui.moveElementBy(self.getRuntimeValue(command['target']), dist)
|
|
246
|
+
return self.nextPC()
|
|
247
|
+
|
|
213
248
|
def k_on(self, command):
|
|
214
249
|
token = self.nextToken()
|
|
215
250
|
if token in ['click', 'tap']:
|
|
@@ -255,37 +290,6 @@ class Graphics(Handler):
|
|
|
255
290
|
RuntimeError(self.program, f'{record['name']} is not a clickable object')
|
|
256
291
|
return self.nextPC()
|
|
257
292
|
|
|
258
|
-
# move an element
|
|
259
|
-
def k_move(self, command):
|
|
260
|
-
if self.nextIsSymbol():
|
|
261
|
-
record = self.getSymbolRecord()
|
|
262
|
-
type = record['keyword']
|
|
263
|
-
if type in ['ellipse', 'rectangle']:
|
|
264
|
-
command['target'] = record['id']
|
|
265
|
-
token = self.nextToken()
|
|
266
|
-
if token == 'to':
|
|
267
|
-
command['x'] = self.nextValue()
|
|
268
|
-
command['y'] = self.nextValue()
|
|
269
|
-
self.add(command)
|
|
270
|
-
return True
|
|
271
|
-
elif token == 'by':
|
|
272
|
-
command['keyword'] = 'moveBy'
|
|
273
|
-
command['dx'] = self.nextValue()
|
|
274
|
-
command['dy'] = self.nextValue()
|
|
275
|
-
self.add(command)
|
|
276
|
-
return True
|
|
277
|
-
return False
|
|
278
|
-
|
|
279
|
-
def r_move(self, command):
|
|
280
|
-
pos = (self.getRuntimeValue(command['x']), self.getRuntimeValue(command['y']))
|
|
281
|
-
self.ui.moveElementTo(self.getRuntimeValue(command['target']), pos)
|
|
282
|
-
return self.nextPC()
|
|
283
|
-
|
|
284
|
-
def r_moveBy(self, command):
|
|
285
|
-
dist = (self.getRuntimeValue(command['dx']), self.getRuntimeValue(command['dy']))
|
|
286
|
-
self.ui.moveElementBy(self.getRuntimeValue(command['target']), dist)
|
|
287
|
-
return self.nextPC()
|
|
288
|
-
|
|
289
293
|
def k_rectangle(self, command):
|
|
290
294
|
return self.compileVariable(command)
|
|
291
295
|
|
|
@@ -306,13 +310,22 @@ class Graphics(Handler):
|
|
|
306
310
|
|
|
307
311
|
def r_render(self, command):
|
|
308
312
|
self.ui = self.renderer.getUI()
|
|
309
|
-
|
|
313
|
+
try:
|
|
314
|
+
ScreenSpec().render(self.getRuntimeValue(command['spec']), self.ui)
|
|
315
|
+
except Exception as e:
|
|
316
|
+
RuntimeError(self.program, e)
|
|
310
317
|
return self.nextPC()
|
|
311
318
|
|
|
312
319
|
# run graphics
|
|
313
320
|
def k_run(self, command):
|
|
314
321
|
if self.nextIs('graphics'):
|
|
315
322
|
self.add(command)
|
|
323
|
+
cmd = {}
|
|
324
|
+
cmd['domain'] = 'graphics'
|
|
325
|
+
cmd['lino'] = command['lino'] + 1
|
|
326
|
+
cmd['keyword'] = 'getui'
|
|
327
|
+
cmd['debug'] = False
|
|
328
|
+
self.addCommand(cmd)
|
|
316
329
|
return True
|
|
317
330
|
return False
|
|
318
331
|
|
|
@@ -323,6 +336,33 @@ class Graphics(Handler):
|
|
|
323
336
|
self.program.run(self.nextPC())
|
|
324
337
|
self.renderer.run()
|
|
325
338
|
|
|
339
|
+
# Set something
|
|
340
|
+
def k_set(self, command):
|
|
341
|
+
if self.nextIs('attribute'):
|
|
342
|
+
command['attribute'] = self.nextValue()
|
|
343
|
+
if self.nextIs('of'):
|
|
344
|
+
if self.nextIsSymbol():
|
|
345
|
+
record = self.getSymbolRecord()
|
|
346
|
+
if record['keyword'] in ['ellipse', 'rectangle', 'text', 'image']:
|
|
347
|
+
command['target'] = record['name']
|
|
348
|
+
if self.nextIs('to'):
|
|
349
|
+
command['value'] = self.nextValue()
|
|
350
|
+
self.addCommand(command)
|
|
351
|
+
return True
|
|
352
|
+
else:
|
|
353
|
+
FatalError(self.program.compiler, f'Invalid type: {record['keyword']}')
|
|
354
|
+
else:
|
|
355
|
+
FatalError(self.program.compiler, f'\'{self.getToken()}\' is not a variable')
|
|
356
|
+
return False
|
|
357
|
+
|
|
358
|
+
def r_set(self, command):
|
|
359
|
+
attribute = self.getRuntimeValue(command['attribute'])
|
|
360
|
+
target = self.getVariable(command['target'])
|
|
361
|
+
id = target['value'][target['index']]['content']
|
|
362
|
+
value = self.getRuntimeValue(command['value'])
|
|
363
|
+
self.ui.setAttribute(id, attribute, value)
|
|
364
|
+
return self.nextPC()
|
|
365
|
+
|
|
326
366
|
#############################################################################
|
|
327
367
|
# Modify a value or leave it unchanged.
|
|
328
368
|
def modifyValue(self, value):
|
|
@@ -333,16 +373,24 @@ class Graphics(Handler):
|
|
|
333
373
|
def compileValue(self):
|
|
334
374
|
value = {}
|
|
335
375
|
value['domain'] = self.getName()
|
|
336
|
-
if self.tokenIs('
|
|
376
|
+
if self.tokenIs('the'):
|
|
377
|
+
self.nextToken()
|
|
378
|
+
kwd = self.getToken()
|
|
379
|
+
value['type'] = kwd
|
|
380
|
+
if kwd == 'attribute':
|
|
337
381
|
attribute = self.nextValue()
|
|
338
382
|
if self.nextIs('of'):
|
|
339
383
|
if self.nextIsSymbol():
|
|
340
384
|
record = self.getSymbolRecord()
|
|
341
385
|
if record['keyword'] in ['ellipse', 'rectangle']:
|
|
342
|
-
value['type'] = 'attribute'
|
|
343
386
|
value['attribute'] = attribute
|
|
344
387
|
value['target'] = record['name']
|
|
345
388
|
return value
|
|
389
|
+
elif kwd == 'window':
|
|
390
|
+
attribute = self.nextToken()
|
|
391
|
+
if attribute in ['left', 'top', 'width', 'height']:
|
|
392
|
+
value['attribute'] = attribute
|
|
393
|
+
return value
|
|
346
394
|
return None
|
|
347
395
|
|
|
348
396
|
#############################################################################
|
|
@@ -361,6 +409,16 @@ class Graphics(Handler):
|
|
|
361
409
|
except Exception as e:
|
|
362
410
|
RuntimeError(self.program, e)
|
|
363
411
|
|
|
412
|
+
def v_window(self, v):
|
|
413
|
+
try:
|
|
414
|
+
attribute = v['attribute']
|
|
415
|
+
value = {}
|
|
416
|
+
value['type'] = 'int'
|
|
417
|
+
value['content'] = int(round(self.ui.getWindowAttribute(attribute)))
|
|
418
|
+
return value
|
|
419
|
+
except Exception as e:
|
|
420
|
+
RuntimeError(self.program, e)
|
|
421
|
+
|
|
364
422
|
#############################################################################
|
|
365
423
|
# Compile a condition
|
|
366
424
|
def compileCondition(self):
|
easycoder/ec_program.py
CHANGED
|
@@ -200,44 +200,60 @@ class Program:
|
|
|
200
200
|
|
|
201
201
|
# Tokenise the script
|
|
202
202
|
def tokenise(self, script):
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
for
|
|
203
|
+
token = ''
|
|
204
|
+
literal = False
|
|
205
|
+
for lino in range(0, len(script.lines)):
|
|
206
|
+
line = script.lines[lino]
|
|
206
207
|
length = len(line)
|
|
207
|
-
|
|
208
|
-
|
|
208
|
+
if length == 0:
|
|
209
|
+
continue
|
|
210
|
+
# Look for the first non-space
|
|
209
211
|
n = 0
|
|
210
|
-
while n < length:
|
|
212
|
+
while n < length and line[n].isspace():
|
|
213
|
+
n += 1
|
|
214
|
+
# The whole line may be empty
|
|
215
|
+
if n == length:
|
|
216
|
+
if literal:
|
|
217
|
+
token += '\n'
|
|
218
|
+
continue
|
|
219
|
+
# If in an unfinished literal, the first char must be a backtick to continue adding to it
|
|
220
|
+
if literal:
|
|
221
|
+
if line[n] != '`':
|
|
222
|
+
# Close the current token
|
|
223
|
+
if len(token) > 0:
|
|
224
|
+
script.tokens.append(Token(lino, token))
|
|
225
|
+
token = ''
|
|
226
|
+
literal = False
|
|
227
|
+
n += 1
|
|
228
|
+
for n in range(n, length):
|
|
211
229
|
c = line[n]
|
|
212
|
-
if
|
|
213
|
-
|
|
214
|
-
|
|
230
|
+
# Test if we are in a literal
|
|
231
|
+
if not literal:
|
|
232
|
+
if c.isspace():
|
|
233
|
+
if len(token) > 0:
|
|
234
|
+
script.tokens.append(Token(lino, token))
|
|
235
|
+
token = ''
|
|
215
236
|
continue
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
inSpace = True
|
|
220
|
-
n += 1
|
|
221
|
-
continue
|
|
222
|
-
inSpace = False
|
|
237
|
+
elif c == '!':
|
|
238
|
+
break
|
|
239
|
+
# Test for the start or end of a literal
|
|
223
240
|
if c == '`':
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
elif c == '!':
|
|
233
|
-
break
|
|
241
|
+
if literal:
|
|
242
|
+
token += c
|
|
243
|
+
literal = False
|
|
244
|
+
else:
|
|
245
|
+
token += c
|
|
246
|
+
literal = True
|
|
247
|
+
m = n
|
|
248
|
+
continue
|
|
234
249
|
else:
|
|
235
250
|
token += c
|
|
236
|
-
n += 1
|
|
237
251
|
if len(token) > 0:
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
252
|
+
if literal:
|
|
253
|
+
token += '\n'
|
|
254
|
+
else:
|
|
255
|
+
script.tokens.append(Token(lino, token))
|
|
256
|
+
token = ''
|
|
241
257
|
return
|
|
242
258
|
|
|
243
259
|
def finish(self):
|
easycoder/ec_renderer.py
CHANGED
|
@@ -24,6 +24,13 @@ class Element():
|
|
|
24
24
|
def getID(self):
|
|
25
25
|
return self.spec.id
|
|
26
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
|
+
|
|
27
34
|
def getPos(self):
|
|
28
35
|
spec = self.spec
|
|
29
36
|
pos = spec.pos
|
|
@@ -32,13 +39,16 @@ class Element():
|
|
|
32
39
|
return pos
|
|
33
40
|
|
|
34
41
|
def setPos(self, pos):
|
|
35
|
-
self.spec.
|
|
42
|
+
self.spec.realpos = pos
|
|
36
43
|
self.spec.item.pos = pos
|
|
37
44
|
|
|
38
45
|
# Called when the parent moves
|
|
39
46
|
def repos(self):
|
|
40
47
|
spec = self.spec
|
|
41
|
-
spec.item.pos = Vector(spec.
|
|
48
|
+
spec.item.pos = Vector(spec.realpos) + spec.parent.realpos
|
|
49
|
+
|
|
50
|
+
def getRealSize(self):
|
|
51
|
+
return self.spec.realsize
|
|
42
52
|
|
|
43
53
|
def getSize(self):
|
|
44
54
|
return self.spec.size
|
|
@@ -68,6 +78,25 @@ class UI(Widget):
|
|
|
68
78
|
self.zlist.append(element)
|
|
69
79
|
|
|
70
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
|
+
|
|
71
100
|
with self.canvas:
|
|
72
101
|
if hasattr(spec, 'fill'):
|
|
73
102
|
c = spec.fill
|
|
@@ -76,13 +105,16 @@ class UI(Widget):
|
|
|
76
105
|
Color(c[0], c[1], c[2])
|
|
77
106
|
else:
|
|
78
107
|
Color(c[0]/255, c[1]/255, c[2]/255)
|
|
79
|
-
pos = spec.pos
|
|
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
|
|
80
112
|
if spec.parent != None:
|
|
81
|
-
pos = Vector(pos) + spec.parent.
|
|
113
|
+
pos = Vector(pos) + spec.parent.realpos
|
|
82
114
|
if spec.type == 'ellipse':
|
|
83
|
-
item = Ellipse(pos=pos, size=
|
|
115
|
+
item = Ellipse(pos=pos, size=size)
|
|
84
116
|
elif spec.type == 'rectangle':
|
|
85
|
-
item = Rectangle(pos=pos, size=
|
|
117
|
+
item = Rectangle(pos=pos, size=size)
|
|
86
118
|
elif spec.type == 'text':
|
|
87
119
|
if hasattr(spec, 'color'):
|
|
88
120
|
c = spec.color
|
|
@@ -96,16 +128,16 @@ class UI(Widget):
|
|
|
96
128
|
label = CoreLabel(text=spec.text, font_size=1000, halign='center', valign='center')
|
|
97
129
|
label.refresh()
|
|
98
130
|
text = label.texture
|
|
99
|
-
item = Rectangle(pos=
|
|
131
|
+
item = Rectangle(pos=pos, size=size, texture=text)
|
|
100
132
|
elif spec.type == 'image':
|
|
101
|
-
item = AsyncImage(pos=
|
|
133
|
+
item = AsyncImage(pos=pos, size=size, source=spec.source)
|
|
102
134
|
spec.item = item
|
|
103
135
|
self.addElement(spec.id, spec)
|
|
104
136
|
|
|
105
137
|
def moveElementBy(self, id, dist):
|
|
106
138
|
element = self.getElement(id)
|
|
107
139
|
if element != None:
|
|
108
|
-
element.setPos(Vector(element.
|
|
140
|
+
element.setPos(Vector(element.getRealPos()) + dist)
|
|
109
141
|
for id in element.getChildren():
|
|
110
142
|
self.getElement(id).repos()
|
|
111
143
|
return
|
|
@@ -113,7 +145,7 @@ class UI(Widget):
|
|
|
113
145
|
def moveElementTo(self, id, pos):
|
|
114
146
|
element = self.getElement(id)
|
|
115
147
|
if element != None:
|
|
116
|
-
self.moveElementBy(id, Vector(pos) - element.
|
|
148
|
+
self.moveElementBy(id, Vector(pos) - element.getRealPos())
|
|
117
149
|
return
|
|
118
150
|
|
|
119
151
|
def on_touch_down(self, touch):
|
|
@@ -123,9 +155,9 @@ class UI(Widget):
|
|
|
123
155
|
for element in reversed(self.zlist):
|
|
124
156
|
if element.cb != None:
|
|
125
157
|
spec = element.spec
|
|
126
|
-
pos =
|
|
158
|
+
pos = self.getRealPos()
|
|
127
159
|
if spec.parent != None:
|
|
128
|
-
pos = Vector(pos) + spec.parent.
|
|
160
|
+
pos = Vector(pos) + spec.parent.getRealPos()
|
|
129
161
|
size = spec.size
|
|
130
162
|
if spec.type == 'ellipse':
|
|
131
163
|
a = size[0]/2
|
|
@@ -144,19 +176,47 @@ class UI(Widget):
|
|
|
144
176
|
def setOnClick(self, id, callback):
|
|
145
177
|
self.getElement(id).cb = callback
|
|
146
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]
|
|
188
|
+
else:
|
|
189
|
+
raise Exception(f'Unknown attribute: {attribute}')
|
|
190
|
+
|
|
147
191
|
def getAttribute(self, id, attribute):
|
|
148
192
|
spec = self.getElement(id).spec
|
|
149
193
|
if attribute == 'left':
|
|
150
|
-
return spec.
|
|
194
|
+
return spec.realpos[0]
|
|
151
195
|
elif attribute == 'bottom':
|
|
152
|
-
return spec.
|
|
196
|
+
return spec.realpos[1]
|
|
153
197
|
elif attribute == 'width':
|
|
154
|
-
return spec.
|
|
198
|
+
return spec.realsize[0]
|
|
155
199
|
elif attribute == 'height':
|
|
156
|
-
return spec.
|
|
200
|
+
return spec.realsize[1]
|
|
201
|
+
else:
|
|
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)
|
|
157
218
|
else:
|
|
158
219
|
raise Exception(f'Unknown attribute: {attribute}')
|
|
159
|
-
|
|
160
220
|
|
|
161
221
|
class Renderer(App):
|
|
162
222
|
|
|
@@ -171,7 +231,7 @@ class Renderer(App):
|
|
|
171
231
|
self.flush()
|
|
172
232
|
|
|
173
233
|
def build(self):
|
|
174
|
-
Clock.schedule_interval(self.flushQueue, 0.
|
|
234
|
+
Clock.schedule_interval(self.flushQueue, 0.01)
|
|
175
235
|
self.ui = UI()
|
|
176
236
|
return self.ui
|
|
177
237
|
|
easycoder/ec_screenspec.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: easycoder
|
|
3
|
-
Version:
|
|
3
|
+
Version: 241231.1
|
|
4
4
|
Summary: Rapid scripting in English
|
|
5
5
|
Keywords: compiler,scripting,prototyping,programming,coding,python,low code,hypertalk,computer language,learn to code
|
|
6
6
|
Author-email: Graham Trott <gtanyware@gmail.com>
|
|
@@ -60,9 +60,17 @@ Here in the repository is a folder called `scripts` containing some sample scrip
|
|
|
60
60
|
`fizzbuzz.ecs` is a simple programming challenge often given at job interviews
|
|
61
61
|
|
|
62
62
|
## Graphical programmming
|
|
63
|
-
**_EasyCoder_**
|
|
63
|
+
**_EasyCoder_** includes a graphical programming environment that is in the early stages of development. A couple of demo scripts are included in the `scripts` directory. To run them, first install the Python `kivy` graphics library if it's not already present on your system. This is done with `pip install kivy`. Then run a script using `easycoder {scriptname}.ecg`.
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
Graphical scripts look much like any other script but their file names must use the extension `.ecg` to signal to **_EasyCoder_** that it needs to load the graphics module. This allows the **_EasyCoder_** application to be used wherever Python is installed, in either a command-line or a graphical environment (but graphics will of course not be available in the former).
|
|
66
|
+
|
|
67
|
+
A couple of demo scripts are included in the `scripts` directory:
|
|
68
|
+
|
|
69
|
+
`graphics-demo.ecg` shows some of the elements that can be created, and demonstrates a variety of the graphical features of the language such as detecting when elements are clicked.
|
|
70
|
+
|
|
71
|
+
`wave.ecg` is a "Mexican Wave" simulation.
|
|
72
|
+
|
|
73
|
+
**_EasyCoder_** graphics are handled by a library module, `ec_renderer` that can be used outside of the **_EasyCoder_** environment, in other Python programs.
|
|
66
74
|
|
|
67
75
|
## EasyCoder programming reference
|
|
68
76
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
easycoder/README.md,sha256=PYqOc_SkIGiFbyCNs90y7JqoqWe4aO1xYIW-6bOnFKU,573
|
|
2
|
+
easycoder/__init__.py,sha256=WpuFq9C1_LWCjt7667A94jo8QMavAs_jT2qZluZgT2E,283
|
|
3
|
+
easycoder/ec.py,sha256=Nj5PRl8GsKjfGJKq0FOM1a7FeK3cN68CoIFg8lswQEg,221
|
|
4
|
+
easycoder/ec_classes.py,sha256=xnWBNak8oKydkFoxHLlq9wo3lIsB3aMnTDrqbtCfoWo,1512
|
|
5
|
+
easycoder/ec_compiler.py,sha256=2r6Nk7px9UMYqIpYc6dAbYOAFu-CoWPy-iqlsed49Lo,4690
|
|
6
|
+
easycoder/ec_condition.py,sha256=WSbONo4zs2sX1icOVpscZDFSCAEFmTsquoc2RGcLx_k,763
|
|
7
|
+
easycoder/ec_core.py,sha256=HtJWpfwz1eon0o4ZFYVM42ECAD6sKT8izvHYIb7dnv8,77463
|
|
8
|
+
easycoder/ec_graphics.py,sha256=o70BdQ-Y3uIo5nheQYwJUmM3gYVerKD9_5arQ8JTP-Y,15556
|
|
9
|
+
easycoder/ec_handler.py,sha256=IJvxcrJJSR53d6DS_8H5qPHKhp9y5-GV4WXAjhZxu_o,2250
|
|
10
|
+
easycoder/ec_program.py,sha256=6jK4blJMcRbspUEh-AW5MUVuLtLP023sZAbbgvPad-Y,8615
|
|
11
|
+
easycoder/ec_renderer.py,sha256=ejVFemHGuFBwGA__6VfZQZeZMnw4Ilvf_y9I34k04LM,7981
|
|
12
|
+
easycoder/ec_screenspec.py,sha256=TeXgccfYoE--r7Rf9t9drV1V3fU-p-iBnZwtjHzIh8M,2524
|
|
13
|
+
easycoder/ec_timestamp.py,sha256=_3QFJPzIWZ9Rzk3SQOQJ-gwmvB07pg78k23SPntoZtY,288
|
|
14
|
+
easycoder/ec_value.py,sha256=XIBtGhcCgh1abrzAn-Wy4l_xH_3cTWakMVIiSlBAZjM,2386
|
|
15
|
+
easycoder-241231.1.dist-info/entry_points.txt,sha256=JXAZbenl0TnsIft2FcGJbJ-4qoztVu2FuT8PFmWFexM,44
|
|
16
|
+
easycoder-241231.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
17
|
+
easycoder-241231.1.dist-info/WHEEL,sha256=ssQ84EZ5gH1pCOujd3iW7HClo_O_aDaClUbX4B8bjKY,100
|
|
18
|
+
easycoder-241231.1.dist-info/METADATA,sha256=MhsFB-Ftja3Q0DFD-IomqX4Sntipma64e6WIUXyfXdQ,4605
|
|
19
|
+
easycoder-241231.1.dist-info/RECORD,,
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
easycoder/__init__.py,sha256=l4J8ZzYaQ2L6tojyFFqc47eck2zDXoR8sUqlCyvanBs,283
|
|
2
|
-
easycoder/ec.py,sha256=Nj5PRl8GsKjfGJKq0FOM1a7FeK3cN68CoIFg8lswQEg,221
|
|
3
|
-
easycoder/ec_classes.py,sha256=xnWBNak8oKydkFoxHLlq9wo3lIsB3aMnTDrqbtCfoWo,1512
|
|
4
|
-
easycoder/ec_compiler.py,sha256=2r6Nk7px9UMYqIpYc6dAbYOAFu-CoWPy-iqlsed49Lo,4690
|
|
5
|
-
easycoder/ec_condition.py,sha256=WSbONo4zs2sX1icOVpscZDFSCAEFmTsquoc2RGcLx_k,763
|
|
6
|
-
easycoder/ec_core.py,sha256=Q-E2TX_yn9OhdV6HvUzYgiKX9fEQ_ro1-VxSQ5Xl-4Y,76508
|
|
7
|
-
easycoder/ec_graphics.py,sha256=Sy1seMMEZ5KmkDKPhTKIkoGjXl5loYArvAS2YpdsFH8,13347
|
|
8
|
-
easycoder/ec_handler.py,sha256=IJvxcrJJSR53d6DS_8H5qPHKhp9y5-GV4WXAjhZxu_o,2250
|
|
9
|
-
easycoder/ec_program.py,sha256=j3eveYucPQX6E1flDwf1OpkPCh9OtDri88z8baXjvqI,8062
|
|
10
|
-
easycoder/ec_renderer.py,sha256=UZk-VSyN4But0fRTs7wUnPwRGrCF6XA7LxhPxgZaYgU,5705
|
|
11
|
-
easycoder/ec_screenspec.py,sha256=gmYYi0Q6S2qSQzCW0lMPB61EC7ZZ1mNQX8B1knxrTCg,2525
|
|
12
|
-
easycoder/ec_timestamp.py,sha256=_3QFJPzIWZ9Rzk3SQOQJ-gwmvB07pg78k23SPntoZtY,288
|
|
13
|
-
easycoder/ec_value.py,sha256=XIBtGhcCgh1abrzAn-Wy4l_xH_3cTWakMVIiSlBAZjM,2386
|
|
14
|
-
easycoder-241227.1.dist-info/entry_points.txt,sha256=JXAZbenl0TnsIft2FcGJbJ-4qoztVu2FuT8PFmWFexM,44
|
|
15
|
-
easycoder-241227.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
16
|
-
easycoder-241227.1.dist-info/WHEEL,sha256=ssQ84EZ5gH1pCOujd3iW7HClo_O_aDaClUbX4B8bjKY,100
|
|
17
|
-
easycoder-241227.1.dist-info/METADATA,sha256=-1vKmMw26mJSHmztn_O049rpIJqAgJ4OQWPC-lDO9ms,4098
|
|
18
|
-
easycoder-241227.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|