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.
- checksums.yaml +7 -0
- data/LICENSE +31 -0
- data/README.md +8 -0
- data/Rakefile +1 -0
- data/bin/shoes +62 -0
- data/bin/shoes-guard +8 -0
- data/bin/shoes-picker +6 -0
- data/bin/shoes-stub +62 -0
- data/ext/install/Rakefile +29 -0
- data/ext/install/shoes.bat +15 -0
- data/fonts/Coolvetica.ttf +0 -0
- data/fonts/Lacuna.ttf +0 -0
- data/lib/rubygems_plugin.rb +24 -0
- data/lib/shoes.rb +1 -0
- data/lib/shoes/animation.rb +56 -0
- data/lib/shoes/app.rb +130 -0
- data/lib/shoes/arc.rb +25 -0
- data/lib/shoes/background.rb +20 -0
- data/lib/shoes/border.rb +20 -0
- data/lib/shoes/builtin_methods.rb +76 -0
- data/lib/shoes/button.rb +29 -0
- data/lib/shoes/check_button.rb +41 -0
- data/lib/shoes/color.rb +387 -0
- data/lib/shoes/common/background_element.rb +9 -0
- data/lib/shoes/common/changeable.rb +34 -0
- data/lib/shoes/common/clickable.rb +24 -0
- data/lib/shoes/common/inspect.rb +14 -0
- data/lib/shoes/common/positioning.rb +30 -0
- data/lib/shoes/common/registration.rb +31 -0
- data/lib/shoes/common/remove.rb +10 -0
- data/lib/shoes/common/state.rb +16 -0
- data/lib/shoes/common/style.rb +160 -0
- data/lib/shoes/common/style_normalizer.rb +16 -0
- data/lib/shoes/common/ui_element.rb +11 -0
- data/lib/shoes/common/visibility.rb +41 -0
- data/lib/shoes/configuration.rb +96 -0
- data/lib/shoes/core.rb +1 -0
- data/lib/shoes/core/version.rb +5 -0
- data/lib/shoes/dialog.rb +56 -0
- data/lib/shoes/dimension.rb +269 -0
- data/lib/shoes/dimensions.rb +203 -0
- data/lib/shoes/download.rb +130 -0
- data/lib/shoes/dsl.rb +656 -0
- data/lib/shoes/file_not_found_error.rb +4 -0
- data/lib/shoes/font.rb +50 -0
- data/lib/shoes/gradient.rb +31 -0
- data/lib/shoes/image.rb +53 -0
- data/lib/shoes/image_pattern.rb +12 -0
- data/lib/shoes/input_box.rb +59 -0
- data/lib/shoes/internal_app.rb +230 -0
- data/lib/shoes/key_event.rb +17 -0
- data/lib/shoes/line.rb +84 -0
- data/lib/shoes/link.rb +57 -0
- data/lib/shoes/link_hover.rb +5 -0
- data/lib/shoes/list_box.rb +50 -0
- data/lib/shoes/logger.rb +65 -0
- data/lib/shoes/logger/ruby.rb +16 -0
- data/lib/shoes/mock.rb +33 -0
- data/lib/shoes/mock/animation.rb +8 -0
- data/lib/shoes/mock/app.rb +49 -0
- data/lib/shoes/mock/arc.rb +9 -0
- data/lib/shoes/mock/background.rb +10 -0
- data/lib/shoes/mock/border.rb +7 -0
- data/lib/shoes/mock/button.rb +22 -0
- data/lib/shoes/mock/check.rb +24 -0
- data/lib/shoes/mock/clickable.rb +8 -0
- data/lib/shoes/mock/common_methods.rb +12 -0
- data/lib/shoes/mock/dialog.rb +13 -0
- data/lib/shoes/mock/download.rb +16 -0
- data/lib/shoes/mock/font.rb +15 -0
- data/lib/shoes/mock/image.rb +13 -0
- data/lib/shoes/mock/image_pattern.rb +8 -0
- data/lib/shoes/mock/input_box.rb +30 -0
- data/lib/shoes/mock/keypress.rb +11 -0
- data/lib/shoes/mock/keyrelease.rb +11 -0
- data/lib/shoes/mock/line.rb +14 -0
- data/lib/shoes/mock/link.rb +11 -0
- data/lib/shoes/mock/list_box.rb +19 -0
- data/lib/shoes/mock/oval.rb +11 -0
- data/lib/shoes/mock/packager.rb +13 -0
- data/lib/shoes/mock/progress.rb +10 -0
- data/lib/shoes/mock/radio.rb +27 -0
- data/lib/shoes/mock/rect.rb +14 -0
- data/lib/shoes/mock/shape.rb +20 -0
- data/lib/shoes/mock/slot.rb +16 -0
- data/lib/shoes/mock/sound.rb +8 -0
- data/lib/shoes/mock/star.rb +14 -0
- data/lib/shoes/mock/text_block.rb +36 -0
- data/lib/shoes/mock/timer.rb +8 -0
- data/lib/shoes/not_implemented_error.rb +4 -0
- data/lib/shoes/oval.rb +20 -0
- data/lib/shoes/packager.rb +26 -0
- data/lib/shoes/point.rb +54 -0
- data/lib/shoes/progress.rb +25 -0
- data/lib/shoes/radio.rb +15 -0
- data/lib/shoes/rect.rb +21 -0
- data/lib/shoes/renamed_delegate.rb +15 -0
- data/lib/shoes/shape.rb +159 -0
- data/lib/shoes/slot.rb +276 -0
- data/lib/shoes/slot_contents.rb +51 -0
- data/lib/shoes/sound.rb +18 -0
- data/lib/shoes/span.rb +16 -0
- data/lib/shoes/star.rb +50 -0
- data/lib/shoes/text.rb +24 -0
- data/lib/shoes/text_block.rb +142 -0
- data/lib/shoes/text_block_dimensions.rb +51 -0
- data/lib/shoes/timer.rb +14 -0
- data/lib/shoes/ui/cli.rb +67 -0
- data/lib/shoes/ui/picker.rb +47 -0
- data/lib/shoes/url.rb +44 -0
- data/lib/shoes/version.rb +3 -0
- data/lib/shoes/widget.rb +67 -0
- data/shoes-core.gemspec +22 -0
- data/spec/shoes/animation_spec.rb +71 -0
- data/spec/shoes/app_spec.rb +484 -0
- data/spec/shoes/arc_spec.rb +51 -0
- data/spec/shoes/background_spec.rb +47 -0
- data/spec/shoes/border_spec.rb +46 -0
- data/spec/shoes/builtin_methods_spec.rb +110 -0
- data/spec/shoes/button_spec.rb +44 -0
- data/spec/shoes/check_spec.rb +35 -0
- data/spec/shoes/color_spec.rb +408 -0
- data/spec/shoes/common/inspect_spec.rb +26 -0
- data/spec/shoes/common/remove_spec.rb +38 -0
- data/spec/shoes/common/style_normalizer_spec.rb +28 -0
- data/spec/shoes/common/style_spec.rb +147 -0
- data/spec/shoes/configuration_spec.rb +36 -0
- data/spec/shoes/constants_spec.rb +38 -0
- data/spec/shoes/dialog_spec.rb +171 -0
- data/spec/shoes/dimension_spec.rb +433 -0
- data/spec/shoes/dimensions_spec.rb +837 -0
- data/spec/shoes/download_spec.rb +146 -0
- data/spec/shoes/flow_spec.rb +133 -0
- data/spec/shoes/font_spec.rb +37 -0
- data/spec/shoes/framework_learning_spec.rb +30 -0
- data/spec/shoes/gradient_spec.rb +32 -0
- data/spec/shoes/helpers/fake_element.rb +17 -0
- data/spec/shoes/helpers/inspect_helpers.rb +5 -0
- data/spec/shoes/helpers/sample17_helper.rb +66 -0
- data/spec/shoes/image_spec.rb +68 -0
- data/spec/shoes/images/shoe.jpg +0 -0
- data/spec/shoes/input_box_spec.rb +80 -0
- data/spec/shoes/integration_spec.rb +20 -0
- data/spec/shoes/internal_app_spec.rb +141 -0
- data/spec/shoes/keypress_spec.rb +11 -0
- data/spec/shoes/keyrelease_spec.rb +12 -0
- data/spec/shoes/line_spec.rb +87 -0
- data/spec/shoes/link_spec.rb +118 -0
- data/spec/shoes/list_box_spec.rb +74 -0
- data/spec/shoes/logger/ruby_spec.rb +8 -0
- data/spec/shoes/logger_spec.rb +45 -0
- data/spec/shoes/oval_spec.rb +24 -0
- data/spec/shoes/packager_spec.rb +25 -0
- data/spec/shoes/point_spec.rb +71 -0
- data/spec/shoes/progress_spec.rb +54 -0
- data/spec/shoes/radio_spec.rb +32 -0
- data/spec/shoes/rect_spec.rb +39 -0
- data/spec/shoes/renamed_delegate_spec.rb +70 -0
- data/spec/shoes/shape_spec.rb +106 -0
- data/spec/shoes/shared_examples/button.rb +6 -0
- data/spec/shoes/shared_examples/changeable.rb +26 -0
- data/spec/shoes/shared_examples/clickable.rb +5 -0
- data/spec/shoes/shared_examples/common_methods.rb +35 -0
- data/spec/shoes/shared_examples/dimensions.rb +32 -0
- data/spec/shoes/shared_examples/dsl.rb +44 -0
- data/spec/shoes/shared_examples/dsl/animate.rb +29 -0
- data/spec/shoes/shared_examples/dsl/arc.rb +45 -0
- data/spec/shoes/shared_examples/dsl/background.rb +26 -0
- data/spec/shoes/shared_examples/dsl/border.rb +10 -0
- data/spec/shoes/shared_examples/dsl/button.rb +5 -0
- data/spec/shoes/shared_examples/dsl/cap.rb +6 -0
- data/spec/shoes/shared_examples/dsl/check.rb +11 -0
- data/spec/shoes/shared_examples/dsl/edit_box.rb +8 -0
- data/spec/shoes/shared_examples/dsl/edit_line.rb +8 -0
- data/spec/shoes/shared_examples/dsl/editable_element.rb +29 -0
- data/spec/shoes/shared_examples/dsl/fill.rb +27 -0
- data/spec/shoes/shared_examples/dsl/flow.rb +15 -0
- data/spec/shoes/shared_examples/dsl/gradient.rb +62 -0
- data/spec/shoes/shared_examples/dsl/image.rb +21 -0
- data/spec/shoes/shared_examples/dsl/line.rb +9 -0
- data/spec/shoes/shared_examples/dsl/nofill.rb +6 -0
- data/spec/shoes/shared_examples/dsl/nostroke.rb +6 -0
- data/spec/shoes/shared_examples/dsl/oval.rb +88 -0
- data/spec/shoes/shared_examples/dsl/pattern.rb +34 -0
- data/spec/shoes/shared_examples/dsl/progress.rb +7 -0
- data/spec/shoes/shared_examples/dsl/rect.rb +92 -0
- data/spec/shoes/shared_examples/dsl/rgb.rb +26 -0
- data/spec/shoes/shared_examples/dsl/shape.rb +57 -0
- data/spec/shoes/shared_examples/dsl/star.rb +111 -0
- data/spec/shoes/shared_examples/dsl/stroke.rb +30 -0
- data/spec/shoes/shared_examples/dsl/strokewidth.rb +19 -0
- data/spec/shoes/shared_examples/dsl/style.rb +32 -0
- data/spec/shoes/shared_examples/dsl/text_elements.rb +81 -0
- data/spec/shoes/shared_examples/dsl/video.rb +5 -0
- data/spec/shoes/shared_examples/dsl_app_context.rb +8 -0
- data/spec/shoes/shared_examples/hover_leave.rb +11 -0
- data/spec/shoes/shared_examples/parent.rb +6 -0
- data/spec/shoes/shared_examples/scroll.rb +41 -0
- data/spec/shoes/shared_examples/shared_element_method.rb +60 -0
- data/spec/shoes/shared_examples/slot.rb +394 -0
- data/spec/shoes/shared_examples/state.rb +19 -0
- data/spec/shoes/shared_examples/style.rb +82 -0
- data/spec/shoes/slot_spec.rb +186 -0
- data/spec/shoes/sound_spec.rb +15 -0
- data/spec/shoes/span_spec.rb +112 -0
- data/spec/shoes/spec_helper.rb +24 -0
- data/spec/shoes/stack_spec.rb +79 -0
- data/spec/shoes/star_spec.rb +48 -0
- data/spec/shoes/text_block_dimensions_spec.rb +75 -0
- data/spec/shoes/text_block_spec.rb +270 -0
- data/spec/shoes/url_spec.rb +68 -0
- data/spec/shoes/widget_spec.rb +70 -0
- data/spec/shoes_spec.rb +44 -0
- data/spec/spec_helper.rb +19 -0
- data/static/downloading.png +0 -0
- data/static/shoes-icon-blue.png +0 -0
- data/static/shoes-icon-brown.png +0 -0
- data/static/shoes-icon.png +0 -0
- 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
|
data/lib/shoes/sound.rb
ADDED
|
@@ -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
|
data/lib/shoes/span.rb
ADDED
|
@@ -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
|
data/lib/shoes/star.rb
ADDED
|
@@ -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
|
data/lib/shoes/text.rb
ADDED
|
@@ -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
|
data/lib/shoes/timer.rb
ADDED
|
@@ -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
|
data/lib/shoes/ui/cli.rb
ADDED
|
@@ -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
|