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
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shoes
4
+ class Widget
5
+ class ResponseWrapper
6
+ attr_reader :response
7
+
8
+ def initialize(response)
9
+ @response = response
10
+ end
11
+
12
+ def headers
13
+ @response.each_header.to_h
14
+ end
15
+
16
+ def body
17
+ @response.body
18
+ end
19
+ end
20
+
21
+ def download(url, method: "GET", save: nil, styles: {}, &block)
22
+ require "net/http"
23
+ require "openssl"
24
+ require "nokogiri"
25
+
26
+ @block = block
27
+
28
+ Thread.new do
29
+ logger = Shoes::Log.logger("Shoes::App#download")
30
+ begin
31
+ uri = URI(url)
32
+ response = perform_request(uri, method, styles)
33
+
34
+ if response.is_a?(Net::HTTPRedirection)
35
+ new_location = response["location"]
36
+ new_uri = URI(new_location)
37
+ response = perform_request(new_uri, method, styles)
38
+ end
39
+
40
+ wrapped_response = ResponseWrapper.new(response) # Wrap the response
41
+ handle_response(wrapped_response, save, styles)
42
+ rescue Net::HTTPError, Net::OpenTimeout, Net::ReadTimeout => e
43
+ handle_error(e, logger)
44
+ rescue StandardError => e
45
+ handle_error(e.message, logger) # Pass the error message as a string
46
+ end
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def perform_request(uri, method, styles)
53
+ port = uri.port || (uri.scheme == "https" ? 443 : 80)
54
+ http = Net::HTTP.start(uri.host, port, use_ssl: uri.scheme == "https", verify_mode: OpenSSL::SSL::VERIFY_NONE)
55
+
56
+ request = Net::HTTP.const_get(method.capitalize).new(uri.request_uri)
57
+ apply_styles(request, styles)
58
+
59
+ http.request(request)
60
+ end
61
+
62
+ def apply_styles(request, styles)
63
+ headers = styles[:headers]
64
+ request["Content-Type"] = headers["Content-Type"] if headers && headers["Content-Type"]
65
+ request.body = styles[:body] if styles[:body]
66
+ # Add more custom styles to the request as needed
67
+ end
68
+
69
+ def handle_response(response, save, styles)
70
+ case response.response.code.to_i
71
+ when 200..299
72
+ content = response.body
73
+ # headers = response.headers # Access headers directly
74
+ if save
75
+ save_content(content, save)
76
+ parse_rss(content) # Parse the downloaded XML content
77
+ else
78
+ handle_finish_event(response) # Pass response and headers to handle_finish_event
79
+ end
80
+ else
81
+ handle_failure(response.response.code)
82
+ end
83
+ end
84
+
85
+ def save_content(content, file_name)
86
+ file = nil
87
+ begin
88
+ file = File.open(file_name, "w")
89
+ file.write(content)
90
+ rescue Errno::EACCES, Errno::ENOENT => e
91
+ raise FileError, "File error occurred: #{e.message}"
92
+ else
93
+ @block&.call
94
+ ensure
95
+ file&.close
96
+ end
97
+ end
98
+
99
+ def handle_finish_event(response)
100
+ passed = Struct.new(:response).new(response) # Create a new Struct with response attribute
101
+ @block&.call(passed) # Pass it ok
102
+ end
103
+
104
+ def handle_failure(code, logger)
105
+ logger.error("Failed to download content. Response code: #{code}")
106
+ end
107
+
108
+ def handle_error(error, logger)
109
+ logger.error("An error occurred while downloading: #{error}")
110
+ end
111
+
112
+ def parse_rss(content)
113
+ doc = Nokogiri::XML(content)
114
+ items = doc.xpath("//item")
115
+ items.each do |item|
116
+ item.xpath("title").text
117
+ item.xpath("link").text
118
+ item.xpath("description").text
119
+ # Do something with the parsed content or use it if needed
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Old-style Shoes logging is really simple. We need more logging for our
4
+ # framework, so we add a not-included-in-old-Shoes module for it. This adds
5
+ # the *possibility* of logging, but Scarpe includes a much more
6
+ # comprehensive solution that plugs into this one.
7
+
8
+ # If used alone, this will fail because the @instance is nil. It needs
9
+ # an implementation to be plugged in.
10
+
11
+ module Shoes
12
+ LOG_LEVELS = [:debug, :info, :warn, :error, :fatal].freeze
13
+
14
+ # Include this module to get a @log instance variable to log as your
15
+ # configured component.
16
+ module Log
17
+ # These constants will wind up included in a lot of places. Should they move?
18
+ DEFAULT_COMPONENT = "default"
19
+ DEFAULT_LOG_CONFIG = {
20
+ "default" => "info",
21
+ }
22
+ DEFAULT_DEBUG_LOG_CONFIG = {
23
+ "default" => "debug",
24
+ }
25
+
26
+ class << self
27
+ attr_reader :instance
28
+ attr_reader :current_log_config
29
+
30
+ def instance=(impl_object)
31
+ raise(Shoes::Error, "Already have an instance for Shoes::Log!") if @instance
32
+
33
+ @instance = impl_object
34
+ end
35
+
36
+ def logger(component = self)
37
+ @instance.logger_for_component(component)
38
+ end
39
+
40
+ def configure_logger(log_config)
41
+ @instance.configure_logger(log_config)
42
+ end
43
+ end
44
+
45
+ def log_init(component = self)
46
+ @log = Shoes::Log.instance.logger_for_component(component)
47
+ end
48
+ end
49
+
50
+ class LoggedWrapper
51
+ include ::Shoes::Log
52
+ def initialize(instance, component = instance)
53
+ log_init(component)
54
+
55
+ @instance = instance
56
+ end
57
+
58
+ def method_missing(method, ...)
59
+ self.singleton_class.define_method(method) do |*args, **kwargs, &block|
60
+ ret = @instance.send(method, *args, **kwargs, &block)
61
+ @log.info("Method: #{method} Args: #{args.inspect} KWargs: #{kwargs.inspect} Block: #{block ? "y" : "n"} Return: #{ret.inspect}")
62
+ ret
63
+ end
64
+ send(method, ...)
65
+ end
66
+
67
+ def respond_to_missing?(method_name, include_private = false)
68
+ @instance.respond_to_missing?(method_name, include_private)
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shoes
4
+ module Spacing
5
+ def self.included(includer)
6
+ includer.display_properties :margin, :padding, :margin_top, :margin_left, :margin_right, :margin_bottom, :options
7
+ end
8
+ end
9
+ end
@@ -1,26 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Scarpe::Widget
4
- #
5
- # Interface:
6
- # A Scarpe::Widget defines the "element" method to indicate that it has custom markup of
7
- # some kind. A Widget with no element method renders as its children's markup, joined.
8
-
9
- class Scarpe
10
- class Widget < DisplayService::Linkable
11
- include Scarpe::Log
12
- include Scarpe::Colors
3
+ module Shoes
4
+ # Shoes::Widget
5
+ #
6
+ # This is the display-service portable Shoes Widget interface. Visible Shoes
7
+ # widgets like buttons inherit from this. Compound widgets made of multiple
8
+ # different smaller Widgets inherit from it in their various apps or libraries.
9
+ # The Shoes Widget helps build a Shoes-side widget tree, with parents and
10
+ # children. Any API that applies to all widgets (e.g. remove) should be
11
+ # defined here.
12
+ #
13
+ class Widget < Shoes::Linkable
14
+ include Shoes::Log
15
+ include Shoes::Colors
13
16
 
14
17
  class << self
15
- attr_accessor :widget_classes, :alias_name
16
-
17
- def alias_as(name)
18
- self.alias_name = name
19
- end
18
+ attr_accessor :widget_classes
20
19
 
21
20
  def inherited(subclass)
22
- self.widget_classes ||= []
23
- self.widget_classes << subclass
21
+ Shoes::Widget.widget_classes ||= []
22
+ Shoes::Widget.widget_classes << subclass
24
23
  super
25
24
  end
26
25
 
@@ -30,7 +29,7 @@ class Scarpe
30
29
  end
31
30
 
32
31
  def widget_class_by_name(name)
33
- widget_classes.detect { |k| k.dsl_name == name.to_s || k.alias_name.to_s == name.to_s }
32
+ widget_classes.detect { |k| k.dsl_name == name.to_s }
34
33
  end
35
34
 
36
35
  private
@@ -56,19 +55,26 @@ class Scarpe
56
55
  linkable_properties_hash[name] = true
57
56
  end
58
57
 
58
+ # Add these names as display properties
59
59
  def display_properties(*names)
60
60
  names.each { |n| display_property(n) }
61
61
  end
62
62
 
63
63
  def display_property_names
64
- linkable_properties.map { |prop| prop[:name] }
64
+ parent_prop_names = self != Shoes::Widget ? self.superclass.display_property_names : []
65
+
66
+ parent_prop_names | linkable_properties.map { |prop| prop[:name] }
65
67
  end
66
68
 
67
69
  def display_property_name?(name)
68
- linkable_properties_hash[name.to_s]
70
+ linkable_properties_hash[name.to_s] ||
71
+ (self != Shoes::Widget && superclass.display_property_name?(name))
69
72
  end
70
73
  end
71
74
 
75
+ # Shoes uses a "hidden" style property for hide/show
76
+ display_property :hidden
77
+
72
78
  def initialize(*args, **kwargs)
73
79
  log_init("Widget")
74
80
 
@@ -81,6 +87,14 @@ class Scarpe
81
87
  super() # linkable_id defaults to object_id
82
88
  end
83
89
 
90
+ def inspect
91
+ "#<#{self.class}:#{self.object_id} " +
92
+ "@linkable_id=#{@linkable_id.inspect} @parent=#{@parent.inspect} " +
93
+ "@children=#{@children.inspect} properties=#{display_property_values.inspect}>"
94
+ end
95
+
96
+ private
97
+
84
98
  def bind_self_event(event_name, &block)
85
99
  raise("Widget has no linkable_id! #{inspect}") unless linkable_id
86
100
 
@@ -91,24 +105,31 @@ class Scarpe
91
105
  bind_shoes_event(event_name:, &block)
92
106
  end
93
107
 
94
- def display_properties
108
+ public
109
+
110
+ def display_property_values
111
+ all_property_names = self.class.display_property_names
112
+
95
113
  properties = {}
96
- self.class.display_property_names.each do |prop|
114
+ all_property_names.each do |prop|
97
115
  properties[prop] = instance_variable_get("@" + prop)
98
116
  end
99
117
  properties["shoes_linkable_id"] = self.linkable_id
100
118
  properties
101
119
  end
102
120
 
121
+ private
122
+
103
123
  def create_display_widget
104
124
  klass_name = self.class.name.delete_prefix("Scarpe::").delete_prefix("Shoes::")
105
125
 
106
126
  # Should we save a reference to widget for later reference?
107
- DisplayService.display_service.create_display_widget_for(klass_name, self.linkable_id, display_properties)
127
+ ::Shoes::DisplayService.display_service.create_display_widget_for(klass_name, self.linkable_id, display_property_values)
108
128
  end
109
129
 
130
+ public
131
+
110
132
  attr_reader :parent
111
- attr_reader :children
112
133
 
113
134
  def set_parent(new_parent)
114
135
  @parent&.remove_child(self)
@@ -117,28 +138,27 @@ class Scarpe
117
138
  send_shoes_event(new_parent.linkable_id, event_name: "parent", target: linkable_id)
118
139
  end
119
140
 
120
- # Do not call directly, use set_parent
121
- def remove_child(child)
122
- @children ||= []
123
- unless @children.include?(child)
124
- @log.warn("remove_child: no such child(#{child.inspect}) for parent(#{parent.inspect})!")
125
- end
126
- @children.delete(child)
141
+ # Removes the element from the Shoes::Widget tree
142
+ def destroy
143
+ @parent&.remove_child(self)
144
+ send_shoes_event(event_name: "destroy", target: linkable_id)
127
145
  end
146
+ alias_method :remove, :destroy
128
147
 
129
- # Do not call directly, use set_parent
130
- def add_child(child)
131
- @children ||= []
132
- @children << child
148
+ # Hide the widget.
149
+ def hide
150
+ self.hidden = true
133
151
  end
134
152
 
135
- # Removes the element from the Scarpe::Widget tree
136
- def destroy
137
- @parent&.remove_child(self)
138
- send_shoes_event(event_name: "destroy", target: linkable_id)
153
+ # Show the widget.
154
+ def show
155
+ self.hidden = false
139
156
  end
140
157
 
141
- alias_method :destroy_self, :destroy
158
+ # Hide the widget if it is currently shown. Show it if it is currently hidden.
159
+ def toggle
160
+ self.hidden = !self.hidden
161
+ end
142
162
 
143
163
  # We use method_missing for widget-creating methods like "button",
144
164
  # and also to auto-create display-property getters and setters.
@@ -172,12 +192,12 @@ class Scarpe
172
192
  klass = Widget.widget_class_by_name(name)
173
193
  return super unless klass
174
194
 
175
- ::Scarpe::Widget.define_method(name) do |*args, **kwargs, &block|
195
+ ::Shoes::Widget.define_method(name) do |*args, **kwargs, &block|
176
196
  # Look up the Shoes widget and create it...
177
197
  widget_instance = klass.new(*args, **kwargs, &block)
178
198
 
179
- unless klass.ancestors.include?(Scarpe::TextWidget)
180
- widget_instance.set_parent(self)
199
+ unless klass.ancestors.include?(Shoes::TextWidget)
200
+ widget_instance.set_parent Shoes::App.instance.current_slot
181
201
  end
182
202
 
183
203
  widget_instance
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Scarpe
4
- class Alert < Scarpe::Widget
3
+ module Shoes
4
+ class Alert < Shoes::Widget
5
5
  display_property :text
6
6
 
7
7
  def initialize(text)
@@ -10,7 +10,7 @@ class Scarpe
10
10
  super
11
11
 
12
12
  bind_self_event("click") do
13
- destroy_self
13
+ remove
14
14
  end
15
15
 
16
16
  create_display_widget
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Scarpe
4
- class InvalidAttributeValueError < Scarpe::Error; end
3
+ module Shoes
4
+ class InvalidAttributeValueError < Shoes::Error; end
5
5
 
6
- class Arc < Scarpe::Widget
7
- display_properties :left, :top, :width, :height, :angle1, :angle2
6
+ class Arc < Shoes::Widget
7
+ display_properties :left, :top, :width, :height, :angle1, :angle2, :draw_context
8
8
 
9
9
  def initialize(*args)
10
10
  @left, @top, @width, @height, @angle1, @angle2 = args
@@ -16,7 +16,9 @@ class Scarpe
16
16
  @angle1 = convert_to_float(@angle1, "angle1")
17
17
  @angle2 = convert_to_float(@angle2, "angle2")
18
18
 
19
- super()
19
+ @draw_context = Shoes::App.instance.current_draw_context
20
+
21
+ super
20
22
  create_display_widget
21
23
  end
22
24
 
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Scarpe
4
- class Button < Scarpe::Widget
5
- include Scarpe::Log
3
+ module Shoes
4
+ class Button < Shoes::Widget
5
+ include Shoes::Log
6
6
  display_properties :text, :width, :height, :top, :left, :color, :padding_top, :padding_bottom, :text_color, :size, :font_size
7
7
 
8
8
  def initialize(text, width: nil, height: nil, top: nil, left: nil, color: nil, padding_top: nil, padding_bottom: nil, size: 12, text_color: nil,
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shoes
4
+ class Check < Shoes::Widget
5
+ display_properties :checked
6
+
7
+ def initialize(checked = nil, &block)
8
+ @block = block
9
+ super
10
+
11
+ bind_self_event("click") { click }
12
+ create_display_widget
13
+ end
14
+
15
+ def click(&block)
16
+ @block = block
17
+ self.checked = !checked?
18
+ end
19
+
20
+ def checked?
21
+ @checked ? true : false
22
+ end
23
+
24
+ def checked(value)
25
+ self.checked = value
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shoes
4
+ class DocumentRoot < Shoes::Flow
5
+ def initialize
6
+ @height = "100%"
7
+ @width = @margin = @padding = nil
8
+ @options = {}
9
+
10
+ super
11
+
12
+ create_display_widget
13
+ end
14
+
15
+ # The default inspect string can be absolutely huge in console output, and it's frequently printed.
16
+ def inspect
17
+ "<Shoes::DocumentRoot>"
18
+ end
19
+ end
20
+ end
@@ -1,17 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Scarpe
4
- class EditBox < Scarpe::Widget
3
+ module Shoes
4
+ class EditBox < Shoes::Widget
5
5
  display_properties :text, :height, :width
6
6
 
7
- def initialize(text = nil, height: nil, width: nil, &block)
8
- @text = text.nil? ? block&.call : text || ""
7
+ def initialize(text = "", height: nil, width: nil, &block)
8
+ @text = text
9
+ @callback = block
9
10
 
10
11
  super
11
12
 
12
13
  bind_self_event("change") do |new_text|
13
14
  self.text = new_text
14
- @callback&.call(new_text)
15
+ @callback&.call(self)
15
16
  end
16
17
 
17
18
  create_display_widget
@@ -20,5 +21,9 @@ class Scarpe
20
21
  def change(&block)
21
22
  @callback = block
22
23
  end
24
+
25
+ def append(new_text)
26
+ self.text = self.text + new_text
27
+ end
23
28
  end
24
29
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Scarpe
4
- class EditLine < Scarpe::Widget
3
+ module Shoes
4
+ class EditLine < Shoes::Widget
5
5
  display_properties :text, :width
6
6
 
7
7
  def initialize(text = "", width: nil, &block)
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shoes
4
+ class Flow < Shoes::Slot
5
+ include Shoes::Background
6
+ include Shoes::Border
7
+ include Shoes::Spacing
8
+
9
+ display_properties :width, :height, :margin, :padding
10
+
11
+ def initialize(width: "100%", height: nil, margin: nil, padding: nil, **options, &block)
12
+ @options = options
13
+
14
+ super
15
+
16
+ # Create the display-side widget *before* instance_eval, which will add child widgets with their display widgets
17
+ create_display_widget
18
+
19
+ Shoes::App.instance.with_slot(self, &block) if block_given?
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shoes
4
+ class Font < Shoes::Widget
5
+ display_properties :font
6
+
7
+ def initialize(font)
8
+ @font = font
9
+ super
10
+
11
+ create_display_widget
12
+ end
13
+ end
14
+ end
@@ -1,10 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "fastimage"
4
- require "open-uri"
5
-
6
- class Scarpe
7
- class Image < Scarpe::Widget
3
+ module Shoes
4
+ class Image < Shoes::Widget
8
5
  display_properties :url, :width, :height, :top, :left, :click
9
6
 
10
7
  def initialize(url, width: nil, height: nil, top: nil, left: nil, click: nil)
@@ -21,10 +18,9 @@ class Scarpe
21
18
  def replace(url)
22
19
  self.url = url
23
20
  end
24
- end
25
21
 
26
- class Widget
27
22
  def size
23
+ require "fastimage"
28
24
  width, height = FastImage.size(@url)
29
25
 
30
26
  [width, height]
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shoes
4
+ class Line < Shoes::Widget
5
+ display_properties :left, :top, :x2, :y2, :draw_context
6
+
7
+ def initialize(left, top, x2, y2)
8
+ @left = left
9
+ @top = top
10
+ @x2 = x2
11
+ @y2 = y2
12
+ @draw_context = Shoes::App.instance.current_draw_context
13
+
14
+ super
15
+ create_display_widget
16
+ end
17
+ end
18
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Scarpe
4
- class Link < Scarpe::TextWidget
3
+ module Shoes
4
+ class Link < Shoes::TextWidget
5
5
  display_properties :text, :click, :has_block
6
6
 
7
7
  def initialize(text, click: nil, &block)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Scarpe
4
- class ListBox < Scarpe::Widget
3
+ module Shoes
4
+ class ListBox < Shoes::Widget
5
5
  display_properties :selected_item, :items, :height, :width
6
6
 
7
7
  def initialize(args = {}, &block)