shoes-swt 4.0.0.pre2
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/CHANGELOG +84 -0
- data/Gemfile +24 -0
- data/Guardfile +11 -0
- data/LICENSE +31 -0
- data/README.md +201 -0
- data/lib/shoes/swt.rb +118 -0
- data/lib/shoes/swt/animation.rb +46 -0
- data/lib/shoes/swt/app.rb +314 -0
- data/lib/shoes/swt/arc.rb +71 -0
- data/lib/shoes/swt/background.rb +41 -0
- data/lib/shoes/swt/border.rb +41 -0
- data/lib/shoes/swt/button.rb +18 -0
- data/lib/shoes/swt/check.rb +14 -0
- data/lib/shoes/swt/check_button.rb +19 -0
- data/lib/shoes/swt/color.rb +49 -0
- data/lib/shoes/swt/color_factory.rb +32 -0
- data/lib/shoes/swt/common/child.rb +16 -0
- data/lib/shoes/swt/common/clickable.rb +68 -0
- data/lib/shoes/swt/common/container.rb +28 -0
- data/lib/shoes/swt/common/fill.rb +38 -0
- data/lib/shoes/swt/common/painter.rb +92 -0
- data/lib/shoes/swt/common/painter_updates_position.rb +12 -0
- data/lib/shoes/swt/common/remove.rb +30 -0
- data/lib/shoes/swt/common/resource.rb +29 -0
- data/lib/shoes/swt/common/selection_listener.rb +14 -0
- data/lib/shoes/swt/common/stroke.rb +42 -0
- data/lib/shoes/swt/common/update_position.rb +15 -0
- data/lib/shoes/swt/common/visibility.rb +13 -0
- data/lib/shoes/swt/dialog.rb +90 -0
- data/lib/shoes/swt/disposed_protection.rb +23 -0
- data/lib/shoes/swt/download.rb +24 -0
- data/lib/shoes/swt/font.rb +32 -0
- data/lib/shoes/swt/gradient.rb +92 -0
- data/lib/shoes/swt/image.rb +128 -0
- data/lib/shoes/swt/image_pattern.rb +31 -0
- data/lib/shoes/swt/input_box.rb +73 -0
- data/lib/shoes/swt/key_listener.rb +145 -0
- data/lib/shoes/swt/line.rb +60 -0
- data/lib/shoes/swt/link.rb +31 -0
- data/lib/shoes/swt/link_segment.rb +111 -0
- data/lib/shoes/swt/list_box.rb +48 -0
- data/lib/shoes/swt/mouse_move_listener.rb +67 -0
- data/lib/shoes/swt/oval.rb +52 -0
- data/lib/shoes/swt/progress.rb +35 -0
- data/lib/shoes/swt/radio.rb +29 -0
- data/lib/shoes/swt/radio_group.rb +54 -0
- data/lib/shoes/swt/rect.rb +30 -0
- data/lib/shoes/swt/rect_painter.rb +23 -0
- data/lib/shoes/swt/redrawing_aspect.rb +123 -0
- data/lib/shoes/swt/shape.rb +133 -0
- data/lib/shoes/swt/shoes_layout.rb +43 -0
- data/lib/shoes/swt/slot.rb +39 -0
- data/lib/shoes/swt/sound.rb +119 -0
- data/lib/shoes/swt/star.rb +50 -0
- data/lib/shoes/swt/support/jl1.0.1.jar +0 -0
- data/lib/shoes/swt/support/jogg-0.0.7.jar +0 -0
- data/lib/shoes/swt/support/jorbis-0.0.15.jar +0 -0
- data/lib/shoes/swt/support/log4j-1.2.16.jar +0 -0
- data/lib/shoes/swt/support/mp3spi1.9.5.jar +0 -0
- data/lib/shoes/swt/support/tritonus_share.jar +0 -0
- data/lib/shoes/swt/support/vorbisspi1.0.3.jar +0 -0
- data/lib/shoes/swt/swt_button.rb +56 -0
- data/lib/shoes/swt/text_block.rb +124 -0
- data/lib/shoes/swt/text_block/centered_text_segment.rb +22 -0
- data/lib/shoes/swt/text_block/cursor_painter.rb +53 -0
- data/lib/shoes/swt/text_block/fitter.rb +212 -0
- data/lib/shoes/swt/text_block/painter.rb +47 -0
- data/lib/shoes/swt/text_block/text_font_factory.rb +50 -0
- data/lib/shoes/swt/text_block/text_segment.rb +108 -0
- data/lib/shoes/swt/text_block/text_segment_collection.rb +160 -0
- data/lib/shoes/swt/text_block/text_style_factory.rb +88 -0
- data/lib/shoes/swt/timer.rb +19 -0
- data/lib/shoes/swt/tooling/leak_hunter.rb +35 -0
- data/lib/shoes/swt/version.rb +5 -0
- data/manifests/common.rb +34 -0
- data/manifests/shoes-swt.rb +29 -0
- data/shoes-swt.gemspec +24 -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/spec/swt_shoes/animation_spec.rb +86 -0
- data/spec/swt_shoes/app_spec.rb +84 -0
- data/spec/swt_shoes/arc_spec.rb +103 -0
- data/spec/swt_shoes/background_spec.rb +67 -0
- data/spec/swt_shoes/border_spec.rb +52 -0
- data/spec/swt_shoes/button_spec.rb +101 -0
- data/spec/swt_shoes/check_spec.rb +28 -0
- data/spec/swt_shoes/color_factory_spec.rb +49 -0
- data/spec/swt_shoes/color_spec.rb +67 -0
- data/spec/swt_shoes/common/painter_spec.rb +49 -0
- data/spec/swt_shoes/common/remove_spec.rb +53 -0
- data/spec/swt_shoes/configuration_spec.rb +12 -0
- data/spec/swt_shoes/dialog_spec.rb +106 -0
- data/spec/swt_shoes/disposed_protection_spec.rb +49 -0
- data/spec/swt_shoes/flow_spec.rb +36 -0
- data/spec/swt_shoes/font_spec.rb +33 -0
- data/spec/swt_shoes/gradient_spec.rb +31 -0
- data/spec/swt_shoes/image_pattern_spec.rb +35 -0
- data/spec/swt_shoes/image_spec.rb +100 -0
- data/spec/swt_shoes/input_box_spec.rb +116 -0
- data/spec/swt_shoes/integration_spec.rb +27 -0
- data/spec/swt_shoes/key_listener_spec.rb +325 -0
- data/spec/swt_shoes/line_spec.rb +49 -0
- data/spec/swt_shoes/link_segment_spec.rb +120 -0
- data/spec/swt_shoes/link_spec.rb +54 -0
- data/spec/swt_shoes/list_box_spec.rb +56 -0
- data/spec/swt_shoes/minimal.png +0 -0
- data/spec/swt_shoes/mouse_move_listener_spec.rb +123 -0
- data/spec/swt_shoes/oval_spec.rb +51 -0
- data/spec/swt_shoes/progress_spec.rb +44 -0
- data/spec/swt_shoes/radio_group_spec.rb +73 -0
- data/spec/swt_shoes/radio_spec.rb +56 -0
- data/spec/swt_shoes/rect_painter_spec.rb +45 -0
- data/spec/swt_shoes/rect_spec.rb +19 -0
- data/spec/swt_shoes/shape_spec.rb +84 -0
- data/spec/swt_shoes/shared_examples/button.rb +21 -0
- data/spec/swt_shoes/shared_examples/clickable.rb +85 -0
- data/spec/swt_shoes/shared_examples/movable.rb +36 -0
- data/spec/swt_shoes/shared_examples/paintable.rb +7 -0
- data/spec/swt_shoes/shared_examples/painter.rb +83 -0
- data/spec/swt_shoes/shared_examples/pattern.rb +32 -0
- data/spec/swt_shoes/shared_examples/removable.rb +41 -0
- data/spec/swt_shoes/shared_examples/swt_app_context.rb +23 -0
- data/spec/swt_shoes/shared_examples/visibility.rb +15 -0
- data/spec/swt_shoes/shell_control_listener_spec.rb +23 -0
- data/spec/swt_shoes/slot_spec.rb +24 -0
- data/spec/swt_shoes/sound.rb +10 -0
- data/spec/swt_shoes/spec_helper.rb +31 -0
- data/spec/swt_shoes/star_spec.rb +47 -0
- data/spec/swt_shoes/text_block/centered_text_segment_spec.rb +16 -0
- data/spec/swt_shoes/text_block/cursor_painter_spec.rb +120 -0
- data/spec/swt_shoes/text_block/fitter_spec.rb +213 -0
- data/spec/swt_shoes/text_block/painter_spec.rb +212 -0
- data/spec/swt_shoes/text_block/text_font_factory_spec.rb +40 -0
- data/spec/swt_shoes/text_block/text_segment_collection_spec.rb +256 -0
- data/spec/swt_shoes/text_block/text_segment_spec.rb +135 -0
- data/spec/swt_shoes/text_block_spec.rb +199 -0
- metadata +496 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
class Shoes
|
|
2
|
+
module Swt
|
|
3
|
+
class TextBlock
|
|
4
|
+
include Common::Remove
|
|
5
|
+
include Common::Visibility
|
|
6
|
+
include Common::Clickable
|
|
7
|
+
include ::Shoes::BackendDimensionsDelegations
|
|
8
|
+
|
|
9
|
+
DEFAULT_SPACING = 4
|
|
10
|
+
|
|
11
|
+
attr_reader :dsl, :app
|
|
12
|
+
attr_accessor :segments
|
|
13
|
+
|
|
14
|
+
def initialize(dsl, app)
|
|
15
|
+
@dsl = dsl
|
|
16
|
+
@app = app
|
|
17
|
+
@segments = []
|
|
18
|
+
@painter = Painter.new @dsl
|
|
19
|
+
@app.add_paint_listener @painter
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def dispose
|
|
23
|
+
dispose_existing_segments
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# has a painter, nothing to do
|
|
27
|
+
def update_position
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def in_bounds?(x, y)
|
|
31
|
+
segments.any? do |segment|
|
|
32
|
+
segment.in_bounds?(x, y)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def contents_alignment(current_position)
|
|
37
|
+
dispose_existing_segments
|
|
38
|
+
@segments = Fitter.new(self, current_position).fit_it_in
|
|
39
|
+
|
|
40
|
+
set_absolutes_on_dsl(current_position)
|
|
41
|
+
set_calculated_sizes
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def adjust_current_position(current_position)
|
|
45
|
+
last_segment = segments.last
|
|
46
|
+
current_position.y = @dsl.absolute_bottom
|
|
47
|
+
current_position.y -= last_segment.last_line_height unless @bumped_to_next_line
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def set_absolutes_on_dsl(current_position)
|
|
51
|
+
if segments.one?
|
|
52
|
+
set_absolutes(@dsl.absolute_left, @dsl.absolute_top)
|
|
53
|
+
else
|
|
54
|
+
set_absolutes(@dsl.parent.absolute_left, current_position.next_line_start)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
if trailing_newline?
|
|
58
|
+
bump_absolutes_to_next_line
|
|
59
|
+
else
|
|
60
|
+
@bumped_to_next_line = false
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def set_absolutes(starting_left, starting_top)
|
|
65
|
+
last_segment = segments.last
|
|
66
|
+
|
|
67
|
+
@dsl.absolute_right = starting_left + last_segment.last_line_width +
|
|
68
|
+
margin_right
|
|
69
|
+
|
|
70
|
+
@dsl.absolute_bottom = starting_top + last_segment.height +
|
|
71
|
+
margin_top + margin_bottom
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def bump_absolutes_to_next_line
|
|
75
|
+
@dsl.absolute_right = @dsl.parent.absolute_left
|
|
76
|
+
@bumped_to_next_line = true
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def set_calculated_sizes
|
|
80
|
+
@dsl.calculated_width = segments.last.width
|
|
81
|
+
@dsl.calculated_height = segments.inject(0) do |total, segment|
|
|
82
|
+
total += segment.bounds.height
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def remove
|
|
87
|
+
super
|
|
88
|
+
clear_contents
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def replace(*_)
|
|
92
|
+
clear_contents
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
private
|
|
96
|
+
|
|
97
|
+
def clear_contents
|
|
98
|
+
dispose_existing_segments
|
|
99
|
+
clear_links
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def clear_links
|
|
103
|
+
@dsl.links.each(&:remove)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def dispose_existing_segments
|
|
107
|
+
@segments.map(&:dispose)
|
|
108
|
+
@segments.clear
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def trailing_newline?
|
|
112
|
+
@dsl.text.end_with?("\n")
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
class Banner < TextBlock; end
|
|
117
|
+
class Title < TextBlock; end
|
|
118
|
+
class Subtitle < TextBlock; end
|
|
119
|
+
class Tagline < TextBlock; end
|
|
120
|
+
class Caption < TextBlock; end
|
|
121
|
+
class Para < TextBlock; end
|
|
122
|
+
class Inscription < TextBlock; end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class Shoes
|
|
2
|
+
module Swt
|
|
3
|
+
class TextBlock
|
|
4
|
+
# Presently centering always takes the whole line, so this class easily
|
|
5
|
+
# allows us to keep those alternate overrides separate from the main
|
|
6
|
+
# flowing text definitions for a segment.
|
|
7
|
+
class CenteredTextSegment < TextSegment
|
|
8
|
+
def initialize(dsl, width)
|
|
9
|
+
super(dsl, dsl.text, width)
|
|
10
|
+
|
|
11
|
+
# Centered text always takes all the width it's given
|
|
12
|
+
layout.width = width
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Overrides to not allow for flowing on final line--whole width only
|
|
16
|
+
def last_line_width
|
|
17
|
+
layout.width
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
class Shoes
|
|
2
|
+
module Swt
|
|
3
|
+
class TextBlock
|
|
4
|
+
class CursorPainter
|
|
5
|
+
def initialize(text_block_dsl, collection)
|
|
6
|
+
@text_block_dsl = text_block_dsl
|
|
7
|
+
@collection = collection
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def draw
|
|
11
|
+
if @text_block_dsl.cursor
|
|
12
|
+
draw_textcursor
|
|
13
|
+
else
|
|
14
|
+
remove_textcursor
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def draw_textcursor
|
|
19
|
+
segment = @collection.segment_at_text_position(@text_block_dsl.cursor)
|
|
20
|
+
relative_cursor = @collection.relative_text_position(@text_block_dsl.cursor)
|
|
21
|
+
position = segment.get_location(relative_cursor)
|
|
22
|
+
|
|
23
|
+
move_if_necessary(segment.element_left + position.x,
|
|
24
|
+
segment.element_top + position.y)
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# It's important to only move when necessary to avoid constant redraws
|
|
29
|
+
def move_if_necessary(x, y)
|
|
30
|
+
unless textcursor.left == x && textcursor.top == y
|
|
31
|
+
move_textcursor(x, y)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def move_textcursor(x, y)
|
|
36
|
+
textcursor.move(x, y)
|
|
37
|
+
textcursor.show
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def textcursor
|
|
41
|
+
@text_block_dsl.textcursor @collection.cursor_height
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def remove_textcursor
|
|
45
|
+
return unless @text_block_dsl.has_textcursor?
|
|
46
|
+
|
|
47
|
+
@text_block_dsl.textcursor.remove
|
|
48
|
+
@text_block_dsl.textcursor = nil
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
class Shoes
|
|
2
|
+
module Swt
|
|
3
|
+
class TextBlock
|
|
4
|
+
class Fitter
|
|
5
|
+
attr_reader :parent
|
|
6
|
+
|
|
7
|
+
def initialize(text_block, current_position)
|
|
8
|
+
@text_block = text_block
|
|
9
|
+
@dsl = @text_block.dsl
|
|
10
|
+
@parent = @dsl.parent
|
|
11
|
+
@current_position = current_position
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Fitting text works by using either 1 or 2 layouts
|
|
15
|
+
#
|
|
16
|
+
# If the text fits in the height and width available, we use one layout.
|
|
17
|
+
#
|
|
18
|
+
# --------------------------
|
|
19
|
+
# | button | text layout 1 |
|
|
20
|
+
# --------------------------
|
|
21
|
+
#
|
|
22
|
+
# If if the text doesn't fit into that space, then we'll break it into
|
|
23
|
+
# two different layouts.
|
|
24
|
+
#
|
|
25
|
+
# --------------------------
|
|
26
|
+
# | button | text layout 1 |
|
|
27
|
+
# --------------------------
|
|
28
|
+
# | text layout 2 goes here|
|
|
29
|
+
# | in space |
|
|
30
|
+
# --------------------------
|
|
31
|
+
# ^
|
|
32
|
+
#
|
|
33
|
+
# If there wasn't any available space in the first layout (very narrow)
|
|
34
|
+
# then we'll make an empty first layout and flow to the second:
|
|
35
|
+
#
|
|
36
|
+
# --------------------------
|
|
37
|
+
# | big big big big button|| < empty layout 1 still present
|
|
38
|
+
# --------------------------
|
|
39
|
+
# | text layout 2 goes here|
|
|
40
|
+
# | in space |
|
|
41
|
+
# --------------------------
|
|
42
|
+
# ^
|
|
43
|
+
#
|
|
44
|
+
# When flowing, the position for the next element gets set to the end of
|
|
45
|
+
# the text in the second layout (shown as ^ in the diagram).
|
|
46
|
+
#
|
|
47
|
+
# Stacks properly move to the next whole line as you'd expect.
|
|
48
|
+
#
|
|
49
|
+
def fit_it_in
|
|
50
|
+
width, height = available_space
|
|
51
|
+
if @dsl.centered?
|
|
52
|
+
fit_as_centered(width, height)
|
|
53
|
+
elsif no_space_in_first_layout?(width)
|
|
54
|
+
fit_as_empty_first_layout(height)
|
|
55
|
+
else
|
|
56
|
+
fit_into_full_layouts(width, height)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def no_space_in_first_layout?(width)
|
|
61
|
+
width <= 0
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def fits_in_one_layout?(layout, height)
|
|
65
|
+
return true if height == :unbounded || layout.line_count == 1
|
|
66
|
+
layout.bounds.height <= height
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def fit_into_full_layouts(width, height)
|
|
70
|
+
layout = generate_layout(width, @dsl.text)
|
|
71
|
+
if fits_in_one_layout?(layout, height)
|
|
72
|
+
fit_as_one_layout(layout)
|
|
73
|
+
else
|
|
74
|
+
fit_as_two_layouts(layout, height, width)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def fit_as_one_layout(layout)
|
|
79
|
+
[layout.position_at(@dsl.element_left, @dsl.element_top)]
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def fit_as_two_layouts(layout, height, width)
|
|
83
|
+
first_text, second_text = split_text(layout, height)
|
|
84
|
+
|
|
85
|
+
# Since we regenerate layouts, we must dispose of first try here.
|
|
86
|
+
layout.dispose
|
|
87
|
+
layout = nil
|
|
88
|
+
|
|
89
|
+
first_layout = generate_layout(width, first_text)
|
|
90
|
+
|
|
91
|
+
if second_text.empty?
|
|
92
|
+
fit_as_one_layout(first_layout)
|
|
93
|
+
else
|
|
94
|
+
generate_two_layouts(first_layout, first_text, second_text, height)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def fit_as_empty_first_layout(height)
|
|
99
|
+
height += ::Shoes::Slot::NEXT_ELEMENT_OFFSET
|
|
100
|
+
generate_two_layouts(empty_segment, "", @dsl.text, height)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def fit_as_centered(width, height)
|
|
104
|
+
if first_element_on_line?
|
|
105
|
+
segment = CenteredTextSegment.new(@dsl, width)
|
|
106
|
+
[segment.position_at(@dsl.element_left, @dsl.element_top)]
|
|
107
|
+
else
|
|
108
|
+
position_two_segments(
|
|
109
|
+
empty_segment,
|
|
110
|
+
CenteredTextSegment.new(@dsl, @dsl.containing_width),
|
|
111
|
+
"",
|
|
112
|
+
height)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def first_element_on_line?
|
|
117
|
+
@dsl.left - @dsl.margin_left <= 0
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def generate_two_layouts(first_layout, first_text, second_text, height)
|
|
121
|
+
second_layout = generate_second_layout(second_text)
|
|
122
|
+
position_two_segments(first_layout, second_layout, first_text, height)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def generate_second_layout(second_text)
|
|
126
|
+
generate_layout(@dsl.containing_width, second_text)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def position_two_segments(first_layout, second_layout, first_text, height)
|
|
130
|
+
first_height = first_height(first_layout, first_text, height)
|
|
131
|
+
|
|
132
|
+
[
|
|
133
|
+
first_layout.position_at(@dsl.element_left,
|
|
134
|
+
@dsl.element_top),
|
|
135
|
+
second_layout.position_at(parent.absolute_left + @dsl.margin_left,
|
|
136
|
+
@dsl.element_top + first_height + 1)
|
|
137
|
+
]
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def available_space
|
|
141
|
+
width = @dsl.desired_width
|
|
142
|
+
height = next_line_start - @dsl.absolute_top - 1
|
|
143
|
+
|
|
144
|
+
if on_new_line?
|
|
145
|
+
height = :unbounded
|
|
146
|
+
|
|
147
|
+
# Try to find a parent container we fit in.
|
|
148
|
+
# If that doesn't work, just bail with [0,0] so we don't crash.
|
|
149
|
+
width = width_from_ancestor if width <= 0
|
|
150
|
+
return [0, 0] if width < 0
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
[width, height]
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# If we're positioned outside our containing width, look up the parent
|
|
157
|
+
# chain until we find a width that accomodates us.
|
|
158
|
+
def width_from_ancestor
|
|
159
|
+
width = -1
|
|
160
|
+
current_ancestor = @dsl.parent
|
|
161
|
+
until width > 0 || current_ancestor.nil?
|
|
162
|
+
width = @dsl.desired_width(current_ancestor.width)
|
|
163
|
+
|
|
164
|
+
break unless current_ancestor.respond_to?(:parent)
|
|
165
|
+
current_ancestor = current_ancestor.parent
|
|
166
|
+
end
|
|
167
|
+
width
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def next_line_start
|
|
171
|
+
@current_position.next_line_start
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def on_new_line?
|
|
175
|
+
next_line_start <= @dsl.absolute_top
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def generate_layout(width, text)
|
|
179
|
+
TextSegment.new(@dsl, text, width)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def empty_segment
|
|
183
|
+
segment = generate_layout(1, @dsl.text)
|
|
184
|
+
segment.text = ""
|
|
185
|
+
segment
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def split_text(layout, height)
|
|
189
|
+
ending_offset = 0
|
|
190
|
+
height_so_far = 0
|
|
191
|
+
|
|
192
|
+
offsets = layout.line_offsets
|
|
193
|
+
offsets[0...-1].each_with_index do |_, i|
|
|
194
|
+
height_so_far += layout.line_bounds(i).height
|
|
195
|
+
break if height_so_far > height
|
|
196
|
+
|
|
197
|
+
ending_offset = offsets[i+1]
|
|
198
|
+
end
|
|
199
|
+
[layout.text[0...ending_offset], layout.text[ending_offset..-1]]
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# If first text is empty, height may be smaller than an actual line in
|
|
203
|
+
# the current font. Take our pre-existing allowed height instead.
|
|
204
|
+
def first_height(first_layout, first_text, height)
|
|
205
|
+
first_height = first_layout.bounds.height - first_layout.spacing
|
|
206
|
+
first_height = height if first_text.empty? && height != :unbounded
|
|
207
|
+
first_height
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
class Shoes
|
|
2
|
+
module Swt
|
|
3
|
+
class TextBlock
|
|
4
|
+
class Painter
|
|
5
|
+
include ::Swt::Events::PaintListener
|
|
6
|
+
include Common::Resource
|
|
7
|
+
|
|
8
|
+
attr_reader :app
|
|
9
|
+
def initialize(dsl)
|
|
10
|
+
@dsl = dsl
|
|
11
|
+
@style = @dsl.style
|
|
12
|
+
@app = @dsl.app.gui
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def paintControl(paint_event)
|
|
16
|
+
reset_graphics_context(paint_event.gc)
|
|
17
|
+
return if @dsl.hidden?
|
|
18
|
+
|
|
19
|
+
draw_layouts(paint_event.gc)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def draw_layouts(graphic_context)
|
|
23
|
+
layouts = TextSegmentCollection.new(@dsl,
|
|
24
|
+
@dsl.gui.segments,
|
|
25
|
+
default_text_styles)
|
|
26
|
+
layouts.paint_control(graphic_context)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def default_text_styles
|
|
32
|
+
{
|
|
33
|
+
:fg => @style[:fg],
|
|
34
|
+
:bg => @style[:bg],
|
|
35
|
+
:strikecolor => @style[:strikecolor],
|
|
36
|
+
:undercolor => @style[:undercolor],
|
|
37
|
+
:font_detail => {
|
|
38
|
+
:name => @dsl.font,
|
|
39
|
+
:size => @dsl.size,
|
|
40
|
+
:styles => [::Swt::SWT::NORMAL]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|