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,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."
|