scarpe 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (251) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -1
  3. data/CHANGELOG.md +36 -4
  4. data/Gemfile +2 -1
  5. data/Gemfile.lock +13 -3
  6. data/LICENSE.txt +7 -1
  7. data/README.md +77 -14
  8. data/Rakefile +67 -0
  9. data/examples/Edit_box_Styles.rb +8 -0
  10. data/examples/Kerning.rb +7 -0
  11. data/examples/border.rb +11 -0
  12. data/examples/check.rb +2 -0
  13. data/examples/download_and_show_image.rb +3 -0
  14. data/examples/flags/finland.rb +15 -0
  15. data/examples/flags/italy.rb +11 -0
  16. data/examples/flags/mauritius.rb +14 -0
  17. data/examples/font_family.rb +17 -0
  18. data/examples/font_shorthand.rb +9 -0
  19. data/examples/gen.rb +4 -0
  20. data/examples/legacy/not_checked/shoes-manual/append.rb +10 -0
  21. data/examples/legacy/not_checked/shoes-manual/background_change.rb +12 -0
  22. data/examples/legacy/not_checked/shoes-manual/background_pattern.rb +5 -0
  23. data/examples/legacy/not_checked/shoes-manual/basic_app.rb +8 -0
  24. data/examples/legacy/not_checked/shoes-manual/border.rb +9 -0
  25. data/examples/legacy/not_checked/shoes-manual/builtins/FONTS.rb +5 -0
  26. data/examples/legacy/not_checked/shoes-manual/builtins/ask.rb +2 -0
  27. data/examples/legacy/not_checked/shoes-manual/builtins/ask_color.rb +5 -0
  28. data/examples/legacy/not_checked/shoes-manual/builtins/ask_open_file.rb +5 -0
  29. data/examples/legacy/not_checked/shoes-manual/builtins/ask_save_folder.rb +2 -0
  30. data/examples/legacy/not_checked/shoes-manual/builtins/confirm.rb +4 -0
  31. data/examples/legacy/not_checked/shoes-manual/builtins/debug.rb +2 -0
  32. data/examples/legacy/not_checked/shoes-manual/builtins/info.rb +3 -0
  33. data/examples/legacy/not_checked/shoes-manual/button.rb +9 -0
  34. data/examples/legacy/not_checked/shoes-manual/clear.rb +7 -0
  35. data/examples/legacy/not_checked/shoes-manual/custom_header.rb +13 -0
  36. data/examples/legacy/not_checked/shoes-manual/displace.rb +14 -0
  37. data/examples/legacy/not_checked/shoes-manual/edit_box.rb +8 -0
  38. data/examples/legacy/not_checked/shoes-manual/fill_pattern.rb +5 -0
  39. data/examples/legacy/not_checked/shoes-manual/fonts.rb +7 -0
  40. data/examples/legacy/not_checked/shoes-manual/gutter.rb +6 -0
  41. data/examples/legacy/not_checked/shoes-manual/image_web.rb +4 -0
  42. data/examples/legacy/not_checked/shoes-manual/keypress.rb +7 -0
  43. data/examples/legacy/not_checked/shoes-manual/list_box.rb +10 -0
  44. data/examples/legacy/not_checked/shoes-manual/motion.rb +10 -0
  45. data/examples/legacy/not_checked/shoes-manual/mouse.rb +8 -0
  46. data/examples/legacy/not_checked/shoes-manual/move.rb +14 -0
  47. data/examples/legacy/not_checked/shoes-manual/nested_ovals.rb +8 -0
  48. data/examples/legacy/not_checked/shoes-manual/oval.rb +7 -0
  49. data/examples/legacy/not_checked/shoes-manual/ovals.rb +6 -0
  50. data/examples/legacy/not_checked/shoes-manual/ovals_image.rb +8 -0
  51. data/examples/legacy/not_checked/shoes-manual/prepend.rb +7 -0
  52. data/examples/legacy/not_checked/shoes-manual/progress_bar.rb +10 -0
  53. data/examples/legacy/not_checked/shoes-manual/radio.rb +18 -0
  54. data/examples/legacy/not_checked/shoes-manual/radio_alternative_1.rb +7 -0
  55. data/examples/legacy/not_checked/shoes-manual/radio_alternative_2.rb +9 -0
  56. data/examples/legacy/not_checked/shoes-manual/rotate_rectangle.rb +6 -0
  57. data/examples/legacy/not_checked/shoes-manual/shape.rb +11 -0
  58. data/examples/legacy/not_checked/shoes-manual/static/avatar.png +0 -0
  59. data/examples/legacy/not_checked/shoes-manual/stroke.rb +5 -0
  60. data/examples/legacy/not_checked/shoes-manual/style.rb +3 -0
  61. data/examples/legacy/not_checked/shoes-manual/style_alternative_1.rb +4 -0
  62. data/examples/legacy/not_checked/shoes-manual/style_alternative_2.rb +5 -0
  63. data/examples/legacy/not_checked/shoes-manual/style_length.rb +5 -0
  64. data/examples/legacy/not_checked/shoes-manual/timer.rb +6 -0
  65. data/examples/legacy/not_checked/shoes-manual/trigger_window.rb +8 -0
  66. data/examples/legacy/not_checked/shoes-manual/window_owner.rb +8 -0
  67. data/examples/legacy/working/shoes_manual/alert_button.rb +2 -0
  68. data/examples/legacy/working/shoes_manual/animate.rb +7 -0
  69. data/examples/legacy/working/shoes_manual/background_para.rb +4 -0
  70. data/examples/legacy/working/shoes_manual/button_alternative.rb +7 -0
  71. data/examples/legacy/working/shoes_manual/checkbox.rb +17 -0
  72. data/examples/legacy/working/shoes_manual/download.rb +12 -0
  73. data/examples/legacy/working/shoes_manual/edit_box.rb +6 -0
  74. data/examples/legacy/working/shoes_manual/editline.rb +7 -0
  75. data/examples/legacy/working/shoes_manual/fixed_height.rb +8 -0
  76. data/examples/legacy/working/shoes_manual/fixed_width.rb +12 -0
  77. data/examples/legacy/working/shoes_manual/image.rb +5 -0
  78. data/examples/legacy/working/shoes_manual/instance_variable_check.rb +10 -0
  79. data/examples/legacy/working/shoes_manual/message.rb +18 -0
  80. data/examples/legacy/working/shoes_manual/rectangle.rb +6 -0
  81. data/examples/legacy/working/shoes_manual/save_download.rb +12 -0
  82. data/examples/legacy/working/shoes_manual/self_check.rb +10 -0
  83. data/examples/legacy/working/shoes_manual/stack.rb +7 -0
  84. data/examples/legacy/working/shoes_manual/style_info.rb +8 -0
  85. data/examples/legacy/working/shoes_manual/utf8_support.rb +8 -0
  86. data/examples/legacy/working/shoes_manual/width.rb +4 -0
  87. data/examples/local_assets/multi_image.rb +5 -0
  88. data/examples/local_assets/small.png +0 -0
  89. data/examples/local_fonts.rb +3 -0
  90. data/examples/margin.rb +13 -0
  91. data/examples/margin_check.rb +27 -0
  92. data/examples/oval-with-kwargs.rb +3 -0
  93. data/examples/oval.rb +26 -0
  94. data/examples/para_font_styles.rb +17 -0
  95. data/examples/para_font_variant.rb +6 -0
  96. data/examples/para_fontweight.rb +13 -0
  97. data/examples/parse_xl_funnies.rb +3 -0
  98. data/examples/rect.rb +1 -1
  99. data/examples/scarpe_ext.rb +3 -0
  100. data/examples/shapes/star.rb +1 -3
  101. data/examples/spacing.rb +1 -1
  102. data/examples/span.rb +4 -2
  103. data/lacci/lacci.gemspec +2 -2
  104. data/lacci/lib/lacci/scarpe_cli.rb +0 -1
  105. data/lacci/lib/lacci/version.rb +1 -1
  106. data/lacci/lib/scarpe/niente/display_service.rb +5 -1
  107. data/lacci/lib/scarpe/niente/drawable.rb +2 -0
  108. data/lacci/lib/scarpe/niente/shoes_spec.rb +7 -1
  109. data/lacci/lib/scarpe/niente.rb +14 -2
  110. data/lacci/lib/shoes/app.rb +44 -50
  111. data/lacci/lib/shoes/constants.rb +23 -2
  112. data/lacci/lib/shoes/display_service.rb +43 -4
  113. data/lacci/lib/shoes/drawable.rb +309 -35
  114. data/lacci/lib/shoes/drawables/arc.rb +2 -24
  115. data/lacci/lib/shoes/drawables/arrow.rb +2 -22
  116. data/lacci/lib/shoes/drawables/border.rb +28 -0
  117. data/lacci/lib/shoes/drawables/button.rb +4 -20
  118. data/lacci/lib/shoes/drawables/check.rb +7 -3
  119. data/lacci/lib/shoes/drawables/document_root.rb +4 -4
  120. data/lacci/lib/shoes/drawables/edit_box.rb +6 -5
  121. data/lacci/lib/shoes/drawables/edit_line.rb +5 -4
  122. data/lacci/lib/shoes/drawables/flow.rb +3 -5
  123. data/lacci/lib/shoes/drawables/font_helper.rb +62 -0
  124. data/lacci/lib/shoes/drawables/image.rb +2 -2
  125. data/lacci/lib/shoes/drawables/line.rb +4 -7
  126. data/lacci/lib/shoes/drawables/link.rb +5 -8
  127. data/lacci/lib/shoes/drawables/list_box.rb +8 -5
  128. data/lacci/lib/shoes/drawables/oval.rb +48 -0
  129. data/lacci/lib/shoes/drawables/para.rb +106 -18
  130. data/lacci/lib/shoes/drawables/progress.rb +2 -1
  131. data/lacci/lib/shoes/drawables/radio.rb +5 -3
  132. data/lacci/lib/shoes/drawables/rect.rb +5 -4
  133. data/lacci/lib/shoes/drawables/shape.rb +2 -1
  134. data/lacci/lib/shoes/drawables/slot.rb +99 -8
  135. data/lacci/lib/shoes/drawables/stack.rb +6 -11
  136. data/lacci/lib/shoes/drawables/star.rb +8 -30
  137. data/lacci/lib/shoes/drawables/text_drawable.rb +93 -34
  138. data/lacci/lib/shoes/drawables/video.rb +3 -2
  139. data/lacci/lib/shoes/drawables/widget.rb +8 -3
  140. data/lacci/lib/shoes/drawables.rb +2 -1
  141. data/lacci/lib/shoes/errors.rb +13 -3
  142. data/lacci/lib/shoes/margin_helper.rb +79 -0
  143. data/lacci/lib/shoes.rb +4 -3
  144. data/lacci/test/.gitignore +1 -0
  145. data/lacci/test/test_draw_context.rb +167 -0
  146. data/lacci/test/test_font_helper.rb +57 -0
  147. data/lacci/test/test_helper.rb +31 -4
  148. data/lacci/test/test_lacci.rb +93 -6
  149. data/lacci/test/test_margin_helper.rb +82 -0
  150. data/lacci/test/test_niente_test_infra.rb +26 -0
  151. data/lacci/test/test_oval.rb +82 -0
  152. data/lacci/test/test_parenting.rb +140 -0
  153. data/lacci/test/test_text_drawables.rb +23 -0
  154. data/lib/scarpe/assets.rb +18 -0
  155. data/lib/scarpe/cats_cradle.rb +57 -98
  156. data/lib/scarpe/shoes_spec.rb +22 -43
  157. data/lib/scarpe/version.rb +1 -1
  158. data/lib/scarpe/wv/app.rb +1 -0
  159. data/lib/scarpe/wv/arc.rb +0 -4
  160. data/lib/scarpe/wv/border.rb +15 -0
  161. data/lib/scarpe/wv/control_interface.rb +2 -10
  162. data/lib/scarpe/wv/document_root.rb +2 -2
  163. data/lib/scarpe/wv/drawable.rb +6 -40
  164. data/lib/scarpe/wv/edit_box.rb +4 -1
  165. data/lib/scarpe/wv/edit_line.rb +5 -2
  166. data/lib/scarpe/wv/image.rb +2 -5
  167. data/lib/scarpe/wv/link.rb +4 -2
  168. data/lib/scarpe/wv/oval.rb +13 -0
  169. data/lib/scarpe/wv/para.rb +1 -0
  170. data/lib/scarpe/wv/scarpe_extensions.rb +8 -0
  171. data/lib/scarpe/wv/shape.rb +10 -5
  172. data/lib/scarpe/wv/text_drawable.rb +72 -14
  173. data/lib/scarpe/wv/web_wrangler.rb +33 -11
  174. data/lib/scarpe/wv/webview_local_display.rb +6 -2
  175. data/lib/scarpe/wv.rb +8 -1
  176. data/scarpe-components/Gemfile +4 -1
  177. data/scarpe-components/Gemfile.lock +2 -3
  178. data/scarpe-components/README.md +2 -2
  179. data/scarpe-components/assets/bootstrap-themes/bootstrap-cerulean.css +12229 -0
  180. data/scarpe-components/assets/bootstrap-themes/bootstrap-cosmo.css +11810 -0
  181. data/scarpe-components/assets/bootstrap-themes/bootstrap-cyborg.css +12210 -0
  182. data/scarpe-components/assets/bootstrap-themes/bootstrap-darkly.css +12153 -0
  183. data/scarpe-components/assets/bootstrap-themes/bootstrap-flatly.css +12126 -0
  184. data/scarpe-components/assets/bootstrap-themes/bootstrap-icons.min.css +5 -0
  185. data/scarpe-components/assets/bootstrap-themes/bootstrap-journal.css +12099 -0
  186. data/scarpe-components/assets/bootstrap-themes/bootstrap-litera.css +12211 -0
  187. data/scarpe-components/assets/bootstrap-themes/bootstrap-lumen.css +12369 -0
  188. data/scarpe-components/assets/bootstrap-themes/bootstrap-lux.css +11928 -0
  189. data/scarpe-components/assets/bootstrap-themes/bootstrap-materia.css +13184 -0
  190. data/scarpe-components/assets/bootstrap-themes/bootstrap-minty.css +12177 -0
  191. data/scarpe-components/assets/bootstrap-themes/bootstrap-morph.css +12750 -0
  192. data/scarpe-components/assets/bootstrap-themes/bootstrap-pulse.css +11890 -0
  193. data/scarpe-components/assets/bootstrap-themes/bootstrap-quartz.css +12622 -0
  194. data/scarpe-components/assets/bootstrap-themes/bootstrap-sandstone.css +12201 -0
  195. data/scarpe-components/assets/bootstrap-themes/bootstrap-simplex.css +12186 -0
  196. data/scarpe-components/assets/bootstrap-themes/bootstrap-sketchy.css +12451 -0
  197. data/scarpe-components/assets/bootstrap-themes/bootstrap-slate.css +12492 -0
  198. data/scarpe-components/assets/bootstrap-themes/bootstrap-solar.css +12149 -0
  199. data/scarpe-components/assets/bootstrap-themes/bootstrap-spacelab.css +12266 -0
  200. data/scarpe-components/assets/bootstrap-themes/bootstrap-superhero.css +12216 -0
  201. data/scarpe-components/assets/bootstrap-themes/bootstrap-united.css +12077 -0
  202. data/scarpe-components/assets/bootstrap-themes/bootstrap-vapor.css +12549 -0
  203. data/scarpe-components/assets/bootstrap-themes/bootstrap-yeti.css +12325 -0
  204. data/scarpe-components/assets/bootstrap-themes/bootstrap-zephyr.css +12283 -0
  205. data/scarpe-components/assets/bootstrap-themes/bootstrap.bundle.min.js +7 -0
  206. data/scarpe-components/lib/scarpe/components/asset_server.rb +219 -0
  207. data/scarpe-components/lib/scarpe/components/base64.rb +22 -0
  208. data/scarpe-components/lib/scarpe/components/calzini/{art_widgets.rb → art_drawables.rb} +42 -18
  209. data/scarpe-components/lib/scarpe/components/calzini/border.rb +38 -0
  210. data/scarpe-components/lib/scarpe/components/calzini/button.rb +6 -8
  211. data/scarpe-components/lib/scarpe/components/calzini/misc.rb +7 -17
  212. data/scarpe-components/lib/scarpe/components/calzini/para.rb +213 -11
  213. data/scarpe-components/lib/scarpe/components/calzini/slots.rb +14 -60
  214. data/scarpe-components/lib/scarpe/components/calzini.rb +88 -1
  215. data/scarpe-components/lib/scarpe/components/errors.rb +4 -0
  216. data/scarpe-components/lib/scarpe/components/html.rb +4 -1
  217. data/scarpe-components/lib/scarpe/components/minitest_export_reporter.rb +11 -3
  218. data/scarpe-components/lib/scarpe/components/minitest_result.rb +41 -0
  219. data/scarpe-components/lib/scarpe/components/print_logger.rb +17 -2
  220. data/scarpe-components/lib/scarpe/components/process_helpers.rb +37 -0
  221. data/scarpe-components/lib/scarpe/components/segmented_file_loader.rb +1 -1
  222. data/scarpe-components/lib/scarpe/components/tiranti.rb +42 -100
  223. data/scarpe-components/lib/scarpe/components/unit_test_helpers.rb +3 -1
  224. data/scarpe-components/lib/scarpe/components/version.rb +1 -1
  225. data/scarpe-components/test/assets/big-image.png +0 -0
  226. data/scarpe-components/test/assets/big-stylesheet.css +497 -0
  227. data/scarpe-components/test/assets/little-image.png +0 -0
  228. data/scarpe-components/test/assets/little-stylesheet.css +1 -0
  229. data/scarpe-components/test/calzini/test_calzini_art_drawables.rb +7 -7
  230. data/scarpe-components/test/calzini/test_calzini_button.rb +7 -5
  231. data/scarpe-components/test/calzini/test_calzini_misc.rb +9 -9
  232. data/scarpe-components/test/calzini/test_calzini_para.rb +6 -9
  233. data/scarpe-components/test/calzini/test_calzini_slots.rb +12 -57
  234. data/scarpe-components/test/calzini/test_calzini_text_drawables.rb +83 -18
  235. data/scarpe-components/test/calzini/test_various.rb +133 -0
  236. data/scarpe-components/test/test_asset_server.rb +72 -0
  237. data/scarpe-components/test/test_components.rb +31 -2
  238. data/scarpe-components/test/test_helper.rb +0 -1
  239. data/scarpe-components/test/test_minitest_result.rb +7 -0
  240. data/scarpe-components/test/test_segmented_app_files.rb +2 -0
  241. data/tasks/check_html_fixtures.rb +140 -0
  242. data/tasks/regenerate_html_fixtures.rb +104 -0
  243. data/templates/class_template_with_shapes.erb +0 -11
  244. metadata +180 -32
  245. data/lacci/lib/scarpe/niente/logger.rb +0 -29
  246. data/lacci/lib/shoes/drawables/span.rb +0 -27
  247. data/lacci/lib/shoes/spacing.rb +0 -9
  248. data/lib/scarpe/evented_assertions.rb +0 -121
  249. data/lib/scarpe/wv/span.rb +0 -44
  250. data/scarpe-components/lib/scarpe/components/calzini/text_widgets.rb +0 -65
  251. /data/examples/legacy/{not_checked → working}/shoes3-tests/editline/editline.rb +0 -0
@@ -0,0 +1,13 @@
1
+ Shoes.app do
2
+ para "This is normal"
3
+
4
+ para "This is bolder" , font_weight: "bold"
5
+
6
+ para "This is a little less bold" , font_weight: 800
7
+
8
+ para "This is bolder than the last one " , font_weight: 700
9
+
10
+ para "Close to normal " , font_weight: 300
11
+
12
+ end
13
+
@@ -1,3 +1,6 @@
1
+ # html_ci: false
2
+ # This is due to a button rendering issue
3
+
1
4
  require 'nokogiri'
2
5
  require 'open-uri'
3
6
  require 'tempfile'
data/examples/rect.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  Shoes.app do
2
2
  para "Behold, the mighty rectangle!"
3
- rect 10, 10, 75, 50, 5
3
+ rect 10, 10, 75, 50, 5, stroke: red, fill: green
4
4
  end
@@ -0,0 +1,3 @@
1
+ Shoes.app(features: :html) do
2
+ button "OK", html_class: "btn-warning"
3
+ end
@@ -1,5 +1,3 @@
1
1
  Shoes.app do
2
2
  star 230, 100, 6, 50, 25
3
-
4
- end
5
-
3
+ end
data/examples/spacing.rb CHANGED
@@ -7,7 +7,7 @@ Shoes.app(title: "Spacing") do
7
7
  background "red"
8
8
  para "with 10px margin-left and margin-right, and 20px margin-bottom", stroke: "white"
9
9
  end
10
- stack margin: [15, 15, nil, 40] do
10
+ stack margin: [15, nil, 15, 40] do
11
11
  background "blue"
12
12
  para "with 15px margin-left and margin-right, and 40px margin-bottom", stroke: "white"
13
13
  end
data/examples/span.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  Shoes.app :height => 500, :width => 500 do
2
2
  stack :margin => 10 do
3
- para span("TEXT EDITOR", :stroke => "blue", :fill => "green"), " * USE ALT-Q TO QUIT", :stroke => "red"
3
+ para span("TEXT EDITOR", :stroke => blue, :fill => green), " * USE ALT-Q TO QUIT", :stroke => red
4
4
  end
5
- span ("text")
5
+ para "Various ", del("text"), " in ", sub("various"), " ", sup("styles"), " can be ", ins("hard to read"), "...\n"
6
+
7
+ para "A ", span("wide", underline: "single", undercolor: blue), " ", span("variety", underline: "error", undercolor: green), " ", span("of", underline: "double"), " ", span("underlines", underline: "low", undercolor: darkgreen)
6
8
  end
data/lacci/lacci.gemspec CHANGED
@@ -23,14 +23,14 @@ Gem::Specification.new do |spec|
23
23
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
24
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
25
  `git ls-files -z`.split("\x0").reject do |f|
26
- (f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
26
+ (f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features|tasks)/|\.(?:git|travis|circleci)|appveyor)})
27
27
  end
28
28
  end
29
29
  spec.bindir = "exe"
30
30
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
31
  spec.require_paths = ["lib"]
32
32
 
33
- spec.add_dependency "scarpe-components" # Scarpe-Components has no dependencies, and includes useful infrastructure
33
+ spec.add_dependency "scarpe-components", "~>0.4.0"
34
34
 
35
35
  # For more information and examples about making a new gem, check out our
36
36
  # guide at: https://bundler.io/guides/creating_gem.html
@@ -28,7 +28,6 @@ module Scarpe
28
28
  "Lacci" => [
29
29
  env_or_default("SCARPE_DISPLAY_SERVICE", "(none)"),
30
30
  env_or_default("SCARPE_LOG_CONFIG", "(default)#{Shoes::Log::DEFAULT_LOG_CONFIG.inspect}"),
31
- env_or_default("SCARPE_APP_TEST", "(none)"),
32
31
  ],
33
32
  "Ruby and Shell" => [
34
33
  ["RUBY_DESCRIPTION", RUBY_DESCRIPTION],
@@ -9,5 +9,5 @@
9
9
  # mostly invisible. Instead, look at the {Shoes} module
10
10
  # to see what's in Lacci.
11
11
  module Lacci
12
- VERSION = "0.3.0"
12
+ VERSION = "0.4.0"
13
13
  end
@@ -29,7 +29,7 @@ module Niente
29
29
  # @param properties [Hash] a JSON-serialisable Hash with the drawable's Shoes styles
30
30
  # @param is_widget [Boolean] whether the class is a user-defined Shoes::Widget subclass
31
31
  # @return [Webview::Drawable] the newly-created Webview drawable
32
- def create_display_drawable_for(drawable_class_name, drawable_id, properties, is_widget:)
32
+ def create_display_drawable_for(drawable_class_name, drawable_id, properties, parent_id:, is_widget:)
33
33
  existing = query_display_drawable_for(drawable_id, nil_ok: true)
34
34
  if existing
35
35
  @log.warn("There is already a display drawable for #{drawable_id.inspect}! Returning #{existing.class.name}.")
@@ -47,6 +47,10 @@ module Niente
47
47
  display_drawable.shoes_type = drawable_class_name
48
48
  set_drawable_pairing(drawable_id, display_drawable)
49
49
 
50
+ # Nil parent is okay for DocumentRoot and TextDrawables, so we have to specify it.
51
+ parent = DisplayService.instance.query_display_drawable_for(parent_id, nil_ok: true)
52
+ display_drawable.set_parent(parent)
53
+
50
54
  return display_drawable
51
55
  end
52
56
 
@@ -12,6 +12,7 @@ module Niente
12
12
 
13
13
  super(linkable_id: @shoes_linkable_id)
14
14
 
15
+ # This should only be used for reparenting after a drawable was initially created.
15
16
  bind_shoes_event(event_name: "parent", target: shoes_linkable_id) do |new_parent_id|
16
17
  display_parent = DisplayService.instance.query_display_drawable_for(new_parent_id)
17
18
  if @parent != display_parent
@@ -28,6 +29,7 @@ module Niente
28
29
  end
29
30
 
30
31
  bind_shoes_event(event_name: "destroy", target: shoes_linkable_id) do
32
+ set_parent(nil)
31
33
  end
32
34
  end
33
35
 
@@ -30,7 +30,6 @@ class Niente::Test
30
30
  Object.const_set(Scarpe::Components::StringHelpers.camelize(class_name), test_class)
31
31
  test_name = "test_" + test_name unless test_name.start_with?("test_")
32
32
  test_class.define_method(test_name) do
33
- STDERR.puts "Started running #{class_name.inspect}::#{test_name.inspect}"
34
33
  eval(code)
35
34
  end
36
35
  end
@@ -50,6 +49,13 @@ class Niente::ShoesSpecTest < Minitest::Test
50
49
  Niente::ShoesSpecProxy.new(drawables[0])
51
50
  end
52
51
  end
52
+
53
+ def drawable(*specs)
54
+ drawables = Shoes::App.instance.find_drawables_by(*specs)
55
+ raise Shoes::Errors::MultipleDrawablesFoundError, "Found more than one #{finder_name} matching #{args.inspect}!" if drawables.size > 1
56
+ raise Shoes::Errors::NoDrawablesFoundError, "Found no #{finder_name} matching #{args.inspect}!" if drawables.empty?
57
+ Niente::ShoesSpecProxy.new(drawables[0])
58
+ end
53
59
  end
54
60
 
55
61
  class Niente::ShoesSpecProxy
@@ -6,8 +6,16 @@
6
6
  # how a real display service should act.
7
7
  module Niente; end
8
8
 
9
- require_relative "niente/logger"
10
- Shoes::Log.instance = Niente::LogImpl.new
9
+ require "scarpe/components/print_logger"
10
+ Shoes::Log.instance = Scarpe::Components::PrintLogImpl.new
11
+ if ENV["NIENTE_LOG_LEVEL"]
12
+ pl = Scarpe::Components::PrintLogImpl::PrintLogger
13
+ level = ENV["NIENTE_LOG_LEVEL"].strip.downcase.to_sym
14
+ unless pl::LEVELS.key?(level)
15
+ raise "Unrecognized Niente log level: #{level.inspect}!"
16
+ end
17
+ pl.min_level = pl::LEVELS[level]
18
+ end
11
19
 
12
20
  require_relative "niente/drawable"
13
21
  require_relative "niente/app"
@@ -16,5 +24,9 @@ require_relative "niente/display_service"
16
24
  require_relative "niente/shoes_spec"
17
25
  Shoes::Spec.instance = Niente::Test
18
26
 
27
+ require "scarpe/components/segmented_file_loader"
28
+ loader = Scarpe::Components::SegmentedFileLoader.new
29
+ Shoes.add_file_loader loader
30
+
19
31
  Shoes::DisplayService.set_display_service_class(Niente::DisplayService)
20
32
 
@@ -8,17 +8,29 @@ class Shoes
8
8
  attr_accessor :instance
9
9
  end
10
10
 
11
+ # The Shoes root of the drawable tree
11
12
  attr_reader :document_root
12
13
 
13
- shoes_styles :title, :width, :height, :resizable
14
+ # The application directory for this app. Often this will be the directory
15
+ # containing the launched application file.
16
+ attr_reader :dir
17
+
18
+ shoes_styles :title, :width, :height, :resizable, :features
19
+
20
+ # This is defined to avoid the linkable-id check in the Shoes-style method_missing def'n
21
+ def features
22
+ @features
23
+ end
14
24
 
15
25
  CUSTOM_EVENT_LOOP_TYPES = ["displaylib", "return", "wait"]
16
26
 
27
+ init_args
17
28
  def initialize(
18
29
  title: "Shoes!",
19
30
  width: 480,
20
31
  height: 420,
21
32
  resizable: true,
33
+ features: [],
22
34
  &app_code_body
23
35
  )
24
36
  log_init("Shoes::App")
@@ -30,36 +42,35 @@ class Shoes
30
42
  Shoes::App.instance = self
31
43
  end
32
44
 
45
+ # We cd to the app's containing dir when running the app
46
+ @dir = Dir.pwd
47
+
33
48
  @do_shutdown = false
34
49
  @event_loop_type = "displaylib" # the default
35
50
 
36
- super
51
+ @features = features
52
+
53
+ unknown_ext = features - Shoes::FEATURES - Shoes::EXTENSIONS
54
+ unsupported_features = unknown_ext & Shoes::KNOWN_FEATURES
55
+ unless unsupported_features.empty?
56
+ @log.error("Shoes app requires feature(s) not supported by this display service: #{unsupported_features.inspect}!")
57
+ raise Shoes::Errors::UnsupportedFeatureError, "Shoes app needs features: #{unsupported_features.inspect}"
58
+ end
59
+ unless unknown_ext.empty?
60
+ @log.warn("Shoes app requested unknown features #{unknown_ext.inspect}! Known: #{(Shoes::FEATURES + Shoes::EXTENSIONS).inspect}")
61
+ end
62
+
63
+ @slots = []
37
64
 
38
- # The draw context tracks current settings like fill and stroke,
39
- # plus potentially other current state that changes from drawable
40
- # to drawable and slot to slot.
41
- @draw_context = {
42
- "fill" => "",
43
- "stroke" => "",
44
- "rotate" => 0,
45
- }
65
+ super
46
66
 
47
67
  # This creates the DocumentRoot, including its corresponding display drawable
48
68
  @document_root = Shoes::DocumentRoot.new
49
69
 
50
- @slots = []
51
-
52
70
  # Now create the App display drawable
53
71
  create_display_drawable
54
72
 
55
- # Set up testing events *after* Display Service basic objects exist
56
- if ENV["SCARPE_APP_TEST"]
57
- test_code = File.read ENV["SCARPE_APP_TEST"]
58
- if test_code != ""
59
- @test_obj = Object.new
60
- @test_obj.instance_eval test_code
61
- end
62
- end
73
+ # Set up testing *after* Display Service basic objects exist
63
74
 
64
75
  if ENV["SHOES_SPEC_TEST"]
65
76
  test_code = File.read ENV["SHOES_SPEC_TEST"]
@@ -133,22 +144,17 @@ class Shoes
133
144
  return super unless klass
134
145
 
135
146
  ::Shoes::App.define_method(name) do |*args, **kwargs, &block|
136
- # Look up the Shoes drawable and create it...
137
- drawable_instance = klass.new(*args, **kwargs, &block)
138
-
139
- unless klass.ancestors.include?(::Shoes::TextDrawable)
140
- # Create this drawable in the current app slot
141
- drawable_instance.set_parent ::Shoes::App.instance.current_slot
142
- end
143
-
144
- drawable_instance
147
+ klass.new(*args, **kwargs, &block)
145
148
  end
146
149
 
147
150
  send(name, *args, **kwargs, &block)
148
151
  end
149
152
 
153
+ # Get the current draw context for the current slot
154
+ #
155
+ # @return [Hash] a hash of Shoes styles for the current draw context
150
156
  def current_draw_context
151
- @draw_context.dup
157
+ current_slot&.current_draw_context
152
158
  end
153
159
 
154
160
  # This usually doesn't return. The display service may take control
@@ -190,7 +196,7 @@ class Shoes
190
196
  def all_drawables
191
197
  out = []
192
198
 
193
- to_add = @document_root.children
199
+ to_add = [@document_root, @document_root.children]
194
200
  until to_add.empty?
195
201
  out.concat(to_add)
196
202
  to_add = to_add.flat_map { |w| w.respond_to?(:children) ? w.children : [] }.compact
@@ -256,30 +262,21 @@ end
256
262
 
257
263
  # These methods will need to be defined on Slots too, but probably need a rework in general.
258
264
  class Shoes::App < Shoes::Drawable
265
+ # This is going to go away. See issue #496
259
266
  def background(...)
260
267
  current_slot.background(...)
261
268
  end
262
269
 
270
+ # This is going to go away. See issue #498
263
271
  def border(...)
264
272
  current_slot.border(...)
265
273
  end
266
274
 
267
- # Draw context methods
268
-
269
- def fill(color)
270
- @draw_context["fill"] = color
271
- end
272
-
273
- def nofill
274
- @draw_context["fill"] = ""
275
- end
276
-
277
- def stroke(color)
278
- @draw_context["stroke"] = color
279
- end
280
-
281
- def nostroke
282
- @draw_context["stroke"] = ""
275
+ # Draw Context methods -- forward to the current slot
276
+ [:fill, :nofill, :stroke, :strokewidth, :nostroke, :rotate].each do |dc_method|
277
+ define_method(dc_method) do |*args|
278
+ current_slot.send(dc_method, *args)
279
+ end
283
280
  end
284
281
 
285
282
  # Shape DSL methods
@@ -300,9 +297,6 @@ class Shoes::App < Shoes::Drawable
300
297
  end
301
298
  end
302
299
 
303
- def rotate(angle)
304
- @draw_context["rotate"] = angle
305
- end
306
300
  # Not implemented yet: curve_to, arc_to
307
301
 
308
302
  alias_method :info, :puts
@@ -13,10 +13,10 @@ class Shoes
13
13
  [ENV["LOCALAPPDATA"], "Shoes"],
14
14
  [ENV["APPDATA"], "Shoes"],
15
15
  [ENV["HOME"], ".shoes"],
16
- [Dir.tmpdir, "shoes"],
17
16
  ]
18
17
 
19
18
  top, file = homes.detect { |home_top, _| home_top && File.exist?(home_top) }
19
+ return nil if top.nil?
20
20
  File.join(top, file)
21
21
  end
22
22
 
@@ -32,8 +32,29 @@ class Shoes
32
32
  HALF_PI = 1.57079632679489661923
33
33
  PI = 3.14159265358979323846
34
34
 
35
- # This should be set up by the Display Service when it loads
35
+ # These should be set up by the Display Service when it loads. They are intentionally
36
+ # *not* frozen so that the Display Service can add to them (and then optionally
37
+ # freeze them.)
38
+
39
+ # Fonts currently loaded and available
36
40
  FONTS = []
41
+
42
+ # Standard features available in this display service - see KNOWN_FEATURES.
43
+ # These may or may not require the Shoes.app requesting them per-app.
44
+ FEATURES = []
45
+
46
+ # Nonstandard extensions, e.g. Scarpe extensions, supported by this display lib.
47
+ # An application may have to request the extensions for them to be available so
48
+ # that a casual reader can see Shoes.app(features: :scarpe) and realize why
49
+ # there are nonstandard styles or drawables.
50
+ EXTENSIONS = []
51
+
52
+ # These are all known features supported by this version of Lacci.
53
+ # Features on this list are allowed to be in FEATURES. Anything else
54
+ # goes in EXTENSIONS and is nonstandard.
55
+ KNOWN_FEATURES = [
56
+ :html, # Supports .to_html on display objects, HTML classes on drawables, etc.
57
+ ].freeze
37
58
  end
38
59
 
39
60
  # Access and assign the release constants
@@ -32,7 +32,14 @@ class Shoes
32
32
  # This is in the eigenclass/metaclass, *not* instances of DisplayService
33
33
  include Shoes::Log
34
34
 
35
+ # Send a Shoes event to all subscribers.
35
36
  # An event_target may be nil, to indicate there is no target.
37
+ #
38
+ # @param event_name [String] the name of the event
39
+ # @param event_target [String] the specific target, if any
40
+ # @param args [Array] arguments to pass to the subscribing block
41
+ # @param args [Array] keyword arguments to pass to the subscribing block
42
+ # @return [void]
36
43
  def dispatch_event(event_name, event_target, *args, **kwargs)
37
44
  @@display_event_handlers ||= {}
38
45
 
@@ -69,10 +76,20 @@ class Shoes
69
76
  kwargs[:event_name] = event_name
70
77
  kwargs[:event_target] = event_target if event_target
71
78
  handlers.each { |h| h[:handler].call(*args, **kwargs) }
79
+ nil
72
80
  end
73
81
 
74
- # It's permitted to subscribe to event_name :any for all event names, and event_target :any for all targets.
75
- # An event_target of nil means "no target", and only matches events dispatched with a nil target.
82
+ # Subscribe to the given event name and target.
83
+ # It's permitted to subscribe to event_name :any for all event names,
84
+ # and event_target :any for all targets. An event_target of nil means
85
+ # "no target", and only matches events dispatched with a nil target.
86
+ # The subscription will return an unsubscribe ID, which can be used
87
+ # later to unsubscribe from the notification.
88
+ #
89
+ # @param event_name [String,Symbol] the event name to subscribe to, or :any for all event names
90
+ # @param event_target [String,Symbol,NilClass] the event target to subscribe to, or :any for all targets - nil is a valid target
91
+ # @block the block to call when the event occurs - it will receive arguments from the event-dispatch call
92
+ # @return [Integer] an unsubscription ID which can be used later to cancel the subscription
76
93
  def subscribe_to_event(event_name, event_target, &handler)
77
94
  @@display_event_handlers ||= {}
78
95
  @@display_event_unsub_id ||= 0
@@ -96,6 +113,10 @@ class Shoes
96
113
  id
97
114
  end
98
115
 
116
+ # Unsubscribe from any event subscriptions matching the unsub ID.
117
+ #
118
+ # @param unsub_id [Integer] the unsub ID returned when subscribing
119
+ # @return [void]
99
120
  def unsub_from_events(unsub_id)
100
121
  raise "Must provide an unsubscribe ID!" if unsub_id.nil?
101
122
 
@@ -106,17 +127,32 @@ class Shoes
106
127
  end
107
128
  end
108
129
 
130
+ # Reset the display service, for instance between unit tests.
131
+ # This destroys all existing subscriptions.
132
+ #
133
+ # @return [void]
109
134
  def full_reset!
110
135
  @@display_event_handlers = {}
111
136
  @json_debug_serialize = nil
112
137
  end
113
138
 
139
+ # Set the Display Service class which will handle display service functions
140
+ # for this process. This can only be set once. The display service can be
141
+ # a subclass of Shoes::DisplayService, but isn't required to be.
142
+ #
143
+ # Shoes will create an instance of this class with no arguments passed to
144
+ # initialize, and use it as the display service for the lifetime of the
145
+ # process.
146
+ #
147
+ # @param klass [Class] the class for the display service
114
148
  def set_display_service_class(klass)
115
149
  raise "Can only set a single display service class!" if @display_service_klass
116
150
 
117
151
  @display_service_klass = klass
118
152
  end
119
153
 
154
+ # Get the current display service instance. This requires a display service
155
+ # class having been set first. @see set_display_service_class
120
156
  def display_service
121
157
  return @service if @service
122
158
 
@@ -126,9 +162,13 @@ class Shoes
126
162
  end
127
163
  end
128
164
 
165
+ def initialize
166
+ @display_drawable_for = {}
167
+ end
168
+
129
169
  # These methods are an interface to DisplayService objects.
130
170
 
131
- def create_display_drawable_for(drawable_class_name, drawable_id, properties, is_widget:)
171
+ def create_display_drawable_for(drawable_class_name, drawable_id, properties, parent_id:, is_widget:)
132
172
  raise "Override in DisplayService implementation!"
133
173
  end
134
174
 
@@ -174,7 +214,6 @@ class Shoes
174
214
  def initialize(linkable_id: object_id)
175
215
  @linkable_id = linkable_id
176
216
  @subscriptions = {}
177
- @display_drawable_for ||= {}
178
217
  end
179
218
 
180
219
  def send_self_event(*args, event_name:, **kwargs)