scarpe 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (347) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -0
  3. data/.yardopts +12 -0
  4. data/CHANGELOG.md +16 -2
  5. data/Gemfile +3 -0
  6. data/Gemfile.lock +116 -0
  7. data/README.md +53 -30
  8. data/Rakefile +13 -1
  9. data/docs/yard/catscradle.md +44 -0
  10. data/docs/yard/template/default/fulldoc/html/setup.rb +13 -0
  11. data/docs/yard/template/default/layout/html/setup.rb +9 -0
  12. data/examples/animate.rb +20 -0
  13. data/examples/arrow.rb +10 -0
  14. data/examples/background_with_image.rb +16 -0
  15. data/examples/bloopsaphone/working/bronx_army_knife.rb +66 -0
  16. data/examples/bloopsaphone/working/morning_serenity.rb +21 -0
  17. data/examples/bloopsaphone/working/simpsons_theme_song_by_why.rb +6 -4
  18. data/examples/btn_tooltip.rb +7 -0
  19. data/examples/button_go_away.rb +1 -1
  20. data/examples/button_style_changed.rb +7 -0
  21. data/examples/button_styles_default.rb +6 -0
  22. data/examples/check.rb +18 -0
  23. data/examples/clear_and_append.rb +24 -0
  24. data/examples/download_and_show_image.rb +28 -0
  25. data/examples/edit_box.rb +3 -5
  26. data/examples/fonts.rb +2 -2
  27. data/examples/gen.rb +8 -8
  28. data/examples/get_headers.rb +10 -0
  29. data/examples/highlander.rb +4 -2
  30. data/examples/legacy/README.md +6 -0
  31. data/examples/legacy/not_checked/shoes-contrib/basic/shoes-notes.rb +1 -1
  32. data/examples/legacy/not_checked/simple/anim-shapes.rb +1 -1
  33. data/examples/legacy/not_checked/speedometer_app.rb +55 -0
  34. data/examples/legacy/working/simple/image-icon.rb +3 -0
  35. data/examples/legacy/{not_checked → working}/simple/image.rb +1 -1
  36. data/examples/link.rb +2 -2
  37. data/examples/list_box_choose.rb +17 -0
  38. data/examples/local_assets/local_file_server.rb +82 -0
  39. data/examples/local_assets/sample.gif +0 -0
  40. data/examples/local_assets/sample.mp4 +0 -0
  41. data/examples/local_fonts.rb +4 -0
  42. data/examples/local_images.rb +3 -0
  43. data/examples/motion_events.rb +20 -0
  44. data/examples/para/para_text.rb +14 -0
  45. data/examples/parse_xl_funnies.rb +58 -0
  46. data/examples/progress.rb +31 -0
  47. data/examples/radio/radio.rb +16 -0
  48. data/examples/radio/radio_groups.rb +18 -0
  49. data/examples/radio/radio_same_slot.rb +6 -0
  50. data/examples/rect.rb +4 -0
  51. data/examples/rotate_shapes.rb +17 -0
  52. data/examples/ruby_racer.rb +13 -15
  53. data/examples/selfitude.rb +18 -0
  54. data/examples/shapes/shapes_fill.rb +4 -3
  55. data/examples/shoes_school.rb +2 -4
  56. data/examples/show_hide.rb +6 -0
  57. data/examples/simpler-menu.rb +21 -0
  58. data/examples/skip_ci/change_my_audio_source.rb +21 -0
  59. data/examples/skip_ci/guitar_fretboard.rb +137 -0
  60. data/examples/video.rb +10 -0
  61. data/exe/scarpe +43 -66
  62. data/fonts/Pacifico.ttf +0 -0
  63. data/lacci/Gemfile +24 -0
  64. data/lacci/Gemfile.lock +79 -0
  65. data/lacci/Rakefile +12 -0
  66. data/lacci/lacci.gemspec +37 -0
  67. data/lacci/lib/lacci/scarpe_cli.rb +71 -0
  68. data/lacci/lib/lacci/scarpe_core.rb +22 -0
  69. data/lacci/lib/lacci/version.rb +13 -0
  70. data/lacci/lib/scarpe/niente/app.rb +23 -0
  71. data/lacci/lib/scarpe/niente/display_service.rb +62 -0
  72. data/lacci/lib/scarpe/niente/drawable.rb +57 -0
  73. data/lacci/lib/scarpe/niente/logger.rb +29 -0
  74. data/lacci/lib/scarpe/niente/shoes_spec.rb +87 -0
  75. data/lacci/lib/scarpe/niente.rb +20 -0
  76. data/lacci/lib/shoes/app.rb +309 -0
  77. data/{lib/scarpe → lacci/lib/shoes}/background.rb +2 -2
  78. data/{lib/scarpe → lacci/lib/shoes}/border.rb +2 -2
  79. data/lacci/lib/shoes/builtins.rb +63 -0
  80. data/lacci/lib/shoes/changelog.rb +52 -0
  81. data/{lib/scarpe → lacci/lib/shoes}/colors.rb +3 -1
  82. data/lacci/lib/shoes/constants.rb +47 -0
  83. data/{lib/scarpe → lacci/lib/shoes}/display_service.rb +71 -53
  84. data/lacci/lib/shoes/download.rb +123 -0
  85. data/lacci/lib/shoes/drawable.rb +380 -0
  86. data/lacci/lib/shoes/drawables/arc.rb +49 -0
  87. data/lacci/lib/shoes/drawables/arrow.rb +41 -0
  88. data/lacci/lib/shoes/drawables/button.rb +73 -0
  89. data/lacci/lib/shoes/drawables/check.rb +29 -0
  90. data/lacci/lib/shoes/drawables/document_root.rb +20 -0
  91. data/lacci/lib/shoes/drawables/edit_box.rb +29 -0
  92. data/{lib/scarpe → lacci/lib/shoes/drawables}/edit_line.rb +6 -6
  93. data/lacci/lib/shoes/drawables/flow.rb +22 -0
  94. data/{lib/scarpe → lacci/lib/shoes/drawables}/image.rb +7 -11
  95. data/lacci/lib/shoes/drawables/line.rb +20 -0
  96. data/lacci/lib/shoes/drawables/link.rb +34 -0
  97. data/lacci/lib/shoes/drawables/list_box.rb +56 -0
  98. data/lacci/lib/shoes/drawables/para.rb +118 -0
  99. data/lacci/lib/shoes/drawables/progress.rb +14 -0
  100. data/lacci/lib/shoes/drawables/radio.rb +33 -0
  101. data/lacci/lib/shoes/drawables/rect.rb +17 -0
  102. data/lacci/lib/shoes/drawables/shape.rb +36 -0
  103. data/lacci/lib/shoes/drawables/slot.rb +87 -0
  104. data/{lib/scarpe → lacci/lib/shoes/drawables}/span.rb +8 -7
  105. data/lacci/lib/shoes/drawables/stack.rb +26 -0
  106. data/lacci/lib/shoes/drawables/star.rb +50 -0
  107. data/lacci/lib/shoes/drawables/subscription_item.rb +93 -0
  108. data/lacci/lib/shoes/drawables/text_drawable.rb +63 -0
  109. data/lacci/lib/shoes/drawables/video.rb +16 -0
  110. data/lacci/lib/shoes/drawables/widget.rb +69 -0
  111. data/lacci/lib/shoes/drawables.rb +31 -0
  112. data/lacci/lib/shoes/errors.rb +28 -0
  113. data/lacci/lib/shoes/log.rb +71 -0
  114. data/lacci/lib/shoes/ruby_extensions.rb +15 -0
  115. data/lacci/lib/shoes/spacing.rb +9 -0
  116. data/lacci/lib/shoes-spec.rb +93 -0
  117. data/lacci/lib/shoes.rb +147 -0
  118. data/lacci/test/test_colors.rb +39 -0
  119. data/lacci/test/test_helper.rb +63 -0
  120. data/lacci/test/test_lacci.rb +18 -0
  121. data/lacci/test/test_shoes_errors.rb +49 -0
  122. data/lib/scarpe/cats_cradle.rb +271 -0
  123. data/lib/scarpe/errors.rb +77 -0
  124. data/lib/scarpe/evented_assertions.rb +121 -0
  125. data/lib/scarpe/shoes_spec.rb +181 -0
  126. data/lib/scarpe/version.rb +2 -2
  127. data/lib/scarpe/wv/app.rb +45 -23
  128. data/lib/scarpe/wv/arc.rb +4 -48
  129. data/lib/scarpe/wv/arrow.rb +9 -0
  130. data/lib/scarpe/wv/button.rb +7 -33
  131. data/lib/scarpe/wv/check.rb +27 -0
  132. data/lib/scarpe/wv/control_interface.rb +32 -40
  133. data/lib/scarpe/wv/document_root.rb +66 -31
  134. data/lib/scarpe/wv/drawable.rb +273 -0
  135. data/lib/scarpe/wv/edit_box.rb +4 -19
  136. data/lib/scarpe/wv/edit_line.rb +4 -18
  137. data/lib/scarpe/wv/flow.rb +2 -28
  138. data/lib/scarpe/wv/image.rb +10 -25
  139. data/lib/scarpe/wv/line.rb +3 -28
  140. data/lib/scarpe/wv/link.rb +3 -15
  141. data/lib/scarpe/wv/list_box.rb +6 -29
  142. data/lib/scarpe/wv/para.rb +11 -28
  143. data/lib/scarpe/wv/progress.rb +19 -0
  144. data/lib/scarpe/wv/radio.rb +33 -0
  145. data/lib/scarpe/wv/rect.rb +13 -0
  146. data/lib/scarpe/wv/shape.rb +41 -10
  147. data/lib/scarpe/wv/slot.rb +64 -0
  148. data/lib/scarpe/wv/span.rb +3 -25
  149. data/lib/scarpe/wv/stack.rb +2 -38
  150. data/lib/scarpe/wv/star.rb +3 -54
  151. data/lib/scarpe/wv/subscription_item.rb +84 -0
  152. data/lib/scarpe/wv/text_drawable.rb +32 -0
  153. data/lib/scarpe/wv/video.rb +34 -0
  154. data/lib/scarpe/wv/web_wrangler.rb +449 -299
  155. data/lib/scarpe/wv/webview_local_display.rb +63 -26
  156. data/lib/scarpe/wv/webview_relay_display.rb +24 -125
  157. data/lib/scarpe/wv/webview_relay_util.rb +140 -0
  158. data/lib/scarpe/wv/wv_display_worker.rb +19 -6
  159. data/lib/scarpe/wv.rb +76 -14
  160. data/lib/scarpe/wv_local.rb +1 -1
  161. data/lib/scarpe/wv_relay.rb +1 -1
  162. data/lib/scarpe.rb +4 -32
  163. data/logger/debug_web_wrangler.json +1 -1
  164. data/logger/scarpe_wv_test.json +1 -1
  165. data/scarpe-components/.gitignore +1 -0
  166. data/scarpe-components/Gemfile +22 -0
  167. data/scarpe-components/Gemfile.lock +86 -0
  168. data/scarpe-components/README.md +35 -0
  169. data/scarpe-components/Rakefile +12 -0
  170. data/scarpe-components/lib/scarpe/components/base64.rb +25 -0
  171. data/scarpe-components/lib/scarpe/components/calzini/alert.rb +49 -0
  172. data/scarpe-components/lib/scarpe/components/calzini/art_widgets.rb +203 -0
  173. data/scarpe-components/lib/scarpe/components/calzini/button.rb +39 -0
  174. data/scarpe-components/lib/scarpe/components/calzini/misc.rb +146 -0
  175. data/scarpe-components/lib/scarpe/components/calzini/para.rb +35 -0
  176. data/scarpe-components/lib/scarpe/components/calzini/slots.rb +155 -0
  177. data/scarpe-components/lib/scarpe/components/calzini/text_widgets.rb +65 -0
  178. data/scarpe-components/lib/scarpe/components/calzini.rb +149 -0
  179. data/scarpe-components/lib/scarpe/components/errors.rb +20 -0
  180. data/scarpe-components/lib/scarpe/components/file_helpers.rb +66 -0
  181. data/scarpe-components/lib/scarpe/components/html.rb +131 -0
  182. data/scarpe-components/lib/scarpe/components/minitest_export_reporter.rb +75 -0
  183. data/scarpe-components/lib/scarpe/components/minitest_import_runnable.rb +98 -0
  184. data/scarpe-components/lib/scarpe/components/minitest_result.rb +86 -0
  185. data/scarpe-components/lib/scarpe/components/modular_logger.rb +113 -0
  186. data/scarpe-components/lib/scarpe/components/print_logger.rb +47 -0
  187. data/{lib/scarpe → scarpe-components/lib/scarpe/components}/promises.rb +115 -48
  188. data/scarpe-components/lib/scarpe/components/segmented_file_loader.rb +189 -0
  189. data/scarpe-components/lib/scarpe/components/string_helpers.rb +10 -0
  190. data/scarpe-components/lib/scarpe/components/tiranti.rb +225 -0
  191. data/scarpe-components/lib/scarpe/components/unit_test_helpers.rb +257 -0
  192. data/scarpe-components/lib/scarpe/components/version.rb +7 -0
  193. data/scarpe-components/scarpe-components.gemspec +38 -0
  194. data/scarpe-components/test/calzini/test_calzini_alert.rb +30 -0
  195. data/scarpe-components/test/calzini/test_calzini_art_drawables.rb +105 -0
  196. data/scarpe-components/test/calzini/test_calzini_button.rb +52 -0
  197. data/scarpe-components/test/calzini/test_calzini_misc.rb +115 -0
  198. data/scarpe-components/test/calzini/test_calzini_para.rb +37 -0
  199. data/scarpe-components/test/calzini/test_calzini_slots.rb +130 -0
  200. data/scarpe-components/test/calzini/test_calzini_text_drawables.rb +41 -0
  201. data/scarpe-components/test/mtr_data/exception.json +1 -0
  202. data/scarpe-components/test/mtr_data/fail_with_message.json +1 -0
  203. data/scarpe-components/test/mtr_data/skipped_no_message.json +1 -0
  204. data/scarpe-components/test/mtr_data/skipped_w_msg.json +1 -0
  205. data/scarpe-components/test/mtr_data/succeed_2_asserts.json +1 -0
  206. data/scarpe-components/test/test_components.rb +9 -0
  207. data/scarpe-components/test/test_dimensions.rb +26 -0
  208. data/scarpe-components/test/test_helper.rb +43 -0
  209. data/scarpe-components/test/test_html.rb +65 -0
  210. data/scarpe-components/test/test_minitest_result.rb +61 -0
  211. data/scarpe-components/test/test_promises.rb +261 -0
  212. data/scarpe-components/test/test_segmented_app_files.rb +184 -0
  213. data/scarpegen.rb +14 -14
  214. data/sig/scarpe.rbs +1 -1
  215. data/{lib/scarpe → spikes}/glibui/widget.rb +2 -2
  216. data/{lib/scarpe → spikes}/glibui.rb +1 -1
  217. data/templates/basic_class_template.erb +13 -14
  218. data/templates/class_template_with_event_bind.erb +4 -4
  219. data/templates/class_template_with_shapes.erb +8 -17
  220. data/templates/example_template.erb +1 -1
  221. data/templates/module_template.erb +4 -4
  222. data/templates/webview_template.erb +3 -5
  223. metadata +236 -145
  224. data/examples/fill.rb +0 -25
  225. data/examples/legacy/not_checked/shoes-contrib/basic/class-book.yaml +0 -387
  226. data/examples/legacy/not_checked/shoes-contrib/elements/image-icon.rb +0 -3
  227. data/examples/legacy/not_checked/shoes-contrib/good/good-clock.rb +0 -51
  228. data/examples/legacy/not_checked/shoes-contrib/good/good-follow.rb +0 -26
  229. data/examples/legacy/not_checked/shoes-contrib/good/good-reminder.rb +0 -174
  230. data/examples/legacy/not_checked/shoes-contrib/good/good-vjot.rb +0 -56
  231. data/examples/legacy/not_checked/shoes-contrib/simple/simple-timer.rb +0 -13
  232. data/examples/legacy/not_checked/shoes-dep-samples/good-clock.rb +0 -51
  233. data/examples/legacy/not_checked/shoes-dep-samples/good-follow.rb +0 -26
  234. data/examples/legacy/not_checked/shoes-dep-samples/good-reminder.rb +0 -174
  235. data/examples/legacy/not_checked/shoes-dep-samples/good-vjot.rb +0 -56
  236. data/examples/legacy/not_checked/shoes-dep-samples/simple-accordion.rb +0 -75
  237. data/examples/legacy/not_checked/shoes-dep-samples/simple-anim-shapes.rb +0 -17
  238. data/examples/legacy/not_checked/shoes-dep-samples/simple-anim-text.rb +0 -13
  239. data/examples/legacy/not_checked/shoes-dep-samples/simple-arc.rb +0 -23
  240. data/examples/legacy/not_checked/shoes-dep-samples/simple-bounce.rb +0 -24
  241. data/examples/legacy/not_checked/shoes-dep-samples/simple-calc.rb +0 -70
  242. data/examples/legacy/not_checked/shoes-dep-samples/simple-chipmunk.rb +0 -26
  243. data/examples/legacy/not_checked/shoes-dep-samples/simple-control-sizes.rb +0 -24
  244. data/examples/legacy/not_checked/shoes-dep-samples/simple-curve.rb +0 -26
  245. data/examples/legacy/not_checked/shoes-dep-samples/simple-dialogs.rb +0 -29
  246. data/examples/legacy/not_checked/shoes-dep-samples/simple-draw.rb +0 -13
  247. data/examples/legacy/not_checked/shoes-dep-samples/simple-editor.rb +0 -28
  248. data/examples/legacy/not_checked/shoes-dep-samples/simple-form.rb +0 -28
  249. data/examples/legacy/not_checked/shoes-dep-samples/simple-form.shy +0 -0
  250. data/examples/legacy/not_checked/shoes-dep-samples/simple-mask.rb +0 -21
  251. data/examples/legacy/not_checked/shoes-dep-samples/simple-menu.rb +0 -31
  252. data/examples/legacy/not_checked/shoes-dep-samples/simple-menu1.rb +0 -35
  253. data/examples/legacy/not_checked/shoes-dep-samples/simple-rubygems.rb +0 -29
  254. data/examples/legacy/not_checked/shoes-dep-samples/simple-slide.rb +0 -45
  255. data/examples/legacy/not_checked/shoes-dep-samples/simple-sphere.rb +0 -28
  256. data/examples/legacy/not_checked/shoes-dep-samples/simple-sqlite3.rb +0 -13
  257. data/examples/legacy/not_checked/shoes-dep-samples/simple-timer.rb +0 -13
  258. data/examples/legacy/not_checked/shoes-dep-samples/simple-video.rb +0 -13
  259. data/examples/legacy/not_checked/simple/anim-text.rb +0 -13
  260. data/examples/legacy/not_checked/simple/arc.rb +0 -23
  261. data/examples/legacy/not_checked/simple/bounce.rb +0 -24
  262. data/examples/legacy/not_checked/simple/chipmunk.rb +0 -26
  263. data/examples/legacy/not_checked/simple/curve.rb +0 -26
  264. data/examples/legacy/not_checked/simple/dialogs.rb +0 -29
  265. data/examples/legacy/not_checked/simple/downloader.rb +0 -40
  266. data/examples/legacy/not_checked/simple/draw.rb +0 -13
  267. data/examples/legacy/not_checked/simple/mask.rb +0 -21
  268. data/examples/legacy/not_checked/simple/slide.rb +0 -45
  269. data/examples/legacy/not_checked/simple/sphere.rb +0 -28
  270. data/lib/constants.rb +0 -5
  271. data/lib/scarpe/alert.rb +0 -19
  272. data/lib/scarpe/app.rb +0 -78
  273. data/lib/scarpe/arc.rb +0 -49
  274. data/lib/scarpe/button.rb +0 -35
  275. data/lib/scarpe/document_root.rb +0 -20
  276. data/lib/scarpe/edit_box.rb +0 -24
  277. data/lib/scarpe/fill.rb +0 -23
  278. data/lib/scarpe/flow.rb +0 -19
  279. data/lib/scarpe/line.rb +0 -25
  280. data/lib/scarpe/link.rb +0 -25
  281. data/lib/scarpe/list_box.rb +0 -25
  282. data/lib/scarpe/logger.rb +0 -155
  283. data/lib/scarpe/para.rb +0 -90
  284. data/lib/scarpe/shape.rb +0 -19
  285. data/lib/scarpe/spacing.rb +0 -9
  286. data/lib/scarpe/stack.rb +0 -70
  287. data/lib/scarpe/star.rb +0 -47
  288. data/lib/scarpe/text_widget.rb +0 -42
  289. data/lib/scarpe/unit_test_helpers.rb +0 -163
  290. data/lib/scarpe/widget.rb +0 -198
  291. data/lib/scarpe/widgets.rb +0 -30
  292. data/lib/scarpe/wv/alert.rb +0 -65
  293. data/lib/scarpe/wv/background.rb +0 -18
  294. data/lib/scarpe/wv/border.rb +0 -22
  295. data/lib/scarpe/wv/control_interface_test.rb +0 -253
  296. data/lib/scarpe/wv/dimensions.rb +0 -22
  297. data/lib/scarpe/wv/fill.rb +0 -30
  298. data/lib/scarpe/wv/html.rb +0 -107
  299. data/lib/scarpe/wv/shape_helper.rb +0 -44
  300. data/lib/scarpe/wv/spacing.rb +0 -41
  301. data/lib/scarpe/wv/text_widget.rb +0 -30
  302. data/lib/scarpe/wv/widget.rb +0 -181
  303. data/scarpe-0.2.0.gem +0 -0
  304. /data/examples/legacy/not_checked/{expert → shoes-contrib/basic}/definr.rb +0 -0
  305. /data/examples/legacy/not_checked/{expert → shoes-contrib/basic}/funnies.rb +0 -0
  306. /data/examples/legacy/not_checked/shoes-contrib/{elements → basic}/list_box-select-class.rb +0 -0
  307. /data/examples/legacy/{not_checked/shoes-contrib/basic → working/simple}/basic-edit-box.rb +0 -0
  308. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/basic-fps.rb +0 -0
  309. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/border-cat.rb +0 -0
  310. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/check-mate.rb +0 -0
  311. /data/examples/legacy/{not_checked/shoes-contrib/manipulation → working/simple}/clear-slot.rb +0 -0
  312. /data/examples/legacy/{not_checked/shoes-contrib/basic → working/simple}/clock.rb +0 -0
  313. /data/examples/legacy/{not_checked/shoes-contrib/basic → working/simple}/gradient-shoes.rb +0 -0
  314. /data/examples/legacy/{not_checked/shoes-contrib/basic → working/simple}/list_box-shape-report.rb +0 -0
  315. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/list_box.rb +0 -0
  316. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/phat-button.rb +0 -0
  317. /data/examples/legacy/{not_checked/shoes-contrib → working}/simple/simple-calc.rb +0 -0
  318. /data/examples/legacy/{not_checked/shoes-contrib/position → working/simple}/stack-width.rb +0 -0
  319. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/width-introspec.rb +0 -0
  320. /data/{lib/scarpe → spikes}/glibui/README.md +0 -0
  321. /data/{lib/scarpe → spikes}/glibui/alert.rb +0 -0
  322. /data/{lib/scarpe → spikes}/glibui/app.rb +0 -0
  323. /data/{lib/scarpe → spikes}/glibui/background.rb +0 -0
  324. /data/{lib/scarpe → spikes}/glibui/border.rb +0 -0
  325. /data/{lib/scarpe → spikes}/glibui/button.rb +0 -0
  326. /data/{lib/scarpe → spikes}/glibui/dimensions.rb +0 -0
  327. /data/{lib/scarpe → spikes}/glibui/document_root.rb +0 -0
  328. /data/{lib/scarpe → spikes}/glibui/edit_box.rb +0 -0
  329. /data/{lib/scarpe → spikes}/glibui/edit_line.rb +0 -0
  330. /data/{lib/scarpe → spikes}/glibui/flow.rb +0 -0
  331. /data/{lib/scarpe → spikes}/glibui/html.rb +0 -0
  332. /data/{lib/scarpe → spikes}/glibui/image.rb +0 -0
  333. /data/{lib/scarpe → spikes}/glibui/link.rb +0 -0
  334. /data/{lib/scarpe → spikes}/glibui/local_display.rb +0 -0
  335. /data/{lib/scarpe → spikes}/glibui/para.rb +0 -0
  336. /data/{lib/scarpe → spikes}/glibui/spacing.rb +0 -0
  337. /data/{lib/scarpe → spikes}/glibui/stack.rb +0 -0
  338. /data/{lib/scarpe → spikes}/glibui/text_widget.rb +0 -0
  339. /data/{lib/scarpe → spikes}/libui/alert.rb +0 -0
  340. /data/{lib/scarpe → spikes}/libui/button.rb +0 -0
  341. /data/{lib/scarpe → spikes}/libui/colors.rb +0 -0
  342. /data/{lib/scarpe → spikes}/libui/core.rb +0 -0
  343. /data/{lib/scarpe → spikes}/libui/flow.rb +0 -0
  344. /data/{lib/scarpe → spikes}/libui/libui.rb +0 -0
  345. /data/{lib/scarpe → spikes}/libui/notepad.md +0 -0
  346. /data/{lib/scarpe → spikes}/libui/para.rb +0 -0
  347. /data/{lib/scarpe → spikes}/libui/stack.rb +0 -0
data/lib/scarpe.rb CHANGED
@@ -1,42 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "scarpe/logger"
4
-
5
- # This will never be triggered -- we use the (...) feature below, which means this
6
- # file won't even parse in old Rubies.
7
3
  if RUBY_VERSION[0..2] < "3.2"
8
- Scarpe::Logger.logger("Scarpe").error("Scarpe requires Ruby 3.2 or higher!")
4
+ Shoes::Log.logger("Scarpe").error("Scarpe requires Ruby 3.2 or higher!")
9
5
  exit(-1)
10
6
  end
11
7
 
12
- require "securerandom"
13
- require "json"
14
-
15
- require_relative "constants"
16
-
17
- class Scarpe::Error < StandardError; end
18
-
19
- require_relative "scarpe/version"
20
- require_relative "scarpe/promises"
21
- require_relative "scarpe/display_service"
22
- require_relative "scarpe/widgets"
23
-
24
- require "bloops"
8
+ require "shoes"
9
+ require "lacci/scarpe_core"
25
10
 
26
11
  d_s = ENV["SCARPE_DISPLAY_SERVICE"] || "wv_local"
27
12
  # This is require, not require_relative, to allow gems to supply a new display service
13
+ require "scarpe/errors"
28
14
  require "scarpe/#{d_s}"
29
-
30
- #Constants Module
31
- include Constants
32
-
33
- class Scarpe
34
- class << self
35
- def app(...)
36
- app = Scarpe::App.new(...)
37
- app.init
38
- app.run
39
- app.destroy
40
- end
41
- end
42
- end
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "default": "warn",
3
- "WV::WebWrangler": ["debug", "logger/web_wrangler.log"]
3
+ "Webview::WebWrangler": ["debug", "logger/web_wrangler.log"]
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "default": ["debug", "logger/test_failure.log"],
3
- "WebviewAPI": ["debug", "logger/test_failure_wv_api.log"]
3
+ "Webview::API": ["debug", "logger/test_failure_wv_api.log"]
4
4
  }
@@ -0,0 +1 @@
1
+ scarpe-components-*.gem
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
6
+
7
+ gem "lacci", path: "../lacci"
8
+
9
+ gem "rake", "~> 13.0"
10
+
11
+ gem "nokogiri"
12
+
13
+ group :test do
14
+ gem "minitest", "~> 5.0"
15
+ gem "minitest-reporters"
16
+ end
17
+
18
+ group :development do
19
+ gem "debug"
20
+ gem "rubocop", "~> 1.21"
21
+ gem "rubocop-shopify"
22
+ end
@@ -0,0 +1,86 @@
1
+ PATH
2
+ remote: ../lacci
3
+ specs:
4
+ lacci (0.3.0)
5
+ scarpe-components
6
+
7
+ PATH
8
+ remote: .
9
+ specs:
10
+ scarpe-components (0.3.0)
11
+
12
+ GEM
13
+ remote: https://rubygems.org/
14
+ specs:
15
+ ansi (1.5.0)
16
+ ast (2.4.2)
17
+ base64 (0.1.1)
18
+ builder (3.2.4)
19
+ debug (1.8.0)
20
+ irb (>= 1.5.0)
21
+ reline (>= 0.3.1)
22
+ io-console (0.6.0)
23
+ irb (1.8.0)
24
+ rdoc (~> 6.5)
25
+ reline (>= 0.3.6)
26
+ json (2.6.3)
27
+ language_server-protocol (3.17.0.3)
28
+ minitest (5.19.0)
29
+ minitest-reporters (1.6.1)
30
+ ansi
31
+ builder
32
+ minitest (>= 5.0)
33
+ ruby-progressbar
34
+ nokogiri (1.15.4-x86_64-darwin)
35
+ racc (~> 1.4)
36
+ parallel (1.23.0)
37
+ parser (3.2.2.3)
38
+ ast (~> 2.4.1)
39
+ racc
40
+ psych (5.1.0)
41
+ stringio
42
+ racc (1.7.1)
43
+ rainbow (3.1.1)
44
+ rake (13.0.6)
45
+ rdoc (6.5.0)
46
+ psych (>= 4.0.0)
47
+ regexp_parser (2.8.1)
48
+ reline (0.3.8)
49
+ io-console (~> 0.5)
50
+ rexml (3.2.6)
51
+ rubocop (1.56.2)
52
+ base64 (~> 0.1.1)
53
+ json (~> 2.3)
54
+ language_server-protocol (>= 3.17.0)
55
+ parallel (~> 1.10)
56
+ parser (>= 3.2.2.3)
57
+ rainbow (>= 2.2.2, < 4.0)
58
+ regexp_parser (>= 1.8, < 3.0)
59
+ rexml (>= 3.2.5, < 4.0)
60
+ rubocop-ast (>= 1.28.1, < 2.0)
61
+ ruby-progressbar (~> 1.7)
62
+ unicode-display_width (>= 2.4.0, < 3.0)
63
+ rubocop-ast (1.29.0)
64
+ parser (>= 3.2.1.0)
65
+ rubocop-shopify (2.14.0)
66
+ rubocop (~> 1.51)
67
+ ruby-progressbar (1.13.0)
68
+ stringio (3.0.8)
69
+ unicode-display_width (2.4.2)
70
+
71
+ PLATFORMS
72
+ x86_64-darwin-22
73
+
74
+ DEPENDENCIES
75
+ debug
76
+ lacci!
77
+ minitest (~> 5.0)
78
+ minitest-reporters
79
+ nokogiri
80
+ rake (~> 13.0)
81
+ rubocop (~> 1.21)
82
+ rubocop-shopify
83
+ scarpe-components!
84
+
85
+ BUNDLED WITH
86
+ 2.4.14
@@ -0,0 +1,35 @@
1
+ # Scarpe-Components
2
+
3
+ Scarpe is several things. We package up the Shoes API with as few implementation details as possible (called Lacci.) We have a Webview-based display library, in both local and over-a-socket (relay) versions. We have a Wasm display library (Scarpe-Wasm) in a separate gem.
4
+
5
+ And we have various default implementations of different reusable components. Scarpe's hierarchical logger isn't particularly specific to your display library or underlying GUI library, but we'd like it to be usable by multiple display libs. CatsCradle is only useful if you're trying to fix up an impedance mismatch between Ruby and an evented under-layer, but it's not really specific to Webview. Scarpe's default downloader, using Ruby's built-in HTTP libraries, is good in many cases but you might want to replace it (e.g. with Typhoeus for better parallel downloads or Hystrix for robustness to bad network connections) in some cases.
6
+
7
+ Part of our solution is the Scarpe-Components gem, which lives in the same repository as Scarpe (for now?). These components can live there. Any specific display library can pick and choose what it wants or needs and handle its dependencies as it sees fit.
8
+
9
+ ## Dependency Hell
10
+
11
+ A "gem full of optional reusable components" presents an awkward challenge for Rubygems. What are the gem's dependencies? Do you make it depend on every possible library, requiring FastImage and Nokogiri and SQLite and whatever else any component might ever require? That would be as bad as making ActiveRecord need MySQL and SQLite and Postgres and Oracle and... But if you don't give it *any* dependencies, you're going to have a harsh surprise at runtime when Bundler can't find any of the gems you need.
12
+
13
+ You can break everything up into tiny pieces, like ActiveRecord having a separate adapter for certain databases. You could do the same with an activerecord-mysql and activerecord-postgres and activerecord-sqlite gem to complete the set. Or, like, ActiveRecord, you can say "declare activerecord as a dependency, and also one or more other database gems, and we'll figure out what's available at runtime." That approach can be pretty fragile and it adds extra complexity -- how do you make sure everything is required at the right time and ActiveRecord can find everything that's available? How do you balance gem dependencies that are built into ActiveRecord with those for unusual databases that get added by other gems, later? Your plugin system (like ActiveRecord's) can get extensive and fragile.
14
+
15
+ Scarpe-Components kicks that problem down the road to the display libraries. Would a particular display library like to use the FastImage-based image implementation? Great! It can declare a dependency on the FastImage gem. Would it like to optionally allow the built-in Ruby downloader, but also have an optional robustified version using RestClient? Lovely. It can either create multiple gems (e.g. scarpe-gtk-rcdownload and scarpe-gtk-plaindownload) or look for RestClient being available at runtime, as it pleases. The FastImage implementation lives in Scarpe-Components, but the dependency is declared by the display library or the app.
16
+
17
+ ## Using an Implementation
18
+
19
+ Components in Scarpe-Components are designed to be used individually. They can require each other, but they should only require components they will actually use. The whole library is designed to be used a la carte, and normally no display service will use every component.
20
+
21
+ A display library will declare scarpe-components as a dependency. Then, usually from its named require file (e.g. wv_local.rb, wv_relay.rb, wasm_local.rb) it will set up those dependencies by requiring components that it wants and if necessary creating and configuring them. That way a specific display service (e.g. wv_local) can require a specific component (e.g. Logging-gem-based hierarchical logging) and configure it how it wants (e.g. ENV var pointing to a local JSON config file.)
22
+
23
+ ## How is this Different from Lacci?
24
+
25
+ Scarpe already has a gem full of reusable components, one that every Scarpe-based application already has to use. Lacci declares the Shoes API, and is 100% required for every Scarpe-based Shoes application everywhere.
26
+
27
+ So how do you tell what goes into Scarpe-Components vs what goes into Lacci?
28
+
29
+ Lacci is, at heart, an API with as little implementation as possible. It declares the Shoes GUI objects, but not how to display them. Ordinarily a Shoes application will require (in the sense of Kernel#require) every part of Lacci -- it will load the entire library. Even if we add optional components (e.g. a Lacci-based Bloops API with no implementation behind it), those components will be loaded by every Shoes app that uses that part of the API.
30
+
31
+ As a result, Lacci should have minimal (preferably zero) dependencies. Any code doing "real work" should be removed from Lacci completely, as soon as possible. Since *every* Shoes app is going to require Lacci, it should be possible to use it with essentially no dependencies, minimal memory footprint, minimal load time. It is a skeleton to hang functionality on, not a thing that functions for itself.
32
+
33
+ Scarpe-Components is a grab bag of default implementations, intended to be replaceable. But each of them does something. Most of them have dependencies. It's fine for a Scarpe-Component implementation to depend on the Logging gem, provided it says it does. Nokogiri? 100% fair. Does it do something with a nontrivial amount of computation, like rendering HTML output? No problem. This is very different from Lacci.
34
+
35
+ If a component should be reused, it's probably fine to put it into Scarpe-Components. It *might* be fine to put it in Lacci. For Scarpe-Components, ask yourself, "will more than one Scarpe display service possibly want to use this?" For Lacci, the test is more strict: "will *every* Scarpe display service want to use this? Does it have no dependencies at all, and do very little computation and take very little memory?"
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/test_*.rb"]
10
+ end
11
+
12
+ task default: [:test]
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "base64"
4
+ require "uri"
5
+
6
+ module Scarpe; end
7
+ module Scarpe::Components; end
8
+ module Scarpe
9
+ module Components::Base64
10
+ def valid_url?(string)
11
+ uri = URI.parse(string)
12
+ uri.is_a?(URI::HTTP) || uri.is_a?(URI::HTTPS)
13
+ rescue URI::InvalidURIError, URI::BadURIError
14
+ false
15
+ end
16
+
17
+ def encode_file_to_base64(image_path)
18
+ image_data = File.binread(image_path)
19
+
20
+ encoded_data = ::Base64.strict_encode64(image_data)
21
+
22
+ encoded_data
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Scarpe::Components::Calzini
4
+ def alert_element(props)
5
+ event = props["event_name"] || "click"
6
+ onclick = handler_js_code(event)
7
+
8
+ HTML.render do |h|
9
+ h.div(id: html_id, style: alert_overlay_style(props)) do
10
+ h.div(style: alert_modal_style) do
11
+ h.div(style: {}) { props["text"] }
12
+ h.button(style: {}, onclick: onclick) { "OK" }
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ # If the whole drawable is hidden, the parent style adds display:none
21
+ def alert_overlay_style(props)
22
+ {
23
+ position: "fixed",
24
+ top: "0",
25
+ left: "0",
26
+ width: "100%",
27
+ height: "100%",
28
+ overflow: "auto",
29
+ "z-index": "1",
30
+ background: "rgba(0,0,0,0.4)",
31
+ display: "flex",
32
+ "align-items": "center",
33
+ "justify-content": "center",
34
+ }.merge(drawable_style(props))
35
+ end
36
+
37
+ def alert_modal_style
38
+ {
39
+ "min-width": "200px",
40
+ "min-height": "50px",
41
+ padding: "10px",
42
+ display: "flex",
43
+ background: "#fefefe",
44
+ "flex-direction": "column",
45
+ "justify-content": "space-between",
46
+ "border-radius": "9px",
47
+ }
48
+ end
49
+ end
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Scarpe::Components::Calzini
4
+ def arc_element(props, &block)
5
+ dc = props["draw_context"] || {}
6
+ rotate = dc["rotate"]
7
+ HTML.render do |h|
8
+ h.div(id: html_id, style: arc_style(props)) do
9
+ h.svg(width: props["width"], height: props["height"]) do
10
+ h.path(d: arc_path(props), transform: "rotate(#{rotate}, #{props["width"] / 2}, #{props["height"] / 2})")
11
+ end
12
+ block.call(h) if block_given?
13
+ end
14
+ end
15
+ end
16
+
17
+ def rect_element(props)
18
+ dc = props["draw_context"] || {}
19
+ rotate = dc["rotate"]
20
+ HTML.render do |h|
21
+ h.div(id: html_id, style: drawable_style(props)) do
22
+ width = props["width"].to_i
23
+ height = props["height"].to_i
24
+ if props["curve"]
25
+ width += 2 * props["curve"].to_i
26
+ height += 2 * props["curve"].to_i
27
+ end
28
+ h.svg(width:, height:) do
29
+ attrs = { x: props["left"], y: props["top"], width: props["width"], height: props["height"], style: rect_svg_style(props) }
30
+ attrs[:rx] = props["curve"] if props["curve"]
31
+
32
+ h.rect(**attrs, transform: "rotate(#{rotate} #{width / 2} #{height / 2})")
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ def line_element(props)
39
+ HTML.render do |h|
40
+ h.div(id: html_id, style: line_div_style(props)) do
41
+ h.svg(width: props["x2"], height: props["y2"]) do
42
+ h.line(x1: props["left"], y1: props["top"], x2: props["x2"], y2: props["y2"], style: line_svg_style(props))
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ def star_element(props, &block)
49
+ dc = props["draw_context"] || {}
50
+ fill = dc["fill"]
51
+ stroke = dc["stroke"]
52
+ fill = "black" if !fill || fill == ""
53
+ stroke = "black" if !stroke || stroke == ""
54
+ HTML.render do |h|
55
+ h.div(id: html_id, style: star_style(props)) do
56
+ h.svg(width: props["outer"], height: props["outer"], style: "fill:#{fill}") do
57
+ h.polygon(points: star_points(props), style: "stroke:#{stroke};stroke-width:2")
58
+ end
59
+ block.call(h) if block_given?
60
+ end
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def arc_style(props)
67
+ drawable_style(props).merge({
68
+ left: "#{props["left"]}px",
69
+ top: "#{props["top"]}px",
70
+ width: "#{props["width"]}px",
71
+ height: "#{props["height"]}px",
72
+ })
73
+ end
74
+
75
+ def arc_path(props)
76
+ center_x = props["width"] / 2
77
+ center_y = props["height"] / 2
78
+ radius_x = props["width"] / 2
79
+ radius_y = props["height"] / 2
80
+ start_angle_degrees = radians_to_degrees(props["angle1"]) % 360
81
+ end_angle_degrees = radians_to_degrees(props["angle2"]) % 360
82
+ large_arc_flag = (end_angle_degrees - start_angle_degrees) % 360 > 180 ? 1 : 0
83
+
84
+ "M#{center_x} #{center_y} L#{props["width"]} #{center_y} " \
85
+ "A#{radius_x} #{radius_y} 0 #{large_arc_flag} 0 " \
86
+ "#{center_x + radius_x * Math.cos(degrees_to_radians(end_angle_degrees))} " \
87
+ "#{center_y + radius_y * Math.sin(degrees_to_radians(end_angle_degrees))} Z"
88
+ end
89
+
90
+ def line_div_style(props)
91
+ drawable_style(props).merge({
92
+ left: "#{props["left"]}px",
93
+ top: "#{props["top"]}px",
94
+ })
95
+ end
96
+
97
+ def line_svg_style(props)
98
+ stroke = if props["draw_context"] && !props["draw_context"]["stroke"].to_s.empty?
99
+ (props["draw_context"]["stroke"]).to_s
100
+ else
101
+ "black"
102
+ end
103
+ {
104
+
105
+ "stroke": stroke,
106
+ "stroke-width": "4",
107
+ }.compact
108
+ end
109
+
110
+ def rect_svg_style(props)
111
+ {
112
+ stroke: (props["draw_context"] || {})["stroke"],
113
+ #"stroke-width": "1",
114
+ }.compact
115
+ end
116
+
117
+ def star_style(props)
118
+ drawable_style(props).merge({
119
+ width: dimensions_length(props["width"]),
120
+ height: dimensions_length(props["height"]),
121
+ }).compact
122
+ end
123
+
124
+ def star_points(props)
125
+ angle = 2 * Math::PI / props["points"]
126
+ coordinates = []
127
+
128
+ props["points"].times do |i|
129
+ outer_angle = i * angle
130
+ inner_angle = outer_angle + angle / 2
131
+
132
+ coordinates.concat(star_get_coordinates(outer_angle, inner_angle, props))
133
+ end
134
+
135
+ coordinates.join(",")
136
+ end
137
+
138
+ def star_get_coordinates(outer_angle, inner_angle, props)
139
+ outer_x = props["outer"] / 2 + Math.cos(outer_angle) * props["outer"] / 2
140
+ outer_y = props["outer"] / 2 + Math.sin(outer_angle) * props["outer"] / 2
141
+
142
+ inner_x = props["outer"] / 2 + Math.cos(inner_angle) * props["inner"] / 2
143
+ inner_y = props["outer"] / 2 + Math.sin(inner_angle) * props["inner"] / 2
144
+
145
+ [outer_x, outer_y, inner_x, inner_y]
146
+ end
147
+
148
+ def arrow_element(props)
149
+ left = props["left"]
150
+ top = props["top"]
151
+ width = props["width"]
152
+ end_x = left + width
153
+ end_y = top
154
+ stroke_width = width / 2
155
+ dc = props["draw_context"] || {}
156
+ fill = dc["fill"]
157
+ stroke = dc["stroke"]
158
+ rotate = dc["rotate"]
159
+ fill = "black" if !fill || fill == ""
160
+ stroke = "black" if !stroke || stroke == ""
161
+
162
+ stroke_width = width / 4
163
+
164
+ HTML.render do |h|
165
+ h.div(id: html_id, style: arrow_div_style(props)) do
166
+ h.svg do
167
+ h.defs do
168
+ h.marker(
169
+ id: "head",
170
+ viewBox: "0 0 70 70",
171
+ markerWidth: stroke_width.to_s,
172
+ markerHeight: stroke_width.to_s,
173
+ refX: "5",
174
+ refY: "5",
175
+ orient: "auto-start-reverse",
176
+ ) do
177
+ h.path(d: "M 0 0 L 10 5 L 0 10 z", fill: fill.to_s)
178
+ end
179
+ end
180
+
181
+ h.line(
182
+ x2: left.to_s,
183
+ y2: top.to_s,
184
+ x1: end_x.to_s,
185
+ y1: end_y.to_s,
186
+ fill: fill.to_s,
187
+ stroke: stroke.to_s,
188
+ "stroke-width" => stroke_width.to_s,
189
+ "marker-end" => "url(#head)",
190
+ transform: "rotate(#{rotate}, #{left + width / 2}, #{top})",
191
+ )
192
+ end
193
+ end
194
+ end
195
+ end
196
+ def arrow_div_style(props)
197
+ drawable_style(props).merge({
198
+ position: "absolute",
199
+ left: "#{props["left"]}px",
200
+ top: "#{props["top"]}px",
201
+ })
202
+ end
203
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Scarpe::Components::Calzini
4
+ def button_element(props)
5
+ HTML.render do |h|
6
+ h.button(
7
+ id: html_id,
8
+ onclick: handler_js_code("click"),
9
+ onmouseover: handler_js_code("hover"),
10
+ style: button_style(props),
11
+ title: props["tooltip"],
12
+ ) do
13
+ props["text"]
14
+ end
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def button_style(props)
21
+ styles = drawable_style(props)
22
+
23
+ styles[:"background-color"] = props["color"] if props["color"]
24
+ styles[:"padding-top"] = props["padding_top"] if props["padding_top"]
25
+ styles[:"padding-bottom"] = props["padding_bottom"] if props["padding_bottom"]
26
+ styles[:color] = props["text_color"] if props["text_color"]
27
+ styles[:width] = dimensions_length(props["width"]) if props["width"]
28
+ styles[:height] = dimensions_length(props["height"]) if props["height"]
29
+ styles[:"font-size"] = props["font_size"] if props["font_size"]
30
+
31
+ styles[:top] = dimensions_length(props["top"]) if props["top"]
32
+ styles[:left] = dimensions_length(props["left"]) if props["left"]
33
+ styles[:position] = "absolute" if props["top"] || props["left"]
34
+ styles[:"font-size"] = dimensions_length(text_size(props["size"])) if props["size"]
35
+ styles[:"font-family"] = props["font"] if props["font"]
36
+
37
+ styles
38
+ end
39
+ end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Scarpe::Components::Calzini
4
+ def check_element(props)
5
+ HTML.render do |h|
6
+ h.input type: :checkbox,
7
+ id: html_id,
8
+ onclick: handler_js_code("click"),
9
+ value: props["text"],
10
+ checked: props["checked"],
11
+ style: drawable_style(props)
12
+ end
13
+ end
14
+
15
+ def edit_box_element(props)
16
+ oninput = handler_js_code("change", "this.value")
17
+
18
+ HTML.render do |h|
19
+ h.textarea(id: html_id, oninput: oninput, style: edit_box_style(props)) { props["text"] }
20
+ end
21
+ end
22
+
23
+ def edit_line_element(props)
24
+ oninput = handler_js_code("change", "this.value")
25
+
26
+ HTML.render do |h|
27
+ h.input(id: html_id, oninput: oninput, value: props["text"], style: edit_line_style(props))
28
+ end
29
+ end
30
+
31
+ def image_element(props)
32
+ style = image_style(props)
33
+
34
+ if props["click"]
35
+ HTML.render do |h|
36
+ h.a(id: html_id, href: props["click"]) { h.img(id: html_id, src: props["url"], style:) }
37
+ end
38
+ else
39
+ HTML.render do |h|
40
+ h.img(id: html_id, src: props["url"], style:)
41
+ end
42
+ end
43
+ end
44
+
45
+ def list_box_element(props)
46
+ onchange = handler_js_code("change", "this.options[this.selectedIndex].value")
47
+
48
+ # Is this useful at all? Is it overridden below completely?
49
+ option_attrs = { value: nil, selected: false }
50
+
51
+ HTML.render do |h|
52
+ h.select(id: html_id, onchange:, style: list_box_style(props)) do
53
+ (props["items"] || []).each do |item|
54
+ option_attrs = {
55
+ value: item,
56
+ }
57
+ if item == props["choose"]
58
+ option_attrs[:selected] = "true"
59
+ end
60
+ h.option(**option_attrs) do
61
+ item
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ def radio_element(props)
69
+ # This is wrong - need to default to the parent slot -- maybe its linkable ID?
70
+ group_name = props["group"] || "no_group"
71
+
72
+ HTML.render do |h|
73
+ h.input(
74
+ type: :radio,
75
+ id: html_id,
76
+ onclick: handler_js_code("click"),
77
+ name: group_name,
78
+ value: props["text"],
79
+ checked: props["checked"],
80
+ style: drawable_style(props),
81
+ )
82
+ end
83
+ end
84
+
85
+ def video_element(props)
86
+ HTML.render do |h|
87
+ h.video(id: html_id, style: drawable_style(props), controls: true) do
88
+ h.source(src: @url, type: props["format"])
89
+ end
90
+ end
91
+ end
92
+
93
+ def progress_element(props)
94
+ HTML.render do |h|
95
+ h.progress(
96
+ id: html_id,
97
+ style: drawable_style(props),
98
+ role: "progressbar",
99
+ "aria-valuenow": props["fraction"],
100
+ "aria-valuemin": 0.0,
101
+ "aria-valuemax": 1.0,
102
+ max: 1,
103
+ value: props["fraction"],
104
+ )
105
+ end
106
+ end
107
+
108
+ private
109
+
110
+ def edit_box_style(props)
111
+ drawable_style(props).merge({
112
+ height: dimensions_length(props["height"]),
113
+ width: dimensions_length(props["width"]),
114
+ }.compact)
115
+ end
116
+
117
+ def edit_line_style(props)
118
+ styles = drawable_style(props)
119
+
120
+ styles[:width] = dimensions_length(props["width"]) if props["width"]
121
+
122
+ styles
123
+ end
124
+
125
+ def image_style(props)
126
+ styles = drawable_style(props)
127
+
128
+ styles[:width] = dimensions_length(props["width"]) if props["width"]
129
+ styles[:height] = dimensions_length(props["height"]) if props["height"]
130
+
131
+ styles[:top] = dimensions_length(props["top"]) if props["top"]
132
+ styles[:left] = dimensions_length(props["left"]) if props["left"]
133
+ styles[:position] = "absolute" if props["top"] || props["left"]
134
+
135
+ styles
136
+ end
137
+
138
+ def list_box_style(props)
139
+ styles = drawable_style(props)
140
+
141
+ styles[:height] = dimensions_length(props["height"]) if props["height"]
142
+ styles[:width] = dimensions_length(props["width"]) if props["width"]
143
+
144
+ styles
145
+ end
146
+ end