scarpe 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (239) 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 +165 -117
  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/{lib/scarpe → spikes}/glibui/README.md +0 -0
  213. /data/{lib/scarpe → spikes}/glibui/alert.rb +0 -0
  214. /data/{lib/scarpe → spikes}/glibui/app.rb +0 -0
  215. /data/{lib/scarpe → spikes}/glibui/background.rb +0 -0
  216. /data/{lib/scarpe → spikes}/glibui/border.rb +0 -0
  217. /data/{lib/scarpe → spikes}/glibui/button.rb +0 -0
  218. /data/{lib/scarpe → spikes}/glibui/dimensions.rb +0 -0
  219. /data/{lib/scarpe → spikes}/glibui/document_root.rb +0 -0
  220. /data/{lib/scarpe → spikes}/glibui/edit_box.rb +0 -0
  221. /data/{lib/scarpe → spikes}/glibui/edit_line.rb +0 -0
  222. /data/{lib/scarpe → spikes}/glibui/flow.rb +0 -0
  223. /data/{lib/scarpe → spikes}/glibui/html.rb +0 -0
  224. /data/{lib/scarpe → spikes}/glibui/image.rb +0 -0
  225. /data/{lib/scarpe → spikes}/glibui/link.rb +0 -0
  226. /data/{lib/scarpe → spikes}/glibui/local_display.rb +0 -0
  227. /data/{lib/scarpe → spikes}/glibui/para.rb +0 -0
  228. /data/{lib/scarpe → spikes}/glibui/spacing.rb +0 -0
  229. /data/{lib/scarpe → spikes}/glibui/stack.rb +0 -0
  230. /data/{lib/scarpe → spikes}/glibui/text_widget.rb +0 -0
  231. /data/{lib/scarpe → spikes}/libui/alert.rb +0 -0
  232. /data/{lib/scarpe → spikes}/libui/button.rb +0 -0
  233. /data/{lib/scarpe → spikes}/libui/colors.rb +0 -0
  234. /data/{lib/scarpe → spikes}/libui/core.rb +0 -0
  235. /data/{lib/scarpe → spikes}/libui/flow.rb +0 -0
  236. /data/{lib/scarpe → spikes}/libui/libui.rb +0 -0
  237. /data/{lib/scarpe → spikes}/libui/notepad.md +0 -0
  238. /data/{lib/scarpe → spikes}/libui/para.rb +0 -0
  239. /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