shoes-core 4.0.0.pre3

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 (219) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +31 -0
  3. data/README.md +8 -0
  4. data/Rakefile +1 -0
  5. data/bin/shoes +62 -0
  6. data/bin/shoes-guard +8 -0
  7. data/bin/shoes-picker +6 -0
  8. data/bin/shoes-stub +62 -0
  9. data/ext/install/Rakefile +29 -0
  10. data/ext/install/shoes.bat +15 -0
  11. data/fonts/Coolvetica.ttf +0 -0
  12. data/fonts/Lacuna.ttf +0 -0
  13. data/lib/rubygems_plugin.rb +24 -0
  14. data/lib/shoes.rb +1 -0
  15. data/lib/shoes/animation.rb +56 -0
  16. data/lib/shoes/app.rb +130 -0
  17. data/lib/shoes/arc.rb +25 -0
  18. data/lib/shoes/background.rb +20 -0
  19. data/lib/shoes/border.rb +20 -0
  20. data/lib/shoes/builtin_methods.rb +76 -0
  21. data/lib/shoes/button.rb +29 -0
  22. data/lib/shoes/check_button.rb +41 -0
  23. data/lib/shoes/color.rb +387 -0
  24. data/lib/shoes/common/background_element.rb +9 -0
  25. data/lib/shoes/common/changeable.rb +34 -0
  26. data/lib/shoes/common/clickable.rb +24 -0
  27. data/lib/shoes/common/inspect.rb +14 -0
  28. data/lib/shoes/common/positioning.rb +30 -0
  29. data/lib/shoes/common/registration.rb +31 -0
  30. data/lib/shoes/common/remove.rb +10 -0
  31. data/lib/shoes/common/state.rb +16 -0
  32. data/lib/shoes/common/style.rb +160 -0
  33. data/lib/shoes/common/style_normalizer.rb +16 -0
  34. data/lib/shoes/common/ui_element.rb +11 -0
  35. data/lib/shoes/common/visibility.rb +41 -0
  36. data/lib/shoes/configuration.rb +96 -0
  37. data/lib/shoes/core.rb +1 -0
  38. data/lib/shoes/core/version.rb +5 -0
  39. data/lib/shoes/dialog.rb +56 -0
  40. data/lib/shoes/dimension.rb +269 -0
  41. data/lib/shoes/dimensions.rb +203 -0
  42. data/lib/shoes/download.rb +130 -0
  43. data/lib/shoes/dsl.rb +656 -0
  44. data/lib/shoes/file_not_found_error.rb +4 -0
  45. data/lib/shoes/font.rb +50 -0
  46. data/lib/shoes/gradient.rb +31 -0
  47. data/lib/shoes/image.rb +53 -0
  48. data/lib/shoes/image_pattern.rb +12 -0
  49. data/lib/shoes/input_box.rb +59 -0
  50. data/lib/shoes/internal_app.rb +230 -0
  51. data/lib/shoes/key_event.rb +17 -0
  52. data/lib/shoes/line.rb +84 -0
  53. data/lib/shoes/link.rb +57 -0
  54. data/lib/shoes/link_hover.rb +5 -0
  55. data/lib/shoes/list_box.rb +50 -0
  56. data/lib/shoes/logger.rb +65 -0
  57. data/lib/shoes/logger/ruby.rb +16 -0
  58. data/lib/shoes/mock.rb +33 -0
  59. data/lib/shoes/mock/animation.rb +8 -0
  60. data/lib/shoes/mock/app.rb +49 -0
  61. data/lib/shoes/mock/arc.rb +9 -0
  62. data/lib/shoes/mock/background.rb +10 -0
  63. data/lib/shoes/mock/border.rb +7 -0
  64. data/lib/shoes/mock/button.rb +22 -0
  65. data/lib/shoes/mock/check.rb +24 -0
  66. data/lib/shoes/mock/clickable.rb +8 -0
  67. data/lib/shoes/mock/common_methods.rb +12 -0
  68. data/lib/shoes/mock/dialog.rb +13 -0
  69. data/lib/shoes/mock/download.rb +16 -0
  70. data/lib/shoes/mock/font.rb +15 -0
  71. data/lib/shoes/mock/image.rb +13 -0
  72. data/lib/shoes/mock/image_pattern.rb +8 -0
  73. data/lib/shoes/mock/input_box.rb +30 -0
  74. data/lib/shoes/mock/keypress.rb +11 -0
  75. data/lib/shoes/mock/keyrelease.rb +11 -0
  76. data/lib/shoes/mock/line.rb +14 -0
  77. data/lib/shoes/mock/link.rb +11 -0
  78. data/lib/shoes/mock/list_box.rb +19 -0
  79. data/lib/shoes/mock/oval.rb +11 -0
  80. data/lib/shoes/mock/packager.rb +13 -0
  81. data/lib/shoes/mock/progress.rb +10 -0
  82. data/lib/shoes/mock/radio.rb +27 -0
  83. data/lib/shoes/mock/rect.rb +14 -0
  84. data/lib/shoes/mock/shape.rb +20 -0
  85. data/lib/shoes/mock/slot.rb +16 -0
  86. data/lib/shoes/mock/sound.rb +8 -0
  87. data/lib/shoes/mock/star.rb +14 -0
  88. data/lib/shoes/mock/text_block.rb +36 -0
  89. data/lib/shoes/mock/timer.rb +8 -0
  90. data/lib/shoes/not_implemented_error.rb +4 -0
  91. data/lib/shoes/oval.rb +20 -0
  92. data/lib/shoes/packager.rb +26 -0
  93. data/lib/shoes/point.rb +54 -0
  94. data/lib/shoes/progress.rb +25 -0
  95. data/lib/shoes/radio.rb +15 -0
  96. data/lib/shoes/rect.rb +21 -0
  97. data/lib/shoes/renamed_delegate.rb +15 -0
  98. data/lib/shoes/shape.rb +159 -0
  99. data/lib/shoes/slot.rb +276 -0
  100. data/lib/shoes/slot_contents.rb +51 -0
  101. data/lib/shoes/sound.rb +18 -0
  102. data/lib/shoes/span.rb +16 -0
  103. data/lib/shoes/star.rb +50 -0
  104. data/lib/shoes/text.rb +24 -0
  105. data/lib/shoes/text_block.rb +142 -0
  106. data/lib/shoes/text_block_dimensions.rb +51 -0
  107. data/lib/shoes/timer.rb +14 -0
  108. data/lib/shoes/ui/cli.rb +67 -0
  109. data/lib/shoes/ui/picker.rb +47 -0
  110. data/lib/shoes/url.rb +44 -0
  111. data/lib/shoes/version.rb +3 -0
  112. data/lib/shoes/widget.rb +67 -0
  113. data/shoes-core.gemspec +22 -0
  114. data/spec/shoes/animation_spec.rb +71 -0
  115. data/spec/shoes/app_spec.rb +484 -0
  116. data/spec/shoes/arc_spec.rb +51 -0
  117. data/spec/shoes/background_spec.rb +47 -0
  118. data/spec/shoes/border_spec.rb +46 -0
  119. data/spec/shoes/builtin_methods_spec.rb +110 -0
  120. data/spec/shoes/button_spec.rb +44 -0
  121. data/spec/shoes/check_spec.rb +35 -0
  122. data/spec/shoes/color_spec.rb +408 -0
  123. data/spec/shoes/common/inspect_spec.rb +26 -0
  124. data/spec/shoes/common/remove_spec.rb +38 -0
  125. data/spec/shoes/common/style_normalizer_spec.rb +28 -0
  126. data/spec/shoes/common/style_spec.rb +147 -0
  127. data/spec/shoes/configuration_spec.rb +36 -0
  128. data/spec/shoes/constants_spec.rb +38 -0
  129. data/spec/shoes/dialog_spec.rb +171 -0
  130. data/spec/shoes/dimension_spec.rb +433 -0
  131. data/spec/shoes/dimensions_spec.rb +837 -0
  132. data/spec/shoes/download_spec.rb +146 -0
  133. data/spec/shoes/flow_spec.rb +133 -0
  134. data/spec/shoes/font_spec.rb +37 -0
  135. data/spec/shoes/framework_learning_spec.rb +30 -0
  136. data/spec/shoes/gradient_spec.rb +32 -0
  137. data/spec/shoes/helpers/fake_element.rb +17 -0
  138. data/spec/shoes/helpers/inspect_helpers.rb +5 -0
  139. data/spec/shoes/helpers/sample17_helper.rb +66 -0
  140. data/spec/shoes/image_spec.rb +68 -0
  141. data/spec/shoes/images/shoe.jpg +0 -0
  142. data/spec/shoes/input_box_spec.rb +80 -0
  143. data/spec/shoes/integration_spec.rb +20 -0
  144. data/spec/shoes/internal_app_spec.rb +141 -0
  145. data/spec/shoes/keypress_spec.rb +11 -0
  146. data/spec/shoes/keyrelease_spec.rb +12 -0
  147. data/spec/shoes/line_spec.rb +87 -0
  148. data/spec/shoes/link_spec.rb +118 -0
  149. data/spec/shoes/list_box_spec.rb +74 -0
  150. data/spec/shoes/logger/ruby_spec.rb +8 -0
  151. data/spec/shoes/logger_spec.rb +45 -0
  152. data/spec/shoes/oval_spec.rb +24 -0
  153. data/spec/shoes/packager_spec.rb +25 -0
  154. data/spec/shoes/point_spec.rb +71 -0
  155. data/spec/shoes/progress_spec.rb +54 -0
  156. data/spec/shoes/radio_spec.rb +32 -0
  157. data/spec/shoes/rect_spec.rb +39 -0
  158. data/spec/shoes/renamed_delegate_spec.rb +70 -0
  159. data/spec/shoes/shape_spec.rb +106 -0
  160. data/spec/shoes/shared_examples/button.rb +6 -0
  161. data/spec/shoes/shared_examples/changeable.rb +26 -0
  162. data/spec/shoes/shared_examples/clickable.rb +5 -0
  163. data/spec/shoes/shared_examples/common_methods.rb +35 -0
  164. data/spec/shoes/shared_examples/dimensions.rb +32 -0
  165. data/spec/shoes/shared_examples/dsl.rb +44 -0
  166. data/spec/shoes/shared_examples/dsl/animate.rb +29 -0
  167. data/spec/shoes/shared_examples/dsl/arc.rb +45 -0
  168. data/spec/shoes/shared_examples/dsl/background.rb +26 -0
  169. data/spec/shoes/shared_examples/dsl/border.rb +10 -0
  170. data/spec/shoes/shared_examples/dsl/button.rb +5 -0
  171. data/spec/shoes/shared_examples/dsl/cap.rb +6 -0
  172. data/spec/shoes/shared_examples/dsl/check.rb +11 -0
  173. data/spec/shoes/shared_examples/dsl/edit_box.rb +8 -0
  174. data/spec/shoes/shared_examples/dsl/edit_line.rb +8 -0
  175. data/spec/shoes/shared_examples/dsl/editable_element.rb +29 -0
  176. data/spec/shoes/shared_examples/dsl/fill.rb +27 -0
  177. data/spec/shoes/shared_examples/dsl/flow.rb +15 -0
  178. data/spec/shoes/shared_examples/dsl/gradient.rb +62 -0
  179. data/spec/shoes/shared_examples/dsl/image.rb +21 -0
  180. data/spec/shoes/shared_examples/dsl/line.rb +9 -0
  181. data/spec/shoes/shared_examples/dsl/nofill.rb +6 -0
  182. data/spec/shoes/shared_examples/dsl/nostroke.rb +6 -0
  183. data/spec/shoes/shared_examples/dsl/oval.rb +88 -0
  184. data/spec/shoes/shared_examples/dsl/pattern.rb +34 -0
  185. data/spec/shoes/shared_examples/dsl/progress.rb +7 -0
  186. data/spec/shoes/shared_examples/dsl/rect.rb +92 -0
  187. data/spec/shoes/shared_examples/dsl/rgb.rb +26 -0
  188. data/spec/shoes/shared_examples/dsl/shape.rb +57 -0
  189. data/spec/shoes/shared_examples/dsl/star.rb +111 -0
  190. data/spec/shoes/shared_examples/dsl/stroke.rb +30 -0
  191. data/spec/shoes/shared_examples/dsl/strokewidth.rb +19 -0
  192. data/spec/shoes/shared_examples/dsl/style.rb +32 -0
  193. data/spec/shoes/shared_examples/dsl/text_elements.rb +81 -0
  194. data/spec/shoes/shared_examples/dsl/video.rb +5 -0
  195. data/spec/shoes/shared_examples/dsl_app_context.rb +8 -0
  196. data/spec/shoes/shared_examples/hover_leave.rb +11 -0
  197. data/spec/shoes/shared_examples/parent.rb +6 -0
  198. data/spec/shoes/shared_examples/scroll.rb +41 -0
  199. data/spec/shoes/shared_examples/shared_element_method.rb +60 -0
  200. data/spec/shoes/shared_examples/slot.rb +394 -0
  201. data/spec/shoes/shared_examples/state.rb +19 -0
  202. data/spec/shoes/shared_examples/style.rb +82 -0
  203. data/spec/shoes/slot_spec.rb +186 -0
  204. data/spec/shoes/sound_spec.rb +15 -0
  205. data/spec/shoes/span_spec.rb +112 -0
  206. data/spec/shoes/spec_helper.rb +24 -0
  207. data/spec/shoes/stack_spec.rb +79 -0
  208. data/spec/shoes/star_spec.rb +48 -0
  209. data/spec/shoes/text_block_dimensions_spec.rb +75 -0
  210. data/spec/shoes/text_block_spec.rb +270 -0
  211. data/spec/shoes/url_spec.rb +68 -0
  212. data/spec/shoes/widget_spec.rb +70 -0
  213. data/spec/shoes_spec.rb +44 -0
  214. data/spec/spec_helper.rb +19 -0
  215. data/static/downloading.png +0 -0
  216. data/static/shoes-icon-blue.png +0 -0
  217. data/static/shoes-icon-brown.png +0 -0
  218. data/static/shoes-icon.png +0 -0
  219. metadata +366 -0
@@ -0,0 +1,130 @@
1
+ class Shoes
2
+ class HttpResponse
3
+ # Struct might be better?
4
+ attr_accessor :headers, :body, :status
5
+ def initalize
6
+ @headers = {}
7
+ @body = ''
8
+ @status = []
9
+ end
10
+ end
11
+
12
+ class Download
13
+ attr_reader :progress, :response, :content_length, :gui, :transferred
14
+ UPDATE_STEPS = 100
15
+
16
+ def initialize(app, _parent, url, opts = {}, &blk)
17
+ @url = url
18
+ @opts = opts
19
+ initialize_blocks(app, blk)
20
+
21
+ @gui = Shoes.configuration.backend_for(self)
22
+
23
+ @response = HttpResponse.new
24
+ @finished = false
25
+ @transferred = 0
26
+ @content_length = 1 # non zero initialized to avoid Zero Div Errors
27
+ end
28
+
29
+ def initialize_blocks(app, blk)
30
+ slot = app.current_slot
31
+ @blk = slot.create_bound_block(blk)
32
+ @progress_blk = slot.create_bound_block(@opts[:progress])
33
+ @finish_blk = slot.create_bound_block(@opts[:finish])
34
+ end
35
+
36
+ def start
37
+ start_download
38
+ end
39
+
40
+ def started?
41
+ @started
42
+ end
43
+
44
+ def finished?
45
+ @finished
46
+ end
47
+
48
+ # needed for the specs (jay multi threading and specs)
49
+ def join_thread
50
+ @thread.join unless @thread.nil?
51
+ end
52
+
53
+ def percent
54
+ @transferred * 100 / @content_length
55
+ end
56
+
57
+ def abort
58
+ @thread.exit if @thread
59
+ end
60
+
61
+ # shoes 3 compatibility
62
+ def length
63
+ @content_length
64
+ end
65
+
66
+ private
67
+
68
+ def start_download
69
+ require 'open-uri'
70
+ @thread = Thread.new do
71
+ uri_opts = {}
72
+ uri_opts[:content_length_proc] = content_length_proc
73
+ uri_opts[:progress_proc] = progress_proc if @progress_blk
74
+
75
+ open @url, uri_opts do |download_data|
76
+ @response.body = download_data.read
77
+ @response.status = download_data.status
78
+ @response.headers = download_data.meta
79
+ save_to_file(@opts[:save]) if @opts[:save]
80
+ finish_download download_data
81
+ end
82
+ end
83
+ end
84
+
85
+ def content_length_proc
86
+ lambda do |content_length|
87
+ download_started(content_length)
88
+ eval_block(@progress_blk, self)
89
+ end
90
+ end
91
+
92
+ def progress_proc
93
+ lambda do |size|
94
+ if !content_length.nil? &&
95
+ (size - transferred) > (content_length / UPDATE_STEPS) &&
96
+ !@gui.busy?
97
+ @gui.busy = true
98
+ eval_block(@progress_blk, self)
99
+ @transferred = size
100
+ end
101
+ end
102
+ end
103
+
104
+ def finish_download(_download_data)
105
+ @finished = true
106
+
107
+ # In case backend didn't catch the 100%
108
+ @transferred = @content_length
109
+ eval_block(@progress_blk, self)
110
+
111
+ #:finish and block are the same
112
+ eval_block(@blk, self)
113
+ eval_block(@finish_blk, self)
114
+ end
115
+
116
+ def eval_block(blk, result)
117
+ return if blk.nil?
118
+ @gui.eval_block(blk, result)
119
+ end
120
+
121
+ def save_to_file(file_path)
122
+ open(file_path, 'wb') { |fw| fw.print @response.body }
123
+ end
124
+
125
+ def download_started(content_length)
126
+ @content_length = content_length
127
+ @started = true
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,656 @@
1
+ require 'delegate'
2
+ require 'fileutils'
3
+ require 'forwardable'
4
+ require 'pathname'
5
+ require 'tmpdir'
6
+ require 'shoes/common/registration'
7
+
8
+ class Shoes
9
+ PI = Math::PI
10
+ TWO_PI = 2 * PI
11
+ HALF_PI = 0.5 * PI
12
+ DIR = Pathname.new(__FILE__).parent.parent.parent.to_s
13
+ LOG = []
14
+ LEFT_MOUSE_BUTTON = 1
15
+ MIDDLE_MOUSE_BUTTON = 2
16
+ RIGHT_MOUSE_BUTTON = 3
17
+
18
+ extend Common::Registration
19
+
20
+ class << self
21
+ def logger
22
+ Shoes.configuration.logger_instance
23
+ end
24
+
25
+ # To ease the upgrade path from Shoes 3 we warn users they need to install
26
+ # and require gems themselves.
27
+ #
28
+ # @example
29
+ # Shoes.setup do
30
+ # gem 'bluecloth =2.0.6'
31
+ # gem 'metaid'
32
+ # end
33
+ #
34
+ # @param block [Proc] The block that describes the gems that are needed
35
+ # @deprecated
36
+ def setup(&block)
37
+ $stderr.puts "WARN: The Shoes.setup method is deprecated, you need to install gems yourself." \
38
+ "You can do this using the 'gem install' command or bundler and a Gemfile."
39
+ DeprecatedShoesGemSetup.new.instance_eval(&block)
40
+ end
41
+
42
+ # Load the backend in memory. This does not set any configuration.
43
+ #
44
+ # @param name [String|Symbol] The name, such as :swt or :mock
45
+ # @return The backend
46
+ def load_backend(name)
47
+ require "shoes/#{name.to_s.downcase}"
48
+ Shoes.const_get(name.to_s.capitalize)
49
+ rescue LoadError => e
50
+ raise LoadError, "Couldn't load backend Shoes::#{name.capitalize}'. Error: #{e.message}\n#{e.backtrace.join("\n")}"
51
+ end
52
+ end
53
+
54
+ class DeprecatedShoesGemSetup
55
+ def gem(name)
56
+ name, version = name.split
57
+ install_cmd = 'gem install ' + name
58
+ install_cmd += " --version \"#{version}\"" if version
59
+ $stderr.puts "WARN: To use the '#{name}' gem, install it with '#{install_cmd}', and put 'require \"#{name}\"' at the top of your Shoes program."
60
+ end
61
+ end
62
+ end
63
+
64
+ require 'shoes/core/version'
65
+ require 'shoes/packager'
66
+
67
+ require 'shoes/renamed_delegate'
68
+ require 'shoes/common/inspect'
69
+ require 'shoes/dimension'
70
+ require 'shoes/dimensions'
71
+ require 'shoes/not_implemented_error'
72
+ require 'shoes/file_not_found_error'
73
+ require 'shoes/text_block_dimensions'
74
+
75
+ require 'shoes/color'
76
+
77
+ require 'shoes/common/background_element'
78
+ require 'shoes/common/changeable'
79
+ require 'shoes/common/clickable'
80
+ require 'shoes/common/positioning'
81
+ require 'shoes/common/remove'
82
+ require 'shoes/common/state'
83
+ require 'shoes/common/style'
84
+ require 'shoes/common/style_normalizer'
85
+ require 'shoes/common/visibility'
86
+
87
+ require 'shoes/common/ui_element'
88
+
89
+ require 'shoes/builtin_methods'
90
+ require 'shoes/check_button'
91
+ require 'shoes/text'
92
+ require 'shoes/span'
93
+ require 'shoes/input_box'
94
+
95
+ # please keep this list tidy and alphabetically sorted
96
+ require 'shoes/animation'
97
+ require 'shoes/arc'
98
+ require 'shoes/background'
99
+ require 'shoes/border'
100
+ require 'shoes/button'
101
+ require 'shoes/configuration'
102
+ require 'shoes/color'
103
+ require 'shoes/dialog'
104
+ require 'shoes/download'
105
+ require 'shoes/font'
106
+ require 'shoes/gradient'
107
+ require 'shoes/image'
108
+ require 'shoes/image_pattern'
109
+ require 'shoes/key_event'
110
+ require 'shoes/line'
111
+ require 'shoes/link'
112
+ require 'shoes/link_hover'
113
+ require 'shoes/list_box'
114
+ require 'shoes/logger'
115
+ require 'shoes/oval'
116
+ require 'shoes/point'
117
+ require 'shoes/progress'
118
+ require 'shoes/radio'
119
+ require 'shoes/rect'
120
+ require 'shoes/shape'
121
+ require 'shoes/slot_contents'
122
+ require 'shoes/slot'
123
+ require 'shoes/star'
124
+ require 'shoes/sound'
125
+ require 'shoes/text_block'
126
+ require 'shoes/timer'
127
+
128
+ class Shoes
129
+ # Methods for creating and manipulating Shoes elements
130
+ #
131
+ # Requirements
132
+ #
133
+ # Including classes must provide:
134
+ #
135
+ # @__app__
136
+ #
137
+ # which provides
138
+ # #style: a hash of styles
139
+ # #element_styles: a hash of {Class => styles}, where styles is
140
+ # a hash of default styles for elements of Class,
141
+ module DSL
142
+ include Common::Style
143
+ include Color::DSLHelpers
144
+
145
+ # Set default style for elements of a particular class, or for all
146
+ # elements, or return the current defaults for all elements
147
+ #
148
+ # @overload style(klass, styles)
149
+ # Set default style for elements of a particular class
150
+ # @param [Class] klass a Shoes element class
151
+ # @param [Hash] styles default styles for elements of klass
152
+ # @example
153
+ # style Para, :text_size => 42, :stroke => green
154
+ #
155
+ # @overload style(styles)
156
+ # Set default style for all elements
157
+ # @param [Hash] styles default style for all elements
158
+ # @example
159
+ # style :stroke => alicewhite, :fill => black
160
+ #
161
+ # @overload style()
162
+ # @return [Hash] the default style for all elements
163
+ def style(klass_or_styles = nil, styles = {})
164
+ if klass_or_styles.kind_of? Class
165
+ klass = klass_or_styles
166
+ @__app__.element_styles[klass] = styles
167
+ else
168
+ @__app__.style(klass_or_styles)
169
+ end
170
+ end
171
+
172
+ private
173
+
174
+ def style_normalizer
175
+ @style_normalizer ||= Common::StyleNormalizer.new
176
+ end
177
+
178
+ def pop_style(opts)
179
+ opts.last.class == Hash ? opts.pop : {}
180
+ end
181
+
182
+ # Default styles for elements of klass
183
+ def style_for_element(klass, styles = {})
184
+ @__app__.element_styles.fetch(klass, {}).merge(styles)
185
+ end
186
+
187
+ def normalize_style_for_element(clazz, texts)
188
+ style = style_normalizer.normalize(pop_style(texts))
189
+ style_for_element(clazz, style)
190
+ end
191
+
192
+ def create(element, *args, &blk)
193
+ element.new(@__app__, @__app__.current_slot, *args, &blk)
194
+ end
195
+
196
+ public
197
+
198
+ def image(path, styles = {}, &blk)
199
+ create Shoes::Image, path, styles, blk
200
+ end
201
+
202
+ def border(color, styles = {})
203
+ create Shoes::Border, pattern(color), styles
204
+ end
205
+
206
+ def background(color, styles = {})
207
+ create Shoes::Background, pattern(color), style_normalizer.normalize(styles)
208
+ end
209
+
210
+ def edit_line(*args, &blk)
211
+ style = pop_style(args)
212
+ text = args.first || ''
213
+ create Shoes::EditLine, text, style, blk
214
+ end
215
+
216
+ def edit_box(*args, &blk)
217
+ style = pop_style(args)
218
+ text = args.first || ''
219
+ create Shoes::EditBox, text, style, blk
220
+ end
221
+
222
+ def progress(opts = {}, &blk)
223
+ create Shoes::Progress, opts, blk
224
+ end
225
+
226
+ def check(opts = {}, &blk)
227
+ create Shoes::Check, opts, blk
228
+ end
229
+
230
+ def radio(*args, &blk)
231
+ style = pop_style(args)
232
+ group = args.first
233
+ create Shoes::Radio, group, style, blk
234
+ end
235
+
236
+ def list_box(opts = {}, &blk)
237
+ create Shoes::ListBox, opts, blk
238
+ end
239
+
240
+ def flow(opts = {}, &blk)
241
+ create Shoes::Flow, opts, blk
242
+ end
243
+
244
+ def stack(opts = {}, &blk)
245
+ create Shoes::Stack, opts, blk
246
+ end
247
+
248
+ def button(text = 'Button', opts = {}, &blk)
249
+ create Shoes::Button, text, opts, blk
250
+ end
251
+
252
+ # Creates an animation that runs the given block of code.
253
+ #
254
+ # @overload animate &blk
255
+ # @param [Proc] blk Code to run for each animation frame
256
+ # @return [Shoes::Animation]
257
+ # Defaults to framerate of 24 frames per second
258
+ # @example
259
+ # # 24 frames per second
260
+ # animate do
261
+ # # animation code
262
+ # end
263
+ # @overload animate(framerate, &blk)
264
+ # @param [Integer] framerate Frames per second
265
+ # @param [Proc] blk Code to run for each animation frame
266
+ # @return [Shoes::Animation]
267
+ # @example
268
+ # # 10 frames per second
269
+ # animate 10 do
270
+ # # animation code
271
+ # end
272
+ # @overload animate(opts = {}, &blk)
273
+ # @param [Hash] opts Animation options
274
+ # @param [Proc] blk Code to run for each animation frame
275
+ # @option opts [Integer] :framerate Frames per second
276
+ # @return [Shoes::Animation]
277
+ # @example
278
+ # # 10 frames per second
279
+ # animate :framerate => 10 do
280
+ # # animation code
281
+ # end
282
+ #
283
+ def animate(opts = {}, &blk)
284
+ opts = { framerate: opts } unless opts.is_a? Hash
285
+ Shoes::Animation.new @__app__, opts, blk
286
+ end
287
+
288
+ def every(n = 1, &blk)
289
+ animate 1.0 / n, &blk
290
+ end
291
+
292
+ def timer(n = 1, &blk)
293
+ n *= 1000
294
+ Timer.new @__app__, n, &blk
295
+ end
296
+
297
+ # similar controls as Shoes::Video (#video)
298
+ def sound(soundfile, opts = {}, &blk)
299
+ Shoes::Sound.new @__app__, soundfile, opts, &blk
300
+ end
301
+
302
+ # Creates an arc at (left, top)
303
+ #
304
+ # @param [Integer] left the x-coordinate of the top-left corner
305
+ # @param [Integer] top the y-coordinate of the top-left corner
306
+ # @param [Integer] width width of the arc's ellipse
307
+ # @param [Integer] height height of the arc's ellipse
308
+ # @param [Float] angle1 angle in radians marking the beginning of the arc segment
309
+ # @param [Float] angle2 angle in radians marking the end of the arc segment
310
+ # @param [Hash] opts Arc style options
311
+ # @option opts [Boolean] wedge (false)
312
+ # @option opts [Boolean] center (false) is (left, top) the center of the rectangle?
313
+ def arc(left, top, width, height, angle1, angle2, styles = {}, &blk)
314
+ create Shoes::Arc, left, top, width, height, angle1, angle2, styles, blk
315
+ end
316
+
317
+ # Draws a line from point A (x1,y1) to point B (x2,y2)
318
+ #
319
+ # @param [Integer] x1 The x-value of point A
320
+ # @param [Integer] y1 The y-value of point A
321
+ # @param [Integer] x2 The x-value of point B
322
+ # @param [Integer] y2 The y-value of point B
323
+ # @param [Hash] opts Style options
324
+ def line(x1, y1, x2, y2, styles = {}, &blk)
325
+ create Shoes::Line, Shoes::Point.new(x1, y1), Shoes::Point.new(x2, y2), styles, blk
326
+ end
327
+
328
+ # Creates an oval at (left, top)
329
+ #
330
+ # @overload oval(left, top, diameter)
331
+ # Creates a circle at (left, top), with the given diameter
332
+ # @param [Integer] left the x-coordinate of the top-left corner
333
+ # @param [Integer] top the y-coordinate of the top-left corner
334
+ # @param [Integer] diameter the diameter
335
+ # @overload oval(left, top, width, height)
336
+ # Creates an oval at (left, top), with the given width and height
337
+ # @param [Integer] left the x-coordinate of the top-left corner
338
+ # @param [Integer] top the y-coordinate of the top-left corner
339
+ # @param [Integer] width the width
340
+ # @param [Integer] height the height
341
+ # @overload oval(styles)
342
+ # Creates an oval using values from the styles Hash.
343
+ # @param [Hash] styles
344
+ # @option styles [Integer] left (0) the x-coordinate of the top-left corner
345
+ # @option styles [Integer] top (0) the y-coordinate of the top-left corner
346
+ # @option styles [Integer] width (0) the width
347
+ # @option styles [Integer] height (0) the height
348
+ # @option styles [Integer] top (0) the y-coordinate of the top-left corner
349
+ # @option styles [Boolean] center (false) is (left, top) the center of the oval
350
+ def oval(*opts, &blk)
351
+ oval_style = pop_style(opts)
352
+ oval_style = style_normalizer.normalize(oval_style)
353
+ case opts.length
354
+ when 3
355
+ left, top, width = opts
356
+ height = width
357
+ when 4
358
+ left, top, width, height = opts
359
+ when 0
360
+ left = oval_style[:left] || 0
361
+ top = oval_style[:top] || 0
362
+ width = oval_style[:diameter] || oval_style[:width] ||
363
+ (oval_style[:radius] || 0) * 2
364
+ height = oval_style[:height] || width
365
+ else
366
+ message = <<EOS
367
+ Wrong number of arguments. Must be one of:
368
+ - oval(left, top, diameter, [opts])
369
+ - oval(left, top, width, height, [opts])
370
+ - oval(styles)
371
+ EOS
372
+ fail ArgumentError, message
373
+ end
374
+ create Shoes::Oval, left, top, width, height, oval_style, blk
375
+ end
376
+
377
+ # Creates a rectangle
378
+ #
379
+ # @overload rect(left, top, side, styles)
380
+ # Creates a square at (left, top), with sides of the given length
381
+ # @param [Integer] left the x-coordinate of the top-left corner
382
+ # @param [Integer] top the y-coordinate of the top-left corner
383
+ # @param [Integer] side the length of a side
384
+ # @overload rect(left, top, width, height, rounded = 0, styles)
385
+ # Creates a rectangle at (left, top), with the given width and height
386
+ # @param [Integer] left the x-coordinate of the top-left corner
387
+ # @param [Integer] top the y-coordinate of the top-left corner
388
+ # @param [Integer] width the width
389
+ # @param [Integer] height the height
390
+ # @overload rect(styles)
391
+ # Creates a rectangle using values from the styles Hash.
392
+ # @param [Hash] styles
393
+ # @option styles [Integer] left (0) the x-coordinate of the top-left corner
394
+ # @option styles [Integer] top (0) the y-coordinate of the top-left corner
395
+ # @option styles [Integer] width (0) the width
396
+ # @option styles [Integer] height (0) the height
397
+ # @option styles [Integer] top (0) the y-coordinate of the top-left corner
398
+ # @option styles [Boolean] center (false) is (left, top) the center of the rectangle?
399
+ def rect(*args, &blk)
400
+ opts = style_normalizer.normalize pop_style(args)
401
+ case args.length
402
+ when 3
403
+ left, top, width = args
404
+ height = width
405
+ opts[:curve] ||= 0
406
+ when 4
407
+ left, top, width, height = args
408
+ opts[:curve] ||= 0
409
+ when 5
410
+ left, top, width, height, opts[:curve] = args
411
+ when 0
412
+ left = opts[:left] || 0
413
+ top = opts[:top] || 0
414
+ width = opts[:width] || 0
415
+ height = opts[:height] || width
416
+ opts[:curve] ||= 0
417
+ else
418
+ message = <<EOS
419
+ Wrong number of arguments. Must be one of:
420
+ - rect(left, top, side, [opts])
421
+ - rect(left, top, width, height, [opts])
422
+ - rect(left, top, width, height, curve, [opts])
423
+ - rect(styles)
424
+ EOS
425
+ fail ArgumentError, message
426
+ end
427
+ create Shoes::Rect, left, top, width, height, style.merge(opts), blk
428
+ end
429
+
430
+ # Creates a new Shoes::Star object
431
+ #
432
+ # @overload shape(left, top, styles, &block)
433
+ # Creates a star at (left, top) with the given style
434
+ # @param [Integer] left the x-coordinate of the top-left corner
435
+ # @param [Integer] top the y-coordinate of the top-left corner
436
+ # @param [Hash] styles optional, additional styling for the element
437
+ # @overload shape(left, top, points, styles, &block)
438
+ # Creates a star at (left, top) with the given style
439
+ # @param [Integer] left the x-coordinate of the top-left corner
440
+ # @param [Integer] top the y-coordinate of the top-left corner
441
+ # @param [Integer] points count of points on the star
442
+ # @param [Hash] styles optional, additional styling for the element
443
+ # @overload shape(left, top, points, outer, styles, &block)
444
+ # Creates a star at (left, top) with the given style
445
+ # @param [Integer] left the x-coordinate of the top-left corner
446
+ # @param [Integer] top the y-coordinate of the top-left corner
447
+ # @param [Integer] points count of points on the star
448
+ # @param [Integer] outer outer radius of star
449
+ # @param [Hash] styles optional, additional styling for the element
450
+ # @overload shape(left, top, points, outer, inner, styles, &block)
451
+ # Creates a star at (left, top) with the given style
452
+ # @param [Integer] left the x-coordinate of the top-left corner
453
+ # @param [Integer] top the y-coordinate of the top-left corner
454
+ # @param [Integer] points count of points on the star
455
+ # @param [Integer] outer outer radius of star
456
+ # @param [Integer] inner inner radius of star
457
+ # @param [Hash] styles optional, additional styling for the element
458
+ def star(left, top, *args, &blk)
459
+ styles = style_normalizer.normalize pop_style(args)
460
+
461
+ points, outer, inner, extras = args
462
+
463
+ if extras
464
+ message = <<EOS
465
+ Wrong number of arguments. Must be one of:
466
+ - star(left, top, [styles])
467
+ - star(left, top, points, [styles])
468
+ - star(left, top, points, outer, [styles])
469
+ - star(left, top, points, outer, inner, [styles])
470
+ EOS
471
+ fail ArgumentError, message
472
+ end
473
+
474
+ create Shoes::Star, left, top, points, outer, inner, styles, blk
475
+ end
476
+
477
+ # Creates a new Shoes::Shape object
478
+ #
479
+ # @overload shape(left, top, styles, &block)
480
+ # Creates a shape at (left, top) with the given style
481
+ # @param [Integer] left the x-coordinate of the top-left corner
482
+ # @param [Integer] top the y-coordinate of the top-left corner
483
+ # @overload shape(left, top)
484
+ # Creates a shape at (left, top, &block)
485
+ # @param [Integer] left the x-coordinate of the top-left corner
486
+ # @param [Integer] top the y-coordinate of the top-left corner
487
+ # @overload shape(styles, &block)
488
+ # Creates a shape at (0, 0)
489
+ # @option styles [Integer] left (0) the x-coordinate of the top-left corner
490
+ # @option styles [Integer] top (0) the y-coordinate of the top-left corner
491
+ def shape(*args, &blk)
492
+ opts = style_normalizer.normalize pop_style(args)
493
+ opts[:left], opts[:top] = args if args.length == 2
494
+
495
+ message = <<EOS
496
+ Wrong number of arguments. Must be one of:
497
+ - shape()
498
+ - shape(left, top, [opts])
499
+ - shape(styles)
500
+ EOS
501
+ fail ArgumentError, message unless [0, 2].include? args.length
502
+ create Shoes::Shape, style.merge(opts), blk
503
+ end
504
+
505
+ # Define app-level setter methods
506
+ PATTERN_APP_STYLES = [:fill, :stroke]
507
+ OTHER_APP_STYLES = [:cap, :rotate, :strokewidth, :transform, :translate]
508
+
509
+ PATTERN_APP_STYLES.each do |style|
510
+ define_method style.to_s do |val|
511
+ @__app__.style[style] = pattern(val)
512
+ end
513
+ end
514
+
515
+ OTHER_APP_STYLES.each do |style|
516
+ define_method style.to_s do |val|
517
+ @__app__.style[style] = val
518
+ end
519
+ end
520
+
521
+ def nostroke
522
+ @__app__.style[:stroke] = nil
523
+ end
524
+
525
+ def nofill
526
+ @__app__.style[:fill] = nil
527
+ end
528
+
529
+ %w(banner title subtitle tagline caption para inscription).each do |method|
530
+ define_method method do |*texts|
531
+ styles = pop_style(texts)
532
+ klass = Shoes.const_get(method.capitalize)
533
+ create klass, texts, styles
534
+ end
535
+ end
536
+
537
+ TEXT_STYLES = {
538
+ code: { font: "Lucida Console" },
539
+ del: { strikethrough: true },
540
+ em: { emphasis: true },
541
+ ins: { underline: true },
542
+ sub: { rise: -10, size_modifier: 0.8 },
543
+ sup: { rise: 10, size_modifier: 0.8 },
544
+ strong: { weight: true },
545
+ }
546
+
547
+ TEXT_STYLES.keys.each do |method|
548
+ define_method method do |*texts|
549
+ styles = style_normalizer.normalize(pop_style(texts))
550
+ styles = TEXT_STYLES[method].merge(styles)
551
+ Shoes::Span.new texts, styles
552
+ end
553
+ end
554
+
555
+ def fg(*texts, color)
556
+ Shoes::Span.new texts, stroke: pattern(color)
557
+ end
558
+
559
+ def bg(*texts, color)
560
+ Shoes::Span.new texts, fill: pattern(color)
561
+ end
562
+
563
+ def link(*texts, &blk)
564
+ opts = normalize_style_for_element(Shoes::Link, texts)
565
+ Shoes::Link.new @__app__, texts, opts, blk
566
+ end
567
+
568
+ def span(*texts)
569
+ opts = normalize_style_for_element(Shoes::Span, texts)
570
+ Shoes::Span.new texts, opts
571
+ end
572
+
573
+ def mouse
574
+ [@__app__.mouse_button, @__app__.mouse_pos[0], @__app__.mouse_pos[1]]
575
+ end
576
+
577
+ def motion(&blk)
578
+ @__app__.mouse_motion << blk
579
+ end
580
+
581
+ def resize(&blk)
582
+ @__app__.add_resize_callback blk
583
+ end
584
+
585
+ # hover and leave just delegate to the current slot as hover and leave
586
+ # are just defined for slots but self is always the app.
587
+ def hover(&blk)
588
+ @__app__.current_slot.hover(blk)
589
+ end
590
+
591
+ def leave(&blk)
592
+ @__app__.current_slot.leave(blk)
593
+ end
594
+
595
+ def keypress(&blk)
596
+ Shoes::Keypress.new @__app__, &blk
597
+ end
598
+
599
+ def keyrelease(&blk)
600
+ Shoes::Keyrelease.new @__app__, &blk
601
+ end
602
+
603
+ def append(&blk)
604
+ blk.call if blk
605
+ end
606
+
607
+ def visit(url)
608
+ match_data = nil
609
+ url_data = Shoes::URL.urls.find { |page, _| match_data = page.match url }
610
+ if url_data
611
+ action_proc = url_data[1]
612
+ url_argument = match_data[1]
613
+ clear do
614
+ @__app__.location = url
615
+ action_proc.call self, url_argument
616
+ end
617
+ end
618
+ end
619
+
620
+ def scroll_top
621
+ @__app__.scroll_top
622
+ end
623
+
624
+ def scroll_top=(n)
625
+ @__app__.scroll_top = n
626
+ end
627
+
628
+ def clipboard
629
+ @__app__.clipboard
630
+ end
631
+
632
+ def clipboard=(str)
633
+ @__app__.clipboard = str
634
+ end
635
+
636
+ def download(name, args = {}, &blk)
637
+ create(Shoes::Download, name, args, &blk).tap(&:start)
638
+ end
639
+
640
+ def gutter
641
+ @__app__.gutter
642
+ end
643
+
644
+ def video(*_args)
645
+ fail Shoes::NotImplementedError,
646
+ 'Sorry video support has been cut from shoes 4!' \
647
+ ' Check out github issue #113 for any changes/updates or if you' \
648
+ ' want to help :)'
649
+ end
650
+ end
651
+ end
652
+
653
+ require 'shoes/internal_app'
654
+ require 'shoes/app'
655
+ require 'shoes/widget'
656
+ require 'shoes/url'