scarpe 0.2.2 → 0.4.0

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.
Files changed (378) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -1
  3. data/.yardopts +1 -0
  4. data/CHANGELOG.md +52 -6
  5. data/Gemfile +2 -1
  6. data/Gemfile.lock +20 -6
  7. data/LICENSE.txt +7 -1
  8. data/README.md +100 -21
  9. data/Rakefile +68 -1
  10. data/examples/Edit_box_Styles.rb +8 -0
  11. data/examples/Kerning.rb +7 -0
  12. data/examples/animate.rb +20 -0
  13. data/examples/arrow.rb +10 -0
  14. data/examples/border.rb +11 -0
  15. data/examples/btn_tooltip.rb +7 -0
  16. data/examples/button_style_changed.rb +7 -0
  17. data/examples/button_styles_default.rb +6 -0
  18. data/examples/check.rb +2 -0
  19. data/examples/download_and_show_image.rb +3 -0
  20. data/examples/flags/finland.rb +15 -0
  21. data/examples/flags/italy.rb +11 -0
  22. data/examples/flags/mauritius.rb +14 -0
  23. data/examples/font_family.rb +17 -0
  24. data/examples/font_shorthand.rb +9 -0
  25. data/examples/gen.rb +12 -8
  26. data/examples/highlander.rb +3 -3
  27. data/examples/legacy/README.md +6 -0
  28. data/examples/legacy/not_checked/shoes-contrib/basic/shoes-notes.rb +1 -1
  29. data/examples/legacy/not_checked/shoes-manual/append.rb +10 -0
  30. data/examples/legacy/not_checked/shoes-manual/background_change.rb +12 -0
  31. data/examples/legacy/not_checked/shoes-manual/background_pattern.rb +5 -0
  32. data/examples/legacy/not_checked/shoes-manual/basic_app.rb +8 -0
  33. data/examples/legacy/not_checked/shoes-manual/border.rb +9 -0
  34. data/examples/legacy/not_checked/shoes-manual/builtins/FONTS.rb +5 -0
  35. data/examples/legacy/not_checked/shoes-manual/builtins/ask.rb +2 -0
  36. data/examples/legacy/not_checked/shoes-manual/builtins/ask_color.rb +5 -0
  37. data/examples/legacy/not_checked/shoes-manual/builtins/ask_open_file.rb +5 -0
  38. data/examples/legacy/not_checked/shoes-manual/builtins/ask_save_folder.rb +2 -0
  39. data/examples/legacy/not_checked/shoes-manual/builtins/confirm.rb +4 -0
  40. data/examples/legacy/not_checked/shoes-manual/builtins/debug.rb +2 -0
  41. data/examples/legacy/not_checked/shoes-manual/builtins/info.rb +3 -0
  42. data/examples/legacy/not_checked/shoes-manual/button.rb +9 -0
  43. data/examples/legacy/not_checked/shoes-manual/clear.rb +7 -0
  44. data/examples/legacy/not_checked/shoes-manual/custom_header.rb +13 -0
  45. data/examples/legacy/not_checked/shoes-manual/displace.rb +14 -0
  46. data/examples/legacy/not_checked/shoes-manual/edit_box.rb +8 -0
  47. data/examples/legacy/not_checked/shoes-manual/fill_pattern.rb +5 -0
  48. data/examples/legacy/not_checked/shoes-manual/fonts.rb +7 -0
  49. data/examples/legacy/not_checked/shoes-manual/gutter.rb +6 -0
  50. data/examples/legacy/not_checked/shoes-manual/image_web.rb +4 -0
  51. data/examples/legacy/not_checked/shoes-manual/keypress.rb +7 -0
  52. data/examples/legacy/not_checked/shoes-manual/list_box.rb +10 -0
  53. data/examples/legacy/not_checked/shoes-manual/motion.rb +10 -0
  54. data/examples/legacy/not_checked/shoes-manual/mouse.rb +8 -0
  55. data/examples/legacy/not_checked/shoes-manual/move.rb +14 -0
  56. data/examples/legacy/not_checked/shoes-manual/nested_ovals.rb +8 -0
  57. data/examples/legacy/not_checked/shoes-manual/oval.rb +7 -0
  58. data/examples/legacy/not_checked/shoes-manual/ovals.rb +6 -0
  59. data/examples/legacy/not_checked/shoes-manual/ovals_image.rb +8 -0
  60. data/examples/legacy/not_checked/shoes-manual/prepend.rb +7 -0
  61. data/examples/legacy/not_checked/shoes-manual/progress_bar.rb +10 -0
  62. data/examples/legacy/not_checked/shoes-manual/radio.rb +18 -0
  63. data/examples/legacy/not_checked/shoes-manual/radio_alternative_1.rb +7 -0
  64. data/examples/legacy/not_checked/shoes-manual/radio_alternative_2.rb +9 -0
  65. data/examples/legacy/not_checked/shoes-manual/rotate_rectangle.rb +6 -0
  66. data/examples/legacy/not_checked/shoes-manual/shape.rb +11 -0
  67. data/examples/legacy/not_checked/shoes-manual/static/avatar.png +0 -0
  68. data/examples/legacy/not_checked/shoes-manual/stroke.rb +5 -0
  69. data/examples/legacy/not_checked/shoes-manual/style.rb +3 -0
  70. data/examples/legacy/not_checked/shoes-manual/style_alternative_1.rb +4 -0
  71. data/examples/legacy/not_checked/shoes-manual/style_alternative_2.rb +5 -0
  72. data/examples/legacy/not_checked/shoes-manual/style_length.rb +5 -0
  73. data/examples/legacy/not_checked/shoes-manual/timer.rb +6 -0
  74. data/examples/legacy/not_checked/shoes-manual/trigger_window.rb +8 -0
  75. data/examples/legacy/not_checked/shoes-manual/window_owner.rb +8 -0
  76. data/examples/legacy/not_checked/simple/anim-shapes.rb +1 -1
  77. data/examples/legacy/not_checked/speedometer_app.rb +55 -0
  78. data/examples/legacy/working/shoes_manual/alert_button.rb +2 -0
  79. data/examples/legacy/working/shoes_manual/animate.rb +7 -0
  80. data/examples/legacy/working/shoes_manual/background_para.rb +4 -0
  81. data/examples/legacy/working/shoes_manual/button_alternative.rb +7 -0
  82. data/examples/legacy/working/shoes_manual/checkbox.rb +17 -0
  83. data/examples/legacy/working/shoes_manual/download.rb +12 -0
  84. data/examples/legacy/working/shoes_manual/edit_box.rb +6 -0
  85. data/examples/legacy/working/shoes_manual/editline.rb +7 -0
  86. data/examples/legacy/working/shoes_manual/fixed_height.rb +8 -0
  87. data/examples/legacy/working/shoes_manual/fixed_width.rb +12 -0
  88. data/examples/legacy/working/shoes_manual/image.rb +5 -0
  89. data/examples/legacy/working/shoes_manual/instance_variable_check.rb +10 -0
  90. data/examples/legacy/working/shoes_manual/message.rb +18 -0
  91. data/examples/legacy/working/shoes_manual/rectangle.rb +6 -0
  92. data/examples/legacy/working/shoes_manual/save_download.rb +12 -0
  93. data/examples/legacy/working/shoes_manual/self_check.rb +10 -0
  94. data/examples/legacy/working/shoes_manual/stack.rb +7 -0
  95. data/examples/legacy/working/shoes_manual/style_info.rb +8 -0
  96. data/examples/legacy/working/shoes_manual/utf8_support.rb +8 -0
  97. data/examples/legacy/working/shoes_manual/width.rb +4 -0
  98. data/examples/legacy/working/simple/image-icon.rb +3 -0
  99. data/examples/legacy/{not_checked → working}/simple/image.rb +1 -1
  100. data/examples/list_box_choose.rb +17 -0
  101. data/examples/local_assets/local_file_server.rb +82 -0
  102. data/examples/local_assets/multi_image.rb +5 -0
  103. data/examples/local_assets/sample.gif +0 -0
  104. data/examples/local_assets/sample.mp4 +0 -0
  105. data/examples/local_assets/small.png +0 -0
  106. data/examples/local_fonts.rb +5 -2
  107. data/examples/local_images.rb +2 -3
  108. data/examples/margin.rb +13 -0
  109. data/examples/margin_check.rb +27 -0
  110. data/examples/oval-with-kwargs.rb +3 -0
  111. data/examples/oval.rb +26 -0
  112. data/examples/para/para_text.rb +14 -0
  113. data/examples/para_font_styles.rb +17 -0
  114. data/examples/para_font_variant.rb +6 -0
  115. data/examples/para_fontweight.rb +13 -0
  116. data/examples/parse_xl_funnies.rb +3 -0
  117. data/examples/progress.rb +31 -0
  118. data/examples/radio/radio_groups.rb +2 -2
  119. data/examples/rect.rb +4 -0
  120. data/examples/rotate_shapes.rb +17 -0
  121. data/examples/scarpe_ext.rb +3 -0
  122. data/examples/shapes/star.rb +1 -3
  123. data/examples/simpler-menu.rb +21 -0
  124. data/examples/spacing.rb +1 -1
  125. data/examples/span.rb +4 -2
  126. data/exe/scarpe +2 -1
  127. data/lacci/Gemfile +2 -0
  128. data/lacci/Gemfile.lock +8 -1
  129. data/lacci/lacci.gemspec +2 -2
  130. data/lacci/lib/lacci/scarpe_cli.rb +2 -2
  131. data/lacci/lib/lacci/scarpe_core.rb +2 -1
  132. data/lacci/lib/lacci/version.rb +1 -1
  133. data/lacci/lib/scarpe/niente/app.rb +23 -0
  134. data/lacci/lib/scarpe/niente/display_service.rb +66 -0
  135. data/lacci/lib/scarpe/niente/drawable.rb +59 -0
  136. data/lacci/lib/scarpe/niente/shoes_spec.rb +93 -0
  137. data/lacci/lib/scarpe/niente.rb +32 -0
  138. data/lacci/lib/shoes/app.rb +111 -72
  139. data/lacci/lib/shoes/background.rb +2 -2
  140. data/lacci/lib/shoes/border.rb +2 -2
  141. data/lacci/lib/shoes/builtins.rb +63 -0
  142. data/lacci/lib/shoes/changelog.rb +52 -0
  143. data/lacci/lib/shoes/colors.rb +3 -1
  144. data/lacci/lib/shoes/constants.rb +41 -2
  145. data/lacci/lib/shoes/display_service.rb +80 -18
  146. data/lacci/lib/shoes/download.rb +2 -2
  147. data/lacci/lib/shoes/drawable.rb +654 -0
  148. data/lacci/lib/shoes/drawables/arc.rb +27 -0
  149. data/lacci/lib/shoes/drawables/arrow.rb +21 -0
  150. data/lacci/lib/shoes/drawables/border.rb +28 -0
  151. data/lacci/lib/shoes/drawables/button.rb +57 -0
  152. data/lacci/lib/shoes/drawables/check.rb +33 -0
  153. data/lacci/lib/shoes/drawables/document_root.rb +20 -0
  154. data/lacci/lib/shoes/{widgets → drawables}/edit_box.rb +9 -8
  155. data/lacci/lib/shoes/{widgets → drawables}/edit_line.rb +8 -7
  156. data/lacci/lib/shoes/drawables/flow.rb +20 -0
  157. data/lacci/lib/shoes/drawables/font_helper.rb +62 -0
  158. data/lacci/lib/shoes/{widgets → drawables}/image.rb +7 -7
  159. data/lacci/lib/shoes/drawables/line.rb +17 -0
  160. data/lacci/lib/shoes/drawables/link.rb +31 -0
  161. data/lacci/lib/shoes/drawables/list_box.rb +59 -0
  162. data/lacci/lib/shoes/drawables/oval.rb +48 -0
  163. data/lacci/lib/shoes/drawables/para.rb +206 -0
  164. data/lacci/lib/shoes/drawables/progress.rb +15 -0
  165. data/lacci/lib/shoes/drawables/radio.rb +35 -0
  166. data/lacci/lib/shoes/drawables/rect.rb +18 -0
  167. data/lacci/lib/shoes/{widgets → drawables}/shape.rb +8 -8
  168. data/lacci/lib/shoes/drawables/slot.rb +178 -0
  169. data/lacci/lib/shoes/drawables/stack.rb +21 -0
  170. data/lacci/lib/shoes/drawables/star.rb +28 -0
  171. data/lacci/lib/shoes/drawables/subscription_item.rb +93 -0
  172. data/lacci/lib/shoes/drawables/text_drawable.rb +122 -0
  173. data/lacci/lib/shoes/drawables/video.rb +17 -0
  174. data/lacci/lib/shoes/drawables/widget.rb +74 -0
  175. data/lacci/lib/shoes/drawables.rb +32 -0
  176. data/lacci/lib/shoes/errors.rb +38 -0
  177. data/lacci/lib/shoes/log.rb +2 -2
  178. data/lacci/lib/shoes/margin_helper.rb +79 -0
  179. data/lacci/lib/shoes/ruby_extensions.rb +15 -0
  180. data/lacci/lib/shoes-spec.rb +93 -0
  181. data/lacci/lib/shoes.rb +31 -10
  182. data/lacci/test/.gitignore +1 -0
  183. data/lacci/test/test_draw_context.rb +167 -0
  184. data/lacci/test/test_font_helper.rb +57 -0
  185. data/lacci/test/test_helper.rb +81 -0
  186. data/lacci/test/test_lacci.rb +99 -3
  187. data/lacci/test/test_margin_helper.rb +82 -0
  188. data/lacci/test/test_niente_test_infra.rb +26 -0
  189. data/lacci/test/test_oval.rb +82 -0
  190. data/lacci/test/test_parenting.rb +140 -0
  191. data/lacci/test/test_shoes_errors.rb +49 -0
  192. data/lacci/test/test_text_drawables.rb +23 -0
  193. data/lib/scarpe/assets.rb +18 -0
  194. data/lib/scarpe/cats_cradle.rb +84 -103
  195. data/lib/scarpe/errors.rb +77 -0
  196. data/lib/scarpe/shoes_spec.rb +160 -0
  197. data/lib/scarpe/version.rb +2 -2
  198. data/lib/scarpe/wv/app.rb +21 -20
  199. data/lib/scarpe/wv/arc.rb +4 -51
  200. data/lib/scarpe/wv/arrow.rb +9 -0
  201. data/lib/scarpe/wv/border.rb +9 -18
  202. data/lib/scarpe/wv/button.rb +7 -35
  203. data/lib/scarpe/wv/check.rb +3 -5
  204. data/lib/scarpe/wv/control_interface.rb +20 -30
  205. data/lib/scarpe/wv/document_root.rb +81 -4
  206. data/lib/scarpe/wv/{widget.rb → drawable.rb} +71 -82
  207. data/lib/scarpe/wv/edit_box.rb +8 -18
  208. data/lib/scarpe/wv/edit_line.rb +9 -20
  209. data/lib/scarpe/wv/flow.rb +2 -18
  210. data/lib/scarpe/wv/image.rb +7 -30
  211. data/lib/scarpe/wv/line.rb +3 -25
  212. data/lib/scarpe/wv/link.rb +6 -17
  213. data/lib/scarpe/wv/list_box.rb +6 -29
  214. data/lib/scarpe/wv/oval.rb +13 -0
  215. data/lib/scarpe/wv/para.rb +12 -30
  216. data/lib/scarpe/wv/progress.rb +19 -0
  217. data/lib/scarpe/wv/radio.rb +9 -10
  218. data/lib/scarpe/wv/rect.rb +13 -0
  219. data/lib/scarpe/wv/scarpe_extensions.rb +8 -0
  220. data/lib/scarpe/wv/shape.rb +13 -13
  221. data/lib/scarpe/wv/slot.rb +8 -25
  222. data/lib/scarpe/wv/stack.rb +2 -18
  223. data/lib/scarpe/wv/star.rb +3 -53
  224. data/lib/scarpe/wv/subscription_item.rb +38 -4
  225. data/lib/scarpe/wv/text_drawable.rb +90 -0
  226. data/lib/scarpe/wv/video.rb +15 -15
  227. data/lib/scarpe/wv/web_wrangler.rb +320 -328
  228. data/lib/scarpe/wv/webview_local_display.rb +52 -33
  229. data/lib/scarpe/wv/webview_relay_display.rb +12 -12
  230. data/lib/scarpe/wv/webview_relay_util.rb +7 -10
  231. data/lib/scarpe/wv/wv_display_worker.rb +2 -2
  232. data/lib/scarpe/wv.rb +52 -12
  233. data/lib/scarpe/wv_local.rb +1 -1
  234. data/lib/scarpe/wv_relay.rb +1 -1
  235. data/lib/scarpe.rb +1 -0
  236. data/logger/debug_web_wrangler.json +1 -1
  237. data/logger/scarpe_wv_test.json +1 -1
  238. data/scarpe-components/Gemfile +4 -1
  239. data/scarpe-components/Gemfile.lock +85 -0
  240. data/scarpe-components/README.md +2 -2
  241. data/scarpe-components/assets/bootstrap-themes/bootstrap-cerulean.css +12229 -0
  242. data/scarpe-components/assets/bootstrap-themes/bootstrap-cosmo.css +11810 -0
  243. data/scarpe-components/assets/bootstrap-themes/bootstrap-cyborg.css +12210 -0
  244. data/scarpe-components/assets/bootstrap-themes/bootstrap-darkly.css +12153 -0
  245. data/scarpe-components/assets/bootstrap-themes/bootstrap-flatly.css +12126 -0
  246. data/scarpe-components/assets/bootstrap-themes/bootstrap-icons.min.css +5 -0
  247. data/scarpe-components/assets/bootstrap-themes/bootstrap-journal.css +12099 -0
  248. data/scarpe-components/assets/bootstrap-themes/bootstrap-litera.css +12211 -0
  249. data/scarpe-components/assets/bootstrap-themes/bootstrap-lumen.css +12369 -0
  250. data/scarpe-components/assets/bootstrap-themes/bootstrap-lux.css +11928 -0
  251. data/scarpe-components/assets/bootstrap-themes/bootstrap-materia.css +13184 -0
  252. data/scarpe-components/assets/bootstrap-themes/bootstrap-minty.css +12177 -0
  253. data/scarpe-components/assets/bootstrap-themes/bootstrap-morph.css +12750 -0
  254. data/scarpe-components/assets/bootstrap-themes/bootstrap-pulse.css +11890 -0
  255. data/scarpe-components/assets/bootstrap-themes/bootstrap-quartz.css +12622 -0
  256. data/scarpe-components/assets/bootstrap-themes/bootstrap-sandstone.css +12201 -0
  257. data/scarpe-components/assets/bootstrap-themes/bootstrap-simplex.css +12186 -0
  258. data/scarpe-components/assets/bootstrap-themes/bootstrap-sketchy.css +12451 -0
  259. data/scarpe-components/assets/bootstrap-themes/bootstrap-slate.css +12492 -0
  260. data/scarpe-components/assets/bootstrap-themes/bootstrap-solar.css +12149 -0
  261. data/scarpe-components/assets/bootstrap-themes/bootstrap-spacelab.css +12266 -0
  262. data/scarpe-components/assets/bootstrap-themes/bootstrap-superhero.css +12216 -0
  263. data/scarpe-components/assets/bootstrap-themes/bootstrap-united.css +12077 -0
  264. data/scarpe-components/assets/bootstrap-themes/bootstrap-vapor.css +12549 -0
  265. data/scarpe-components/assets/bootstrap-themes/bootstrap-yeti.css +12325 -0
  266. data/scarpe-components/assets/bootstrap-themes/bootstrap-zephyr.css +12283 -0
  267. data/scarpe-components/assets/bootstrap-themes/bootstrap.bundle.min.js +7 -0
  268. data/scarpe-components/lib/scarpe/components/asset_server.rb +219 -0
  269. data/scarpe-components/lib/scarpe/components/base64.rb +23 -5
  270. data/scarpe-components/lib/scarpe/components/calzini/alert.rb +49 -0
  271. data/scarpe-components/lib/scarpe/components/calzini/art_drawables.rb +227 -0
  272. data/scarpe-components/lib/scarpe/components/calzini/border.rb +38 -0
  273. data/scarpe-components/lib/scarpe/components/calzini/button.rb +37 -0
  274. data/scarpe-components/lib/scarpe/components/calzini/misc.rb +136 -0
  275. data/scarpe-components/lib/scarpe/components/calzini/para.rb +237 -0
  276. data/scarpe-components/lib/scarpe/components/calzini/slots.rb +109 -0
  277. data/scarpe-components/lib/scarpe/components/calzini.rb +236 -0
  278. data/scarpe-components/lib/scarpe/components/errors.rb +24 -0
  279. data/scarpe-components/lib/scarpe/components/file_helpers.rb +1 -0
  280. data/scarpe-components/lib/scarpe/components/html.rb +134 -0
  281. data/scarpe-components/lib/scarpe/components/minitest_export_reporter.rb +83 -0
  282. data/scarpe-components/lib/scarpe/components/minitest_import_runnable.rb +98 -0
  283. data/scarpe-components/lib/scarpe/components/minitest_result.rb +127 -0
  284. data/scarpe-components/lib/scarpe/components/modular_logger.rb +5 -5
  285. data/scarpe-components/lib/scarpe/components/print_logger.rb +22 -3
  286. data/scarpe-components/lib/scarpe/components/process_helpers.rb +37 -0
  287. data/scarpe-components/lib/scarpe/components/promises.rb +14 -14
  288. data/scarpe-components/lib/scarpe/components/segmented_file_loader.rb +36 -17
  289. data/scarpe-components/lib/scarpe/components/string_helpers.rb +10 -0
  290. data/scarpe-components/lib/scarpe/components/tiranti.rb +167 -0
  291. data/scarpe-components/lib/scarpe/components/unit_test_helpers.rb +48 -6
  292. data/scarpe-components/lib/scarpe/components/version.rb +2 -2
  293. data/scarpe-components/test/assets/big-image.png +0 -0
  294. data/scarpe-components/test/assets/big-stylesheet.css +497 -0
  295. data/scarpe-components/test/assets/little-image.png +0 -0
  296. data/scarpe-components/test/assets/little-stylesheet.css +1 -0
  297. data/scarpe-components/test/calzini/test_calzini_alert.rb +30 -0
  298. data/scarpe-components/test/calzini/test_calzini_art_drawables.rb +105 -0
  299. data/scarpe-components/test/calzini/test_calzini_button.rb +54 -0
  300. data/scarpe-components/test/calzini/test_calzini_misc.rb +115 -0
  301. data/scarpe-components/test/calzini/test_calzini_para.rb +34 -0
  302. data/scarpe-components/test/calzini/test_calzini_slots.rb +85 -0
  303. data/scarpe-components/test/calzini/test_calzini_text_drawables.rb +106 -0
  304. data/scarpe-components/test/calzini/test_various.rb +133 -0
  305. data/scarpe-components/test/mtr_data/exception.json +1 -0
  306. data/scarpe-components/test/mtr_data/fail_with_message.json +1 -0
  307. data/scarpe-components/test/mtr_data/skipped_no_message.json +1 -0
  308. data/scarpe-components/test/mtr_data/skipped_w_msg.json +1 -0
  309. data/scarpe-components/test/mtr_data/succeed_2_asserts.json +1 -0
  310. data/scarpe-components/test/test_asset_server.rb +72 -0
  311. data/scarpe-components/test/test_components.rb +31 -2
  312. data/scarpe-components/test/test_dimensions.rb +26 -0
  313. data/scarpe-components/test/test_helper.rb +20 -1
  314. data/scarpe-components/test/test_html.rb +65 -0
  315. data/scarpe-components/test/test_minitest_result.rb +68 -0
  316. data/scarpe-components/test/test_promises.rb +5 -4
  317. data/scarpe-components/test/test_segmented_app_files.rb +10 -6
  318. data/scarpegen.rb +14 -14
  319. data/sig/scarpe.rbs +1 -1
  320. data/tasks/check_html_fixtures.rb +140 -0
  321. data/tasks/regenerate_html_fixtures.rb +104 -0
  322. data/templates/basic_class_template.erb +13 -14
  323. data/templates/class_template_with_event_bind.erb +4 -4
  324. data/templates/class_template_with_shapes.erb +8 -28
  325. data/templates/example_template.erb +1 -1
  326. data/templates/module_template.erb +4 -4
  327. data/templates/webview_template.erb +3 -2
  328. metadata +286 -80
  329. data/examples/legacy/not_checked/shoes-contrib/elements/image-icon.rb +0 -3
  330. data/lacci/lib/shoes/spacing.rb +0 -9
  331. data/lacci/lib/shoes/widget.rb +0 -218
  332. data/lacci/lib/shoes/widgets/alert.rb +0 -19
  333. data/lacci/lib/shoes/widgets/arc.rb +0 -51
  334. data/lacci/lib/shoes/widgets/button.rb +0 -35
  335. data/lacci/lib/shoes/widgets/check.rb +0 -28
  336. data/lacci/lib/shoes/widgets/document_root.rb +0 -20
  337. data/lacci/lib/shoes/widgets/flow.rb +0 -22
  338. data/lacci/lib/shoes/widgets/font.rb +0 -14
  339. data/lacci/lib/shoes/widgets/line.rb +0 -18
  340. data/lacci/lib/shoes/widgets/link.rb +0 -25
  341. data/lacci/lib/shoes/widgets/list_box.rb +0 -25
  342. data/lacci/lib/shoes/widgets/para.rb +0 -68
  343. data/lacci/lib/shoes/widgets/radio.rb +0 -35
  344. data/lacci/lib/shoes/widgets/slot.rb +0 -75
  345. data/lacci/lib/shoes/widgets/span.rb +0 -26
  346. data/lacci/lib/shoes/widgets/stack.rb +0 -24
  347. data/lacci/lib/shoes/widgets/star.rb +0 -44
  348. data/lacci/lib/shoes/widgets/subscription_item.rb +0 -60
  349. data/lacci/lib/shoes/widgets/text_widget.rb +0 -51
  350. data/lacci/lib/shoes/widgets/video.rb +0 -15
  351. data/lacci/lib/shoes/widgets.rb +0 -29
  352. data/lib/scarpe/evented_assertions.rb +0 -88
  353. data/lib/scarpe/wv/alert.rb +0 -66
  354. data/lib/scarpe/wv/background.rb +0 -27
  355. data/lib/scarpe/wv/control_interface_test.rb +0 -238
  356. data/lib/scarpe/wv/dimensions.rb +0 -22
  357. data/lib/scarpe/wv/font.rb +0 -36
  358. data/lib/scarpe/wv/html.rb +0 -108
  359. data/lib/scarpe/wv/spacing.rb +0 -41
  360. data/lib/scarpe/wv/span.rb +0 -68
  361. data/lib/scarpe/wv/text_widget.rb +0 -30
  362. /data/examples/legacy/not_checked/{expert → shoes-contrib/basic}/definr.rb +0 -0
  363. /data/examples/legacy/not_checked/{expert → shoes-contrib/basic}/funnies.rb +0 -0
  364. /data/examples/legacy/not_checked/shoes-contrib/{elements → basic}/list_box-select-class.rb +0 -0
  365. /data/examples/legacy/{not_checked → working}/shoes3-tests/editline/editline.rb +0 -0
  366. /data/examples/legacy/{not_checked/shoes-contrib/basic → working/simple}/basic-edit-box.rb +0 -0
  367. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/basic-fps.rb +0 -0
  368. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/border-cat.rb +0 -0
  369. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/check-mate.rb +0 -0
  370. /data/examples/legacy/{not_checked/shoes-contrib/manipulation → working/simple}/clear-slot.rb +0 -0
  371. /data/examples/legacy/{not_checked/shoes-contrib/basic → working/simple}/clock.rb +0 -0
  372. /data/examples/legacy/{not_checked/shoes-contrib/basic → working/simple}/gradient-shoes.rb +0 -0
  373. /data/examples/legacy/{not_checked/shoes-contrib/basic → working/simple}/list_box-shape-report.rb +0 -0
  374. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/list_box.rb +0 -0
  375. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/phat-button.rb +0 -0
  376. /data/examples/legacy/{not_checked/shoes-contrib → working}/simple/simple-calc.rb +0 -0
  377. /data/examples/legacy/{not_checked/shoes-contrib/position → working/simple}/stack-width.rb +0 -0
  378. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/width-introspec.rb +0 -0
@@ -0,0 +1,654 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'margin_helper'
3
+ class Shoes
4
+ # Shoes::Drawable
5
+ #
6
+ # This is the display-service portable Shoes Drawable interface. Visible Shoes
7
+ # drawables like buttons inherit from this. Compound drawables made of multiple
8
+ # different smaller Drawables inherit from it in their various apps or libraries.
9
+ # The Shoes Drawable helps build a Shoes-side drawable tree, with parents and
10
+ # children. Any API that applies to all drawables (e.g. remove) should be
11
+ # defined here.
12
+ #
13
+ class Drawable < Shoes::Linkable
14
+ include Shoes::Log
15
+ include Shoes::Colors
16
+
17
+ # All Drawables have these so they go in Shoes::Drawable and are inherited
18
+ @shoes_events = ["parent", "destroy", "prop_change", "hover", "leave", "motion"]
19
+
20
+ class << self
21
+ attr_accessor :drawable_classes
22
+ attr_accessor :drawable_default_styles
23
+ attr_accessor :widget_classes
24
+
25
+ def inherited(subclass)
26
+ Shoes::Drawable.drawable_classes ||= []
27
+ Shoes::Drawable.drawable_classes << subclass
28
+
29
+ Shoes::Drawable.drawable_default_styles ||= {}
30
+ Shoes::Drawable.drawable_default_styles[subclass] = {}
31
+
32
+ Shoes::Drawable.widget_classes ||= []
33
+ if subclass < Shoes::Widget
34
+ Shoes::Drawable.widget_classes << subclass.name
35
+ end
36
+
37
+ super
38
+ end
39
+
40
+ def dsl_name
41
+ n = name.split("::").last.chomp("Drawable")
42
+ n.gsub(/(.)([A-Z])/, '\1_\2').downcase
43
+ end
44
+
45
+ def drawable_class_by_name(name)
46
+ name = name.to_s
47
+ drawable_classes.detect { |k| k.dsl_name == name }
48
+ end
49
+
50
+ def is_widget_class?(name)
51
+ !!Shoes::Drawable.widget_classes.intersect?([name.to_s])
52
+ end
53
+
54
+ def validate_as(prop_name, value)
55
+ prop_name = prop_name.to_s
56
+ hashes = shoes_style_hashes
57
+
58
+ h = hashes.detect { |hash| hash[:name] == prop_name }
59
+ raise(Shoes::Errors::NoSuchStyleError, "Can't find property #{prop_name.inspect} in #{self} property list: #{hashes.inspect}!") unless h
60
+
61
+ return value if h[:validator].nil?
62
+
63
+ # Pass both the property name and value to the validator block
64
+ h[:validator].call(value,prop_name)
65
+ end
66
+
67
+ # Return a list of Shoes events for this class.
68
+ #
69
+ # @return Array[String] the list of event names
70
+ def get_shoes_events
71
+ if @shoes_events.nil?
72
+ raise Shoes::Errors::UnknownEventsForClassError, "Drawable type #{self} hasn't defined its list of Shoes events!"
73
+ end
74
+
75
+ @shoes_events
76
+ end
77
+
78
+ # Return whether Shoes events have already been registered for this class
79
+ #
80
+ # @return [Boolean] true if events have been registered, false if not
81
+ def registered_shoes_events?
82
+ !@shoes_events.nil?
83
+ end
84
+
85
+ # Set the list of Shoes event names that are allowed for this class.
86
+ #
87
+ # @param args [Array] an array of event names, which will be coerced to Strings
88
+ # @return [void]
89
+ def shoes_events(*args)
90
+ if @shoes_events
91
+ raise Shoes::Errors::DoubleRegisteredShoesEventError, "Registering shoes events #{args.inspect} for class #{self} but already registered events as #{@shoes_events.inspect}!"
92
+ end
93
+ @shoes_events = args.map(&:to_s) + self.superclass.get_shoes_events
94
+ end
95
+
96
+ # Require supplying these Shoes style values as positional arguments to
97
+ # initialize. Initialize will get the arg list, then set the specified styles
98
+ # if args are given for them. @see opt_init_args for additional non-required
99
+ # init args.
100
+ #
101
+ # @param args [Array<String,Symbol>] an array of Shoes style names
102
+ # @return [void]
103
+ def init_args(*args)
104
+ raise Shoes::Errors::BadArgumentListError, "Positional init args already set for #{self}!" if @required_init_args
105
+ @required_init_args = args.map(&:to_s)
106
+ end
107
+
108
+ # Allow supplying these Shoes style values as optional positional arguments to
109
+ # initialize after the mandatory args. @see init_args for setting required
110
+ # init args.
111
+ #
112
+ # @param args [Array<String,Symbol>] an array of Shoes style names
113
+ # @return [void]
114
+ def opt_init_args(*args)
115
+ raise Shoes::Errors::BadArgumentListError, "Positional init args already set for #{self}!" if @opt_init_args
116
+ @opt_init_args = args.map(&:to_s)
117
+ end
118
+
119
+ # Return the list of style names for required init args for this class
120
+ #
121
+ # @return [Array<String>] the array of style names as strings
122
+ def required_init_args
123
+ @required_init_args ||= [] # TODO: eventually remove the ||= here
124
+ end
125
+
126
+ # Return the list of style names for optional init args for this class
127
+ #
128
+ # @return [Array<String>] the array of style names as strings
129
+ def optional_init_args
130
+ @opt_init_args ||= []
131
+ end
132
+
133
+ # Assign a new Shoes Drawable ID number, starting from 1.
134
+ # This allows non-overlapping small integer IDs for Shoes
135
+ # linkable IDs - the number part of making it clear what
136
+ # widget you're talking about.
137
+ def allocate_drawable_id
138
+ @drawable_id_counter ||= 0
139
+ @drawable_id_counter += 1
140
+ @drawable_id_counter
141
+ end
142
+
143
+ def register_drawable_id(id, drawable)
144
+ @drawables_by_id ||= {}
145
+ @drawables_by_id[id] = drawable
146
+ end
147
+
148
+ def unregister_drawable_id(id)
149
+ @drawables_by_id ||= {}
150
+ @drawables_by_id.delete(id)
151
+ end
152
+
153
+ def drawable_by_id(id, none_ok: false)
154
+ val = @drawables_by_id[id]
155
+ unless val || none_ok
156
+ raise "No Drawable Found! #{@drawables_by_id.inspect}"
157
+ end
158
+
159
+ val
160
+ end
161
+
162
+ private
163
+
164
+ def linkable_properties
165
+ @linkable_properties ||= []
166
+ end
167
+
168
+ def linkable_properties_hash
169
+ @linkable_properties_hash ||= {}
170
+ end
171
+
172
+ public
173
+
174
+ # Shoes styles in Shoes Linkables are automatically sync'd with the display side objects.
175
+ # If a block is passed to shoes_style, that's the validation for the property. It should
176
+ # convert a given value to a valid value for the property or throw an exception.
177
+ #
178
+ # If feature is non-nil, it's the feature that an app must request in order to see this
179
+ # property.
180
+ #
181
+ # @param name [String,Symbol] the style name
182
+ # @param feature [Symbol,NilClass] the feature that must be defined for an app to request this style, or nil
183
+ # @block if block is given, call it to map the given style value to a valid value, or raise an exception
184
+ def shoes_style(name, feature: nil, &validator)
185
+ name = name.to_s
186
+
187
+ return if linkable_properties_hash[name]
188
+
189
+ linkable_properties << { name: name, validator:, feature: }
190
+ linkable_properties_hash[name] = true
191
+ end
192
+
193
+ # Add these names as Shoes styles with the given validator and feature, if any
194
+ def shoes_styles(*names, feature: nil, &validator)
195
+ names.each { |n| shoes_style(n, feature:, &validator) }
196
+ end
197
+
198
+ # Query what feature, if any, is required to use a specific shoes_style.
199
+ # If no specific feature is needed, nil will be returned.
200
+ def feature_for_shoes_style(style_name)
201
+ style_name = style_name.to_s
202
+ lp = linkable_properties.detect { |prop| prop[:name] == style_name }
203
+ return lp[:feature] if lp
204
+
205
+ # If we get to the top of the superclass tree and we didn't find it, it's not here
206
+ if self.class == ::Shoes::Drawable
207
+ raise Shoes::Errors::NoSuchStyleError, "Can't find information for style #{style_name.inspect}!"
208
+ end
209
+
210
+ super
211
+ end
212
+
213
+ # Return a list of shoes_style names with the given features. If with_features is nil,
214
+ # return them with a list of features for the current Shoes::App. For the list of
215
+ # styles available with no features requested, pass nil to with_features.
216
+ def shoes_style_names(with_features: nil)
217
+ # No with_features given? Use the ones requested by this Shoes::App
218
+ with_features ||= Shoes::App.instance.features
219
+ parent_prop_names = self != Shoes::Drawable ? self.superclass.shoes_style_names(with_features:) : []
220
+
221
+ if with_features == :all
222
+ subclass_props = linkable_properties
223
+ else
224
+ subclass_props = linkable_properties.select { |prop| !prop[:feature] || with_features.include?(prop[:feature]) }
225
+ end
226
+ parent_prop_names | subclass_props.map { |prop| prop[:name] }
227
+ end
228
+
229
+ def shoes_style_hashes
230
+ parent_hashes = self != Shoes::Drawable ? self.superclass.shoes_style_hashes : []
231
+
232
+ parent_hashes + linkable_properties
233
+ end
234
+
235
+ def shoes_style_name?(name)
236
+ linkable_properties_hash[name.to_s] ||
237
+ (self != Shoes::Drawable && superclass.shoes_style_name?(name))
238
+ end
239
+ end
240
+
241
+ # Every Shoes drawable has positioning properties
242
+ shoes_styles :top, :left, :width, :height
243
+
244
+ # Margins around drawable
245
+ shoes_styles :margin, :margin_top, :margin_bottom, :margin_left, :margin_right
246
+
247
+ # Padding around drawable
248
+ shoes_styles :padding, :padding_top, :padding_bottom, :padding_left, :padding_right
249
+
250
+ # Shoes uses a "hidden" style property for hide/show
251
+ shoes_style :hidden
252
+
253
+ attr_reader :debug_id
254
+
255
+ # These styles can be set to a current per-slot value and inherited from parent slots.
256
+ # Their value is set at drawable-create time.
257
+ DRAW_CONTEXT_STYLES = [:fill, :stroke, :strokewidth, :rotate, :transform, :translate]
258
+
259
+ include MarginHelper
260
+
261
+ def initialize(*args, **kwargs)
262
+ kwargs = margin_parse(kwargs)
263
+ log_init("Shoes::#{self.class.name}") unless @log
264
+
265
+ # First, get the list of allowed and disallowed styles for the given features
266
+ # and make sure no disallowed styles were given.
267
+
268
+ app_features = Shoes::App.instance.features
269
+ this_app_styles = self.class.shoes_style_names.map(&:to_sym)
270
+ not_this_app_styles = self.class.shoes_style_names(with_features: :all).map(&:to_sym) - this_app_styles
271
+
272
+ bad_styles = kwargs.keys & not_this_app_styles
273
+ unless bad_styles.empty?
274
+ features_needed = bad_styles.map { |s| self.class.feature_for_shoes_style(s) }.uniq
275
+ raise Shoes::Errors::UnsupportedFeatureError, "The style(s) #{bad_styles.inspect} are only defined for applications that request specific features: #{features_needed.inspect} (you requested #{app_features.inspect})!"
276
+ end
277
+
278
+ # Next, check positional arguments and make sure the correct number and type
279
+ # were passed and match positional args with style names.
280
+
281
+ supplied_args = kwargs.keys
282
+
283
+ req_args = self.class.required_init_args
284
+ opt_args = self.class.optional_init_args
285
+ pos_args = req_args + opt_args
286
+ if req_args != ["any"]
287
+ if args.size > pos_args.size
288
+ raise Shoes::Errors::BadArgumentListError, "Too many arguments given for #{self.class}#initialize! #{args.inspect}"
289
+ end
290
+
291
+ if args.size == 0
292
+ # It's fine to use keyword args instead, but we should make sure they're actually there
293
+ needed_args = req_args.map(&:to_sym) - kwargs.keys
294
+ unless needed_args.empty?
295
+ raise Shoes::Errors::BadArgumentListError, "Keyword arguments for #{self.class}#initialize should also supply #{needed_args.inspect}! #{args.inspect}"
296
+ end
297
+ elsif args.size < req_args.size
298
+ raise Shoes::Errors::BadArgumentListError, "Too few arguments given for #{self.class}#initialize! #{args.inspect}"
299
+ end
300
+
301
+ # Set each positional argument
302
+ args.each.with_index do |val, idx|
303
+ style_name = pos_args[idx]
304
+ next if style_name.nil? || style_name == "" # It's possible to have non-style positional args
305
+
306
+ val = self.class.validate_as(style_name, args[idx])
307
+ instance_variable_set("@#{style_name}", val)
308
+ supplied_args << style_name.to_sym
309
+ end
310
+ end
311
+
312
+ this_drawable_styles = self.class.shoes_style_names.map(&:to_sym)
313
+ dc = Shoes::App.instance.current_draw_context || {}
314
+
315
+ # Styles not passed as arguments can come from the draw context
316
+
317
+ # What styles are in the draw context, are used by this drawable, and weren't
318
+ # given as positional or keyword arguments?
319
+ draw_context_styles = (DRAW_CONTEXT_STYLES & this_drawable_styles) - supplied_args
320
+ unless draw_context_styles.empty?
321
+ # When we first call this, there is no parent. We don't want to set the parent
322
+ # yet because that will send a notification, and *that* should wait until after
323
+ # we've told the display service that this drawable was created. So instead
324
+ # we'll query the parent object's draw context directly.
325
+
326
+ draw_context_styles.each do |style|
327
+ dc_val = dc[style.to_s]
328
+ next if dc_val.nil?
329
+
330
+ val = self.class.validate_as(style, dc[style.to_s])
331
+ instance_variable_set("@#{style}", val)
332
+ supplied_args << style
333
+ end
334
+ end
335
+
336
+ # Styles that were *not* passed should be set to defaults
337
+
338
+ default_styles = Shoes::Drawable.drawable_default_styles[self.class]
339
+
340
+ # No arg specified for a property with a default value? Set it to default.
341
+ (default_styles.keys - supplied_args).each do |key|
342
+ val = self.class.validate_as(key, default_styles[key])
343
+ instance_variable_set("@#{key}", val)
344
+ end
345
+
346
+ # If we have a keyword arg for a style, set it as specified.
347
+ (this_drawable_styles & kwargs.keys).each do |key|
348
+ val = self.class.validate_as(key, kwargs[key])
349
+ instance_variable_set("@#{key}", val)
350
+ end
351
+
352
+ # We'd like to avoid unexpected keywords. But we're not disciplined enough to
353
+ # raise an error by default yet. Non-style keywords passed to Drawable#initialize
354
+ # are deprecated at this point, but I need to hunt down the last of them
355
+ # and prevent them.
356
+ unexpected = (kwargs.keys - this_drawable_styles)
357
+ unless unexpected.empty?
358
+ STDERR.puts "Unexpected non-style keyword(s) in #{self.class} initialize: #{unexpected.inspect}"
359
+ end
360
+
361
+ super(linkable_id: Shoes::Drawable.allocate_drawable_id)
362
+ Shoes::Drawable.register_drawable_id(self.linkable_id, self)
363
+
364
+ generate_debug_id
365
+
366
+ parent = ::Shoes::App.instance.current_slot
367
+ if self.class.expects_parent?
368
+ set_parent(parent, notify: false)
369
+ end
370
+
371
+ unless self.class.registered_shoes_events?
372
+ # No Shoes events declared and we're creating an instance?
373
+ # Default to no class-specific events.
374
+ self.class.shoes_events
375
+ end
376
+
377
+ # Binding the motion events here isn't perfect.
378
+ # What about drawables like SubscriptionItem that
379
+ # have no motion events? With the current Lacci
380
+ # implementation, the answer is that those events
381
+ # will never be sent. Calling .hover on one will
382
+ # be useless, harmless, and allowed. If you want
383
+ # to make it disallowed, you can do something like
384
+ # define a SubscriptionItem#hover that raises an
385
+ # exception instead.
386
+
387
+ bind_self_event("hover") do
388
+ @hover&.call
389
+ end
390
+
391
+ bind_self_event("leave") do
392
+ @leave&.call
393
+ end
394
+
395
+ bind_self_event("motion") do |x, y|
396
+ @motion&.call(x, y)
397
+ end
398
+ end
399
+
400
+ def self.expects_parent?
401
+ return false if [::Shoes::App, ::Shoes::DocumentRoot].include?(self)
402
+ return false if self < ::Shoes::TextDrawable
403
+
404
+ true
405
+ end
406
+
407
+ # Calling stack.app or drawable.app will execute the block
408
+ # with the Shoes::App as self, and with that stack or
409
+ # flow as the current slot.
410
+ #
411
+ # @incompatibility In Shoes Classic this is the only way
412
+ # to change self, while Scarpe will also change self
413
+ # with the other Slot Manipulation methods: #clear,
414
+ # #append, #prepend, #before and #after.
415
+ #
416
+ # @return [Shoes::App] the Shoes app
417
+ # @yield the block to call with the Shoes App as self
418
+ def app(&block)
419
+ Shoes::App.instance.with_slot(self, &block) if block_given?
420
+ Shoes::App.instance
421
+ end
422
+
423
+ private
424
+
425
+ def generate_debug_id
426
+ cl = caller_locations(3)
427
+ da = cl.detect { |loc| !loc.path.include?("lacci/lib/shoes") }
428
+ @drawable_defined_at = "#{File.basename(da.path)}:#{da.lineno}"
429
+
430
+ class_name = self.class.name.split("::")[-1]
431
+
432
+ @debug_id = "#{class_name}##{@linkable_id}(#{@drawable_defined_at})"
433
+ end
434
+
435
+ public
436
+
437
+ def inspect
438
+ "#<#{debug_id} " +
439
+ " @parent=#{@parent ? @parent.debug_id : "(none)"} " +
440
+ "@children=#{@children ? @children.map(&:debug_id) : "(none)"} properties=#{shoes_style_values.inspect}>"
441
+ end
442
+
443
+ private
444
+
445
+ def validate_event_name(event_name)
446
+ events = self.class.get_shoes_events
447
+ unless events.include?(event_name.to_s)
448
+ raise Shoes::Errors::UnregisteredShoesEventError, "Drawable #{self.inspect} tried to bind Shoes event #{event_name}, which is not in #{events.inspect}!"
449
+ end
450
+ end
451
+
452
+ def bind_self_event(event_name, &block)
453
+ raise(Shoes::Errors::NoSuchLinkableIdError, "Drawable has no linkable_id! #{inspect}") unless linkable_id
454
+
455
+ validate_event_name(event_name)
456
+
457
+ bind_shoes_event(event_name: event_name, target: linkable_id, &block)
458
+ end
459
+
460
+ def bind_no_target_event(event_name, &block)
461
+ validate_event_name(event_name)
462
+
463
+ bind_shoes_event(event_name:, &block)
464
+ end
465
+
466
+ public
467
+
468
+ def event(event_name, *args, **kwargs)
469
+ validate_event_name(event_name)
470
+
471
+ send_shoes_event(*args, **kwargs, event_name:, target: linkable_id)
472
+ end
473
+
474
+ def shoes_style_values
475
+ all_property_names = self.class.shoes_style_names
476
+
477
+ properties = {}
478
+ all_property_names.each do |prop|
479
+ properties[prop] = instance_variable_get("@" + prop)
480
+ end
481
+ properties["shoes_linkable_id"] = self.linkable_id
482
+ properties
483
+ end
484
+
485
+ def style(*args, **kwargs)
486
+ if args.empty? && kwargs.empty?
487
+ # Just called as .style()
488
+ shoes_style_values
489
+ elsif args.empty?
490
+ # This is called to set one or more Shoes styles
491
+ prop_names = self.class.shoes_style_names
492
+ unknown_styles = kwargs.keys.select { |k| !prop_names.include?(k.to_s) }
493
+ unless unknown_styles.empty?
494
+ raise Shoes::Errors::NoSuchStyleError, "Unknown styles for drawable type #{self.class.name}: #{unknown_styles.join(", ")}"
495
+ end
496
+
497
+ kwargs.each do |name, val|
498
+ instance_variable_set("@#{name}", val)
499
+ end
500
+ elsif args.length == 1 && args[0] < Shoes::Drawable
501
+ # Shoes supports calling .style with a Shoes class, e.g. .style(Shoes::Button, displace_left: 5)
502
+ kwargs.each do |name, val|
503
+ Shoes::Drawable.drawable_default_styles[args[0]][name.to_sym] = val
504
+ end
505
+ else
506
+ raise Shoes::Errors::InvalidAttributeValueError, "Unexpected arguments to style! args: #{args.inspect}, keyword args: #{kwargs.inspect}"
507
+ end
508
+ end
509
+
510
+ private
511
+
512
+ def create_display_drawable
513
+ klass_name = self.class.name.delete_prefix("Scarpe::").delete_prefix("Shoes::")
514
+
515
+ is_widget = Shoes::Drawable.is_widget_class?(klass_name)
516
+ parent_id = @parent&.linkable_id
517
+
518
+ # Should we send an event so this can be discovered from someplace other than
519
+ # the DisplayService?
520
+ ::Shoes::DisplayService.display_service.create_display_drawable_for(klass_name, self.linkable_id, shoes_style_values, parent_id:, is_widget:)
521
+ end
522
+
523
+ public
524
+
525
+ attr_reader :parent
526
+ attr_reader :destroyed
527
+
528
+ # Set the Drawable's parent drawable. Notify the display service
529
+ # that the parent has changed unless instructed not to.
530
+ # We don't notify when first creating the Drawable. The create
531
+ # event that is first sent will include the parent.
532
+ def set_parent(new_parent, notify: true)
533
+ @parent&.remove_child(self)
534
+ new_parent&.add_child(self)
535
+ @parent = new_parent
536
+ return unless notify
537
+
538
+ send_shoes_event(new_parent&.linkable_id, event_name: "parent", target: linkable_id)
539
+ end
540
+
541
+ # Removes the element from the Shoes::Drawable tree and removes all event subscriptions
542
+ def destroy
543
+ @parent&.remove_child(self)
544
+ @parent = nil
545
+ @destroyed = true
546
+ unsub_all_shoes_events
547
+ send_shoes_event(event_name: "destroy", target: linkable_id)
548
+ Shoes::Drawable.unregister_drawable_id(linkable_id)
549
+ end
550
+ alias_method :remove, :destroy
551
+
552
+ # Hide the drawable.
553
+ def hide
554
+ self.hidden = true
555
+ end
556
+
557
+ # Show the drawable.
558
+ def show
559
+ self.hidden = false
560
+ end
561
+
562
+ # Hide the drawable if it is currently shown. Show it if it is currently hidden.
563
+ def toggle
564
+ self.hidden = !self.hidden
565
+ end
566
+
567
+ # Set the hover handler. Not every drawable may do something useful with this.
568
+ #
569
+ # @yield A block to be called when the cursor moves to be over the drawable.
570
+ def hover(&block)
571
+ @hover = block
572
+ end
573
+
574
+ # Set the leave handler. Not every drawable may do something useful with this.
575
+ #
576
+ # @yield A block to be called when the cursor moves to be off of the drawable.
577
+ def leave(&block)
578
+ @leave = block
579
+ end
580
+
581
+ # Set the motion handler, called with x and y coordinates as params.
582
+ # Not every drawable may do something useful with this.
583
+ #
584
+ # @yield A block to be called when the cursor moves around over the drawable.
585
+ def motion(&block)
586
+ @motion = block
587
+ end
588
+
589
+ # We use method_missing to auto-create Shoes style getters and setters.
590
+ def method_missing(name, *args, **kwargs, &block)
591
+ name_s = name.to_s
592
+
593
+ if name_s[-1] == "="
594
+ prop_name = name_s[0..-2]
595
+ if self.class.shoes_style_name?(prop_name)
596
+ self.class.define_method(name) do |new_value|
597
+ raise(Shoes::Errors::NoSuchLinkableIdError, "Trying to set Shoes styles in a #{self.class} with no linkable ID!") unless linkable_id
598
+
599
+ new_value = self.class.validate_as(prop_name, new_value)
600
+ instance_variable_set("@" + prop_name, new_value)
601
+ send_shoes_event({ prop_name => new_value }, event_name: "prop_change", target: linkable_id)
602
+ end
603
+
604
+ return self.send(name, *args, **kwargs, &block)
605
+ end
606
+ end
607
+
608
+ if self.class.shoes_style_name?(name_s)
609
+ self.class.define_method(name) do
610
+ raise(Shoes::Errors::NoSuchLinkableIdError, "Trying to get Shoes styles in an object with no linkable ID! #{inspect}") unless linkable_id
611
+
612
+ instance_variable_get("@" + name_s)
613
+ end
614
+
615
+ return self.send(name, *args, **kwargs, &block)
616
+ end
617
+
618
+ super(name, *args, **kwargs, &block)
619
+ end
620
+
621
+ def respond_to_missing?(name, include_private = false)
622
+ name_s = name.to_s
623
+ return true if self.class.shoes_style_name?(name_s)
624
+ return true if self.class.shoes_style_name?(name_s[0..-2]) && name_s[-1] == "="
625
+ return true if Drawable.drawable_class_by_name(name_s)
626
+
627
+ super
628
+ end
629
+
630
+ def self.convert_to_integer(value, attribute_name)
631
+ begin
632
+ value = Integer(value)
633
+ raise Shoes::Errors::InvalidAttributeValueError, "Negative number '#{value}' not allowed for attribute '#{attribute_name}'" if value < 0
634
+
635
+ value
636
+ rescue ArgumentError
637
+ error_message = "Invalid value '#{value}' provided for attribute '#{attribute_name}'. The value should be a number."
638
+ raise Shoes::Errors::InvalidAttributeValueError, error_message
639
+ end
640
+ end
641
+
642
+ def self.convert_to_float(value, attribute_name)
643
+ begin
644
+ value = Float(value)
645
+ raise Shoes::Errors::InvalidAttributeValueError, "Negative number '#{value}' not allowed for attribute '#{attribute_name}'" if value < 0
646
+
647
+ value
648
+ rescue ArgumentError
649
+ error_message = "Invalid value '#{value}' provided for attribute '#{attribute_name}'. The value should be a number."
650
+ raise Shoes::Errors::InvalidAttributeValueError, error_message
651
+ end
652
+ end
653
+ end
654
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Shoes
4
+ class Arc < Shoes::Drawable
5
+ shoes_style :draw_context
6
+ shoes_events # No Arc-specific events yet
7
+
8
+ [:left, :top, :width, :height].each do |prop|
9
+ shoes_style(prop) { |val| convert_to_integer(val, prop) }
10
+ end
11
+
12
+ [:angle1, :angle2].each do |prop|
13
+ shoes_style(prop) { |val| convert_to_float(val, prop) }
14
+ end
15
+
16
+ init_args :left, :top, :width, :height, :angle1, :angle2
17
+ def initialize(*args, **kwargs)
18
+ @draw_context = Shoes::App.instance.current_draw_context
19
+
20
+ super
21
+
22
+ create_display_drawable
23
+ end
24
+
25
+
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Shoes
4
+ class Arrow < Shoes::Drawable
5
+ shoes_style :draw_context
6
+ shoes_events # No Arrow-specific events yet
7
+
8
+ [:left, :top, :width].each do |prop|
9
+ shoes_style(prop) { |val| val.is_a?(Hash) ? val : convert_to_integer(val, prop) }
10
+ end
11
+
12
+ init_args :left, :top, :width
13
+ def initialize(*args, **kwargs)
14
+ @draw_context = Shoes::App.instance.current_draw_context
15
+
16
+ super
17
+
18
+ create_display_drawable
19
+ end
20
+ end
21
+ end