easycoder 241218.1__py2.py3-none-any.whl → 241227.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/ec_program.py CHANGED
@@ -11,23 +11,18 @@ class Program:
11
11
 
12
12
  def __init__(self, argv):
13
13
  print(f'EasyCoder version {version("easycoder")}')
14
- scriptName = None
15
14
  if len(argv) == 0:
16
15
  print('No script supplied')
17
16
  exit()
18
17
  self.classes=[Core]
19
- for n in range(len(argv)):
20
- arg = argv[n]
21
- if arg == '-g':
22
- from .ec_graphics import Graphics
23
- self.classes.append(Graphics)
24
- else:
25
- scriptName = arg
18
+ scriptName = argv[0]
19
+ if scriptName.endswith('.ecg'):
20
+ from .ec_graphics import Graphics
21
+ self.classes.append(Graphics)
26
22
 
27
23
  f = open(scriptName, 'r')
28
24
  source = f.read()
29
25
  f.close()
30
- self.argv = argv
31
26
  self.domains = []
32
27
  self.domainIndex = {}
33
28
  self.name = '<anon>'
@@ -43,6 +38,8 @@ class Program:
43
38
  self.condition = self.compiler.condition
44
39
  self.processClasses()
45
40
  self.queue = deque()
41
+ self.externalControl = False
42
+ self.quit = False
46
43
 
47
44
  def start(self):
48
45
  startCompile = time.time()
@@ -242,18 +239,17 @@ class Program:
242
239
  index += 1
243
240
  lino += 1
244
241
  return
242
+
243
+ def finish(self):
244
+ self.quit = True
245
245
 
246
- # Run the script
247
- def run(self, pc):
248
- # print(f'Run from {pc}')
249
- length = len(self.queue)
250
- self.queue.append(pc)
251
- if length > 0:
252
- return
253
-
246
+ # Flush the queue
247
+ def flush(self):
254
248
  while len(self.queue):
255
249
  self.pc = self.queue.popleft()
256
250
  while True:
251
+ if self.quit:
252
+ return
257
253
  command = self.code[self.pc]
258
254
  domainName = command['domain']
259
255
  if domainName == None:
@@ -272,11 +268,20 @@ class Program:
272
268
  self.pc = handler(command)
273
269
  try:
274
270
  if self.pc == 0 or self.pc >= len(self.code):
275
- return 0
271
+ break
276
272
  except:
277
- return 0
278
- if self.pc < 0:
279
- return -1
273
+ break
274
+
275
+ def setExternalControl(self):
276
+ self.externalControl = True
277
+
278
+ # Run the script
279
+ def run(self, pc):
280
+ length = len(self.queue)
281
+ self.queue.append(pc)
282
+ if not self.externalControl:
283
+ if length == 0:
284
+ return self.flush()
280
285
 
281
286
  def nonNumericValueError(self):
282
287
  FatalError(self.compiler, 'Non-numeric value')
@@ -322,10 +327,3 @@ class Program:
322
327
  if v1 < v2:
323
328
  return -1
324
329
  return 0
325
-
326
- # This is the program launcher
327
- def Main():
328
- if (len(sys.argv) > 1):
329
- Program(sys.argv[1:]).start()
330
- else:
331
- print('Syntax: easycoder <scriptname> [plugins]')
easycoder/ec_renderer.py CHANGED
@@ -1,335 +1,185 @@
1
- # renderer.py
2
-
3
- import sys, json
4
- import tkinter as tk
5
- from PIL import Image, ImageTk
6
-
7
- elements = {}
8
- zlist = []
9
- images = {}
10
- onTick = None
11
-
12
- # Set the canvas
13
- def setCanvas(c):
14
- global canvas
15
- canvas = c
16
-
17
- # Get the canvas
18
- def getCanvas():
19
- global canvas
20
- return canvas
21
-
22
- def createScreen(values):
23
- global screen, canvas, screenLeft, screenTop, running
24
- running = True
25
- screen = tk.Tk()
26
- screen.title('EasyCoder')
27
- # screen.attributes('-fullscreen', True)
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 getPos(self):
28
+ spec = self.spec
29
+ pos = spec.pos
30
+ if spec.parent != None:
31
+ pos = Vector(pos) + spec.parent.pos
32
+ return pos
33
+
34
+ def setPos(self, pos):
35
+ self.spec.pos = pos
36
+ self.spec.item.pos = pos
37
+
38
+ # Called when the parent moves
39
+ def repos(self):
40
+ spec = self.spec
41
+ spec.item.pos = Vector(spec.pos) + spec.parent.pos
42
+
43
+ def getSize(self):
44
+ return self.spec.size
45
+
46
+ def setSize(self, size):
47
+ self.spec.size = size
48
+
49
+ def getChildren(self):
50
+ return self.spec.children
28
51
 
29
- # screen.overrideredirect(True)
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']
52
+ class UI(Widget):
38
53
 
39
- geometry = str(width) + 'x' + str(height) + '+' + str(screenLeft) + '+' + str(screenTop)
40
- screen.geometry(geometry)
54
+ elements = {}
55
+ zlist = []
41
56
 
42
- # Handle a click in the screen
43
- def onClick(event):
44
- global screenLeft, screenTop, zlist
45
- x = event.x
46
- y = event.y
47
- # print('Clicked at : '+ str(x) +","+ str(y))
48
- for i in range(1, len(zlist) + 1):
49
- element = zlist[-i]
50
- id = list(element)[0]
51
- values = element[id]
52
- x1 = values['left']
53
- x2 = x1 + values['width'] + getScreenLeft(values['parent'])
54
- y1 = values['top'] + getScreenTop(values['parent'])
55
- y2 = y1 + values['height']
56
- if x >= x1 and x < x2 and y >= y1 and y < y2:
57
- if id in elements:
58
- element = elements[id]
59
- if 'cb' in element:
60
- element['cb']()
61
- break
57
+ def getElement(self, id):
58
+ if id in self.elements.keys():
59
+ return self.elements[id]
60
+ return None
61
+
62
+ def addElement(self, id, spec):
63
+ if id in self.elements.keys():
64
+ raise(Exception(f'Element {id} already exists'))
65
+ element = Element(type, spec)
66
+ element.cb = None
67
+ self.elements[id] = element
68
+ self.zlist.append(element)
69
+
70
+ def createElement(self, spec):
71
+ with self.canvas:
72
+ if hasattr(spec, 'fill'):
73
+ c = spec.fill
74
+ if isinstance(c, str):
75
+ c = colormap[c]
76
+ Color(c[0], c[1], c[2])
62
77
  else:
63
- RuntimeError(None, f'Element \'{id}\' does not exist')
64
-
65
- screen.bind('<Button-1>', onClick)
66
-
67
- fill = values['fill']['content'] if 'fill' in values else 'white'
68
- canvas = tk.Canvas(master=screen, width=width, height=height, bg=fill)
69
- canvas.place(x=0, y=0)
70
- setCanvas(canvas)
71
-
72
- # Close the screen
73
- def closeScreen():
74
- global screen
75
- screen.destroy()
76
-
77
- # Set up a click handler in an element
78
- def setOnClick(id, cb):
79
- global elements
80
- if id in elements:
81
- elements[id]['cb'] = cb
82
- else:
83
- RuntimeError(None, f'Element \'{id}\' does not exist')
84
- return
85
-
86
- # Set up the tick handler
87
- def setOnTick(cb):
88
- global onTick
89
- onTick = cb
90
-
91
- # Show the screen and issue tick callbacks
92
- def showScreen():
93
- global screen, onTick
94
- def afterCB(screen):
95
- if onTick != None:
96
- onTick()
97
- screen.after(100, lambda: afterCB(screen))
98
- screen.after(1000, lambda: afterCB(screen))
99
- screen.mainloop()
100
- sys.exit()
101
-
102
- # Render a graphic specification
103
- def render(spec, parent):
104
- global elements
105
-
106
- def getValue(args, item):
107
- if item in args:
108
- if type(item) == int:
109
- return item
110
- return args[item]
111
- return item
112
-
113
- def renderIntoRectangle(widgetType, values, parent, args):
114
- global zlist
115
- left = getValue(args, values['left']) if 'left' in values else 10
116
- screenLeft = left + getScreenLeft(parent)
117
- top = getValue(args, values['top']) if 'top' in values else 10
118
- screenTop = top + getScreenTop(parent)
119
- width = getValue(args, values['width']) if 'width' in values else 100
120
- height = getValue(args, values['height']) if 'height' in values else 100
121
- right = screenLeft + width
122
- bottom = screenTop + height
123
- fill = values['fill'] if 'fill' in values else None
124
- outline = values['outline'] if 'outline' in values else None
125
- if outline != None:
126
- outlineWidth = getValue(args, values['outlineWidth']) if 'outlineWidth' in values else 1
127
- else:
128
- outlineWidth = 0
129
- if widgetType == 'rectangle':
130
- widgetId = getCanvas().create_rectangle(screenLeft, screenTop, right, bottom, fill=fill, outline=outline, width=outlineWidth)
131
- elif widgetType == 'ellipse':
132
- widgetId = getCanvas().create_oval(screenLeft, screenTop, right, bottom, fill=fill, outline=outline, width=outlineWidth)
133
- else:
134
- return f'Unknown widget type \'{widgetType}\''
135
- if 'name' in values:
136
- widgetName = getValue(args, values['name'])
137
- else:
138
- widgetName = None
139
- widgetSpec = {
140
- "type": widgetType,
141
- "name": widgetName,
142
- "id": widgetId,
143
- "left": left,
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'])
203
- else:
204
- widgetName = None
205
- widgetSpec = {
206
- "type": "text",
207
- "name": widgetName,
208
- "id": textId,
209
- "left": left,
210
- "top": top,
211
- "width": width,
212
- "height": height,
213
- "parent": parent
214
- }
215
- elements[widgetName] = widgetSpec
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']
229
- else:
230
- widgetName = None
231
- if source == None:
232
- raise(Exception(f'No image source given for \'{id}\''))
233
- img = (Image.open(source))
234
- height = int(round(img.height * width / img.width))
235
- resized_image= img.resize((width, height), Image.LANCZOS)
236
- new_image= ImageTk.PhotoImage(resized_image)
237
- imageid = getCanvas().create_image(screenLeft, screenTop, anchor='nw', image=new_image)
238
- images[widgetName] = {'id': imageid, "image": new_image}
239
- widgetSpec = {
240
- "type": "image",
241
- "nme": widgetName,
242
- "left": left,
243
- "top": top,
244
- "width": width,
245
- "height": height,
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
78
+ Color(c[0]/255, c[1]/255, c[2]/255)
79
+ pos = spec.pos
80
+ if spec.parent != None:
81
+ pos = Vector(pos) + spec.parent.pos
82
+ if spec.type == 'ellipse':
83
+ item = Ellipse(pos=pos, size=spec.size)
84
+ elif spec.type == 'rectangle':
85
+ item = Rectangle(pos=pos, size=spec.size)
86
+ elif spec.type == 'text':
87
+ if hasattr(spec, 'color'):
88
+ c = spec.color
89
+ if isinstance(c, str):
90
+ c = colormap[c]
91
+ Color(c[0], c[1], c[2])
92
+ else:
93
+ Color(c[0]/255, c[1]/255, c[2]/255)
94
+ else:
95
+ Color(1, 1, 1, 1)
96
+ label = CoreLabel(text=spec.text, font_size=1000, halign='center', valign='center')
97
+ label.refresh()
98
+ text = label.texture
99
+ item = Rectangle(pos=spec.pos, size=spec.size, texture=text)
100
+ elif spec.type == 'image':
101
+ item = AsyncImage(pos=spec.pos, size=spec.size, source=spec.source)
102
+ spec.item = item
103
+ self.addElement(spec.id, spec)
104
+
105
+ def moveElementBy(self, id, dist):
106
+ element = self.getElement(id)
107
+ if element != None:
108
+ element.setPos(Vector(element.getPos()) + dist)
109
+ for id in element.getChildren():
110
+ self.getElement(id).repos()
111
+ return
112
+
113
+ def moveElementTo(self, id, pos):
114
+ element = self.getElement(id)
115
+ if element != None:
116
+ self.moveElementBy(id, Vector(pos) - element.getPos())
117
+ return
118
+
119
+ def on_touch_down(self, touch):
120
+ tp = touch.pos
121
+ x = tp[0]
122
+ y = tp[1]
123
+ for element in reversed(self.zlist):
124
+ if element.cb != None:
125
+ spec = element.spec
126
+ pos = spec.pos
127
+ if spec.parent != None:
128
+ pos = Vector(pos) + spec.parent.pos
129
+ size = spec.size
130
+ if spec.type == 'ellipse':
131
+ a = size[0]/2
132
+ b = size[1]/2
133
+ ctr = (pos[0] + a, pos[1] +b)
134
+ h = ctr[0]
135
+ k = ctr[1]
136
+ if (math.pow((x - h), 2) / math.pow(a, 2)) + (math.pow((y - k), 2) / math.pow(b, 2)) <= 1:
137
+ element.cb()
138
+ break
139
+ elif spec.type in ['rectangle', 'text', 'image']:
140
+ if tp[0] >= pos[0] and tp[0] < pos[0] + size[0] and tp[1] >= pos[1] and tp[1] < pos[1] + size[1]:
141
+ element.cb()
142
+ break
143
+
144
+ def setOnClick(self, id, callback):
145
+ self.getElement(id).cb = callback
146
+
147
+ def getAttribute(self, id, attribute):
148
+ spec = self.getElement(id).spec
149
+ if attribute == 'left':
150
+ return spec.pos[0]
151
+ elif attribute == 'bottom':
152
+ return spec.pos[1]
153
+ elif attribute == 'width':
154
+ return spec.size[0]
155
+ elif attribute == 'height':
156
+ return spec.size[1]
271
157
  else:
272
- renderWidget(spec[widgets], parent, args)
273
-
274
- # Main entry point
275
- if parent != screen:
276
- RuntimeError(None, 'Can\'t yet render into parent widget')
277
-
278
- # If it'a string, process it
279
- if type(spec) is str:
280
- renderSpec(json.loads(spec), None, {})
158
+ raise Exception(f'Unknown attribute: {attribute}')
281
159
 
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
160
 
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')
161
+ class Renderer(App):
295
162
 
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)
163
+ def getUI(self):
164
+ return self.ui
304
165
 
305
- # Move an element by an amount
306
- def moveElement(name, dx, dy):
307
- element = getElement(name)
308
- getCanvas().move(element['id'], dx, dy)
309
- element['left'] += dx
310
- element['top'] += dy
311
- for childName in element['children']:
312
- element = getElement(childName)
313
- getCanvas().move(element['id'], dx, dy)
314
-
315
- # Move an element to a new location
316
- def moveElementTo(name, left, top):
317
- element = getElement(name)
318
- moveElement(name, left - element['left'], top - element['top'])
319
-
320
- # Get an attribute of an element
321
- def getAttribute(name, attribute):
322
- element = getElement(name)
323
- return element[attribute]
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'])
166
+ def request_close(self):
167
+ print('close window')
168
+ Window.close()
169
+
170
+ def flushQueue(self, dt):
171
+ self.flush()
172
+
173
+ def build(self):
174
+ Clock.schedule_interval(self.flushQueue, 0.05)
175
+ self.ui = UI()
176
+ return self.ui
177
+
178
+ def init(self, spec):
179
+ self.title = spec.title
180
+ self.flush = spec.flush
181
+ Window.size = spec.size
182
+ Window.left = spec.pos[0]
183
+ Window.top = spec.pos[1]
184
+ Window.clearcolor = spec.fill
185
+ Window.on_request_close=self.request_close