shoes-core 4.0.0.pre3
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/shoes/point.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
class Shoes
|
2
|
+
class Point
|
3
|
+
include Common::Inspect
|
4
|
+
|
5
|
+
def initialize(x, y)
|
6
|
+
@x, @y = x, y
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_accessor :x, :y
|
10
|
+
|
11
|
+
# @param [Shoes::Point] other the other point
|
12
|
+
# @return [Integer] if this is further left, this.x; otherwise other.x
|
13
|
+
def left(other = self)
|
14
|
+
[x, other.x].min
|
15
|
+
end
|
16
|
+
|
17
|
+
# @param [Shoes::Point] other the other point
|
18
|
+
# @return [Integer] if this is higher, this.y; otherwise other.y
|
19
|
+
def top(other = self)
|
20
|
+
[y, other.y].min
|
21
|
+
end
|
22
|
+
|
23
|
+
# Creates a new point at an offset of (x,y) from this point. Positive
|
24
|
+
# offsets move right and down; negative offsets move left and up.
|
25
|
+
#
|
26
|
+
# @param [Integer] x the x-component of the offset
|
27
|
+
# @param [Integer] y the y-component of the offset
|
28
|
+
# @return [Shoes::Point] a new point at offset (x,y) from this point
|
29
|
+
def to(x, y)
|
30
|
+
Shoes::Point.new(@x + x, @y + y)
|
31
|
+
end
|
32
|
+
|
33
|
+
def width(other = self)
|
34
|
+
(@x - other.x).abs
|
35
|
+
end
|
36
|
+
|
37
|
+
def height(other = self)
|
38
|
+
(@y - other.y).abs
|
39
|
+
end
|
40
|
+
|
41
|
+
def ==(other)
|
42
|
+
other.respond_to?(:x) && @x == other.x && other.respond_to?(:y) && @y == other.y
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
nothing = '_'
|
47
|
+
"(#{@x || nothing},#{@y || nothing})"
|
48
|
+
end
|
49
|
+
|
50
|
+
def inspect
|
51
|
+
super.insert(-2, " #{self}")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class Shoes
|
2
|
+
class Progress
|
3
|
+
include Common::UIElement
|
4
|
+
include Common::Style
|
5
|
+
|
6
|
+
attr_reader :app, :parent, :dimensions, :gui
|
7
|
+
style_with :common_styles, :dimensions, :fraction
|
8
|
+
STYLES = { fraction: 0.0 }
|
9
|
+
|
10
|
+
def initialize(app, parent, styles = {}, _blk = nil)
|
11
|
+
@app = app
|
12
|
+
@parent = parent
|
13
|
+
style_init styles
|
14
|
+
@dimensions = Dimensions.new parent, @style
|
15
|
+
@parent.add_child self
|
16
|
+
@gui = Shoes.configuration.backend_for self, @parent.gui
|
17
|
+
@gui.fraction = @style[:fraction]
|
18
|
+
end
|
19
|
+
|
20
|
+
def fraction=(value)
|
21
|
+
style(fraction: value)
|
22
|
+
@gui.fraction = value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/shoes/radio.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
class Shoes
|
2
|
+
class Radio < CheckButton
|
3
|
+
style_with :checked, :click, :common_styles, :dimensions, :group, :state
|
4
|
+
|
5
|
+
def initialize(app, parent, group, styles = {}, blk = nil)
|
6
|
+
styles[:group] = group
|
7
|
+
super(app, parent, styles, blk)
|
8
|
+
end
|
9
|
+
|
10
|
+
def group=(value)
|
11
|
+
style(group: value)
|
12
|
+
gui.group = value
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/shoes/rect.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
class Shoes
|
2
|
+
class Rect
|
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, :curve, :common_styles, :dimensions
|
9
|
+
STYLES = { angle: 0 }
|
10
|
+
|
11
|
+
def initialize(app, parent, left, top, width, height, styles = {}, blk = nil)
|
12
|
+
@app = app
|
13
|
+
@parent = parent
|
14
|
+
style_init styles
|
15
|
+
@dimensions = AbsoluteDimensions.new left, top, width, height, @style
|
16
|
+
@parent.add_child self
|
17
|
+
@gui = Shoes.backend_for self
|
18
|
+
register_click blk
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module RenamedDelegate
|
2
|
+
include Forwardable
|
3
|
+
|
4
|
+
def renamed_delegate_to(getter, methods, renamings)
|
5
|
+
methods.each do |method|
|
6
|
+
method_name = method.to_s
|
7
|
+
renamed_method_name = renamings.inject(method_name) do |name, (word, sub)|
|
8
|
+
name.gsub word, sub
|
9
|
+
end
|
10
|
+
if renamed_method_name != method_name
|
11
|
+
def_delegator getter, method_name, renamed_method_name
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/shoes/shape.rb
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
class Shoes
|
2
|
+
class Shape
|
3
|
+
include Common::UIElement
|
4
|
+
include Common::Style
|
5
|
+
include Common::Clickable
|
6
|
+
|
7
|
+
attr_reader :app, :parent, :dimensions, :gui, :blk, :x, :y
|
8
|
+
attr_reader :left_bound, :top_bound, :right_bound, :bottom_bound
|
9
|
+
style_with :art_styles, :center, :common_styles, :dimensions
|
10
|
+
|
11
|
+
# Creates a new Shoes::Shape
|
12
|
+
#
|
13
|
+
def initialize(app, parent, styles = {}, blk = nil)
|
14
|
+
@app = app
|
15
|
+
@parent = parent
|
16
|
+
style_init styles
|
17
|
+
@dimensions = AbsoluteDimensions.new @style
|
18
|
+
@parent.add_child self
|
19
|
+
@gui = Shoes.backend_for self
|
20
|
+
register_click
|
21
|
+
|
22
|
+
@blk = blk
|
23
|
+
# True until we've asked the pen to draw
|
24
|
+
@before_drawing = true
|
25
|
+
@app.eval_with_additional_context self, &blk
|
26
|
+
end
|
27
|
+
|
28
|
+
def width
|
29
|
+
@app.width
|
30
|
+
end
|
31
|
+
|
32
|
+
def height
|
33
|
+
@app.height
|
34
|
+
end
|
35
|
+
|
36
|
+
# Moves the shape
|
37
|
+
#
|
38
|
+
# @param [Integer] left The new left value
|
39
|
+
# @param [Integer] top The new top value
|
40
|
+
# @return [Shoes::Shape] This shape
|
41
|
+
def move(left, top)
|
42
|
+
self.left = left
|
43
|
+
self.top = top
|
44
|
+
@gui.update_position
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
# Draws a line from the current position to the given point
|
49
|
+
#
|
50
|
+
# @param [Integer] x The new point's x-value
|
51
|
+
# @param [Integer] y The new point's y-value
|
52
|
+
# @return [Shoes::Shape] This shape
|
53
|
+
def line_to(x, y)
|
54
|
+
update_bounds_rect(@x, @y, x, y)
|
55
|
+
@x, @y = x, y
|
56
|
+
@gui.line_to(x, y)
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
# Moves the drawing "pen" to the given point
|
61
|
+
#
|
62
|
+
# @param [Integer] x The new point's x-value
|
63
|
+
# @param [Integer] y The new point's y-value
|
64
|
+
# @return [Shoes::Shape] self This shape
|
65
|
+
def move_to(x, y)
|
66
|
+
@x, @y = x, y
|
67
|
+
@gui.move_to(x, y)
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
# Draws a curve
|
72
|
+
#
|
73
|
+
# @param [Integer] cx1 The first control point's x-value
|
74
|
+
# @param [Integer] cy1 The first control point's y-value
|
75
|
+
# @param [Integer] cx2 The second control point's x-value
|
76
|
+
# @param [Integer] cy2 The second control point's y-value
|
77
|
+
# @param [Integer] x The end point's x-value
|
78
|
+
# @param [Integer] y The end point's y-value
|
79
|
+
# @return [Shoes::Shape] This shape
|
80
|
+
def curve_to(cx1, cy1, cx2, cy2, x, y)
|
81
|
+
update_bounds([@x, cx1, cx2, x], [@y, cy1, cy2, y])
|
82
|
+
@x, @y = x, y
|
83
|
+
@gui.curve_to(cx1, cy1, cx2, cy2, x, y)
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
# Draws an arc
|
88
|
+
#
|
89
|
+
# @param [Integer] x The left position
|
90
|
+
# @param [Integer] y The top position
|
91
|
+
# @param [Integer] width The width of the arc
|
92
|
+
# @param [Integer] height The height of the arc
|
93
|
+
# @param [Integer] start_angle The start angle
|
94
|
+
# @param [Integer] arc_angle The angular extent of the arc, relative to the start angle
|
95
|
+
# @return [Shoes::Shape] This shape
|
96
|
+
def arc(x, y, width, height, start_angle, arc_angle)
|
97
|
+
update_bounds_rect(x - width / 2, y - height / 2, x + width / 2, y + height / 2)
|
98
|
+
@x, @y = x, y
|
99
|
+
@gui.arc(x, y, width, height, start_angle, arc_angle)
|
100
|
+
self
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
# Updates the bounds of this shape to include the rectangle described by
|
106
|
+
# (x1, y1) and (x2, y2)
|
107
|
+
#
|
108
|
+
# @param [Integer] x1 The x-value of the first coordinate
|
109
|
+
# @param [Integer] y1 The y-value of the first coordinate
|
110
|
+
# @param [Integer] x2 The x-value of the second coordinate
|
111
|
+
# @param [Integer] y2 The y-value of the second coordinate
|
112
|
+
# @return nil
|
113
|
+
def update_bounds_rect(x1, y1, x2, y2)
|
114
|
+
update_bounds([x1, x2], [y1, y2])
|
115
|
+
end
|
116
|
+
|
117
|
+
# Updates the bounds of this shape to the rectangle covering all
|
118
|
+
# the given coordinates.
|
119
|
+
#
|
120
|
+
# @param [Array<Integer>] xs Array of X coordinates
|
121
|
+
# @param [Array<Integer>] ys Array of Y coordinates
|
122
|
+
# @return nil
|
123
|
+
def update_bounds(xs, ys)
|
124
|
+
all_xs = all_x_values(xs)
|
125
|
+
all_ys = all_y_values(ys)
|
126
|
+
@left_bound = calculate_primary_dimension_value @left_bound, all_xs
|
127
|
+
@top_bound = calculate_primary_dimension_value @top_bound, all_ys
|
128
|
+
@right_bound = calculate_secondary_dimension_value @right_bound, all_xs
|
129
|
+
@bottom_bound = calculate_secondary_dimension_value @bottom_bound, all_ys
|
130
|
+
@before_drawing = false
|
131
|
+
nil
|
132
|
+
end
|
133
|
+
|
134
|
+
def all_x_values(xs)
|
135
|
+
all_values xs, @x, @left_bound, @right_bound
|
136
|
+
end
|
137
|
+
|
138
|
+
def all_y_values(ys)
|
139
|
+
all_values ys, @y, @top_bound, @bottom_bound
|
140
|
+
end
|
141
|
+
|
142
|
+
def all_values(values, current, min, max)
|
143
|
+
additional = @before_drawing ? [current] : [current, min, max]
|
144
|
+
(values + additional).map(&:to_i)
|
145
|
+
end
|
146
|
+
|
147
|
+
def calculate_primary_dimension_value(current, new)
|
148
|
+
new_min = Array(new).min
|
149
|
+
return new_min if @before_drawing || new_min < current
|
150
|
+
current
|
151
|
+
end
|
152
|
+
|
153
|
+
def calculate_secondary_dimension_value(current, new)
|
154
|
+
new_max = Array(new).max
|
155
|
+
return new_max if @before_drawing || new_max > current
|
156
|
+
current
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
data/lib/shoes/slot.rb
ADDED
@@ -0,0 +1,276 @@
|
|
1
|
+
class Shoes
|
2
|
+
class Slot
|
3
|
+
include Common::UIElement
|
4
|
+
include Common::Clickable
|
5
|
+
include Common::Style
|
6
|
+
|
7
|
+
# We need that offset because otherwise element overlap e.g. occupy
|
8
|
+
# the same pixel - this way they start right next to each other
|
9
|
+
# See #update_current_position
|
10
|
+
NEXT_ELEMENT_OFFSET = 1
|
11
|
+
|
12
|
+
attr_reader :parent, :dimensions, :gui, :contents, :blk, :hover_proc, :leave_proc
|
13
|
+
style_with :art_styles, :attach, :common_styles, :dimensions, :scroll
|
14
|
+
STYLES = { scroll: false }
|
15
|
+
|
16
|
+
def initialize(app, parent, styles = {}, blk = nil)
|
17
|
+
init_attributes(app, parent, styles, blk)
|
18
|
+
@parent.add_child self
|
19
|
+
@gui = Shoes.configuration.backend_for self, @parent.gui
|
20
|
+
eval_block blk
|
21
|
+
contents_alignment
|
22
|
+
end
|
23
|
+
|
24
|
+
def init_attributes(app, parent, styles, blk)
|
25
|
+
@app = app
|
26
|
+
@parent = parent
|
27
|
+
@contents = SlotContents.new
|
28
|
+
@blk = blk
|
29
|
+
style_init styles
|
30
|
+
@dimensions = Dimensions.new parent, @style
|
31
|
+
@fixed_height = height || false
|
32
|
+
@scroll_top = 0
|
33
|
+
set_default_dimension_values
|
34
|
+
@pass_coordinates = true
|
35
|
+
end
|
36
|
+
|
37
|
+
def set_default_dimension_values
|
38
|
+
self.width ||= 1.0
|
39
|
+
self.height ||= 0
|
40
|
+
self.absolute_left ||= 0
|
41
|
+
self.absolute_top ||= 0
|
42
|
+
end
|
43
|
+
|
44
|
+
def clear(&blk)
|
45
|
+
contents.clear
|
46
|
+
eval_block blk
|
47
|
+
end
|
48
|
+
|
49
|
+
def eval_block(blk, *args)
|
50
|
+
old_current_slot = @app.current_slot
|
51
|
+
@app.current_slot = self
|
52
|
+
blk.call(*args) if blk
|
53
|
+
@app.current_slot = old_current_slot
|
54
|
+
end
|
55
|
+
|
56
|
+
def create_bound_block(blk)
|
57
|
+
Proc.new do |*args|
|
58
|
+
eval_block(blk, *args)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_child(element)
|
63
|
+
contents.add_element element
|
64
|
+
end
|
65
|
+
|
66
|
+
def remove_child(element)
|
67
|
+
contents.delete element
|
68
|
+
end
|
69
|
+
|
70
|
+
def append(&blk)
|
71
|
+
eval_block blk
|
72
|
+
end
|
73
|
+
|
74
|
+
def prepend(&blk)
|
75
|
+
contents.prepend do
|
76
|
+
eval_block blk
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def contents_alignment(_ = nil)
|
81
|
+
position_contents
|
82
|
+
determine_slot_height
|
83
|
+
end
|
84
|
+
|
85
|
+
def hovered?
|
86
|
+
@hovered
|
87
|
+
end
|
88
|
+
|
89
|
+
def hover(blk)
|
90
|
+
@hover_proc = blk
|
91
|
+
@app.add_mouse_hover_control self
|
92
|
+
end
|
93
|
+
|
94
|
+
def leave(blk)
|
95
|
+
@leave_proc = blk
|
96
|
+
@app.add_mouse_hover_control self
|
97
|
+
end
|
98
|
+
|
99
|
+
def mouse_hovered
|
100
|
+
@hovered = true
|
101
|
+
@hover_proc.call(self) if @hover_proc
|
102
|
+
end
|
103
|
+
|
104
|
+
def mouse_left
|
105
|
+
@hovered = false
|
106
|
+
@leave_proc.call(self) if @leave_proc
|
107
|
+
end
|
108
|
+
|
109
|
+
def scroll_height
|
110
|
+
position_contents.y
|
111
|
+
end
|
112
|
+
|
113
|
+
def scroll_max
|
114
|
+
scroll_height - height
|
115
|
+
end
|
116
|
+
|
117
|
+
attr_reader :scroll_top
|
118
|
+
|
119
|
+
attr_writer :scroll_top
|
120
|
+
|
121
|
+
def app
|
122
|
+
@app.app # return the Shoes::App not the internal app
|
123
|
+
end
|
124
|
+
|
125
|
+
def inspect
|
126
|
+
"#<#{self.class}:0x#{hash.to_s(16)} @contents=#{@contents.inspect} and so much stuff literally breaks the memory limit. Look at it selectively.>"
|
127
|
+
end
|
128
|
+
|
129
|
+
protected
|
130
|
+
|
131
|
+
CurrentPosition = Struct.new(:x, :y, :next_line_start)
|
132
|
+
|
133
|
+
def position_contents
|
134
|
+
current_position = CurrentPosition.new element_left,
|
135
|
+
element_top,
|
136
|
+
element_top
|
137
|
+
|
138
|
+
contents.each do |element|
|
139
|
+
next if element.hidden?
|
140
|
+
current_position = positioning(element, current_position)
|
141
|
+
end
|
142
|
+
current_position
|
143
|
+
end
|
144
|
+
|
145
|
+
def positioning(element, current_position)
|
146
|
+
position_element element, current_position
|
147
|
+
element.contents_alignment(current_position) if element.respond_to? :contents_alignment
|
148
|
+
if element.takes_up_space?
|
149
|
+
update_current_position(current_position, element)
|
150
|
+
else
|
151
|
+
current_position
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def position_element(_element, _current_position)
|
156
|
+
fail 'position_element is a subclass responsibility'
|
157
|
+
end
|
158
|
+
|
159
|
+
def position_in_current_line(element, current_position)
|
160
|
+
position_element_at element,
|
161
|
+
position_x(current_position.x, element),
|
162
|
+
position_y(current_position.y, element)
|
163
|
+
end
|
164
|
+
|
165
|
+
def move_to_next_line(element, current_position)
|
166
|
+
position_element_at element,
|
167
|
+
position_x(element_left, element),
|
168
|
+
position_y(current_position.next_line_start, element)
|
169
|
+
end
|
170
|
+
|
171
|
+
def position_element_at(element, x, y)
|
172
|
+
return if element_did_not_move?(element, x, y)
|
173
|
+
element._position x, y
|
174
|
+
end
|
175
|
+
|
176
|
+
def element_did_not_move?(element, x, y)
|
177
|
+
element.absolute_left == x && element.absolute_top == y
|
178
|
+
end
|
179
|
+
|
180
|
+
def update_current_position(current_position, element)
|
181
|
+
return current_position if element.absolutely_positioned?
|
182
|
+
current_position.x = element.absolute_right + NEXT_ELEMENT_OFFSET
|
183
|
+
current_position.y = element.absolute_top
|
184
|
+
next_element_line_start = next_line_start_from element
|
185
|
+
if current_position.next_line_start < next_element_line_start
|
186
|
+
current_position.next_line_start = next_element_line_start
|
187
|
+
end
|
188
|
+
element.adjust_current_position current_position
|
189
|
+
current_position
|
190
|
+
end
|
191
|
+
|
192
|
+
def next_line_start_from(element)
|
193
|
+
element.absolute_bottom + NEXT_ELEMENT_OFFSET
|
194
|
+
end
|
195
|
+
|
196
|
+
def position_x(relative_x, element)
|
197
|
+
if element.absolute_x_position?
|
198
|
+
absolute_x_position(element)
|
199
|
+
else
|
200
|
+
relative_x
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def absolute_x_position(element)
|
205
|
+
if element.absolute_left_position?
|
206
|
+
self.element_left + element.left
|
207
|
+
elsif element.absolute_right_position?
|
208
|
+
self.element_right - (element.right + element.width)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def position_y(relative_y, element)
|
213
|
+
if element.absolute_y_position?
|
214
|
+
absolute_y_position(element)
|
215
|
+
else
|
216
|
+
relative_y
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def absolute_y_position(element)
|
221
|
+
if element.absolute_top_position?
|
222
|
+
self.element_top + element.top
|
223
|
+
elsif element.absolute_bottom_position?
|
224
|
+
# TODO: slots grow... to really position it relative to the bottom
|
225
|
+
# we probably need to position it after everything has been positioned
|
226
|
+
self.element_bottom - (element.bottom + element.height)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def fits_on_the_same_line?(element, current_x)
|
231
|
+
fitting_width = element.width
|
232
|
+
fitting_width = element.fitting_width if element.respond_to?(:fitting_width)
|
233
|
+
current_x + fitting_width - 1 <= element_right
|
234
|
+
end
|
235
|
+
|
236
|
+
def determine_slot_height
|
237
|
+
content_height = compute_content_height
|
238
|
+
self.height = content_height if has_variable_height?
|
239
|
+
content_height
|
240
|
+
end
|
241
|
+
|
242
|
+
def compute_content_height
|
243
|
+
max_bottom = contents.
|
244
|
+
select(&:takes_up_space?).
|
245
|
+
reject(&:hidden?).
|
246
|
+
map(&:absolute_bottom).
|
247
|
+
max
|
248
|
+
|
249
|
+
if max_bottom
|
250
|
+
max_bottom - self.absolute_top + NEXT_ELEMENT_OFFSET
|
251
|
+
else
|
252
|
+
0
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def has_variable_height?
|
257
|
+
!@fixed_height
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
class Flow < Slot
|
262
|
+
def position_element(element, current_position)
|
263
|
+
if fits_on_the_same_line?(element, current_position.x)
|
264
|
+
position_in_current_line(element, current_position)
|
265
|
+
else
|
266
|
+
move_to_next_line(element, current_position)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
class Stack < Slot
|
272
|
+
def position_element(element, current_position)
|
273
|
+
move_to_next_line(element, current_position)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|