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,51 @@
1
+ class Shoes
2
+ class SlotContents < SimpleDelegator
3
+ include Common::Inspect
4
+
5
+ def initialize
6
+ @contents = []
7
+ @prepending = false
8
+ @prepending_index = 0
9
+ super(@contents)
10
+ end
11
+
12
+ def add_element(element)
13
+ if @prepending
14
+ prepend_element element
15
+ else
16
+ append_element element
17
+ end
18
+ end
19
+
20
+ def prepend(&blk)
21
+ @prepending_index = 0
22
+ @prepending = true
23
+ blk.call
24
+ @prepending = false
25
+ end
26
+
27
+ def clear
28
+ # reverse_each is important as otherwise we always miss to delete one
29
+ # element
30
+ @contents.reverse_each do |element|
31
+ element.is_a?(Shoes::Slot) ? element.clear : element.remove
32
+ end
33
+ @contents.clear
34
+ end
35
+
36
+ def inspect
37
+ super.insert(-2, " @size=#{size} @prepending=#{@prepending} @prepending_index=#{@prepending_index}")
38
+ end
39
+
40
+ private
41
+
42
+ def append_element(element)
43
+ @contents << element
44
+ end
45
+
46
+ def prepend_element(element)
47
+ @contents.insert @prepending_index, element
48
+ @prepending_index += 1
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,18 @@
1
+ class Shoes
2
+ class Sound
3
+ include Common::Inspect
4
+
5
+ def initialize(parent, filepath, _opts = {}, &_blk)
6
+ @parent = parent
7
+ @filepath = filepath
8
+
9
+ @gui = Shoes.configuration.backend_for(self)
10
+ end
11
+
12
+ attr_reader :gui, :filepath, :parent
13
+
14
+ def play
15
+ @gui.play
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ class Shoes
2
+ class Span < Text
3
+ def initialize(texts, styles = {})
4
+ @style = styles
5
+ super texts, styles.delete(:color)
6
+ end
7
+
8
+ def style
9
+ if @parent && @parent.respond_to?(:style)
10
+ @parent.style.merge(@style)
11
+ else
12
+ @style
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,50 @@
1
+ class Shoes
2
+ class Star
3
+ include Common::UIElement
4
+ include Common::Style
5
+ include Common::Clickable
6
+
7
+ attr_reader :app, :parent, :dimensions, :gui
8
+ style_with :angle, :art_styles, :common_styles, :dimensions, :inner, :outer, :points
9
+ STYLES = { angle: 0 }
10
+
11
+ def initialize(app, parent, left, top, points, outer, inner, styles = {}, blk = nil)
12
+ @app = app
13
+ @parent = parent
14
+
15
+ # Don't use param defaults as DSL explicit passes nil for missing params
16
+ points ||= 10
17
+ outer ||= 100.0
18
+ inner ||= 50.0
19
+
20
+ # Careful not to turn Fixnum to Float, lest Dimensions make you relative!
21
+ width = outer * 2
22
+
23
+ # Ignore calculated height on Dimensions--will force to match width
24
+ @dimensions = AbsoluteDimensions.new left, top, width, 0
25
+ @dimensions.height = @dimensions.width
26
+
27
+ # Calculate the inner dimensions, which might be relative too
28
+ inner_dimensions = AbsoluteDimensions.new 0, 0, inner * 2, 0
29
+
30
+ # Get actual outer/inner from the dimension to handle relative values
31
+ outer = @dimensions.width / 2
32
+ inner = inner_dimensions.width / 2
33
+
34
+ # Now set style using adjust outer and inner
35
+ style_init(styles, inner: inner, outer: outer, points: points)
36
+
37
+ @parent.add_child self
38
+ @gui = Shoes.backend_for self
39
+
40
+ register_click blk
41
+ end
42
+
43
+ def in_bounds?(x, y)
44
+ dx = width / 2.0
45
+ dy = height / 2.0
46
+ element_left - dx <= x && x <= element_right - dx &&
47
+ element_top - dy <= y && y <= element_bottom - dy
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,24 @@
1
+ class Shoes
2
+ class Text
3
+ include Common::Inspect
4
+
5
+ attr_reader :to_s, :texts, :color
6
+ attr_accessor :parent, :text_block
7
+
8
+ def initialize(texts, color = nil)
9
+ @texts = texts
10
+ @color = color
11
+ @to_s = @texts.map(&:to_s).join
12
+ @parent = nil
13
+ @text_block = nil
14
+ end
15
+
16
+ def app
17
+ @parent.app
18
+ end
19
+
20
+ def inspect
21
+ super.insert(-2, %( "#{self}"))
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,142 @@
1
+ class Shoes
2
+ CENTER = "center".freeze
3
+ DEFAULT_TEXTBLOCK_FONT = "Arial"
4
+
5
+ class TextBlock
6
+ include Common::UIElement
7
+ include Common::Style
8
+ include Common::Clickable
9
+ include TextBlockDimensionsDelegations
10
+
11
+ attr_reader :gui, :parent, :text, :contents, :app, :text_styles, :dimensions
12
+ attr_accessor :cursor, :textcursor
13
+ style_with :common_styles, :dimensions, :text_block_styles
14
+ STYLES = { font: "Arial" } # used in TextBlock specs only
15
+
16
+ def initialize(app, parent, text, styles = {})
17
+ @parent = parent
18
+ @app = app
19
+ style_init styles
20
+ @dimensions = TextBlockDimensions.new parent, @style
21
+ handle_styles @style
22
+ @gui = Shoes.backend_for self
23
+ @parent.add_child self
24
+
25
+ # Important to use accessor and do this after the backend exists!
26
+ self.text = Array(text)
27
+
28
+ register_click
29
+ end
30
+
31
+ def in_bounds?(*args)
32
+ @gui.in_bounds?(*args)
33
+ end
34
+
35
+ def text=(*texts)
36
+ replace(*texts[0])
37
+ end
38
+
39
+ def replace(*texts)
40
+ # Order here matters as well--backend#replace shouldn't rely on DSL state
41
+ # but the texts that it's passed if it needs information at this point.
42
+ @gui.replace(*texts)
43
+
44
+ @text = texts.map(&:to_s).join
45
+ @contents = texts
46
+ @text_styles = gather_text_styles(self, texts)
47
+ end
48
+
49
+ def to_s
50
+ text
51
+ end
52
+
53
+ def contents_alignment(current_position = nil)
54
+ @gui.contents_alignment(current_position)
55
+ end
56
+
57
+ def adjust_current_position(current_position)
58
+ @gui.adjust_current_position(current_position)
59
+ end
60
+
61
+ def textcursor(line_height = 0)
62
+ @textcursor ||= app.textcursor(line_height)
63
+ end
64
+
65
+ def has_textcursor?
66
+ @textcursor
67
+ end
68
+
69
+ def centered?
70
+ style[:align] == CENTER
71
+ end
72
+
73
+ def links
74
+ return [] unless @contents
75
+
76
+ @contents.select do |element|
77
+ element.is_a?(Shoes::Link)
78
+ end
79
+ end
80
+
81
+ private
82
+
83
+ def gather_text_styles(parent_text, texts, styles = {}, start_point = 0)
84
+ texts.each do |text|
85
+ if text.is_a? Shoes::Text
86
+ text.text_block = self
87
+ text.parent = parent_text
88
+ end_point = start_point + text.to_s.length - 1
89
+
90
+ # If our endpoint is before our start, it's an empty string. We treat
91
+ # those specially with the (0...0) range that has an empty count.
92
+ if end_point < start_point
93
+ range = (0...0)
94
+ else
95
+ range = start_point..end_point
96
+ end
97
+
98
+ styles[range] ||= []
99
+ styles[range] << text
100
+ gather_text_styles(text, text.texts, styles, start_point)
101
+ end
102
+ start_point += text.to_s.length
103
+ end
104
+ styles
105
+ end
106
+
107
+ def handle_styles(style)
108
+ parse_font_style style[:font] if style[:font] # if is needed for the specs
109
+ end
110
+
111
+ def parse_font_style(type)
112
+ size_regex = /(\d+)(\s*px)?/
113
+ style_regex = /none|bold|normal|oblique|italic/i # TODO: add more
114
+
115
+ font_family = type.gsub(style_regex, '').gsub(size_regex, '')
116
+ .split(',').map { |x| x.strip.gsub(/["]/, '') }
117
+
118
+ @style[:font] = font_family.first unless (font_family.size == 1 &&
119
+ font_family[0] == "") || font_family.size == 0
120
+
121
+ fsize = size_regex.match(type)
122
+ @style[:size] = fsize[1].to_i unless fsize.nil?
123
+
124
+ # TODO: Style options
125
+ end
126
+ end
127
+
128
+ {
129
+ "Banner" => { size: 48 },
130
+ "Title" => { size: 34 },
131
+ "Subtitle" => { size: 26 },
132
+ "Tagline" => { size: 18 },
133
+ "Caption" => { size: 14 },
134
+ "Para" => { size: 12 },
135
+ "Inscription" => { size: 10 }
136
+ }.each do |name, styles|
137
+ clazz = Class.new(TextBlock) do
138
+ const_set("STYLES", { font: "Arial", fill: nil }.merge(styles))
139
+ end
140
+ Shoes.const_set(name, clazz)
141
+ end
142
+ end
@@ -0,0 +1,51 @@
1
+ class Shoes
2
+ # We take over a bunch of the absolute_* measurements since the jagged
3
+ # shape of a flowed TextBlock doesn't follow the usual rules for dimensions
4
+ # when we get to positioning (which is the main use of these values).
5
+ class TextBlockDimensions < Dimensions
6
+ attr_writer :absolute_right, :absolute_bottom,
7
+ :calculated_width, :calculated_height
8
+
9
+ def absolute_right
10
+ @absolute_right || super
11
+ end
12
+
13
+ def absolute_bottom
14
+ @absolute_bottom || super
15
+ end
16
+
17
+ # It might seem weird these reverse from above, but if explicit sizes get
18
+ # reported verbatim, while boundaries are set by text fitting.
19
+ def width
20
+ super || @calculated_width
21
+ end
22
+
23
+ def height
24
+ super || @calculated_height
25
+ end
26
+
27
+ # Since we flow, try to fit in almost any space
28
+ def fitting_width
29
+ 10
30
+ end
31
+
32
+ # This is the width the text block initially wants to try and fit into.
33
+ def desired_width(containing = containing_width)
34
+ parent.absolute_left + containing - absolute_left
35
+ end
36
+
37
+ # If an explicit width's set, use that when asking how much space we need.
38
+ # If not, we look to the parent.
39
+ def containing_width
40
+ element_width || parent.element_width
41
+ end
42
+ end
43
+
44
+ module TextBlockDimensionsDelegations
45
+ extend Forwardable
46
+
47
+ DELEGATED_METHODS = TextBlockDimensions.public_instance_methods(false)
48
+
49
+ def_delegators :dimensions, *DELEGATED_METHODS
50
+ end
51
+ end
@@ -0,0 +1,14 @@
1
+ class Shoes
2
+ class Timer
3
+ include Common::Inspect
4
+
5
+ def initialize(app, n = 1000, &blk)
6
+ @app = app
7
+ @n = n
8
+ @blk = @app.current_slot.create_bound_block(blk)
9
+ @gui = Shoes.configuration.backend_for(self, @app.gui, @blk)
10
+ end
11
+
12
+ attr_reader :n, :gui
13
+ end
14
+ end
@@ -0,0 +1,67 @@
1
+ require 'optparse'
2
+ require 'shoes'
3
+
4
+ class Shoes
5
+ class CLI
6
+ attr_reader :packager
7
+
8
+ def initialize
9
+ @packager = Shoes::Packager.new
10
+ end
11
+
12
+ def parse!(args)
13
+ options = OptionParser.new do |opts|
14
+ opts.program_name = 'shoes'
15
+ opts.banner = <<-EOS
16
+ Usage: #{opts.program_name} [-h] [-p package] file
17
+ EOS
18
+ opts.separator ''
19
+ opts.separator 'Options:'
20
+
21
+ opts.on('-p', '--package PACKAGE_TYPE', 'Package as BACKEND:PACKAGE') do |package|
22
+ @packager.create_package(opts.program_name, package)
23
+ end
24
+
25
+ opts.on('-v', '--version', 'Shoes version') do
26
+ puts "Shoes #{Shoes::Core::VERSION}"
27
+ exit
28
+ end
29
+
30
+ opts.on('-m', '--manual', 'Run the Shoes manual') do
31
+ require 'shoes/manual'
32
+ Shoes::Manual.run "English"
33
+ exit
34
+ end
35
+
36
+ opts.separator @packager.help(opts.program_name)
37
+ end
38
+
39
+ options.parse!(args)
40
+ options
41
+ end
42
+
43
+ # Execute a shoes app.
44
+ #
45
+ # @param [String] app the location of the app to run
46
+ def execute_app(app)
47
+ $LOAD_PATH.unshift(Dir.pwd)
48
+ require 'shoes/swt'
49
+ load app
50
+ end
51
+
52
+ def run(args)
53
+ opts = parse!(args)
54
+ if args.empty?
55
+ puts opts.banner
56
+ puts "Try '#{opts.program_name} --help' for more information"
57
+ exit(0)
58
+ end
59
+
60
+ if @packager.should_package?
61
+ @packager.run(args.shift)
62
+ else
63
+ execute_app(args.first)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,47 @@
1
+ class Shoes
2
+ module UI
3
+ # This class is used for interactively (if necessary) picking the Shoes
4
+ # backend that the user will run their Shoes app with.
5
+ class Picker
6
+ def run
7
+ bundle
8
+ generator_file = select_generator
9
+ write_backend(generator_file)
10
+ end
11
+
12
+ # Only bundle if we find a local Gemfile. This allows us to work properly
13
+ # running from source without finding gem-nstalled backends.
14
+ def bundle
15
+ if File.exist?("Gemfile")
16
+ require 'bundler/setup'
17
+ Bundler.require
18
+ end
19
+ end
20
+
21
+ def select_generator
22
+ puts "Selecting Shoes backend to use. This is a one-time operation."
23
+ candidates = Gem.find_files("shoes/**/generate-backend.rb")
24
+ if candidates.one?
25
+ generator_file = candidates.first
26
+ else
27
+ fail NotImplementedError("Currently can't interactively select a backend. See #929")
28
+ end
29
+
30
+ generator_file
31
+ end
32
+
33
+ def write_backend(generator_file)
34
+ require generator_file
35
+
36
+ # On Windows getting odd paths with trailing double-quote
37
+ bin_dir = ARGV[0].gsub('"', '')
38
+
39
+ File.open(File.expand_path(File.join(bin_dir, "shoes-backend")), "w") do |file|
40
+ # Contract with backends is to define generate_backend method that we
41
+ # can call. Bit ugly, open to better options for that interchange.
42
+ file.write(generate_backend(ENV["SHOES_PICKER_BIN_DIR"] || bin_dir))
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end