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,4 @@
1
+ class Shoes
2
+ class FileNotFoundError < StandardError
3
+ end
4
+ end
@@ -0,0 +1,50 @@
1
+ class Shoes
2
+ FONT_DIR = DIR + "/fonts/"
3
+
4
+ module Font
5
+ FONT_TYPES = "{ttf,ttc,otf,fnt,fon,bdf,pcf,snf,mmm,pfb,pfm}"
6
+ @loaded_fonts = {}
7
+
8
+ class << self
9
+ attr_reader :loaded_fonts
10
+
11
+ def font_paths_from_dir(path)
12
+ font_paths = []
13
+ Dir.glob(path + "**/*." + FONT_TYPES).each do |font_path|
14
+ font_paths << font_path
15
+ end
16
+ font_paths
17
+ end
18
+
19
+ def add_font(path)
20
+ Shoes.backend::Font.add_font(path)
21
+ end
22
+
23
+ def add_font_to_fonts(path)
24
+ name = font_name(path)
25
+ Shoes::FONTS << name
26
+ name
27
+ end
28
+
29
+ def initial_fonts
30
+ Shoes.backend::Font.initial_fonts
31
+ end
32
+
33
+ private
34
+
35
+ def font_name(path)
36
+ remove_file_ext(parse_filename_from_path(path))
37
+ end
38
+
39
+ def parse_filename_from_path(file_path)
40
+ Pathname.new(file_path).basename.to_s
41
+ end
42
+
43
+ def remove_file_ext(file_name)
44
+ file_name.chomp(File.extname(file_name))
45
+ end
46
+ end
47
+ end
48
+
49
+ FONTS = []
50
+ end
@@ -0,0 +1,31 @@
1
+ class Shoes
2
+ class Gradient
3
+ include Common::Inspect
4
+ include Comparable
5
+
6
+ def initialize(color1, color2, alpha = Shoes::Color::OPAQUE)
7
+ @color1, @color2 = color1, color2
8
+ @alpha = alpha
9
+ end
10
+
11
+ attr_reader :alpha, :color1, :color2
12
+
13
+ def inspect
14
+ super.insert(-2, " #{color1}->#{color2}")
15
+ end
16
+
17
+ def <=>(other) # arbitrarily compare 1st non-equal color
18
+ raise_class_mismatch_error(other) unless other.is_a?(self.class)
19
+ if @color1 == other.color1
20
+ @color2 <=> other.color2
21
+ else
22
+ @color1 <=> other.color1
23
+ end
24
+ end
25
+
26
+ def raise_class_mismatch_error(other)
27
+ fail ArgumentError,
28
+ "can't compare #{self.class.name} with #{other.class.name}"
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,53 @@
1
+ class Shoes
2
+ class Image
3
+ include Common::UIElement
4
+ include Common::Style
5
+ include Common::Clickable
6
+
7
+ BINARY_ENCODING = Encoding.find('binary')
8
+
9
+ attr_reader :app, :parent, :dimensions, :gui
10
+ style_with :art_styles, :common_styles, :dimensions, :file_path
11
+
12
+ def initialize(app, parent, file_path_or_data, styles = {}, blk = nil)
13
+ @app = app
14
+ @parent = parent
15
+ style_init styles, file_path: normalized_source(file_path_or_data)
16
+ @dimensions = Dimensions.new parent, @style
17
+ @parent.add_child self
18
+ @gui = Shoes.configuration.backend_for self, @parent.gui
19
+ register_click blk
20
+ end
21
+
22
+ def path
23
+ @style[:file_path]
24
+ end
25
+
26
+ def path=(path_or_data)
27
+ style(file_path: normalized_source(path_or_data))
28
+ @gui.update_image
29
+ end
30
+
31
+ def url?(path_or_data)
32
+ path_or_data =~ %r{^https?://}
33
+ end
34
+
35
+ def raw_image_data?(name_or_data)
36
+ name_or_data.encoding == BINARY_ENCODING
37
+ end
38
+
39
+ private
40
+
41
+ def normalized_source(path_or_data)
42
+ return path_or_data if raw_image_data?(path_or_data)
43
+ return path_or_data if url?(path_or_data)
44
+ absolute_file_path(path_or_data)
45
+ end
46
+
47
+ def absolute_file_path(path)
48
+ path = File.join(Dir.pwd, path) unless Pathname(path).absolute?
49
+ fail FileNotFoundError, "#{path} not found." unless File.exist?(path)
50
+ path
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,12 @@
1
+ class Shoes
2
+ class ImagePattern
3
+ include Common::Inspect
4
+
5
+ def initialize(path)
6
+ @path = path
7
+ @gui = Shoes.configuration.backend_for(self)
8
+ end
9
+
10
+ attr_reader :gui, :path
11
+ end
12
+ end
@@ -0,0 +1,59 @@
1
+ class Shoes
2
+ class InputBox
3
+ include Common::UIElement
4
+ include Common::Style
5
+ include Common::Changeable
6
+
7
+ attr_reader :app, :parent, :dimensions, :gui
8
+
9
+ def initialize(app, parent, text, styles = {}, blk = nil)
10
+ @app = app
11
+ @parent = parent
12
+ style_init styles, text: text.to_s
13
+ @dimensions = Dimensions.new parent, @style
14
+ @parent.add_child self
15
+ @gui = Shoes.configuration.backend_for self, @parent.gui
16
+ change(&blk) if blk
17
+ end
18
+
19
+ def state=(value)
20
+ style(state: value)
21
+ @gui.enabled value.nil?
22
+ end
23
+
24
+ def focus
25
+ @gui.focus
26
+ end
27
+
28
+ def text
29
+ @gui.text
30
+ end
31
+
32
+ def text=(value)
33
+ style(text: value.to_s)
34
+ @gui.text = value.to_s
35
+ end
36
+
37
+ def highlight_text(start_index, final_index)
38
+ @gui.highlight_text(start_index, final_index)
39
+ end
40
+
41
+ def caret_to(index)
42
+ @gui.caret_to(index)
43
+ end
44
+ end
45
+
46
+ class EditBox < InputBox
47
+ style_with :change, :common_styles, :dimensions, :text, :state
48
+ STYLES = { width: 200, height: 108, text: '' }
49
+ end
50
+
51
+ class EditLine < InputBox
52
+ style_with :change, :common_styles, :dimensions, :text, :secret, :state
53
+ STYLES = { width: 200, height: 28, text: '' }
54
+
55
+ def secret?
56
+ secret
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,230 @@
1
+ class Shoes
2
+ # This is the representation of the app that is used internally by Shoes
3
+ # objects. It is *NOT* the app object that a user interacts with in a
4
+ # Shoes.app block. The user facing App object is...the App object.
5
+ #
6
+ # The InternalApp object is responsible for maintaining the state of the App
7
+ # and providing the bulk of the functionality, leaving the App a relatively
8
+ # blank slate for users to bend to their will.
9
+ class InternalApp
10
+ include Common::Style
11
+ include Common::Clickable
12
+ include DimensionsDelegations
13
+
14
+ extend Forwardable
15
+
16
+ DEFAULT_OPTIONS = { width: 600,
17
+ height: 500,
18
+ title: "Shoes 4",
19
+ resizable: true,
20
+ background: Shoes::COLORS.fetch(:shoes_background) }.freeze
21
+
22
+ def initialize(app, opts, &blk)
23
+ @app = app
24
+ @blk = blk
25
+ set_attributes_from_options(opts)
26
+ set_initial_attributes
27
+ end
28
+
29
+ def setup_gui
30
+ @gui = Shoes.configuration.backend::App.new self
31
+
32
+ self.current_slot = create_top_slot
33
+ execution_blk = create_execution_block(blk)
34
+ eval_block execution_blk
35
+
36
+ setup_global_keypresses
37
+ register_console_keypress
38
+ end
39
+
40
+ attr_reader :gui, :top_slot, :app, :dimensions,
41
+ :mouse_motion, :owner, :element_styles, :resize_callbacks
42
+ attr_accessor :elements, :current_slot, :opts, :blk, :mouse_button,
43
+ :mouse_pos, :mouse_hover_controls, :resizable, :app_title,
44
+ :width, :height, :start_as_fullscreen, :location
45
+
46
+ def_delegators :@app, :eval_with_additional_context
47
+
48
+ def clear(&blk)
49
+ current_slot.clear(&blk)
50
+ end
51
+
52
+ def contents
53
+ top_slot.contents
54
+ end
55
+
56
+ def width
57
+ started? ? gui.width : @dimensions.width
58
+ end
59
+
60
+ def height
61
+ started? ? gui.height : @dimensions.height
62
+ end
63
+
64
+ def font(path = Shoes::DEFAULT_TEXTBLOCK_FONT)
65
+ app.font path
66
+ end
67
+
68
+ def started?
69
+ gui && gui.started?
70
+ end
71
+
72
+ def add_child(_child)
73
+ # No-op. The top_slot needs this method, but we already hold an explicit
74
+ # reference to the top_slot, so we don't need to add it as a child. Other
75
+ # elements should be added as children of the top_slot.
76
+ end
77
+
78
+ def default_styles
79
+ Common::Style::DEFAULT_STYLES.clone
80
+ end
81
+
82
+ def in_bounds?(_x, _y)
83
+ true
84
+ end
85
+
86
+ def fullscreen=(state)
87
+ gui.fullscreen = state
88
+ end
89
+
90
+ def fullscreen
91
+ gui.fullscreen
92
+ end
93
+
94
+ alias_method :start_as_fullscreen?, :start_as_fullscreen
95
+
96
+ # Necessary for click/mouse positioning checks
97
+ def hidden?
98
+ false
99
+ end
100
+
101
+ def add_mouse_hover_control(element)
102
+ unless mouse_hover_controls.include? element
103
+ mouse_hover_controls << element
104
+ end
105
+ end
106
+
107
+ def open_gui
108
+ gui.open
109
+ end
110
+
111
+ def quit
112
+ @gui.quit
113
+ end
114
+
115
+ def scroll_top
116
+ gui.scroll_top
117
+ end
118
+
119
+ def scroll_top=(n)
120
+ gui.scroll_top = n
121
+ end
122
+
123
+ def clipboard
124
+ gui.clipboard
125
+ end
126
+
127
+ def clipboard=(str)
128
+ gui.clipboard = str
129
+ end
130
+
131
+ def download(url, opts, &block)
132
+ app.download url, opts, &block
133
+ end
134
+
135
+ def textcursor(line_height)
136
+ app.line(0, 0, 0, line_height, hidden: true)
137
+ end
138
+
139
+ def execute_block(blk)
140
+ app.instance_eval(&blk)
141
+ end
142
+
143
+ def gutter
144
+ gui.gutter
145
+ end
146
+
147
+ def add_resize_callback(blk)
148
+ @resize_callbacks << blk
149
+ end
150
+
151
+ def inspect
152
+ super.insert(-2, " \"#{@app_title}\" #{@dimensions.inspect})")
153
+ end
154
+
155
+ def self.global_keypresses
156
+ @global_keypresses ||= {}
157
+ end
158
+
159
+ def self.add_global_keypress(key, &blk)
160
+ global_keypresses[key] = blk
161
+ end
162
+
163
+ def wait_until_closed
164
+ return unless gui
165
+ gui.wait_until_closed
166
+ end
167
+
168
+ private
169
+
170
+ def create_top_slot
171
+ @top_slot = Flow.new self, self, width: width, height: height
172
+ end
173
+
174
+ def eval_block(execution_blk)
175
+ @top_slot.append(&execution_blk)
176
+ end
177
+
178
+ def create_execution_block(blk)
179
+ if blk
180
+ execution_blk = proc do
181
+ execute_block blk
182
+ end
183
+ elsif Shoes::URL.urls.keys.any? { |page| page.match '/' }
184
+ execution_blk = proc do
185
+ app.visit '/'
186
+ end
187
+ else
188
+ execution_blk = nil
189
+ end
190
+ execution_blk
191
+ end
192
+
193
+ def set_initial_attributes
194
+ @style = default_styles
195
+ @element_styles = {}
196
+ @mouse_motion = []
197
+ @mouse_button = 0
198
+ @mouse_pos = [0, 0]
199
+ @mouse_hover_controls = []
200
+ @resize_callbacks = []
201
+ @pass_coordinates = true
202
+ end
203
+
204
+ def set_attributes_from_options(opts)
205
+ opts = DEFAULT_OPTIONS.merge(opts)
206
+
207
+ @app_title = opts[:title]
208
+ @resizable = opts[:resizable]
209
+ @start_as_fullscreen = opts[:fullscreen]
210
+ @opts = opts
211
+ @owner = opts[:owner]
212
+ @dimensions = AbsoluteDimensions.new opts
213
+ self.absolute_left = 0
214
+ self.absolute_top = 0
215
+ end
216
+
217
+ def setup_global_keypresses
218
+ @app.keypress do |key|
219
+ blk = self.class.global_keypresses[key]
220
+ @app.instance_eval(&blk) unless blk.nil?
221
+ end
222
+ end
223
+
224
+ def register_console_keypress
225
+ self.class.add_global_keypress(:"alt_/") do
226
+ Logger.setup
227
+ end
228
+ end
229
+ end
230
+ end
@@ -0,0 +1,17 @@
1
+ class Shoes
2
+ class KeyEvent
3
+ def initialize(app, &blk)
4
+ @app = app
5
+ @gui = Shoes.backend_for self, &blk
6
+ end
7
+
8
+ attr_reader :app
9
+
10
+ def remove
11
+ @gui.remove
12
+ end
13
+ end
14
+
15
+ class Keypress < KeyEvent; end
16
+ class Keyrelease < KeyEvent; end
17
+ end