Class: Shoes::Swt::TextBlock::TextSegment

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
shoes-swt/lib/shoes/swt/text_block/text_segment.rb

Overview

Resources created here need to be disposed (see #dispose). Note that this applies to ::Swt::Font and ::Swt::TextLayout. ::Swt::TextStyle does not need to be disposed, because it is not backed by system resources.

The instance factories and our own instances will track these resources and ensure that they get properly disposed when TextBlock or Fitter tell us we're done.

These are only expected to be called during contents_alignment

Direct Known Subclasses

CenteredTextSegment

Constant Summary collapse

DEFAULT_SPACING =
4

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dsl, text, width) ⇒ TextSegment

Returns a new instance of TextSegment


27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment.rb', line 27

def initialize(dsl, text, width)
  @dsl = dsl
  @layout = ::Swt::TextLayout.new Shoes.display
  @fill_background = false

  @font_factory = TextFontFactory.new
  @style_factory = TextStyleFactory.new
  @color_factory = ColorFactory.new

  layout.text = text
  layout.width = width
  style_from(font_styling, @dsl.style)
end

Instance Attribute Details

#element_leftObject (readonly)

Returns the value of attribute element_left


21
22
23
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment.rb', line 21

def element_left
  @element_left
end

#element_topObject (readonly)

Returns the value of attribute element_top


21
22
23
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment.rb', line 21

def element_top
  @element_top
end

#fill_backgroundObject

Returns the value of attribute fill_background


22
23
24
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment.rb', line 22

def fill_background
  @fill_background
end

#layoutObject (readonly)

Returns the value of attribute layout


21
22
23
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment.rb', line 21

def layout
  @layout
end

Instance Method Details

#disposeObject


41
42
43
44
45
46
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment.rb', line 41

def dispose
  @layout.dispose unless @layout.disposed?
  @font_factory.dispose
  @style_factory.dispose
  @color_factory.dispose
end

#draw(graphics_context) ⇒ Object


110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment.rb', line 110

def draw(graphics_context)
  # Why not use TextLayout's background? Unfortunately it doesn't draw
  # all the way to the edges--just around the literal text. This leaves
  # things jagged when we flow, so do it ourselves.
  if fill_background && @dsl.style[:fill]
    background_color = @color_factory.create(@dsl.style[:fill])
    background_color.apply_as_fill(graphics_context)
    graphics_context.fill_rectangle(@dsl.translate_left + element_left,
                                    @dsl.translate_top + element_top,
                                    width,
                                    height)
  end

  layout.draw(graphics_context,
              @dsl.translate_left + element_left,
              @dsl.translate_top + element_top)
end

#font_stylingObject


79
80
81
82
83
84
85
86
87
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment.rb', line 79

def font_styling
  {
    font_detail: {
      name: @dsl.font,
      size: @dsl.size,
      styles: [::Swt::SWT::NORMAL]
    }
  }
end

#get_location(cursor, trailing = false) ⇒ Object


54
55
56
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment.rb', line 54

def get_location(cursor, trailing = false)
  @layout.get_location(cursor, trailing)
end

#heightObject

Why not just use layout.bounds? Recent versions of SWT have shown platform dependent behavior about whether spacing is included in bounds, leading to unpredictable placement. Doing it more directly per-line in this fashion insulates us from the regression. #1295


93
94
95
96
97
98
99
100
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment.rb', line 93

def height
  line_count = layout.line_count
  h = (line_count - 1) * layout.spacing
  line_count.times do |i|
    h += layout.get_line_bounds(i).height
  end
  h
end

#in_bounds?(x, y) ⇒ Boolean

x,y in app coordinates, so translate for layout's element-local values

Returns:

  • (Boolean)

129
130
131
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment.rb', line 129

def in_bounds?(x, y)
  layout.bounds.contains?(x - element_left, y - element_top)
end

#last_line_heightObject


102
103
104
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment.rb', line 102

def last_line_height
  layout.get_line_bounds(layout.line_count - 1).height
end

#last_line_widthObject


106
107
108
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment.rb', line 106

def last_line_width
  layout.get_line_bounds(layout.line_count - 1).width
end

#position_at(element_left, element_top) ⇒ Object


48
49
50
51
52
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment.rb', line 48

def position_at(element_left, element_top)
  @element_left = element_left
  @element_top = element_top
  self
end

#set_style(styles, range = (0...text.length)) ⇒ Object


70
71
72
73
74
75
76
77
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment.rb', line 70

def set_style(styles, range = (0...text.length))
  # If we've been given an empty/nonsense range, just ignore it
  return unless range.count.positive?

  font = @font_factory.create_font(styles[:font_detail])
  style = @style_factory.create_style(font, styles[:fg], styles[:bg], styles)
  layout.set_style(style, range.min, range.max)
end

#style_from(default_text_styles, style) ⇒ Object


58
59
60
61
62
63
64
65
66
67
68
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment.rb', line 58

def style_from(default_text_styles, style)
  layout.justify = style[:justify]
  layout.spacing = (style[:leading] || DEFAULT_SPACING)
  layout.alignment = case style[:align]
                     when 'center' then ::Swt::SWT::CENTER
                     when 'right' then  ::Swt::SWT::RIGHT
                     else ::Swt::SWT::LEFT
                     end

  set_style(TextStyleFactory.apply_styles(default_text_styles, style))
end