scarpe 0.2.1 → 0.2.2

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 (240) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -0
  3. data/.yardopts +11 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +112 -0
  6. data/README.md +31 -24
  7. data/Rakefile +13 -1
  8. data/docs/yard/catscradle.md +44 -0
  9. data/docs/yard/template/default/fulldoc/html/setup.rb +13 -0
  10. data/docs/yard/template/default/layout/html/setup.rb +9 -0
  11. data/examples/background_with_image.rb +16 -0
  12. data/examples/bloopsaphone/working/bronx_army_knife.rb +66 -0
  13. data/examples/bloopsaphone/working/morning_serenity.rb +21 -0
  14. data/examples/bloopsaphone/working/simpsons_theme_song_by_why.rb +6 -4
  15. data/examples/button_go_away.rb +1 -1
  16. data/examples/check.rb +18 -0
  17. data/examples/clear_and_append.rb +24 -0
  18. data/examples/download_and_show_image.rb +28 -0
  19. data/examples/edit_box.rb +3 -5
  20. data/examples/fonts.rb +2 -2
  21. data/examples/get_headers.rb +10 -0
  22. data/examples/highlander.rb +2 -0
  23. data/examples/link.rb +2 -2
  24. data/examples/local_fonts.rb +4 -0
  25. data/examples/local_images.rb +4 -0
  26. data/examples/motion_events.rb +20 -0
  27. data/examples/parse_xl_funnies.rb +58 -0
  28. data/examples/radio/radio.rb +16 -0
  29. data/examples/radio/radio_groups.rb +18 -0
  30. data/examples/radio/radio_same_slot.rb +6 -0
  31. data/examples/ruby_racer.rb +13 -15
  32. data/examples/selfitude.rb +18 -0
  33. data/examples/shapes/shapes_fill.rb +4 -3
  34. data/examples/shoes_school.rb +2 -4
  35. data/examples/show_hide.rb +6 -0
  36. data/examples/skip_ci/change_my_audio_source.rb +21 -0
  37. data/examples/skip_ci/guitar_fretboard.rb +137 -0
  38. data/examples/video.rb +10 -0
  39. data/exe/scarpe +42 -66
  40. data/fonts/Pacifico.ttf +0 -0
  41. data/lacci/Gemfile +22 -0
  42. data/lacci/Gemfile.lock +72 -0
  43. data/lacci/Rakefile +12 -0
  44. data/lacci/lacci.gemspec +37 -0
  45. data/lacci/lib/lacci/scarpe_cli.rb +70 -0
  46. data/lacci/lib/lacci/scarpe_core.rb +21 -0
  47. data/lacci/lib/lacci/version.rb +13 -0
  48. data/lacci/lib/shoes/app.rb +264 -0
  49. data/{lib/scarpe → lacci/lib/shoes}/background.rb +1 -1
  50. data/{lib/scarpe → lacci/lib/shoes}/border.rb +1 -1
  51. data/{lib/scarpe → lacci/lib/shoes}/colors.rb +1 -1
  52. data/lacci/lib/shoes/constants.rb +29 -0
  53. data/{lib/scarpe → lacci/lib/shoes}/display_service.rb +40 -45
  54. data/lacci/lib/shoes/download.rb +123 -0
  55. data/lacci/lib/shoes/log.rb +71 -0
  56. data/lacci/lib/shoes/spacing.rb +9 -0
  57. data/{lib/scarpe → lacci/lib/shoes}/widget.rb +63 -43
  58. data/{lib/scarpe → lacci/lib/shoes/widgets}/alert.rb +3 -3
  59. data/{lib/scarpe → lacci/lib/shoes/widgets}/arc.rb +7 -5
  60. data/{lib/scarpe → lacci/lib/shoes/widgets}/button.rb +3 -3
  61. data/lacci/lib/shoes/widgets/check.rb +28 -0
  62. data/lacci/lib/shoes/widgets/document_root.rb +20 -0
  63. data/{lib/scarpe → lacci/lib/shoes/widgets}/edit_box.rb +10 -5
  64. data/{lib/scarpe → lacci/lib/shoes/widgets}/edit_line.rb +2 -2
  65. data/lacci/lib/shoes/widgets/flow.rb +22 -0
  66. data/lacci/lib/shoes/widgets/font.rb +14 -0
  67. data/{lib/scarpe → lacci/lib/shoes/widgets}/image.rb +3 -7
  68. data/lacci/lib/shoes/widgets/line.rb +18 -0
  69. data/{lib/scarpe → lacci/lib/shoes/widgets}/link.rb +2 -2
  70. data/{lib/scarpe → lacci/lib/shoes/widgets}/list_box.rb +2 -2
  71. data/{lib/scarpe → lacci/lib/shoes/widgets}/para.rb +4 -26
  72. data/lacci/lib/shoes/widgets/radio.rb +35 -0
  73. data/lacci/lib/shoes/widgets/shape.rb +37 -0
  74. data/lacci/lib/shoes/widgets/slot.rb +75 -0
  75. data/{lib/scarpe → lacci/lib/shoes/widgets}/span.rb +2 -2
  76. data/lacci/lib/shoes/widgets/stack.rb +24 -0
  77. data/{lib/scarpe → lacci/lib/shoes/widgets}/star.rb +6 -9
  78. data/lacci/lib/shoes/widgets/subscription_item.rb +60 -0
  79. data/lacci/lib/shoes/widgets/text_widget.rb +51 -0
  80. data/lacci/lib/shoes/widgets/video.rb +15 -0
  81. data/lacci/lib/shoes/widgets.rb +29 -0
  82. data/lacci/lib/shoes.rb +127 -0
  83. data/lacci/test/test_colors.rb +39 -0
  84. data/lacci/test/test_helper.rb +9 -0
  85. data/lacci/test/test_lacci.rb +9 -0
  86. data/lib/scarpe/cats_cradle.rb +249 -0
  87. data/lib/scarpe/evented_assertions.rb +88 -0
  88. data/lib/scarpe/version.rb +1 -1
  89. data/lib/scarpe/wv/alert.rb +3 -2
  90. data/lib/scarpe/wv/app.rb +30 -8
  91. data/lib/scarpe/wv/arc.rb +5 -6
  92. data/lib/scarpe/wv/background.rb +10 -1
  93. data/lib/scarpe/wv/border.rb +5 -3
  94. data/lib/scarpe/wv/button.rb +11 -9
  95. data/lib/scarpe/wv/check.rb +29 -0
  96. data/lib/scarpe/wv/control_interface.rb +14 -20
  97. data/lib/scarpe/wv/control_interface_test.rb +13 -28
  98. data/lib/scarpe/wv/document_root.rb +3 -45
  99. data/lib/scarpe/wv/edit_box.rb +5 -7
  100. data/lib/scarpe/wv/edit_line.rb +2 -2
  101. data/lib/scarpe/wv/flow.rb +10 -20
  102. data/lib/scarpe/wv/font.rb +36 -0
  103. data/lib/scarpe/wv/html.rb +3 -2
  104. data/lib/scarpe/wv/image.rb +7 -2
  105. data/lib/scarpe/wv/line.rb +4 -7
  106. data/lib/scarpe/wv/link.rb +1 -0
  107. data/lib/scarpe/wv/list_box.rb +3 -3
  108. data/lib/scarpe/wv/para.rb +16 -14
  109. data/lib/scarpe/wv/radio.rb +34 -0
  110. data/lib/scarpe/wv/shape.rb +44 -8
  111. data/lib/scarpe/wv/slot.rb +81 -0
  112. data/lib/scarpe/wv/spacing.rb +1 -1
  113. data/lib/scarpe/wv/span.rb +10 -8
  114. data/lib/scarpe/wv/stack.rb +10 -30
  115. data/lib/scarpe/wv/star.rb +11 -12
  116. data/lib/scarpe/wv/subscription_item.rb +50 -0
  117. data/lib/scarpe/wv/video.rb +34 -0
  118. data/lib/scarpe/wv/web_wrangler.rb +238 -58
  119. data/lib/scarpe/wv/webview_local_display.rb +27 -5
  120. data/lib/scarpe/wv/webview_relay_display.rb +18 -119
  121. data/lib/scarpe/wv/webview_relay_util.rb +143 -0
  122. data/lib/scarpe/wv/widget.rb +80 -11
  123. data/lib/scarpe/wv/wv_display_worker.rb +17 -4
  124. data/lib/scarpe/wv.rb +33 -4
  125. data/lib/scarpe/wv_local.rb +1 -1
  126. data/lib/scarpe/wv_relay.rb +1 -1
  127. data/lib/scarpe.rb +3 -32
  128. data/scarpe-components/.gitignore +1 -0
  129. data/scarpe-components/Gemfile +22 -0
  130. data/scarpe-components/README.md +35 -0
  131. data/scarpe-components/Rakefile +12 -0
  132. data/scarpe-components/lib/scarpe/components/base64.rb +29 -0
  133. data/scarpe-components/lib/scarpe/components/file_helpers.rb +65 -0
  134. data/scarpe-components/lib/scarpe/components/modular_logger.rb +113 -0
  135. data/scarpe-components/lib/scarpe/components/print_logger.rb +43 -0
  136. data/{lib/scarpe → scarpe-components/lib/scarpe/components}/promises.rb +102 -35
  137. data/scarpe-components/lib/scarpe/components/segmented_file_loader.rb +170 -0
  138. data/scarpe-components/lib/scarpe/components/unit_test_helpers.rb +217 -0
  139. data/scarpe-components/lib/scarpe/components/version.rb +7 -0
  140. data/scarpe-components/scarpe-components.gemspec +38 -0
  141. data/scarpe-components/test/test_components.rb +9 -0
  142. data/scarpe-components/test/test_helper.rb +23 -0
  143. data/scarpe-components/test/test_promises.rb +260 -0
  144. data/scarpe-components/test/test_segmented_app_files.rb +182 -0
  145. data/{lib/scarpe → spikes}/glibui/widget.rb +2 -2
  146. data/{lib/scarpe → spikes}/glibui.rb +1 -1
  147. data/templates/basic_class_template.erb +1 -1
  148. data/templates/class_template_with_event_bind.erb +1 -1
  149. data/templates/class_template_with_shapes.erb +1 -1
  150. data/templates/webview_template.erb +0 -3
  151. metadata +151 -118
  152. data/examples/fill.rb +0 -25
  153. data/examples/legacy/not_checked/shoes-contrib/basic/class-book.yaml +0 -387
  154. data/examples/legacy/not_checked/shoes-contrib/good/good-clock.rb +0 -51
  155. data/examples/legacy/not_checked/shoes-contrib/good/good-follow.rb +0 -26
  156. data/examples/legacy/not_checked/shoes-contrib/good/good-reminder.rb +0 -174
  157. data/examples/legacy/not_checked/shoes-contrib/good/good-vjot.rb +0 -56
  158. data/examples/legacy/not_checked/shoes-contrib/simple/simple-timer.rb +0 -13
  159. data/examples/legacy/not_checked/shoes-dep-samples/good-clock.rb +0 -51
  160. data/examples/legacy/not_checked/shoes-dep-samples/good-follow.rb +0 -26
  161. data/examples/legacy/not_checked/shoes-dep-samples/good-reminder.rb +0 -174
  162. data/examples/legacy/not_checked/shoes-dep-samples/good-vjot.rb +0 -56
  163. data/examples/legacy/not_checked/shoes-dep-samples/simple-accordion.rb +0 -75
  164. data/examples/legacy/not_checked/shoes-dep-samples/simple-anim-shapes.rb +0 -17
  165. data/examples/legacy/not_checked/shoes-dep-samples/simple-anim-text.rb +0 -13
  166. data/examples/legacy/not_checked/shoes-dep-samples/simple-arc.rb +0 -23
  167. data/examples/legacy/not_checked/shoes-dep-samples/simple-bounce.rb +0 -24
  168. data/examples/legacy/not_checked/shoes-dep-samples/simple-calc.rb +0 -70
  169. data/examples/legacy/not_checked/shoes-dep-samples/simple-chipmunk.rb +0 -26
  170. data/examples/legacy/not_checked/shoes-dep-samples/simple-control-sizes.rb +0 -24
  171. data/examples/legacy/not_checked/shoes-dep-samples/simple-curve.rb +0 -26
  172. data/examples/legacy/not_checked/shoes-dep-samples/simple-dialogs.rb +0 -29
  173. data/examples/legacy/not_checked/shoes-dep-samples/simple-draw.rb +0 -13
  174. data/examples/legacy/not_checked/shoes-dep-samples/simple-editor.rb +0 -28
  175. data/examples/legacy/not_checked/shoes-dep-samples/simple-form.rb +0 -28
  176. data/examples/legacy/not_checked/shoes-dep-samples/simple-form.shy +0 -0
  177. data/examples/legacy/not_checked/shoes-dep-samples/simple-mask.rb +0 -21
  178. data/examples/legacy/not_checked/shoes-dep-samples/simple-menu.rb +0 -31
  179. data/examples/legacy/not_checked/shoes-dep-samples/simple-menu1.rb +0 -35
  180. data/examples/legacy/not_checked/shoes-dep-samples/simple-rubygems.rb +0 -29
  181. data/examples/legacy/not_checked/shoes-dep-samples/simple-slide.rb +0 -45
  182. data/examples/legacy/not_checked/shoes-dep-samples/simple-sphere.rb +0 -28
  183. data/examples/legacy/not_checked/shoes-dep-samples/simple-sqlite3.rb +0 -13
  184. data/examples/legacy/not_checked/shoes-dep-samples/simple-timer.rb +0 -13
  185. data/examples/legacy/not_checked/shoes-dep-samples/simple-video.rb +0 -13
  186. data/examples/legacy/not_checked/simple/anim-text.rb +0 -13
  187. data/examples/legacy/not_checked/simple/arc.rb +0 -23
  188. data/examples/legacy/not_checked/simple/bounce.rb +0 -24
  189. data/examples/legacy/not_checked/simple/chipmunk.rb +0 -26
  190. data/examples/legacy/not_checked/simple/curve.rb +0 -26
  191. data/examples/legacy/not_checked/simple/dialogs.rb +0 -29
  192. data/examples/legacy/not_checked/simple/downloader.rb +0 -40
  193. data/examples/legacy/not_checked/simple/draw.rb +0 -13
  194. data/examples/legacy/not_checked/simple/mask.rb +0 -21
  195. data/examples/legacy/not_checked/simple/slide.rb +0 -45
  196. data/examples/legacy/not_checked/simple/sphere.rb +0 -28
  197. data/lib/constants.rb +0 -5
  198. data/lib/scarpe/app.rb +0 -78
  199. data/lib/scarpe/document_root.rb +0 -20
  200. data/lib/scarpe/fill.rb +0 -23
  201. data/lib/scarpe/flow.rb +0 -19
  202. data/lib/scarpe/line.rb +0 -25
  203. data/lib/scarpe/logger.rb +0 -155
  204. data/lib/scarpe/shape.rb +0 -19
  205. data/lib/scarpe/spacing.rb +0 -9
  206. data/lib/scarpe/stack.rb +0 -70
  207. data/lib/scarpe/text_widget.rb +0 -42
  208. data/lib/scarpe/unit_test_helpers.rb +0 -163
  209. data/lib/scarpe/widgets.rb +0 -30
  210. data/lib/scarpe/wv/fill.rb +0 -30
  211. data/lib/scarpe/wv/shape_helper.rb +0 -44
  212. data/scarpe-0.2.0.gem +0 -0
  213. /data/{lib/scarpe → spikes}/glibui/README.md +0 -0
  214. /data/{lib/scarpe → spikes}/glibui/alert.rb +0 -0
  215. /data/{lib/scarpe → spikes}/glibui/app.rb +0 -0
  216. /data/{lib/scarpe → spikes}/glibui/background.rb +0 -0
  217. /data/{lib/scarpe → spikes}/glibui/border.rb +0 -0
  218. /data/{lib/scarpe → spikes}/glibui/button.rb +0 -0
  219. /data/{lib/scarpe → spikes}/glibui/dimensions.rb +0 -0
  220. /data/{lib/scarpe → spikes}/glibui/document_root.rb +0 -0
  221. /data/{lib/scarpe → spikes}/glibui/edit_box.rb +0 -0
  222. /data/{lib/scarpe → spikes}/glibui/edit_line.rb +0 -0
  223. /data/{lib/scarpe → spikes}/glibui/flow.rb +0 -0
  224. /data/{lib/scarpe → spikes}/glibui/html.rb +0 -0
  225. /data/{lib/scarpe → spikes}/glibui/image.rb +0 -0
  226. /data/{lib/scarpe → spikes}/glibui/link.rb +0 -0
  227. /data/{lib/scarpe → spikes}/glibui/local_display.rb +0 -0
  228. /data/{lib/scarpe → spikes}/glibui/para.rb +0 -0
  229. /data/{lib/scarpe → spikes}/glibui/spacing.rb +0 -0
  230. /data/{lib/scarpe → spikes}/glibui/stack.rb +0 -0
  231. /data/{lib/scarpe → spikes}/glibui/text_widget.rb +0 -0
  232. /data/{lib/scarpe → spikes}/libui/alert.rb +0 -0
  233. /data/{lib/scarpe → spikes}/libui/button.rb +0 -0
  234. /data/{lib/scarpe → spikes}/libui/colors.rb +0 -0
  235. /data/{lib/scarpe → spikes}/libui/core.rb +0 -0
  236. /data/{lib/scarpe → spikes}/libui/flow.rb +0 -0
  237. /data/{lib/scarpe → spikes}/libui/libui.rb +0 -0
  238. /data/{lib/scarpe → spikes}/libui/notepad.md +0 -0
  239. /data/{lib/scarpe → spikes}/libui/para.rb +0 -0
  240. /data/{lib/scarpe → spikes}/libui/stack.rb +0 -0
@@ -1,15 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Scarpe
4
- class Para < Scarpe::Widget
5
- class << self
6
- def inherited(subclass)
7
- Scarpe::Widget.widget_classes ||= []
8
- Scarpe::Widget.widget_classes << subclass
9
- super
10
- end
11
- end
12
-
3
+ module Shoes
4
+ class Para < Shoes::Widget
13
5
  display_properties :text_items, :stroke, :size, :font, :html_attributes, :hidden
14
6
 
15
7
  def initialize(*args, stroke: nil, size: :para, font: nil, hidden: false, **html_attributes)
@@ -42,24 +34,10 @@ class Scarpe
42
34
  # This should signal the display widget to change
43
35
  self.text_items = text_children_to_items(@text_children)
44
36
  end
45
-
46
- def hide
47
- # idempotent
48
- return unless @hidden_text_items.empty?
49
-
50
- @hidden_text_items = self.text_items
51
- self.text_items = []
52
- end
53
-
54
- def show
55
- # idempotent
56
- return unless self.text_items.empty?
57
-
58
- self.text_items = @hidden_text_items
59
- @hidden_text_items = []
60
- end
61
37
  end
38
+ end
62
39
 
40
+ module Shoes
63
41
  class Widget
64
42
  def banner(*args, **kwargs)
65
43
  para(*args, **{ size: :banner }.merge(kwargs))
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shoes
4
+ class Radio < Shoes::Widget
5
+ display_properties :group, :checked
6
+
7
+ def initialize(group = nil, checked = nil, &block)
8
+ @group = group
9
+ @block = block
10
+ super
11
+
12
+ bind_self_event("click") { click }
13
+ create_display_widget
14
+ end
15
+
16
+ def click(&block)
17
+ @block = block
18
+ self.checked = !checked?
19
+ end
20
+
21
+ def checked?
22
+ @checked ? true : false
23
+ end
24
+
25
+ def checked(value)
26
+ self.checked = value
27
+ end
28
+
29
+ private
30
+
31
+ def group_name
32
+ @group || @parent
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shoes
4
+ # A Shape acts as a sort of union type for drawn shapes. In Shoes you can use it to merge multiple
5
+ # ovals, arcs, stars, etc. into a single drawn shape.
6
+ #
7
+ # In Shoes3, a Shape isn't really a Slot. It's a kind of DSL with drawing commands that happen
8
+ # to have the same name as the Art widgets like star, arc, etc. Here we're treating it as
9
+ # a slot containing those widgets, which is wrong but not *too* wrong.
10
+ #
11
+ # @incompatibility A Shoes3 Shape is *not* a slot; Scarpe does *not* do union shapes
12
+ class Shape < Shoes::Slot
13
+ display_properties :left, :top, :shape_commands, :draw_context
14
+
15
+ def initialize(left: nil, top: nil, &block)
16
+ @left = left
17
+ @top = top
18
+ @shape_commands = []
19
+ @draw_context = Shoes::App.instance.current_draw_context
20
+
21
+ super
22
+ create_display_widget
23
+
24
+ Shoes::App.instance.with_slot(self, &block) if block_given?
25
+ end
26
+
27
+ # The cmd should be an array of the form:
28
+ #
29
+ # [cmd_name, *args]
30
+ #
31
+ # such as ["move_to", 50, 50]. Note that these must
32
+ # be JSON-serializable.
33
+ def add_shape_command(cmd)
34
+ @shape_commands << cmd
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Shoes::Slot < Shoes::Widget
4
+ # @incompatibility Shoes uses #content, not #children, for this
5
+ attr_reader :children
6
+
7
+ # Do not call directly, use set_parent
8
+ def remove_child(child)
9
+ @children ||= []
10
+ unless @children.include?(child)
11
+ @log.warn("remove_child: no such child(#{child.inspect}) for parent(#{parent.inspect})!")
12
+ end
13
+ @children.delete(child)
14
+ end
15
+
16
+ # Do not call directly, use set_parent
17
+ def add_child(child)
18
+ @children ||= []
19
+ @children << child
20
+ end
21
+
22
+ # Get a list of child widgets
23
+ def contents
24
+ @children ||= []
25
+ @children.dup
26
+ end
27
+
28
+ # Calling stack.app or flow.app will execute the block
29
+ # with the Shoes::App as self, and with that stack or
30
+ # flow as the current slot.
31
+ #
32
+ # @incompatibility Shoes Classic will only change self
33
+ # via this method, while Scarpe will also change self
34
+ # with the other Slot Manipulation methods: #clear,
35
+ # #append, #prepend, #before and #after.
36
+ #
37
+ # @return [Shoes::App] the Shoes app
38
+ # @yield the block to call with the Shoes App as self
39
+ def app(&block)
40
+ Shoes::App.instance.with_slot(self, &block) if block_given?
41
+ Shoes::App.instance
42
+ end
43
+
44
+ # Remove all children from this widget. If a block
45
+ # is given, call the block to replace the children with
46
+ # new contents from that block.
47
+ #
48
+ # Should only be called on Slots, which can
49
+ # have children.
50
+ #
51
+ # @incompatibility Shoes Classic calls the clear block with current self, while Scarpe uses the Shoes::App as self
52
+ #
53
+ # @yield The block to call to replace the contents of the widget (optional)
54
+ # @return [void]
55
+ def clear(&block)
56
+ @children.dup.each(&:destroy)
57
+ append(&block) if block_given?
58
+ nil
59
+ end
60
+
61
+ # Call the block to append new children to a Slot.
62
+ #
63
+ # Should only be called on a Slot, since only Slots can have children.
64
+ #
65
+ # @incompatibility Shoes Classic calls the append block with current self, while Scarpe uses the Shoes::App as self
66
+ #
67
+ # @yield the block to call to replace children; will be called on the Shoes::App, appending to the called Slot as the current slot
68
+ # @return [void]
69
+ def append(&block)
70
+ raise("append requires a block!") unless block_given?
71
+ raise("Don't append to something that isn't a slot!") unless self.is_a?(Shoes::Slot)
72
+
73
+ Shoes::App.instance.with_slot(self, &block)
74
+ end
75
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Scarpe
4
- class Span < Scarpe::Widget
3
+ module Shoes
4
+ class Span < Shoes::Widget
5
5
  display_properties :text, :stroke, :size, :font, :html_attributes
6
6
 
7
7
  def initialize(text, stroke: nil, size: :span, font: nil, **html_attributes)
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shoes
4
+ class Stack < Shoes::Slot
5
+ include Shoes::Background
6
+ include Shoes::Border
7
+ include Shoes::Spacing
8
+
9
+ # TODO: sort out various margin and padding properties, including putting stuff into spacing
10
+ display_properties :width, :height, :scroll
11
+
12
+ def initialize(width: nil, height: nil, margin: nil, padding: nil, scroll: false, margin_top: nil, margin_bottom: nil, margin_left: nil,
13
+ margin_right: nil, **options, &block)
14
+
15
+ @options = options
16
+
17
+ super
18
+
19
+ create_display_widget
20
+ # Create the display-side widget *before* running the block, which will add child widgets with their display widgets
21
+ Shoes::App.instance.with_slot(self, &block) if block_given?
22
+ end
23
+ end
24
+ end
@@ -1,20 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "wv/shape_helper"
4
- class Scarpe
5
- class InvalidAttributeValueError < Scarpe::Error; end
6
-
7
- class Star < Scarpe::Widget
8
- include ShapeHelper
9
- display_properties :left, :top, :points, :outer, :inner, :color
3
+ module Shoes
4
+ class Star < Shoes::Widget
5
+ display_properties :left, :top, :points, :outer, :inner, :draw_context
10
6
 
11
7
  def initialize(left, top, points = 10, outer = 100, inner = 50)
12
8
  @points = convert_to_integer(points, "points", 10)
13
9
  @outer = convert_to_float(outer, "outer", 100.0)
14
10
  @inner = convert_to_float(inner, "inner", 50.0)
15
- @color = color_for_fill
16
11
 
17
- super()
12
+ @draw_context = Shoes::App.instance.current_draw_context
13
+
14
+ super
18
15
  create_display_widget
19
16
  end
20
17
 
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Certain Shoes calls like motion and keydown are basically an
4
+ # event subscription, with no other visible presence. However,
5
+ # they have a place in the widget tree and can be deleted.
6
+ #
7
+ # Depending on the display library they may not have any
8
+ # direct visual (or similar) presence there either.
9
+ #
10
+ # Inheriting from Widget gives these a parent slot and a
11
+ # linkable_id automatically.
12
+ class Shoes::SubscriptionItem < Shoes::Widget
13
+ display_property :shoes_api_name
14
+
15
+ def initialize(shoes_api_name:, &block)
16
+ super
17
+
18
+ @callback = block
19
+
20
+ case shoes_api_name
21
+ when "hover"
22
+ # Hover passes the Shoes widget as the block param
23
+ @unsub_id = bind_self_event("hover") do
24
+ @callback&.call(self)
25
+ end
26
+ when "motion"
27
+ # Shoes sends back x, y, mods as the args.
28
+ # Shoes3 uses the strings "control" "shift" and
29
+ # "control_shift" as the mods arg.
30
+ @unsub_id = bind_self_event("motion") do |x, y, ctrl_key, shift_key, **_kwargs|
31
+ mods = [ctrl_key ? "control" : nil, shift_key ? "shift" : nil].compact.join("_")
32
+ @callback&.call(x, y, mods)
33
+ end
34
+ when "click"
35
+ # Click has block params button, left, top
36
+ # button is the button number, left and top are coords
37
+ @unsub_id = bind_self_event("click") do |button, x, y, **_kwargs|
38
+ @callback&.call(button, x, y)
39
+ end
40
+ else
41
+ raise "Unknown Shoes API call #{shoes_api_name.inspect} passed to SubscriptionItem!"
42
+ end
43
+
44
+ @unsub_id = bind_self_event(shoes_api_name) do |*args|
45
+ @callback&.call(*args)
46
+ end
47
+
48
+ # This won't create a visible display widget, but will turn into
49
+ # an invisible widget and a stream of events.
50
+ create_display_widget
51
+ end
52
+
53
+ def destroy
54
+ # TODO: we need a better way to do this automatically. See https://github.com/scarpe-team/scarpe/issues/291
55
+ unsub_shoes_event(@unsub_id) if @unsub_id
56
+ @unsub_id = nil
57
+
58
+ super
59
+ end
60
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Shoes::TextWidget
4
+
5
+ module Shoes
6
+ class TextWidget < Shoes::Widget
7
+ class << self
8
+ # rubocop:disable Lint/MissingSuper
9
+ def inherited(subclass)
10
+ Shoes::Widget.widget_classes ||= []
11
+ Shoes::Widget.widget_classes << subclass
12
+ end
13
+ # rubocop:enable Lint/MissingSuper
14
+ end
15
+ end
16
+
17
+ class << self
18
+ def default_text_widget_with(element)
19
+ class_name = element.capitalize
20
+
21
+ widget_class = Class.new(Shoes::TextWidget) do
22
+ # Can we just change content to text to match the Shoes API?
23
+ display_property :content
24
+
25
+ def initialize(content)
26
+ @content = content
27
+
28
+ super
29
+
30
+ create_display_widget
31
+ end
32
+
33
+ def text
34
+ self.content
35
+ end
36
+
37
+ def text=(new_text)
38
+ self.content = new_text
39
+ end
40
+ end
41
+ Shoes.const_set class_name, widget_class
42
+ widget_class.class_eval do
43
+ display_property :content
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ Shoes.default_text_widget_with(:code)
50
+ Shoes.default_text_widget_with(:em)
51
+ Shoes.default_text_widget_with(:strong)
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shoes
4
+ class Video < Shoes::Widget
5
+ display_properties :url
6
+
7
+ def initialize(url)
8
+ @url = url
9
+ super
10
+ create_display_widget
11
+ end
12
+
13
+ # other methods
14
+ end
15
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "shoes/widgets/slot"
4
+ require "shoes/widgets/stack"
5
+ require "shoes/widgets/flow"
6
+ require "shoes/widgets/document_root"
7
+
8
+ require "shoes/widgets/text_widget"
9
+
10
+ require "shoes/widgets/font"
11
+ require "shoes/widgets/subscription_item"
12
+
13
+ require "shoes/widgets/arc"
14
+ require "shoes/widgets/line"
15
+ require "shoes/widgets/shape"
16
+ require "shoes/widgets/star"
17
+
18
+ require "shoes/widgets/alert"
19
+ require "shoes/widgets/button"
20
+ require "shoes/widgets/check"
21
+ require "shoes/widgets/edit_box"
22
+ require "shoes/widgets/edit_line"
23
+ require "shoes/widgets/image"
24
+ require "shoes/widgets/link"
25
+ require "shoes/widgets/list_box"
26
+ require "shoes/widgets/para"
27
+ require "shoes/widgets/radio"
28
+ require "shoes/widgets/span"
29
+ require "shoes/widgets/video"
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ # We're separating Shoes from Scarpe, a little at a time. This should be requirable
4
+ # without using Scarpe at all.
5
+ #
6
+ # The Lacci gem is like the old Shoes-core from Shoes4: a way
7
+ # to handle the DSL and command-line parts of Shoes without knowing anything about how the
8
+ # display side works at all.
9
+
10
+ if RUBY_VERSION[0..2] < "3.2"
11
+ Shoes::Log.logger("Shoes").error("Lacci (Scarpe, Shoes) requires Ruby 3.2 or higher!")
12
+ exit(-1)
13
+ end
14
+
15
+ module Shoes; end
16
+ class Shoes::Error < StandardError; end
17
+
18
+ require_relative "shoes/constants"
19
+
20
+ # Shoes adds some top-level methods and constants that can be used everywhere. Kernel is where they go.
21
+ module Kernel
22
+ include Shoes::Constants
23
+ end
24
+
25
+ require_relative "shoes/log"
26
+ require_relative "shoes/display_service"
27
+ require_relative "shoes/colors"
28
+
29
+ require_relative "shoes/background"
30
+ require_relative "shoes/border"
31
+ require_relative "shoes/spacing"
32
+
33
+ require_relative "shoes/widget"
34
+ require_relative "shoes/app"
35
+ require_relative "shoes/widgets"
36
+
37
+ require_relative "shoes/download"
38
+
39
+ # The module containing Shoes in all its glory.
40
+ # Shoes is a platform-independent GUI library, designed to create
41
+ # small visual applications in Ruby.
42
+ #
43
+ module Shoes
44
+ class << self
45
+ # Creates a Shoes app with a new window. The block parameter is used to create
46
+ # widgets and set up handlers. Arguments are passed to Shoes::App.new internally.
47
+ #
48
+ # @incompatibility In Shoes3, this method will return normally.
49
+ # In Scarpe, after the block is executed, the method will not return and Scarpe
50
+ # will retain control of execution until the window is closed and the app quits.
51
+ #
52
+ # @incompatibility In Shoes3 the parameters were a hash of options, not keyword arguments.
53
+ #
54
+ # @example Simple one-button app
55
+ # Shoes.app(title: "Button!", width: 200, height: 200) do
56
+ # @p = para "Press it NOW!"
57
+ # button("clicky") { @p.replace("You pressed it! CELEBRATION!") }
58
+ # end
59
+ #
60
+ # @param title [String] The new app window title
61
+ # @param width [Integer] The new app window width
62
+ # @param height [Integer] The new app window height
63
+ # @param resizable [Boolean] Whether the app window should be resizeable
64
+ # @return [void]
65
+ # @see Shoes::App#new
66
+ def app(
67
+ title: "Shoes!",
68
+ width: 480,
69
+ height: 420,
70
+ resizable: true,
71
+ &app_code_body
72
+ )
73
+ app = Shoes::App.new(title:, width:, height:, resizable:, &app_code_body)
74
+ app.init
75
+ app.run
76
+ nil
77
+ end
78
+
79
+ # Load a Shoes app from a file. By default, this will load old-style Shoes apps
80
+ # from a .rb file with all the appropriate libraries loaded. By setting one or
81
+ # more loaders, a Lacci-based display library can accept new file formats as
82
+ # well, not just raw Shoes .rb files.
83
+ #
84
+ # @param path [String] The current-dir-relative path to the file
85
+ # @return [void]
86
+ # @see Shoes.add_file_loader
87
+ def run_app(relative_path)
88
+ path = File.expand_path relative_path
89
+ loaded = false
90
+ file_loaders.each do |loader|
91
+ if loader.call(path)
92
+ loaded = true
93
+ break
94
+ end
95
+ end
96
+ raise "Could not find a file loader for #{path.inspect}!" unless loaded
97
+
98
+ nil
99
+ end
100
+
101
+ def default_file_loaders
102
+ [
103
+ # By default we will always try to load any file, regardless of extension, as a Shoes Ruby file.
104
+ proc do |path|
105
+ load path
106
+ true
107
+ end,
108
+ ]
109
+ end
110
+
111
+ def file_loaders
112
+ @file_loaders ||= default_file_loaders
113
+ end
114
+
115
+ def add_file_loader(loader)
116
+ file_loaders.prepend(loader)
117
+ end
118
+
119
+ def reset_file_loaders
120
+ @file_loaders = default_file_loaders
121
+ end
122
+
123
+ def set_file_loaders(loaders)
124
+ @file_loaders = loaders
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class TestColors < Minitest::Test
6
+ class Dummy
7
+ include Shoes::Colors
8
+ end
9
+
10
+ def test_default_colors_are_accessible_via_methods
11
+ assert_equal [0, 0, 0, 255], Dummy.new.black
12
+ assert_equal [255, 255, 255, 255], Dummy.new.white
13
+ end
14
+
15
+ def test_default_colors_can_accept_alpha
16
+ assert_equal [0, 0, 0, 0.5], Dummy.new.black(0.5)
17
+ end
18
+
19
+ def test_gray_accepts_single_value_for_darkness
20
+ assert_equal [0, 0, 0, 255], Dummy.new.gray(0)
21
+ assert_equal [255, 255, 255, 255], Dummy.new.gray(255)
22
+ end
23
+
24
+ def test_gray_accepts_darkness_and_alpha
25
+ assert_equal [0, 0, 0, 128], Dummy.new.gray(0, 128)
26
+ end
27
+
28
+ def test_gray_defaults_to_50_percent_darkness
29
+ assert_equal [128, 128, 128, 255], Dummy.new.gray
30
+ end
31
+
32
+ def test_rgb_accepts_three_values
33
+ assert_equal [255, 0, 0, 255], Dummy.new.rgb(255, 0, 0)
34
+ end
35
+
36
+ def test_rgb_accepts_alpha
37
+ assert_equal [255, 0, 0, 128], Dummy.new.rgb(255, 0, 0, 128)
38
+ end
39
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
+ require "shoes"
5
+
6
+ require "minitest/autorun"
7
+
8
+ require "minitest/reporters"
9
+ Minitest::Reporters.use! [Minitest::Reporters::SpecReporter.new]
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "test_helper"
4
+
5
+ class TestLacci < Minitest::Test
6
+ def test_truth
7
+ assert_equal true, true
8
+ end
9
+ end