shoes-dsl 4.0.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG +84 -0
- data/Gemfile +24 -0
- data/Guardfile +11 -0
- data/LICENSE +31 -0
- data/README.md +201 -0
- data/ext/install/Rakefile +29 -0
- data/ext/install/shoes.bat +9 -0
- data/fonts/Coolvetica.ttf +0 -0
- data/fonts/Lacuna.ttf +0 -0
- data/lib/shoes/animation.rb +56 -0
- data/lib/shoes/app.rb +131 -0
- data/lib/shoes/arc.rb +25 -0
- data/lib/shoes/background.rb +24 -0
- data/lib/shoes/border.rb +24 -0
- data/lib/shoes/builtin_methods.rb +77 -0
- data/lib/shoes/button.rb +30 -0
- data/lib/shoes/check_button.rb +44 -0
- data/lib/shoes/color.rb +385 -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 +33 -0
- data/lib/shoes/common/remove.rb +10 -0
- data/lib/shoes/common/state.rb +18 -0
- data/lib/shoes/common/style.rb +152 -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 +40 -0
- data/lib/shoes/configuration.rb +96 -0
- data/lib/shoes/dialog.rb +27 -0
- data/lib/shoes/dimension.rb +239 -0
- data/lib/shoes/dimensions.rb +209 -0
- data/lib/shoes/download.rb +121 -0
- data/lib/shoes/dsl.rb +591 -0
- data/lib/shoes/font.rb +49 -0
- data/lib/shoes/gradient.rb +31 -0
- data/lib/shoes/image.rb +29 -0
- data/lib/shoes/image_pattern.rb +12 -0
- data/lib/shoes/input_box.rb +60 -0
- data/lib/shoes/internal_app.rb +219 -0
- data/lib/shoes/key_event.rb +17 -0
- data/lib/shoes/line.rb +87 -0
- data/lib/shoes/link.rb +59 -0
- data/lib/shoes/link_hover.rb +5 -0
- data/lib/shoes/list_box.rb +50 -0
- data/lib/shoes/logger.rb +66 -0
- data/lib/shoes/logger/ruby.rb +18 -0
- data/lib/shoes/mock.rb +31 -0
- data/lib/shoes/mock/animation.rb +8 -0
- data/lib/shoes/mock/app.rb +47 -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 +10 -0
- data/lib/shoes/mock/check.rb +25 -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 +18 -0
- data/lib/shoes/mock/font.rb +17 -0
- data/lib/shoes/mock/image.rb +13 -0
- data/lib/shoes/mock/image_pattern.rb +9 -0
- data/lib/shoes/mock/input_box.rb +30 -0
- data/lib/shoes/mock/keypress.rb +10 -0
- data/lib/shoes/mock/keyrelease.rb +10 -0
- data/lib/shoes/mock/line.rb +14 -0
- data/lib/shoes/mock/link.rb +12 -0
- data/lib/shoes/mock/list_box.rb +19 -0
- data/lib/shoes/mock/oval.rb +12 -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/point.rb +54 -0
- data/lib/shoes/progress.rb +25 -0
- data/lib/shoes/radio.rb +16 -0
- data/lib/shoes/rect.rb +21 -0
- data/lib/shoes/renamed_delegate.rb +15 -0
- data/lib/shoes/shape.rb +158 -0
- data/lib/shoes/slot.rb +271 -0
- data/lib/shoes/slot_contents.rb +50 -0
- data/lib/shoes/sound.rb +18 -0
- data/lib/shoes/span.rb +16 -0
- data/lib/shoes/star.rb +45 -0
- data/lib/shoes/text.rb +24 -0
- data/lib/shoes/text_block.rb +143 -0
- data/lib/shoes/text_block_dimensions.rb +52 -0
- data/lib/shoes/timer.rb +12 -0
- data/lib/shoes/url.rb +44 -0
- data/lib/shoes/version.rb +3 -0
- data/lib/shoes/widget.rb +69 -0
- data/manifests/common.rb +34 -0
- data/manifests/shoes-dsl.rb +34 -0
- data/shoes-dsl.gemspec +19 -0
- data/spec/code_coverage.rb +14 -0
- data/spec/shoes/animation_spec.rb +65 -0
- data/spec/shoes/app_spec.rb +484 -0
- data/spec/shoes/arc_spec.rb +51 -0
- data/spec/shoes/background_spec.rb +53 -0
- data/spec/shoes/border_spec.rb +47 -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/cli_spec.rb +15 -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 +163 -0
- data/spec/shoes/dimension_spec.rb +407 -0
- data/spec/shoes/dimensions_spec.rb +837 -0
- data/spec/shoes/download_spec.rb +142 -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 +49 -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 +49 -0
- data/spec/shoes/link_spec.rb +105 -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/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 +95 -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 +21 -0
- data/spec/shoes/shared_examples/dsl/star.rb +48 -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 +331 -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 +130 -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 +31 -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 +18 -0
- data/static/Shoes.icns +0 -0
- data/static/shoes-icon.png +0 -0
- metadata +354 -0
@@ -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,158 @@
|
|
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
|
+
# Updates the bounds of this shape to include the rectangle described by
|
105
|
+
# (x1, y1) and (x2, y2)
|
106
|
+
#
|
107
|
+
# @param [Integer] x1 The x-value of the first coordinate
|
108
|
+
# @param [Integer] y1 The y-value of the first coordinate
|
109
|
+
# @param [Integer] x2 The x-value of the second coordinate
|
110
|
+
# @param [Integer] y2 The y-value of the second coordinate
|
111
|
+
# @return nil
|
112
|
+
def update_bounds_rect(x1, y1, x2, y2)
|
113
|
+
update_bounds( [x1, x2], [y1, y2] )
|
114
|
+
end
|
115
|
+
|
116
|
+
# Updates the bounds of this shape to the rectangle covering all
|
117
|
+
# the given coordinates.
|
118
|
+
#
|
119
|
+
# @param [Array<Integer>] xs Array of X coordinates
|
120
|
+
# @param [Array<Integer>] ys Array of Y coordinates
|
121
|
+
# @return nil
|
122
|
+
def update_bounds(xs, ys)
|
123
|
+
all_xs = all_x_values(xs)
|
124
|
+
all_ys = all_y_values(ys)
|
125
|
+
@left_bound = calculate_primary_dimension_value @left_bound, all_xs
|
126
|
+
@top_bound = calculate_primary_dimension_value @top_bound, all_ys
|
127
|
+
@right_bound = calculate_secondary_dimension_value @right_bound, all_xs
|
128
|
+
@bottom_bound = calculate_secondary_dimension_value @bottom_bound, all_ys
|
129
|
+
@before_drawing = false
|
130
|
+
nil
|
131
|
+
end
|
132
|
+
|
133
|
+
def all_x_values(xs)
|
134
|
+
all_values xs, @x, @left_bound, @right_bound
|
135
|
+
end
|
136
|
+
|
137
|
+
def all_y_values(ys)
|
138
|
+
all_values ys, @y, @top_bound, @bottom_bound
|
139
|
+
end
|
140
|
+
|
141
|
+
def all_values(values, current, min, max)
|
142
|
+
additional = @before_drawing ? [current] : [current, min, max]
|
143
|
+
(values + additional).map &:to_i
|
144
|
+
end
|
145
|
+
|
146
|
+
def calculate_primary_dimension_value(current, new)
|
147
|
+
new_min = Array(new).min
|
148
|
+
return new_min if @before_drawing || new_min < current
|
149
|
+
current
|
150
|
+
end
|
151
|
+
|
152
|
+
def calculate_secondary_dimension_value(current, new)
|
153
|
+
new_max = Array(new).max
|
154
|
+
return new_max if @before_drawing || new_max > current
|
155
|
+
current
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
data/lib/shoes/slot.rb
ADDED
@@ -0,0 +1,271 @@
|
|
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
|
50
|
+
old_current_slot = @app.current_slot
|
51
|
+
@app.current_slot = self
|
52
|
+
blk.call if blk
|
53
|
+
@app.current_slot = old_current_slot
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_child(element)
|
57
|
+
contents.add_element element
|
58
|
+
end
|
59
|
+
|
60
|
+
def remove_child(element)
|
61
|
+
contents.delete element
|
62
|
+
end
|
63
|
+
|
64
|
+
def append(&blk)
|
65
|
+
eval_block blk
|
66
|
+
end
|
67
|
+
|
68
|
+
def prepend(&blk)
|
69
|
+
contents.prepend do
|
70
|
+
eval_block blk
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def contents_alignment(_=nil)
|
75
|
+
position_contents
|
76
|
+
determine_slot_height
|
77
|
+
end
|
78
|
+
|
79
|
+
def hovered?
|
80
|
+
@hovered
|
81
|
+
end
|
82
|
+
|
83
|
+
def hover(blk)
|
84
|
+
@hover_proc = blk
|
85
|
+
@app.add_mouse_hover_control self
|
86
|
+
end
|
87
|
+
|
88
|
+
def leave(blk)
|
89
|
+
@leave_proc = blk
|
90
|
+
@app.add_mouse_hover_control self
|
91
|
+
end
|
92
|
+
|
93
|
+
def mouse_hovered
|
94
|
+
@hovered = true
|
95
|
+
@hover_proc.call(self) if @hover_proc
|
96
|
+
end
|
97
|
+
|
98
|
+
def mouse_left
|
99
|
+
@hovered = false
|
100
|
+
@leave_proc.call(self) if @leave_proc
|
101
|
+
end
|
102
|
+
|
103
|
+
def scroll_height
|
104
|
+
position_contents.y
|
105
|
+
end
|
106
|
+
|
107
|
+
def scroll_max
|
108
|
+
scroll_height - height
|
109
|
+
end
|
110
|
+
|
111
|
+
def scroll_top
|
112
|
+
@scroll_top
|
113
|
+
end
|
114
|
+
|
115
|
+
def scroll_top=(position)
|
116
|
+
@scroll_top = position
|
117
|
+
end
|
118
|
+
|
119
|
+
def app
|
120
|
+
@app.app #return the Shoes::App not the internal app
|
121
|
+
end
|
122
|
+
|
123
|
+
def inspect
|
124
|
+
"#<#{self.class}:0x#{hash.to_s(16)} @contents=#{@contents.inspect} and so much stuff literally breaks the memory limit. Look at it selectively.>"
|
125
|
+
end
|
126
|
+
|
127
|
+
protected
|
128
|
+
CurrentPosition = Struct.new(:x, :y, :next_line_start)
|
129
|
+
|
130
|
+
def position_contents
|
131
|
+
current_position = CurrentPosition.new element_left,
|
132
|
+
element_top,
|
133
|
+
element_top
|
134
|
+
|
135
|
+
contents.each do |element|
|
136
|
+
next if element.hidden?
|
137
|
+
current_position = positioning(element, current_position)
|
138
|
+
end
|
139
|
+
current_position
|
140
|
+
end
|
141
|
+
|
142
|
+
def positioning(element, current_position)
|
143
|
+
return current_position unless element.needs_to_be_positioned?
|
144
|
+
position_element element, current_position
|
145
|
+
element.contents_alignment(current_position) if element.respond_to? :contents_alignment
|
146
|
+
if element.takes_up_space?
|
147
|
+
update_current_position(current_position, element)
|
148
|
+
else
|
149
|
+
current_position
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def position_element(element, current_position)
|
154
|
+
raise 'position_element is a subclass responsibility'
|
155
|
+
end
|
156
|
+
|
157
|
+
def position_in_current_line(element, current_position)
|
158
|
+
position_element_at element,
|
159
|
+
position_x(current_position.x, element),
|
160
|
+
position_y(current_position.y, element)
|
161
|
+
end
|
162
|
+
|
163
|
+
def move_to_next_line(element, current_position)
|
164
|
+
position_element_at element,
|
165
|
+
position_x(self.element_left, element),
|
166
|
+
position_y(current_position.next_line_start, element)
|
167
|
+
end
|
168
|
+
|
169
|
+
def position_element_at(element, x, y)
|
170
|
+
return if element_did_not_move?(element, x, y)
|
171
|
+
element._position x, y
|
172
|
+
end
|
173
|
+
|
174
|
+
def element_did_not_move?(element, x, y)
|
175
|
+
element.absolute_left == x && element.absolute_top == y
|
176
|
+
end
|
177
|
+
|
178
|
+
def update_current_position(current_position, element)
|
179
|
+
return current_position if element.absolutely_positioned?
|
180
|
+
current_position.x = element.absolute_right + NEXT_ELEMENT_OFFSET
|
181
|
+
current_position.y = element.absolute_top
|
182
|
+
next_element_line_start = next_line_start_from element
|
183
|
+
if current_position.next_line_start < next_element_line_start
|
184
|
+
current_position.next_line_start = next_element_line_start
|
185
|
+
end
|
186
|
+
element.adjust_current_position current_position
|
187
|
+
current_position
|
188
|
+
end
|
189
|
+
|
190
|
+
def next_line_start_from element
|
191
|
+
element.absolute_bottom + NEXT_ELEMENT_OFFSET
|
192
|
+
end
|
193
|
+
|
194
|
+
def position_x(relative_x, element)
|
195
|
+
if element.absolute_x_position?
|
196
|
+
absolute_x_position(element)
|
197
|
+
else
|
198
|
+
relative_x
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def absolute_x_position(element)
|
203
|
+
if element.absolute_left_position?
|
204
|
+
self.absolute_left + element.left
|
205
|
+
elsif element.absolute_right_position?
|
206
|
+
self.absolute_right - (element.right + element.width)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def position_y(relative_y, element)
|
211
|
+
if element.absolute_y_position?
|
212
|
+
absolute_y_position(element)
|
213
|
+
else
|
214
|
+
relative_y
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def absolute_y_position(element)
|
219
|
+
if element.absolute_top_position?
|
220
|
+
self.absolute_top + element.top
|
221
|
+
elsif element.absolute_bottom_position?
|
222
|
+
# TODO: slots grow... to really position it relative to the bottom
|
223
|
+
# we probably need to position it after everything has been positioned
|
224
|
+
self.absolute_bottom - (element.bottom + element.height)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def fits_on_the_same_line?(element, current_x)
|
229
|
+
fitting_width = element.width
|
230
|
+
fitting_width = element.fitting_width if element.respond_to?(:fitting_width)
|
231
|
+
current_x + fitting_width - 1 <= element_right
|
232
|
+
end
|
233
|
+
|
234
|
+
def determine_slot_height
|
235
|
+
content_height = compute_content_height
|
236
|
+
self.height = content_height if has_variable_height?
|
237
|
+
content_height
|
238
|
+
end
|
239
|
+
|
240
|
+
def compute_content_height
|
241
|
+
max_bottom = contents.reject(&:hidden?).
|
242
|
+
map(&:absolute_bottom).
|
243
|
+
max
|
244
|
+
if max_bottom
|
245
|
+
max_bottom - self.absolute_top + NEXT_ELEMENT_OFFSET
|
246
|
+
else
|
247
|
+
0
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def has_variable_height?
|
252
|
+
not @fixed_height
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
class Flow < Slot
|
257
|
+
def position_element(element, current_position)
|
258
|
+
if fits_on_the_same_line?(element, current_position.x)
|
259
|
+
position_in_current_line(element, current_position)
|
260
|
+
else
|
261
|
+
move_to_next_line(element, current_position)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
class Stack < Slot
|
267
|
+
def position_element(element, current_position)
|
268
|
+
move_to_next_line(element, current_position)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
@@ -0,0 +1,50 @@
|
|
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
|
+
def append_element(element)
|
42
|
+
@contents << element
|
43
|
+
end
|
44
|
+
|
45
|
+
def prepend_element(element)
|
46
|
+
@contents.insert @prepending_index, element
|
47
|
+
@prepending_index += 1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|