shoes-swt 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/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,50 @@
|
|
1
|
+
class Shoes
|
2
|
+
module Swt
|
3
|
+
class TextFontFactory
|
4
|
+
def initialize
|
5
|
+
@fonts = []
|
6
|
+
end
|
7
|
+
|
8
|
+
def create_font(font_style)
|
9
|
+
name = font_style[:name]
|
10
|
+
size = font_style[:size]
|
11
|
+
styles = styles_bitmask(font_style[:styles])
|
12
|
+
|
13
|
+
existing_font = find_existing_font(name, size, styles)
|
14
|
+
if existing_font
|
15
|
+
existing_font
|
16
|
+
else
|
17
|
+
build_font(name, size, styles)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def dispose
|
22
|
+
@fonts.each { |font| font.dispose unless font.disposed? }
|
23
|
+
@fonts.clear
|
24
|
+
end
|
25
|
+
|
26
|
+
def find_existing_font(name, size, styles)
|
27
|
+
# Bit odd, but fonts on some OS's have multiple font_data elements,
|
28
|
+
# so check if any of them match.
|
29
|
+
@fonts.find do |font|
|
30
|
+
font.font_data.any? do |font_data|
|
31
|
+
font_data.name == name &&
|
32
|
+
# Windows seems to create fonts of height 15.75 when requesting 16
|
33
|
+
font_data.height.round == size.round &&
|
34
|
+
font_data.style == styles
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def build_font(name, size, styles)
|
40
|
+
font = ::Swt::Graphics::Font.new @display, name, size, styles
|
41
|
+
@fonts << font
|
42
|
+
font
|
43
|
+
end
|
44
|
+
|
45
|
+
def styles_bitmask(styles)
|
46
|
+
styles.reduce { |result, s| result | s }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
class Shoes
|
2
|
+
module Swt
|
3
|
+
class TextBlock
|
4
|
+
# Resources created here need to be disposed (see #dispose). Note that
|
5
|
+
# this applies to ::Swt::Font and ::Swt::TextLayout. ::Swt::TextStyle
|
6
|
+
# does not need to be disposed, because it is not backed by system
|
7
|
+
# resources.
|
8
|
+
#
|
9
|
+
# The instance factories and our own instances will track these resources
|
10
|
+
# and ensure that they get properly disposed when TextBlock or Fitter
|
11
|
+
# tell us we're done.
|
12
|
+
#
|
13
|
+
# These are only expected to be called during contents_alignment
|
14
|
+
class TextSegment
|
15
|
+
DEFAULT_SPACING = 4
|
16
|
+
|
17
|
+
attr_reader :layout, :element_left, :element_top
|
18
|
+
|
19
|
+
extend Forwardable
|
20
|
+
def_delegators :@layout, :text, :text=, :bounds, :width, :spacing,
|
21
|
+
:line_bounds, :line_count, :line_offsets
|
22
|
+
|
23
|
+
def initialize(dsl, text, width)
|
24
|
+
@dsl = dsl
|
25
|
+
@layout = ::Swt::TextLayout.new Shoes.display
|
26
|
+
@font_factory = TextFontFactory.new
|
27
|
+
@style_factory = TextStyleFactory.new
|
28
|
+
|
29
|
+
layout.text = text
|
30
|
+
layout.width = width unless layout_fits_in?(width)
|
31
|
+
style_from(font_styling, @dsl.style)
|
32
|
+
end
|
33
|
+
|
34
|
+
def dispose
|
35
|
+
@layout.dispose unless @layout.disposed?
|
36
|
+
@font_factory.dispose
|
37
|
+
@style_factory.dispose
|
38
|
+
end
|
39
|
+
|
40
|
+
def position_at(element_left, element_top)
|
41
|
+
@element_left = element_left
|
42
|
+
@element_top = element_top
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_location(cursor, trailing=false)
|
47
|
+
@layout.get_location(cursor, trailing)
|
48
|
+
end
|
49
|
+
|
50
|
+
def style_from(default_text_styles, style)
|
51
|
+
layout.justify = style[:justify]
|
52
|
+
layout.spacing = (style[:leading] || DEFAULT_SPACING)
|
53
|
+
layout.alignment = case style[:align]
|
54
|
+
when 'center'; ::Swt::SWT::CENTER
|
55
|
+
when 'right'; ::Swt::SWT::RIGHT
|
56
|
+
else ::Swt::SWT::LEFT
|
57
|
+
end
|
58
|
+
|
59
|
+
set_style(TextStyleFactory.apply_styles(default_text_styles, style))
|
60
|
+
end
|
61
|
+
|
62
|
+
def set_style(styles, range=(0...text.length))
|
63
|
+
# If we've been given an empty/nonsense range, just ignore it
|
64
|
+
return unless range.count > 0
|
65
|
+
|
66
|
+
font = @font_factory.create_font(styles[:font_detail])
|
67
|
+
style = @style_factory.create_style(font, styles[:fg], styles[:bg], styles)
|
68
|
+
layout.set_style(style, range.min, range.max)
|
69
|
+
end
|
70
|
+
|
71
|
+
def font_styling
|
72
|
+
{
|
73
|
+
font_detail: {
|
74
|
+
name: @dsl.font,
|
75
|
+
size: @dsl.size,
|
76
|
+
styles:[::Swt::SWT::NORMAL]
|
77
|
+
}
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
def layout_fits_in?(width)
|
82
|
+
layout.bounds.width <= width
|
83
|
+
end
|
84
|
+
|
85
|
+
def height
|
86
|
+
layout.bounds.height - layout.spacing
|
87
|
+
end
|
88
|
+
|
89
|
+
def last_line_height
|
90
|
+
layout.line_bounds(layout.line_count - 1).height
|
91
|
+
end
|
92
|
+
|
93
|
+
def last_line_width
|
94
|
+
layout.line_bounds(layout.line_count - 1).width
|
95
|
+
end
|
96
|
+
|
97
|
+
def draw(graphics_context)
|
98
|
+
layout.draw(graphics_context, element_left, element_top)
|
99
|
+
end
|
100
|
+
|
101
|
+
# x,y in app coordinates, so translate for layout's element-local values
|
102
|
+
def in_bounds?(x, y)
|
103
|
+
layout.bounds.contains?(x - element_left, y - element_top)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
class Shoes
|
2
|
+
module Swt
|
3
|
+
class TextBlock
|
4
|
+
class TextSegmentCollection
|
5
|
+
extend Forwardable
|
6
|
+
def_delegators :@segments, :length
|
7
|
+
|
8
|
+
attr_reader :dsl, :default_text_styles
|
9
|
+
|
10
|
+
def initialize(dsl, segments, default_text_styles)
|
11
|
+
@dsl = dsl
|
12
|
+
@segments = segments
|
13
|
+
@default_text_styles = default_text_styles
|
14
|
+
end
|
15
|
+
|
16
|
+
def paint_control(graphic_context)
|
17
|
+
style_from(dsl.style)
|
18
|
+
style_segment_ranges(dsl.text_styles)
|
19
|
+
create_links(dsl.text_styles)
|
20
|
+
draw(graphic_context)
|
21
|
+
draw_cursor
|
22
|
+
end
|
23
|
+
|
24
|
+
def style_from(style)
|
25
|
+
@segments.each do |segment|
|
26
|
+
segment.style_from(default_text_styles, style)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def draw(graphic_context)
|
31
|
+
@segments.each do |segment|
|
32
|
+
segment.draw(graphic_context)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def draw_cursor
|
37
|
+
TextBlock::CursorPainter.new(dsl, self).draw
|
38
|
+
end
|
39
|
+
|
40
|
+
def style_segment_ranges(elements_by_range)
|
41
|
+
elements_by_range.each do |range, elements|
|
42
|
+
style = calculate_style(elements)
|
43
|
+
segment_ranges(range).each do |segment, inner_range|
|
44
|
+
segment.set_style(style, inner_range)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def calculate_style(elements)
|
50
|
+
elements.inject(default_text_styles) do |current_style, element|
|
51
|
+
if element.respond_to?(:style)
|
52
|
+
TextStyleFactory.apply_styles(current_style, element.style)
|
53
|
+
else
|
54
|
+
# Didn't know how to style from the element, so punt
|
55
|
+
current_style
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def create_links(elements_by_range)
|
61
|
+
elements_by_range.each do |range, elements|
|
62
|
+
elements.each do |element|
|
63
|
+
if supports_links?(element)
|
64
|
+
element.gui.create_links_in(segment_ranges(range))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def supports_links?(element)
|
71
|
+
element.respond_to?(:gui) &&
|
72
|
+
element.gui &&
|
73
|
+
element.gui.respond_to?(:create_links_in)
|
74
|
+
end
|
75
|
+
|
76
|
+
def segment_at_text_position(index)
|
77
|
+
return @segments.last if index < 0
|
78
|
+
segment_ranges(index..index).first.first
|
79
|
+
end
|
80
|
+
|
81
|
+
# If we've got segments that style us across different ranges, it might
|
82
|
+
# be in either, or both, of the segments. This method figures out which
|
83
|
+
# segments apply, and what the relative ranges within each segment to use.
|
84
|
+
def segment_ranges(text_range)
|
85
|
+
return [] unless @segments.first # TODO WTF #636
|
86
|
+
first_text = @segments.first.text
|
87
|
+
slice = first_text[text_range]
|
88
|
+
|
89
|
+
if slice.nil? || slice.empty?
|
90
|
+
results_in_last_segment(text_range, first_text)
|
91
|
+
elsif slice.length < text_range.count
|
92
|
+
results_spanning_segments(text_range, first_text, slice)
|
93
|
+
else
|
94
|
+
results_in_first_segment(text_range)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def results_in_first_segment(text_range)
|
99
|
+
[[@segments.first, text_range]]
|
100
|
+
end
|
101
|
+
|
102
|
+
def results_spanning_segments(text_range, first_text, slice)
|
103
|
+
result = []
|
104
|
+
result << [@segments.first, (text_range.first..first_text.length)]
|
105
|
+
# If first == last, then requested range was longer than our one and
|
106
|
+
# only segment, so just stick with full range of the first segment.
|
107
|
+
if @segments.first != @segments.last
|
108
|
+
result << [@segments.last, (0..text_range.count - slice.length - 1)]
|
109
|
+
end
|
110
|
+
result
|
111
|
+
end
|
112
|
+
|
113
|
+
def results_in_last_segment(text_range, first_text)
|
114
|
+
range_start = text_range.first - first_text.length
|
115
|
+
range_end = text_range.last - first_text.length
|
116
|
+
[[@segments.last, (range_start..range_end)]]
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns the relative position within the appropriate segment for index
|
120
|
+
# in the overall DSL text
|
121
|
+
def relative_text_position(index)
|
122
|
+
if at_end?(index)
|
123
|
+
relative_end_position
|
124
|
+
elsif relative_in_first_segment?(index)
|
125
|
+
relative_in_first_segment(index)
|
126
|
+
else
|
127
|
+
relative_in_last_segment(index)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def relative_in_first_segment?(index)
|
132
|
+
index >= 0 &&
|
133
|
+
(@segments.one? || index < @segments.first.text.length)
|
134
|
+
end
|
135
|
+
|
136
|
+
def at_end?(index)
|
137
|
+
index < 0 || index > @dsl.text.length
|
138
|
+
end
|
139
|
+
|
140
|
+
def relative_end_position
|
141
|
+
@segments.last.text.length
|
142
|
+
end
|
143
|
+
|
144
|
+
def relative_in_first_segment(index)
|
145
|
+
index
|
146
|
+
end
|
147
|
+
|
148
|
+
def relative_in_last_segment(index)
|
149
|
+
index - @segments.first.text.length
|
150
|
+
end
|
151
|
+
|
152
|
+
# This could be smarter, basing height on the actual line the cursor's
|
153
|
+
# in. For now, just use the first line's height.
|
154
|
+
def cursor_height
|
155
|
+
@segments.first.line_bounds(0).height
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
class Shoes
|
2
|
+
module Swt
|
3
|
+
class TextStyleFactory
|
4
|
+
UNDERLINE_STYLES = {
|
5
|
+
"single" => 0,
|
6
|
+
"double" => 1,
|
7
|
+
"error" => 2,
|
8
|
+
}
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@colors = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def dispose
|
15
|
+
@colors.each { |color| color.dispose unless color.disposed? }
|
16
|
+
@colors.clear
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_style(font, foreground, background, style)
|
20
|
+
fg = swt_color(foreground, ::Shoes::COLORS[:black])
|
21
|
+
bg = swt_color(background)
|
22
|
+
@gui_style = ::Swt::TextStyle.new font, fg, bg
|
23
|
+
set_underline(style)
|
24
|
+
set_undercolor(style)
|
25
|
+
set_rise(style)
|
26
|
+
set_strikethrough(style)
|
27
|
+
set_strikecolor(style)
|
28
|
+
@gui_style
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.apply_styles(gui_style, dsl_style)
|
32
|
+
gui_style[:font_detail][:styles] = parse_font_style(dsl_style)
|
33
|
+
gui_style[:font_detail][:name] = dsl_style[:font] if dsl_style[:font]
|
34
|
+
gui_style[:font_detail][:size] = dsl_style[:size] if dsl_style[:size]
|
35
|
+
gui_style[:fg] = dsl_style[:stroke]
|
36
|
+
gui_style[:bg] = dsl_style[:fill]
|
37
|
+
gui_style[:font_detail][:size] *= dsl_style[:size_modifier] if dsl_style[:size_modifier]
|
38
|
+
gui_style.merge(dsl_style)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.parse_font_style(style)
|
42
|
+
font_styles = []
|
43
|
+
font_styles << ::Swt::SWT::BOLD if style[:weight]
|
44
|
+
font_styles << ::Swt::SWT::ITALIC if style[:emphasis]
|
45
|
+
font_styles << ::Swt::SWT::NORMAL if !style[:weight] && !style[:emphasis]
|
46
|
+
font_styles
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def set_rise(style)
|
51
|
+
@gui_style.rise = style[:rise]
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_underline(style)
|
55
|
+
@gui_style.underline = style[:underline].nil? || style[:underline] == "none" ? false : true
|
56
|
+
@gui_style.underlineStyle = UNDERLINE_STYLES[style[:underline]]
|
57
|
+
end
|
58
|
+
|
59
|
+
def set_undercolor(style)
|
60
|
+
@gui_style.underlineColor = color_from_dsl style[:undercolor]
|
61
|
+
end
|
62
|
+
|
63
|
+
def set_strikethrough(style)
|
64
|
+
@gui_style.strikeout = style[:strikethrough].nil? || style[:strikethrough] == "none" ? false : true
|
65
|
+
end
|
66
|
+
|
67
|
+
def set_strikecolor(style)
|
68
|
+
@gui_style.strikeoutColor = color_from_dsl style[:strikecolor]
|
69
|
+
end
|
70
|
+
|
71
|
+
def swt_color(color, default = nil)
|
72
|
+
return color if color.is_a? ::Swt::Color
|
73
|
+
color_from_dsl color, default
|
74
|
+
end
|
75
|
+
|
76
|
+
def color_from_dsl(dsl_color, default = nil)
|
77
|
+
return nil if dsl_color.nil? and default.nil?
|
78
|
+
return color_from_dsl default if dsl_color.nil?
|
79
|
+
color = ::Swt::Color.new(Shoes.display, dsl_color.red, dsl_color.green, dsl_color.blue)
|
80
|
+
|
81
|
+
# Hold a reference to the color so we can dispose it when the time comes
|
82
|
+
@colors << color
|
83
|
+
|
84
|
+
color
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Shoes
|
2
|
+
module Swt
|
3
|
+
class Timer
|
4
|
+
def initialize(dsl, app, blk)
|
5
|
+
@blk = blk
|
6
|
+
task = Proc.new do
|
7
|
+
unless app.real.disposed?
|
8
|
+
eval_block
|
9
|
+
end
|
10
|
+
end
|
11
|
+
::Swt.display.timer_exec(dsl.n, task)
|
12
|
+
end
|
13
|
+
|
14
|
+
def eval_block
|
15
|
+
@blk.call
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'swt'
|
2
|
+
require 'shoes/swt'
|
3
|
+
# Interested what hometown is and what it does?
|
4
|
+
# check here: https://github.com/jasonrclark/hometown
|
5
|
+
require 'hometown'
|
6
|
+
|
7
|
+
# All known subclasses of Swt::Graphics::Resource
|
8
|
+
# see http://help.eclipse.org/helios/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fswt%2Fpackage-summary.html
|
9
|
+
[
|
10
|
+
::Swt::Graphics::Color,
|
11
|
+
::Swt::Graphics::Cursor,
|
12
|
+
::Swt::Graphics::Font,
|
13
|
+
::Swt::Graphics::Image,
|
14
|
+
::Swt::Graphics::Path,
|
15
|
+
::Swt::Graphics::Pattern,
|
16
|
+
::Swt::Graphics::Region,
|
17
|
+
::Swt::Graphics::TextLayout,
|
18
|
+
::Swt::Graphics::Transform,
|
19
|
+
|
20
|
+
# Excluded GC as we don't create any directly and it's quite noisy
|
21
|
+
#::Swt::Graphics::GC,
|
22
|
+
].each do |clazz|
|
23
|
+
Hometown.watch_for_disposal(clazz, :dispose)
|
24
|
+
end
|
25
|
+
|
26
|
+
Hometown.undisposed_report_at_exit
|
27
|
+
|
28
|
+
# Register an internal keystroke for closing the app, making sure to clear
|
29
|
+
# out the contents first (to avoid false positives for still-exiting elements.
|
30
|
+
Shoes::InternalApp.add_global_keypress(:'control_alt_q') do
|
31
|
+
clear
|
32
|
+
quit
|
33
|
+
end
|
34
|
+
|
35
|
+
puts "Registered Ctrl+Alt+Q for leak hunting clean shutdown."
|