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,44 @@
1
+ class Shoes
2
+ # Backwards compatibility, kind of likely to be removed
3
+ def self.inherited(base_class)
4
+ base_class.send :include, URL # include is private, therefore send
5
+ end
6
+
7
+ module URL
8
+ attr_accessor :app
9
+
10
+ Shoes::App.subscribe_to_dsl_methods self
11
+
12
+ def self.included(base_class)
13
+ base_class.extend URLDefiner
14
+ end
15
+
16
+ def self.urls
17
+ @urls ||= {}
18
+ end
19
+ end
20
+
21
+ module URLDefiner
22
+ def url(page, method)
23
+ page = convert_page_to_regex(page)
24
+ url_class = self
25
+
26
+ Shoes::URL.urls[page] = proc do |app, arg|
27
+ new_url_instance = url_class.new
28
+ new_url_instance.app = app
29
+
30
+ if arg
31
+ new_url_instance.send(method, arg)
32
+ else
33
+ new_url_instance.send method
34
+ end
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def convert_page_to_regex(page)
41
+ /^#{page}$/
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,3 @@
1
+ class Shoes
2
+ VERSION = "4.0.0.pre3"
3
+ end
@@ -0,0 +1,67 @@
1
+ class Shoes
2
+ # This is the superclass for creating custom Shoes widgets.
3
+ #
4
+ # To use, inherit from {Shoes::Widget}. You get a few magical effects:
5
+ #
6
+ # * When you inherit from {Shoes::Widget}, you get a method in your Apps to
7
+ # create your widgets. The method is lower- and snake-cased. It returns
8
+ # an instance of your widget class.
9
+ # * Your widgets delegate missing methods to their app object. This
10
+ # allows you to use the Shoes DSL within your widgets.
11
+ #
12
+ # @example
13
+ # class SayHello < Shoes::Widget
14
+ # def initialize word
15
+ # para "Hello #{word}", stroke: green, size: 80
16
+ # end
17
+ # end
18
+ #
19
+ # Shoes.app do
20
+ # say_hello 'Shoes'
21
+ # end
22
+ #
23
+ class Widget
24
+ include Common::Inspect
25
+
26
+ Shoes::App.subscribe_to_dsl_methods self
27
+
28
+ attr_accessor :parent
29
+ attr_writer :app
30
+
31
+ class << self
32
+ attr_accessor :app
33
+ end
34
+
35
+ # lookup a bit more complicated as during initialize we do
36
+ # not have @app yet...
37
+ def app
38
+ @app || self.class.app
39
+ end
40
+
41
+ def self.inherited(klass, &_blk)
42
+ dsl_method = dsl_method_name(klass)
43
+ Shoes::App.new_dsl_method(dsl_method) do |*args, &blk|
44
+ # we set app 2 times because widgets execute most of their code
45
+ # straight in initialize. I dunno if there is a good way of setting
46
+ # an @app instance variable before initialize is executed. We could
47
+ # hand it over in #initialize but that would break the interface
48
+ # and people would have to set it themselves or make sure to call
49
+ # super so for not it's like this.
50
+ # Setting the ref on the instance is important as we might have
51
+ # instances of the same widget in different Shoes::Apps so each one
52
+ # needs to save the reference to the one it was started with
53
+ klass.app = self
54
+ widget_instance = klass.new(*args, &blk)
55
+ widget_instance.app = self
56
+ widget_instance.parent = @__app__.current_slot
57
+ widget_instance
58
+ end
59
+ end
60
+
61
+ def self.dsl_method_name(klass)
62
+ klass.to_s[/(^|::)(\w+)$/, 2]
63
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
64
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('lib/shoes/core/version')
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "shoes-core"
6
+ s.version = Shoes::Core::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Team Shoes"]
9
+ s.email = ["shoes@librelist.com"]
10
+ s.homepage = "https://github.com/shoes/shoes4"
11
+ s.summary = %q{The best little DSL for the best little GUI toolkit for Ruby.}
12
+ s.description = %q{Shoes is the best little GUI toolkit for Ruby. Shoes makes building for Mac, Windows, and Linux super simple. This is the DSL for writing your app. You'll need a backend to run it.}
13
+ s.license = 'MIT'
14
+
15
+ s.files = `git ls-files`.split($/)
16
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
17
+ s.require_paths = ["lib"]
18
+
19
+ # Curious why we don't install shoes? See ext/Rakefile for the nitty-gritty.
20
+ s.executables = ['shoes-picker', 'shoes-stub']
21
+ s.extensions = ['ext/install/Rakefile']
22
+ end
@@ -0,0 +1,71 @@
1
+ require 'shoes/spec_helper'
2
+
3
+ shared_examples_for Shoes::Animation do
4
+ it "should start" do
5
+ subject.start
6
+ expect(subject).not_to be_stopped
7
+ end
8
+
9
+ it "should stop" do
10
+ subject.stop
11
+ expect(subject).to be_stopped
12
+ end
13
+
14
+ it "should toggle on" do
15
+ subject.stop
16
+ subject.toggle
17
+ expect(subject).not_to be_stopped
18
+ end
19
+
20
+ it "should toggle off" do
21
+ subject.start
22
+ subject.toggle
23
+ expect(subject).to be_stopped
24
+ end
25
+
26
+ it "increments frame" do
27
+ frame = subject.current_frame
28
+ subject.increment_frame
29
+ expect(subject.current_frame).to eq(frame + 1)
30
+ end
31
+ end
32
+
33
+ describe Shoes::Animation do
34
+ let(:app) { double('app', current_slot: slot) }
35
+ let(:slot) { double('slot', create_bound_block: bound_block) }
36
+ let(:app_gui) { double('app gui') }
37
+ let(:opts) { {} }
38
+ let(:block) { double('block') }
39
+ let(:bound_block) { double('bound block') }
40
+ subject { Shoes::Animation.new( app, opts, block ) }
41
+
42
+ before :each do
43
+ expect(app).to receive(:gui) { app_gui }
44
+ end
45
+
46
+ it_behaves_like Shoes::Animation
47
+
48
+ it "sets default framerate" do
49
+ expect(subject.framerate).to eq(10)
50
+ end
51
+
52
+ it "sets current frame to 0" do
53
+ expect(subject.current_frame).to eq(0)
54
+ end
55
+
56
+ it "calls through slot's context" do
57
+ expect(subject.blk).to eq(bound_block)
58
+ end
59
+
60
+ it { is_expected.not_to be_stopped }
61
+
62
+ describe "with framerate" do
63
+ let(:opts) { {:framerate => 36, :app => app} }
64
+
65
+ it "sets framerate" do
66
+ expect(subject.framerate).to eq(36)
67
+ end
68
+
69
+ it_behaves_like Shoes::Animation
70
+ end
71
+ end
@@ -0,0 +1,484 @@
1
+ require 'shoes/spec_helper'
2
+
3
+ describe Shoes::App do
4
+ let(:input_blk) { Proc.new {} }
5
+ let(:opts) { Hash.new }
6
+ subject(:app) { Shoes::App.new(opts, &input_blk) }
7
+
8
+ after do
9
+ Shoes.unregister_all
10
+ end
11
+
12
+ it_behaves_like "DSL container"
13
+ it { is_expected.to respond_to :clipboard }
14
+ it { is_expected.to respond_to :clipboard= }
15
+ it { is_expected.to respond_to :owner }
16
+
17
+ # For Shoes 3 compatibility
18
+ it "exposes self as #app" do
19
+ expect(app.app).to eq(app)
20
+ end
21
+
22
+ describe "initialize" do
23
+ let(:input_blk) { Proc.new {} }
24
+
25
+ it "initializes style hash", :qt do
26
+ style = Shoes::App.new.style
27
+ expect(style.class).to eq(Hash)
28
+ end
29
+
30
+ context "console" do
31
+ end
32
+
33
+ context "defaults" do
34
+ let(:opts) { Hash.new }
35
+ let(:defaults) { Shoes::InternalApp::DEFAULT_OPTIONS }
36
+
37
+ it "sets width", :qt do
38
+ expect(subject.width).to eq defaults[:width]
39
+ end
40
+
41
+ it "sets height", :qt do
42
+ expect(subject.height).to eq defaults[:height]
43
+ end
44
+
45
+ it 'has an absolute_left of 0' do
46
+ expect(subject.absolute_left).to eq 0
47
+ end
48
+
49
+ it 'has an absolute_top of 0' do
50
+ expect(subject.absolute_top).to eq 0
51
+ end
52
+
53
+ describe "inspect" do
54
+ include InspectHelpers
55
+
56
+ it "shows title in #to_s" do
57
+ expect(subject.to_s).to eq("(Shoes::App \"#{defaults.fetch :title}\")")
58
+ end
59
+
60
+ it "shows title in #inspect" do
61
+ expect(subject.inspect).to match("(Shoes::App:#{shoes_object_id_pattern} \"#{defaults.fetch :title}\")")
62
+ end
63
+ end
64
+ end
65
+
66
+ context "from opts" do
67
+ let(:opts) { {:width => 150, :height => 2, :title => "Shoes::App Spec", :resizable => false} }
68
+
69
+ it "sets width", :qt do
70
+ expect(subject.width).to eq opts[:width]
71
+ end
72
+
73
+ it "sets height", :qt do
74
+ expect(subject.height).to eq opts[:height]
75
+ end
76
+
77
+ it "passes opts to InternalApp" do
78
+ expect(Shoes::InternalApp).to receive(:new).with(kind_of(Shoes::App), opts).and_call_original
79
+ subject
80
+ end
81
+
82
+ it 'initializes a flow with the right parameters' do
83
+ expect(Shoes::Flow).to receive(:new).with(anything, anything,
84
+ {width: opts[:width],
85
+ height: opts[:height]}).
86
+ and_call_original
87
+ subject
88
+ end
89
+ end
90
+
91
+ context "when registering" do
92
+ before :each do
93
+ Shoes.unregister_all
94
+ end
95
+
96
+ it "registers" do
97
+ old_apps_length = Shoes.apps.length
98
+ subject
99
+ expect(Shoes.apps.length).to eq(old_apps_length + 1)
100
+ expect(Shoes.apps).to include(subject)
101
+ end
102
+ end
103
+ end
104
+
105
+ describe "style with defaults" do
106
+ let(:default_styles) { Shoes::Common::Style::DEFAULT_STYLES }
107
+
108
+ it "sets app defaults" do
109
+ expect(app.style).to eq(default_styles)
110
+ end
111
+
112
+ it "merges new styles with existing styles" do
113
+ subject.style strokewidth: 4
114
+ expect(subject.style).to eq(default_styles.merge(strokewidth: 4))
115
+ end
116
+
117
+ default_styles = Shoes::Common::Style::DEFAULT_STYLES
118
+
119
+ default_styles.each do |key, value|
120
+ describe "#{key}" do
121
+ it "defaults to #{value}" do
122
+ expect(subject.style[key]).to eq(value)
123
+ end
124
+
125
+ it "passes default to objects" do
126
+ expect(subject.line(0, 100, 100, 0).style[key]).to eq(value)
127
+ end
128
+
129
+ end
130
+ end
131
+
132
+
133
+ describe "default styles" do
134
+ it "are independent among Shoes::App instances" do
135
+ app1 = Shoes::App.new
136
+ app2 = Shoes::App.new
137
+
138
+ app1.strokewidth 10
139
+ expect(app1.line(0, 100, 100, 0).style[:strokewidth]).to eq(10)
140
+
141
+ # .. but does not affect app2
142
+ expect(app2.line(0, 100, 100, 0).style[:strokewidth]).not_to eq(10)
143
+
144
+ end
145
+ end
146
+ end
147
+
148
+ describe "app-level style setter" do
149
+ let(:goldenrod) { Shoes::COLORS[:goldenrod] }
150
+
151
+ pattern_styles = Shoes::DSL::PATTERN_APP_STYLES
152
+ other_styles = Shoes::DSL::OTHER_APP_STYLES
153
+
154
+ pattern_styles.each do |style|
155
+ it "sets #{style} for objects" do
156
+ subject.public_send(style, goldenrod)
157
+ expect(subject.line(0, 100, 100, 0).style[style]).to eq(goldenrod)
158
+ end
159
+ end
160
+
161
+ other_styles.each do |style|
162
+ it "sets #{style} for objects" do
163
+ subject.public_send(style, 'val')
164
+ expect(subject.line(0, 100, 100, 0).style[style]).to eq('val')
165
+ end
166
+ end
167
+
168
+ end
169
+
170
+ describe "connecting with gui" do
171
+ let(:gui) { app.instance_variable_get(:@__app__).gui }
172
+
173
+ describe "clipboard" do
174
+ it "gets clipboard" do
175
+ expect(gui).to receive(:clipboard)
176
+ subject.clipboard
177
+ end
178
+
179
+ it "sets clipboard" do
180
+ expect(gui).to receive(:clipboard=).with("test")
181
+ subject.clipboard = "test"
182
+ end
183
+ end
184
+
185
+ describe "quitting" do
186
+ it "#quit tells the GUI to quit" do
187
+ expect(gui).to receive :quit
188
+ subject.quit
189
+ end
190
+
191
+ it '#close tells the GUI to quit' do
192
+ expect(gui).to receive :quit
193
+ subject.close
194
+ end
195
+ end
196
+ end
197
+
198
+ describe "#started?" do
199
+ it "checks the window has been displayed or not" do
200
+ subject.started?
201
+ end
202
+ end
203
+
204
+ describe 'Execution context' do
205
+ it 'starts with self as the execution context' do
206
+ my_self = nil
207
+ app = Shoes.app do my_self = self end
208
+ expect(my_self).to eq app
209
+ end
210
+ end
211
+
212
+ describe '#append' do
213
+ let(:input_blk) {Proc.new do append do para 'Hi' end end}
214
+
215
+ it 'understands append' do
216
+ expect(subject).to respond_to :append
217
+ end
218
+
219
+ it 'should receive a call to what is called in the append block' do
220
+ expect_any_instance_of(Shoes::App).to receive :para
221
+ subject
222
+ end
223
+ end
224
+
225
+ describe '#resize' do
226
+ it 'understands resize' do
227
+ expect(subject).to respond_to :resize
228
+ end
229
+ end
230
+
231
+ describe 'fullscreen' do
232
+ context 'defaults' do
233
+ it 'is not fullscreen' do
234
+ expect(app).not_to be_fullscreen
235
+ end
236
+
237
+ it 'can enter fullscreen' do
238
+ app.fullscreen = true
239
+ expect(app).to be_fullscreen
240
+ end
241
+ end
242
+
243
+ describe 'going into fullscreen and back out again' do
244
+ let(:defaults) { Shoes::InternalApp::DEFAULT_OPTIONS }
245
+
246
+ before :each do
247
+ app.fullscreen = true
248
+ app.fullscreen = false
249
+ end
250
+
251
+ # Failing on Mac fullscreen doesnt seem to work see #397
252
+ it 'is not in fullscreen', :fails_on_osx do
253
+ expect(app).not_to be_fullscreen
254
+ end
255
+
256
+ # Failing on Mac fullscreen doesnt seem to work see #397
257
+ it 'has its origina', :fails_on_osx do
258
+ expect(app.width).to eq(defaults[:width])
259
+ end
260
+
261
+ # Failing on Mac fullscreen doesnt seem to work see #397
262
+ it 'has its original height', :fails_on_osx do
263
+ expect(app.height).to eq(defaults[:height])
264
+ end
265
+ end
266
+ end
267
+
268
+ describe '#clear' do
269
+ let(:input_blk) do
270
+ Proc.new do
271
+ para 'Hello'
272
+ end
273
+ end
274
+ let(:internal_app) {subject.instance_variable_get(:@__app__)}
275
+
276
+ it 'has initial contents' do
277
+ expect(subject.contents).to_not be_empty
278
+ end
279
+
280
+ it 'removes everything (regression)' do
281
+ subject.clear
282
+ expect(subject.contents).to be_empty
283
+ end
284
+ end
285
+
286
+ describe "#gutter" do
287
+ context "when app has a scrollbar" do
288
+ let(:input_opts) { {width: 100, height: 100} }
289
+ let(:input_block) { Proc.new { para "Round peg, square hole" * 200 } }
290
+
291
+ it "has gutter of 16" do
292
+ expect(app.gutter).to be_within(2).of(16)
293
+ end
294
+ end
295
+
296
+ context "when app has no scrollbar" do
297
+ let(:input_block) { Proc.new { para "Round peg, square hole" } }
298
+
299
+ it "has gutter of 16" do
300
+ expect(app.gutter).to be_within(2).of(16)
301
+ end
302
+ end
303
+ end
304
+
305
+ describe "#parent" do
306
+ context "for a top-level element (not explicitly in a slot)" do
307
+ it "returns the top_slot" do
308
+ my_parent = nil
309
+ app = Shoes.app do
310
+ flow do
311
+ my_parent = parent
312
+ end
313
+ end
314
+ expect(my_parent).to eq app.instance_variable_get(:@__app__).top_slot
315
+ end
316
+ end
317
+
318
+ context "for an element within a slot" do
319
+ it "returns the enclosing slot" do
320
+ my_parent = nil
321
+ my_stack = nil
322
+ app = Shoes.app do
323
+ my_stack = stack do
324
+ flow do
325
+ my_parent = parent
326
+ end
327
+ end
328
+ end
329
+
330
+ expect(my_parent).to eq my_stack
331
+ end
332
+ end
333
+
334
+ end
335
+
336
+ describe "additional context" do
337
+ it "fails on unknown method" do
338
+ expect { subject.asdf }.to raise_error(NoMethodError)
339
+ end
340
+
341
+ it "calls through to context if available" do
342
+ context = double("context", asdf: nil)
343
+ expect(context).to receive(:asdf)
344
+
345
+ subject.eval_with_additional_context(context) do
346
+ asdf
347
+ end
348
+ end
349
+
350
+ it "clears context when finished" do
351
+ context = double("context")
352
+
353
+ captured_context = nil
354
+ subject.eval_with_additional_context(context) do
355
+ captured_context = @__additional_context__
356
+ end
357
+
358
+ expect(captured_context).to eq(context)
359
+ expect(subject.instance_variable_get(:@__additional_context__)).to be_nil
360
+ end
361
+
362
+ it "still clears context when failure in eval" do
363
+ context = double("context")
364
+
365
+ expect do
366
+ subject.eval_with_additional_context(context) { raise "O_o" }
367
+ end.to raise_error(RuntimeError)
368
+
369
+ expect(subject.instance_variable_get(:@__additional_context__)).to be_nil
370
+ end
371
+ end
372
+
373
+ describe 'subscribing to DSL methods' do
374
+
375
+ class TestSubscribeClass
376
+ attr_reader :app
377
+ def initialize(app)
378
+ @app = app
379
+ end
380
+ Shoes::App.subscribe_to_dsl_methods(self)
381
+ end
382
+
383
+ let(:subscribed_instance) {TestSubscribeClass.new subject}
384
+
385
+ AUTO_SUBSCRIBED_CLASSES = [Shoes::App, Shoes::URL, Shoes::Widget]
386
+ SUBSCRIBED_CLASSES = AUTO_SUBSCRIBED_CLASSES + [TestSubscribeClass]
387
+
388
+ describe '.subscribe_to_dsl_methods' do
389
+ it 'has its instances respond to the dsl methods of the app' do
390
+ expect(subscribed_instance).to respond_to :para, :image
391
+ end
392
+
393
+ it 'delegates does methods to the passed in app' do
394
+ expect(subject).to receive(:para)
395
+ subscribed_instance.para
396
+ end
397
+
398
+ SUBSCRIBED_CLASSES.each do |klazz|
399
+ it "#{klazz} responds to a regular DSL method" do
400
+ expect(klazz).to be_public_method_defined(:para)
401
+ end
402
+ end
403
+ end
404
+
405
+ describe '.new_dsl_method (for widget method notifications etc.)' do
406
+
407
+ before :each do
408
+ Shoes::App.new_dsl_method :widget_method do
409
+ # noop
410
+ end
411
+ end
412
+
413
+ SUBSCRIBED_CLASSES.each do |klazz|
414
+ it "#{klazz} now responds to this method" do
415
+ expect(klazz).to be_public_method_defined(:widget_method)
416
+ end
417
+ end
418
+ end
419
+
420
+ describe 'DELEGATE_METHODS' do
421
+ subject {Shoes::App::DELEGATE_METHODS}
422
+
423
+ describe 'does not include general ruby object methods' do
424
+ it {is_expected.not_to include :new, :initialize}
425
+ end
426
+
427
+ describe 'it has access to Shoes app and DSL methods' do
428
+ it {is_expected.to include :para, :rect, :stack, :flow, :image, :location}
429
+ end
430
+
431
+ describe 'it does not have access to private methods' do
432
+ it {is_expected.not_to include :pop_style, :style_normalizer, :create}
433
+ end
434
+
435
+ describe 'there are blacklisted methods that wreck havoc' do
436
+ it {is_expected.not_to include :parent, :app}
437
+ end
438
+ end
439
+
440
+ end
441
+ end
442
+
443
+ describe "App registry" do
444
+ subject { Shoes.apps }
445
+
446
+ before :each do
447
+ Shoes.unregister_all
448
+ end
449
+
450
+ it "only exposes a copy" do
451
+ subject << double("app")
452
+ expect(Shoes.apps.length).to eq(0)
453
+ end
454
+
455
+ context "with no apps" do
456
+ it { is_expected.to be_empty }
457
+ end
458
+
459
+ context "with one app" do
460
+ let(:app) { double('app') }
461
+ before :each do
462
+ Shoes.register(app)
463
+ end
464
+
465
+ its(:length) { should eq(1) }
466
+ it "marks first app as main app" do
467
+ expect(Shoes.main_app).to be(app)
468
+ end
469
+ end
470
+
471
+ context "with two apps" do
472
+ let(:app_1) { double("app 1") }
473
+ let(:app_2) { double("app 2") }
474
+
475
+ before :each do
476
+ [app_1, app_2].each { |a| Shoes.register(a) }
477
+ end
478
+
479
+ its(:length) { should eq(2) }
480
+ it "marks first app as main app" do
481
+ expect(Shoes.main_app).to be(app_1)
482
+ end
483
+ end
484
+ end