easycoder 250107.4__tar.gz → 250109.2__tar.gz

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.

Files changed (164) hide show
  1. {easycoder-250107.4 → easycoder-250109.2}/PKG-INFO +1 -1
  2. {easycoder-250107.4 → easycoder-250109.2}/easycoder/__init__.py +1 -1
  3. {easycoder-250107.4 → easycoder-250109.2}/easycoder/ec_graphics.py +30 -44
  4. {easycoder-250107.4 → easycoder-250109.2}/easycoder/ec_program.py +1 -1
  5. {easycoder-250107.4 → easycoder-250109.2}/easycoder/ec_renderer.py +36 -18
  6. {easycoder-250107.4 → easycoder-250109.2}/easycoder/ec_screenspec.py +14 -7
  7. {easycoder-250107.4 → easycoder-250109.2}/easycoder/ec_value.py +9 -2
  8. easycoder-250109.2/plugins/ec_keyboard.py +248 -0
  9. easycoder-250109.2/plugins/keyboards/4-function.json +58 -0
  10. easycoder-250109.2/plugins/keyboards/round-button.png +0 -0
  11. {easycoder-250107.4 → easycoder-250109.2}/scripts/graphics-demo.ecg +2 -3
  12. easycoder-250109.2/scripts/keyboard.ecg +19 -0
  13. {easycoder-250107.4 → easycoder-250109.2}/scripts/wave.ecg +20 -4
  14. {easycoder-250107.4 → easycoder-250109.2}/LICENSE +0 -0
  15. {easycoder-250107.4 → easycoder-250109.2}/README.md +0 -0
  16. {easycoder-250107.4 → easycoder-250109.2}/doc/README.md +0 -0
  17. {easycoder-250107.4 → easycoder-250109.2}/doc/core/README.md +0 -0
  18. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/boolean.md +0 -0
  19. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/empty.md +0 -0
  20. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/ends.md +0 -0
  21. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/even.md +0 -0
  22. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/exists.md +0 -0
  23. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/greater.md +0 -0
  24. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/hasProperty.md +0 -0
  25. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/includes.md +0 -0
  26. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/is.md +0 -0
  27. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/less.md +0 -0
  28. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/list.md +0 -0
  29. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/none.md +0 -0
  30. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/not.md +0 -0
  31. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/numeric.md +0 -0
  32. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/object.md +0 -0
  33. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/odd.md +0 -0
  34. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/starts.md +0 -0
  35. {easycoder-250107.4 → easycoder-250109.2}/doc/core/conditions/string.md +0 -0
  36. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/add.md +0 -0
  37. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/append.md +0 -0
  38. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/assert.md +0 -0
  39. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/begin.md +0 -0
  40. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/clear.md +0 -0
  41. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/close.md +0 -0
  42. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/create.md +0 -0
  43. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/debug.md +0 -0
  44. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/decrement.md +0 -0
  45. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/delete.md +0 -0
  46. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/divide.md +0 -0
  47. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/exit.md +0 -0
  48. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/file.md +0 -0
  49. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/fork.md +0 -0
  50. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/get.md +0 -0
  51. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/go.md +0 -0
  52. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/gosub.md +0 -0
  53. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/if.md +0 -0
  54. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/import.md +0 -0
  55. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/increment.md +0 -0
  56. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/index.md +0 -0
  57. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/init.md +0 -0
  58. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/input.md +0 -0
  59. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/load.md +0 -0
  60. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/lock.md +0 -0
  61. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/module.md +0 -0
  62. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/multiply.md +0 -0
  63. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/negate.md +0 -0
  64. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/open.md +0 -0
  65. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/pop.md +0 -0
  66. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/post.md +0 -0
  67. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/print.md +0 -0
  68. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/push.md +0 -0
  69. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/put.md +0 -0
  70. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/read.md +0 -0
  71. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/release.md +0 -0
  72. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/replace.md +0 -0
  73. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/return.md +0 -0
  74. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/run.md +0 -0
  75. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/save.md +0 -0
  76. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/script.md +0 -0
  77. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/set.md +0 -0
  78. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/split.md +0 -0
  79. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/stack.md +0 -0
  80. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/stop.md +0 -0
  81. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/system.md +0 -0
  82. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/take.md +0 -0
  83. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/toggle.md +0 -0
  84. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/truncate.md +0 -0
  85. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/unlock.md +0 -0
  86. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/variable.md +0 -0
  87. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/wait.md +0 -0
  88. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/while.md +0 -0
  89. {easycoder-250107.4 → easycoder-250109.2}/doc/core/keywords/write.md +0 -0
  90. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/arg.md +0 -0
  91. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/args.md +0 -0
  92. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/cos.md +0 -0
  93. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/datime.md +0 -0
  94. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/decode.md +0 -0
  95. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/element.md +0 -0
  96. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/elements.md +0 -0
  97. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/empty.md +0 -0
  98. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/encode.md +0 -0
  99. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/error.md +0 -0
  100. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/files.md +0 -0
  101. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/float.md +0 -0
  102. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/from.md +0 -0
  103. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/hash.md +0 -0
  104. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/index.md +0 -0
  105. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/integer.md +0 -0
  106. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/json.md +0 -0
  107. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/keys.md +0 -0
  108. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/left.md +0 -0
  109. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/length.md +0 -0
  110. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/lowercase.md +0 -0
  111. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/memory.md +0 -0
  112. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/modification.md +0 -0
  113. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/modulo.md +0 -0
  114. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/newline.md +0 -0
  115. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/now.md +0 -0
  116. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/position.md +0 -0
  117. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/property.md +0 -0
  118. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/random.md +0 -0
  119. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/right.md +0 -0
  120. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/sin.md +0 -0
  121. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/stringify.md +0 -0
  122. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/tab.md +0 -0
  123. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/tan.md +0 -0
  124. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/timestamp.md +0 -0
  125. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/today.md +0 -0
  126. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/trim.md +0 -0
  127. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/type.md +0 -0
  128. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/uppercase.md +0 -0
  129. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/value.md +0 -0
  130. {easycoder-250107.4 → easycoder-250109.2}/doc/core/values/weekday.md +0 -0
  131. {easycoder-250107.4 → easycoder-250109.2}/doc/graphics/README.md +0 -0
  132. {easycoder-250107.4 → easycoder-250109.2}/doc/graphics/keywords/attach.md +0 -0
  133. {easycoder-250107.4 → easycoder-250109.2}/doc/graphics/keywords/close.md +0 -0
  134. {easycoder-250107.4 → easycoder-250109.2}/doc/graphics/keywords/create.md +0 -0
  135. {easycoder-250107.4 → easycoder-250109.2}/doc/graphics/keywords/ellipse.md +0 -0
  136. {easycoder-250107.4 → easycoder-250109.2}/doc/graphics/keywords/image.md +0 -0
  137. {easycoder-250107.4 → easycoder-250109.2}/doc/graphics/keywords/move.md +0 -0
  138. {easycoder-250107.4 → easycoder-250109.2}/doc/graphics/keywords/on.md +0 -0
  139. {easycoder-250107.4 → easycoder-250109.2}/doc/graphics/keywords/rectangle.md +0 -0
  140. {easycoder-250107.4 → easycoder-250109.2}/doc/graphics/keywords/render.md +0 -0
  141. {easycoder-250107.4 → easycoder-250109.2}/doc/graphics/keywords/run.md +0 -0
  142. {easycoder-250107.4 → easycoder-250109.2}/doc/graphics/keywords/set.md +0 -0
  143. {easycoder-250107.4 → easycoder-250109.2}/doc/graphics/keywords/text.md +0 -0
  144. {easycoder-250107.4 → easycoder-250109.2}/doc/graphics/values/attribute.md +0 -0
  145. {easycoder-250107.4 → easycoder-250109.2}/doc/graphics/values/window.md +0 -0
  146. {easycoder-250107.4 → easycoder-250109.2}/easycoder/README.md +0 -0
  147. {easycoder-250107.4 → easycoder-250109.2}/easycoder/ec.py +0 -0
  148. {easycoder-250107.4 → easycoder-250109.2}/easycoder/ec_classes.py +0 -0
  149. {easycoder-250107.4 → easycoder-250109.2}/easycoder/ec_compiler.py +0 -0
  150. {easycoder-250107.4 → easycoder-250109.2}/easycoder/ec_condition.py +0 -0
  151. {easycoder-250107.4 → easycoder-250109.2}/easycoder/ec_core.py +0 -0
  152. {easycoder-250107.4 → easycoder-250109.2}/easycoder/ec_handler.py +0 -0
  153. {easycoder-250107.4 → easycoder-250109.2}/easycoder/ec_timestamp.py +0 -0
  154. {easycoder-250107.4 → easycoder-250109.2}/images/Semoigo Dawn.jpg +0 -0
  155. {easycoder-250107.4 → easycoder-250109.2}/json/graphics-demo.json +0 -0
  156. {easycoder-250107.4 → easycoder-250109.2}/plugins/ec_p100.py +0 -0
  157. {easycoder-250107.4 → easycoder-250109.2}/plugins/example.py +0 -0
  158. {easycoder-250107.4 → easycoder-250109.2}/pyproject.toml +0 -0
  159. {easycoder-250107.4 → easycoder-250109.2}/scripts/README.md +0 -0
  160. {easycoder-250107.4 → easycoder-250109.2}/scripts/benchmark.ecs +0 -0
  161. {easycoder-250107.4 → easycoder-250109.2}/scripts/fizzbuzz.ecs +0 -0
  162. {easycoder-250107.4 → easycoder-250109.2}/scripts/hello.ecs +0 -0
  163. {easycoder-250107.4 → easycoder-250109.2}/scripts/points.ecs +0 -0
  164. {easycoder-250107.4 → easycoder-250109.2}/scripts/tests.ecs +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: easycoder
3
- Version: 250107.4
3
+ Version: 250109.2
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>
@@ -10,4 +10,4 @@ from .ec_program import *
10
10
  from .ec_timestamp import *
11
11
  from .ec_value import *
12
12
 
13
- __version__ = "250107.4"
13
+ __version__ = "250109.2"
@@ -1,8 +1,7 @@
1
- import sys, threading, json
2
1
  from .ec_classes import FatalError, RuntimeError, Object
3
2
  from .ec_handler import Handler
4
3
  from .ec_screenspec import ScreenSpec
5
- from .ec_renderer import Renderer
4
+ from .ec_renderer import Renderer, getUI
6
5
  from .ec_program import flush
7
6
 
8
7
  class Graphics(Handler):
@@ -32,7 +31,7 @@ class Graphics(Handler):
32
31
  targetRecord = self.getVariable(command['name'])
33
32
  keyword = targetRecord['keyword']
34
33
  id = self.getRuntimeValue(command['id'])
35
- uiElement = self.ui.getElement(id)
34
+ uiElement = getUI().getElement(id)
36
35
  if uiElement == None:
37
36
  FatalError(self.program.compiler, f'There is no screen element with id \'{id}\'')
38
37
  return -1
@@ -122,6 +121,7 @@ class Graphics(Handler):
122
121
  for item in ['width', 'height', 'left', 'bottom', 'r', 'g', 'b', 'text']:
123
122
  if command[item] == None:
124
123
  FatalError(self.program.compiler, f'Missing property \'{item}\'')
124
+ else: return False
125
125
  self.add(command)
126
126
  record['elementID'] = command['id']
127
127
  return False
@@ -182,7 +182,6 @@ class Graphics(Handler):
182
182
  command['source'] = source
183
183
 
184
184
  def r_create(self, command):
185
-
186
185
  try:
187
186
  type = command['type']
188
187
  if type == 'window':
@@ -198,8 +197,13 @@ class Graphics(Handler):
198
197
  self.windowSpec.size = (self.getRuntimeValue(command['size'][0]), self.getRuntimeValue(command['size'][1]))
199
198
  self.windowSpec.fill = (self.getRuntimeValue(command['fill'][0])/255, self.getRuntimeValue(command['fill'][1])/255, self.getRuntimeValue(command['fill'][2])/255)
200
199
  self.windowCreated = True
200
+ self.renderer = Renderer()
201
+ self.renderer.init(self.windowSpec)
202
+ self.program.setExternalControl()
203
+ self.program.run(self.nextPC())
204
+ self.renderer.run()
201
205
  else:
202
- element = self.ui.createWidget(self.getWidgetSpec(command))
206
+ element = getUI().createWidget(self.getWidgetSpec(command))
203
207
  print(element)
204
208
  except Exception as e:
205
209
  RuntimeError(self.program, e)
@@ -224,10 +228,6 @@ class Graphics(Handler):
224
228
  def r_ellipse(self, command):
225
229
  return self.nextPC()
226
230
 
227
- def r_getui(self, command):
228
- self.ui = self.renderer.getUI()
229
- return self.nextPC()
230
-
231
231
  # Hide an element
232
232
  def k_hide(self, command):
233
233
  if self.nextIsSymbol():
@@ -240,7 +240,7 @@ class Graphics(Handler):
240
240
  return False
241
241
 
242
242
  def r_hide(self, command):
243
- self.ui.setVisible(self.getRuntimeValue(command['target']), False)
243
+ getUI().setVisible(self.getRuntimeValue(command['target']), False)
244
244
  return self.nextPC()
245
245
 
246
246
  def k_image(self, command):
@@ -272,12 +272,12 @@ class Graphics(Handler):
272
272
 
273
273
  def r_move(self, command):
274
274
  pos = (self.getRuntimeValue(command['x']), self.getRuntimeValue(command['y']))
275
- self.ui.moveElementTo(self.getRuntimeValue(command['target']), pos)
275
+ getUI().moveElementTo(self.getRuntimeValue(command['target']), pos)
276
276
  return self.nextPC()
277
277
 
278
278
  def r_moveBy(self, command):
279
279
  dist = (self.getRuntimeValue(command['dx']), self.getRuntimeValue(command['dy']))
280
- self.ui.moveElementBy(self.getRuntimeValue(command['target']), dist)
280
+ getUI().moveElementBy(self.getRuntimeValue(command['target']), dist)
281
281
  return self.nextPC()
282
282
 
283
283
  # on click/tap {element} {action}
@@ -288,7 +288,7 @@ class Graphics(Handler):
288
288
  if self.nextIsSymbol():
289
289
  target = self.getSymbolRecord()
290
290
  else:
291
- FatalError(self.program.compiler, f'{self.getToken()} is not a screen element')
291
+ Warning(f'{self.getToken()} is not a screen element')
292
292
  return False
293
293
  command['target'] = target['name']
294
294
  command['goto'] = self.getPC() + 2
@@ -329,7 +329,7 @@ class Graphics(Handler):
329
329
  data = Object()
330
330
  data.pc = pc
331
331
  data.index = index
332
- self.ui.setOnClick(id, data, oncb)
332
+ getUI().setOnClick(id, data, oncb)
333
333
  else:
334
334
  name = record['name']
335
335
  RuntimeError(self.program, f'{name} is not a clickable object')
@@ -341,44 +341,30 @@ class Graphics(Handler):
341
341
  def r_rectangle(self, command):
342
342
  return self.nextPC()
343
343
 
344
- # render {spec}
344
+ # render spec {spec}
345
345
  def k_render(self, command):
346
- command['spec'] = self.nextValue()
347
- command['parent'] = None
348
- if self.peek() == 'in':
349
- self.nextToken()
350
- if self.nextIsSymbol():
351
- command['parent'] = self.getSymbolRecord()['name']
352
- self.add(command)
353
- return True
346
+ if self.nextToken() in ['specification', 'spec']:
347
+ command['spec'] = self.nextValue()
348
+ command['parent'] = None
349
+ if self.peek() == 'in':
350
+ self.nextToken()
351
+ if self.nextIsSymbol():
352
+ command['parent'] = self.getSymbolRecord()['name']
353
+ self.add(command)
354
+ return True
355
+ return False
354
356
 
355
357
  def r_render(self, command):
356
358
  spec = self.getRuntimeValue(command['spec'])
357
359
  parent = command['parent']
358
360
  if parent !=None:
359
361
  parent = self.getVariable(command['parent'])
360
- self.ui = self.renderer.getUI()
361
362
  try:
362
- ScreenSpec().render(spec, parent, self.ui)
363
+ ScreenSpec().render(spec, parent)
363
364
  except Exception as e:
364
365
  RuntimeError(self.program, e)
365
366
  return self.nextPC()
366
367
 
367
- # run graphics
368
- def k_run(self, command):
369
- if self.nextIs('graphics'):
370
- self.add(command)
371
- return True
372
- return False
373
-
374
- def r_run(self, command):
375
- self.renderer = Renderer()
376
- self.renderer.init(self.windowSpec)
377
- self.ui = self.renderer.getUI()
378
- self.program.setExternalControl()
379
- self.program.run(self.nextPC())
380
- self.renderer.run()
381
-
382
368
  # Set something
383
369
  def k_set(self, command):
384
370
  if self.nextIs('attribute'):
@@ -405,7 +391,7 @@ class Graphics(Handler):
405
391
  target = self.getVariable(command['target'])
406
392
  id = target['value'][target['index']]['content']
407
393
  value = self.getRuntimeValue(command['value'])
408
- self.ui.setAttribute(id, attribute, value)
394
+ getUI().setAttribute(id, attribute, value)
409
395
  return self.nextPC()
410
396
 
411
397
  # Show an element (restore it to its current position)
@@ -420,7 +406,7 @@ class Graphics(Handler):
420
406
  return False
421
407
 
422
408
  def r_show(self, command):
423
- self.ui.setVisible(self.getRuntimeValue(command['target']), True)
409
+ getUI().setVisible(self.getRuntimeValue(command['target']), True)
424
410
  return self.nextPC()
425
411
 
426
412
  def k_text(self, command):
@@ -483,7 +469,7 @@ class Graphics(Handler):
483
469
  attribute = self.getRuntimeValue(v['attribute'])
484
470
  target = self.getVariable(v['target'])
485
471
  val = self.getSymbolValue(target)
486
- v = self.ui.getAttribute(val['content'], attribute)
472
+ v = getUI().getAttribute(val['content'], attribute)
487
473
  value = {}
488
474
  value['type'] = 'int'
489
475
  value['content'] = int(round(v))
@@ -505,7 +491,7 @@ class Graphics(Handler):
505
491
  attribute = v['attribute']
506
492
  value = {}
507
493
  value['type'] = 'int'
508
- value['content'] = int(round(self.ui.getWindowAttribute(attribute)))
494
+ value['content'] = int(round(getUI().getWindowAttribute(attribute)))
509
495
  return value
510
496
  except Exception as e:
511
497
  RuntimeError(self.program, e)
@@ -18,7 +18,6 @@ class Program:
18
18
 
19
19
  def __init__(self, argv):
20
20
  global queue
21
- print(f'EasyCoder version {version("easycoder")}')
22
21
  if len(argv) == 0:
23
22
  print('No script supplied')
24
23
  exit()
@@ -387,6 +386,7 @@ class Program:
387
386
 
388
387
  # This is the program launcher
389
388
  def Main():
389
+ print(f'EasyCoder version {version("easycoder")}')
390
390
  if (len(sys.argv) > 1):
391
391
  Program(sys.argv[1]).start()
392
392
  else:
@@ -1,23 +1,31 @@
1
1
  from kivy.app import App
2
2
  from kivy.uix.widget import Widget
3
+ from kivy.graphics import Color, Ellipse, Rectangle
3
4
  from kivy.uix.label import CoreLabel
4
5
  from kivy.uix.image import AsyncImage
5
6
  from kivy.core.window import Window
6
- from kivy.graphics import Color, Ellipse, Rectangle
7
7
  from kivy.utils import colormap
8
8
  from kivy.clock import Clock
9
9
  from kivy.vector import Vector
10
- import math
10
+ import math, os
11
+
12
+ os.environ['KIVY_TEXT'] = 'pango'
11
13
 
12
- # Get a real position or size value
13
- # These are {n}w/h, where w/h are percentages
14
+ ec_ui = None
15
+
16
+ def getUI():
17
+ global ec_ui
18
+ return ec_ui
19
+
20
+ # Get an actual screeen position or size value from a specified value
21
+ # such as {n}w/h, where w/h are percentages
14
22
  # e.g. 25w or 50h
15
- def getReal(spec, val):
23
+ def getActual(val, spec=None):
16
24
  if isinstance(val, str):
17
25
  c = val[-1]
18
26
  if c in ['w', 'h']:
19
27
  val = int(val[0:len(val)-1])
20
- if spec.parent == None:
28
+ if spec == None or spec.parent == None:
21
29
  if c == 'w':
22
30
  n = Window.width
23
31
  else:
@@ -40,8 +48,8 @@ class Element():
40
48
 
41
49
  def getRelativePosition(self):
42
50
  spec = self.spec
43
- x = getReal(spec, spec.pos[0])
44
- y = getReal(spec, spec.pos[1])
51
+ x = getActual(spec.pos[0], spec)
52
+ y = getActual(spec.pos[1], spec)
45
53
  return Vector(x, y)
46
54
 
47
55
  def getType(self):
@@ -108,10 +116,19 @@ class UI(Widget):
108
116
  Color(c[0], c[1], c[2])
109
117
  else:
110
118
  Color(c[0]/255, c[1]/255, c[2]/255)
111
- pos = (getReal(spec, spec.pos[0]), getReal(spec, spec.pos[1]))
112
- spec.realpos = pos
113
- size = (getReal(spec, spec.size[0]), getReal(spec, spec.size[1]))
119
+ size = (getActual(spec.size[0], spec), getActual(spec.size[1], spec))
114
120
  spec.realsize = size
121
+ # Deal with special case of 'center'
122
+ if spec.pos[0] == 'center':
123
+ left = getActual('50w', spec) - spec.realsize[0]/2
124
+ else:
125
+ left = getActual(spec.pos[0], spec)
126
+ if spec.pos[1] == 'center':
127
+ bottom = getActual('50h', spec) - spec.realsize[1]/2
128
+ else:
129
+ bottom = getActual(spec.pos[1], spec)
130
+ pos = (left, bottom)
131
+ spec.realpos = pos
115
132
  if spec.parent != None:
116
133
  pos = Vector(pos) + spec.parent.realpos
117
134
  if spec.type == 'ellipse':
@@ -128,10 +145,12 @@ class UI(Widget):
128
145
  Color(c[0]/255, c[1]/255, c[2]/255)
129
146
  else:
130
147
  Color(1, 1, 1, 1)
131
- label = CoreLabel(text=spec.text, font_size=1000, halign='center', valign='center')
148
+ if self.font == None:
149
+ label = CoreLabel(text=spec.text, font_size=1000, halign='center', valign='center')
150
+ else:
151
+ label = CoreLabel(text=spec.text, font_context = None, font_name=self.font, font_size=1000, halign='center', valign='center')
132
152
  label.refresh()
133
- text = label.texture
134
- item = Rectangle(pos=pos, size=size, texture=text)
153
+ item = Rectangle(pos=pos, size=size, texture=label.texture)
135
154
  elif spec.type == 'image':
136
155
  item = AsyncImage(pos=pos, size=size, source=spec.source)
137
156
  spec.item = item
@@ -231,9 +250,6 @@ class UI(Widget):
231
250
 
232
251
  class Renderer(App):
233
252
 
234
- def getUI(self):
235
- return self.ui
236
-
237
253
  def request_close(self):
238
254
  print('close window')
239
255
  self.kill()
@@ -247,7 +263,9 @@ class Renderer(App):
247
263
  return self.ui
248
264
 
249
265
  def init(self, spec):
250
- self.ui = UI()
266
+ global ec_ui
267
+ ec_ui = UI()
268
+ self.ui = ec_ui
251
269
  self.title = spec.title
252
270
  self.flush = spec.flush
253
271
  self.kill = spec.kill
@@ -1,21 +1,28 @@
1
1
  # screenspec.py
2
2
 
3
3
  from json import loads
4
- from .ec_renderer import Object
4
+ from .ec_renderer import Object, getUI
5
+
6
+ global_id = 0
5
7
 
6
8
  class ScreenSpec():
7
9
 
10
+ id = 0
11
+
8
12
  # Get an attribute of an element
9
13
  def getAttribute(self, id, attribute):
10
- element = self.ui.getElement(id)
14
+ element = getUI().getElement(id)
11
15
  return element[attribute]
12
16
 
13
17
  # Render a single widget
14
18
  def createWidget(self, widget, parent):
19
+ global global_id
15
20
  spec = Object()
16
21
  type = widget['type']
17
22
  spec.type = type
18
- spec.id = widget['id']
23
+ global_id += 1
24
+ if 'id' in widget: spec.id = widget['id']
25
+ else: spec.id = f'_{global_id}'
19
26
  spec.pos = (widget['left'], widget['bottom'])
20
27
  spec.size = (widget['width'], widget['height'])
21
28
  if widget.get('fill') != None:
@@ -30,7 +37,7 @@ class ScreenSpec():
30
37
  spec.color = widget['color']
31
38
  spec.parent = parent
32
39
  spec.children = []
33
- self.ui.createElement(spec)
40
+ getUI().createElement(spec)
34
41
 
35
42
  if '#' in widget:
36
43
  children = widget['#']
@@ -51,6 +58,8 @@ class ScreenSpec():
51
58
 
52
59
  # Render a complete specification
53
60
  def renderSpec(self, spec, parent):
61
+ if 'font' in spec: getUI().font = spec['font']
62
+ else: getUI().font = None
54
63
  widgets = spec['#']
55
64
  # If a list, iterate it
56
65
  if isinstance(widgets, list):
@@ -61,8 +70,7 @@ class ScreenSpec():
61
70
  self.createWidget(spec[widgets], parent)
62
71
 
63
72
  # Render a graphic specification
64
- def render(self, spec, parent, ui):
65
- self.ui = ui
73
+ def render(self, spec, parent):
66
74
 
67
75
  # If it'a string, process it
68
76
  if isinstance(spec, str):
@@ -71,4 +79,3 @@ class ScreenSpec():
71
79
  # If it's a 'dict', extract the spec and the args
72
80
  else:
73
81
  self.renderSpec(spec, parent)
74
-
@@ -1,5 +1,12 @@
1
1
  from .ec_classes import FatalError
2
2
 
3
+ # Create a constant
4
+ def getConstant(str):
5
+ value = {}
6
+ value['type'] = 'text'
7
+ value['content'] = str
8
+ return value
9
+
3
10
  class Value:
4
11
 
5
12
  def __init__(self, compiler):
@@ -15,7 +22,7 @@ class Value:
15
22
  return None
16
23
 
17
24
  value = {}
18
-
25
+
19
26
  if token == 'true':
20
27
  value['type'] = 'boolean'
21
28
  value['content'] = True
@@ -80,7 +87,7 @@ class Value:
80
87
  value = domain.modifyValue(value)
81
88
 
82
89
  return value
83
-
90
+
84
91
  def compileConstant(self, token):
85
92
  value = {}
86
93
  if type(token) == 'str':
@@ -0,0 +1,248 @@
1
+ from easycoder import Object, FatalError, RuntimeError
2
+ from easycoder import Handler
3
+ from easycoder import getConstant
4
+ from easycoder.ec_screenspec import ScreenSpec
5
+ from easycoder.ec_renderer import getActual, getUI
6
+ import json
7
+
8
+ class Keyboard(Handler):
9
+
10
+ def __init__(self, compiler):
11
+ Handler.__init__(self, compiler)
12
+ self.keyboard = None
13
+ self.key = None
14
+ self.onTap = None
15
+
16
+ def getName(self):
17
+ return 'keyboard'
18
+
19
+ #############################################################################
20
+ # Keyword handlers
21
+
22
+ # Create a keyboard
23
+ def k_create(self, command):
24
+ if self.nextIs('keyboard'):
25
+ command['template'] = self.nextValue()
26
+ buttonStyle = 'ellipse'
27
+ buttonTemplate = None
28
+ buttonTextWidth = getConstant('50w')
29
+ buttonTextHeight = getConstant('50h')
30
+ buttonTextColor = getConstant('black')
31
+ buttonTextX = getConstant('center')
32
+ buttonTextY = getConstant('center')
33
+ buttonColor = getConstant('white')
34
+ buttonFont = None
35
+ while True:
36
+ token = self.peek()
37
+ if token == 'button':
38
+ self.nextToken()
39
+ token = self.nextToken()
40
+ if token == 'style':
41
+ token = self.nextToken()
42
+ if token in ['ellipse', 'rectangle', 'image']:
43
+ buttonStyle = token
44
+ else: RuntimeError(self.program, f'Unknown style \'token\'')
45
+ elif token == 'color':
46
+ buttonColor = self.nextValue()
47
+ elif token == 'font':
48
+ buttonFont = self.nextValue()
49
+ elif token == 'template':
50
+ buttonTemplate = self.nextValue()
51
+ elif token == 'text':
52
+ token = self.nextToken()
53
+ if token =='width':
54
+ buttonTextWidth = self.nextValue()
55
+ elif token == 'height':
56
+ buttonTextHeight = self.nextValue()
57
+ elif token == 'color':
58
+ buttonTextColor = self.nextValue()
59
+ elif token == 'x':
60
+ buttonTextX = self.nextValue()
61
+ elif token == 'y':
62
+ buttonTextY = self.nextValue()
63
+ else: RuntimeError(self.program, f'Unknown property \'token\'')
64
+ else:
65
+ break
66
+ command['button-style'] = buttonStyle
67
+ command['button-template'] = buttonTemplate
68
+ command['button-text-width'] = buttonTextWidth
69
+ command['button-text-height'] = buttonTextHeight
70
+ command['button-text-color'] = buttonTextColor
71
+ command['button-text-x'] = buttonTextX
72
+ command['button-text-y'] = buttonTextY
73
+ command['button-color'] = buttonColor
74
+ command['button-font'] = buttonFont
75
+ self.add(command)
76
+ return True
77
+ return False
78
+
79
+ def r_create(self, command):
80
+ self.keyboard = Object()
81
+ template = self.getRuntimeValue(command['template'])
82
+ with open(f'{template}') as f: s = f.read()
83
+ self.keyboard.layout = json.loads(s)
84
+ self.keyboard.buttonStyle = command['button-style']
85
+ self.keyboard.buttonTemplate = self.getRuntimeValue(command['button-template'])
86
+ self.keyboard.buttonTextWidth = self.getRuntimeValue(command['button-text-width'])
87
+ self.keyboard.buttonTextHeight = self.getRuntimeValue(command['button-text-height'])
88
+ self.keyboard.buttonTextColor = self.getRuntimeValue(command['button-text-color'])
89
+ self.keyboard.buttonTextX = self.getRuntimeValue(command['button-text-x'])
90
+ self.keyboard.buttonTextY = self.getRuntimeValue(command['button-text-y'])
91
+ self.keyboard.buttonColor = self.getRuntimeValue(command['button-color'])
92
+ self.keyboard.buttonFont = self.getRuntimeValue(command['button-font'])
93
+ return self.nextPC()
94
+
95
+ # on click/tap keyboard
96
+ def k_on(self, command):
97
+ token = self.nextToken()
98
+ if token in ['click', 'tap']:
99
+ if self.nextIs('keyboard'):
100
+ command['goto'] = self.getPC() + 2
101
+ self.add(command)
102
+ self.nextToken()
103
+ pcNext = self.getPC()
104
+ cmd = {}
105
+ cmd['domain'] = 'core'
106
+ cmd['lino'] = command['lino']
107
+ cmd['keyword'] = 'gotoPC'
108
+ cmd['goto'] = 0
109
+ cmd['debug'] = False
110
+ self.addCommand(cmd)
111
+ self.compileOne()
112
+ cmd = {}
113
+ cmd['domain'] = 'core'
114
+ cmd['lino'] = command['lino']
115
+ cmd['keyword'] = 'stop'
116
+ cmd['debug'] = False
117
+ self.addCommand(cmd)
118
+ # Fixup the link
119
+ self.getCommandAt(pcNext)['goto'] = self.getPC()
120
+ return True
121
+ return False
122
+
123
+ # Set a handler
124
+ def r_on(self, command):
125
+ self.onTap = command['goto']
126
+ return self.nextPC()
127
+
128
+ # Render a keyboard
129
+ # render keyboard at {left} {bottom} width {width}
130
+ def k_render(self, command):
131
+ if self.nextIs('keyboard'):
132
+ token = self.peek()
133
+ while token in ['at', 'width']:
134
+ self.nextToken()
135
+ if token == 'at':
136
+ command['x'] = self.nextValue()
137
+ command['y'] = self.nextValue()
138
+ elif token == 'width':
139
+ command['w'] = self.nextValue()
140
+ token = self.peek()
141
+ self.add(command)
142
+ return True
143
+ return False
144
+
145
+ def r_render(self, command):
146
+ x = getActual(self.getRuntimeValue(command['x']))
147
+ y = getActual(self.getRuntimeValue(command['y']))
148
+ w = getActual(self.getRuntimeValue(command['w']))
149
+ # Scan the keyboard layout to find the longest row
150
+ max = 0
151
+ nrows = len(self.keyboard.layout)
152
+ for r in range(0, nrows):
153
+ row = self.keyboard.layout[r]
154
+ # Count the number of buttons
155
+ if len(row) > max: max = len(row)
156
+ # Divide the keyboard width by the number of buttons to get the button size
157
+ bs = w / max
158
+ # Compute the keyboard height
159
+ h = bs * nrows
160
+ # Build the spec
161
+ buttons = []
162
+ list = []
163
+ by = y
164
+ for r in reversed(range(0, nrows)):
165
+ row = self.keyboard.layout[r]
166
+ bx = x
167
+ for b in range(0, len(row)):
168
+ button = row[b]
169
+ id = button['id']
170
+ button['type'] = self.keyboard.buttonStyle
171
+ button['source'] = self.keyboard.buttonTemplate
172
+ button['left'] = bx
173
+ button['bottom'] = by
174
+ button['width'] = bs
175
+ button['height'] = bs
176
+ button['fill'] = self.keyboard.buttonColor
177
+ label = {}
178
+ label['type'] = 'text'
179
+ label['left'] = self.keyboard.buttonTextX
180
+ label['bottom'] = self.keyboard.buttonTextY
181
+ label['width'] = self.keyboard.buttonTextWidth
182
+ label['height'] = self.keyboard.buttonTextHeight
183
+ label['text'] = id
184
+ label['color'] = self.keyboard.buttonTextColor
185
+ button['#'] = 'Label'
186
+ button['Label'] = label
187
+ buttons.append(button)
188
+ list.append(id)
189
+ bx += bs
190
+ by += bs
191
+ spec = {}
192
+ spec['#'] = list
193
+ for n in range(0, len(list)):
194
+ spec[list[n]] = buttons[n]
195
+
196
+ spec['font'] = self.keyboard.buttonFont
197
+ try:
198
+ ScreenSpec().render(spec, None)
199
+ except Exception as e:
200
+ RuntimeError(self.program, e)
201
+
202
+ # Add a callback to each button
203
+ def oncb(id):
204
+ self.key = id
205
+ if self.onTap != None:
206
+ self.program.run(self.onTap)
207
+ for b in range(0, len(list)):
208
+ id = list[b]
209
+ getUI().setOnClick(id, id, oncb)
210
+
211
+ return self.nextPC()
212
+
213
+ #############################################################################
214
+ # Modify a value or leave it unchanged.
215
+ def modifyValue(self, value):
216
+ return value
217
+
218
+ #############################################################################
219
+ # Compile a value in this domain
220
+ def compileValue(self):
221
+ value = {}
222
+ value['domain'] = self.getName()
223
+ if self.tokenIs('the'):
224
+ self.nextToken()
225
+ kwd = self.getToken()
226
+
227
+ if kwd == 'key':
228
+ value['type'] = kwd
229
+ return value
230
+ return None
231
+
232
+ #############################################################################
233
+ # Value handlers
234
+
235
+ def v_key(self, v):
236
+ value = {}
237
+ value['type'] = 'text'
238
+ value['content'] = self.key
239
+ return value
240
+
241
+ #############################################################################
242
+ # Compile a condition in this domain
243
+ def compileCondition(self):
244
+ condition = {}
245
+ return condition
246
+
247
+ #############################################################################
248
+ # Condition handlers