Class: Shoes::Swt::TextBlock::TextSegmentCollection

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dsl, segments, default_text_styles) ⇒ TextSegmentCollection

Returns a new instance of TextSegmentCollection


13
14
15
16
17
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 13

def initialize(dsl, segments, default_text_styles)
  @dsl = dsl
  @segments = segments
  @default_text_styles = default_text_styles
end

Instance Attribute Details

#default_text_stylesObject (readonly)

Returns the value of attribute default_text_styles


11
12
13
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 11

def default_text_styles
  @default_text_styles
end

#dslObject (readonly)

Returns the value of attribute dsl


11
12
13
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 11

def dsl
  @dsl
end

Instance Method Details

#at_end?(index) ⇒ Boolean

Returns:

  • (Boolean)

152
153
154
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 152

def at_end?(index)
  index.negative? || index > @dsl.text.length
end

#calculate_style(elements) ⇒ Object


64
65
66
67
68
69
70
71
72
73
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 64

def calculate_style(elements)
  elements.inject(default_text_styles) do |current_style, element|
    if element.respond_to?(:style)
      TextStyleFactory.apply_styles(current_style, element.style)
    else
      # Didn't know how to style from the element, so punt
      current_style
    end
  end
end

#clearObject


19
20
21
22
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 19

def clear
  @segments.map(&:dispose)
  @segments.clear
end

75
76
77
78
79
80
81
82
83
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 75

def create_links(elements_by_range)
  elements_by_range.each do |range, elements|
    elements.each do |element|
      if supports_links?(element)
        element.gui.create_links_in(segment_ranges(range))
      end
    end
  end
end

#cursor_heightObject

This could be smarter, basing height on the actual line the cursor's in. For now, just use the first line's (purported) height.


170
171
172
173
174
175
176
177
178
179
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 170

def cursor_height
  if @segments.first.text.empty?
    # Heights are off for empty text layouts. Fake it to make it (it
    # being a real height).
    new_segment = TextSegment.new(@dsl, "Hi", 100)
    height_from_segment(new_segment)
  else
    height_from_segment(@segments.first)
  end
end

#draw(graphic_context) ⇒ Object


45
46
47
48
49
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 45

def draw(graphic_context)
  @segments.each do |segment|
    segment.draw(graphic_context)
  end
end

#draw_cursorObject


51
52
53
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 51

def draw_cursor
  TextBlock::CursorPainter.new(dsl, self).draw
end

#ensure_styledObject


30
31
32
33
34
35
36
37
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 30

def ensure_styled
  return if @styled

  style_from(@dsl.style)
  style_segment_ranges(@dsl.text_styles)
  create_links(@dsl.text_styles)
  @styled = true
end

#height_from_segment(segment) ⇒ Object


181
182
183
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 181

def height_from_segment(segment)
  segment.get_line_bounds(0).height
end

#paint_control(graphic_context) ⇒ Object


24
25
26
27
28
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 24

def paint_control(graphic_context)
  ensure_styled
  draw(graphic_context)
  draw_cursor
end

#relative_end_positionObject


156
157
158
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 156

def relative_end_position
  @segments.last.text.length
end

#relative_in_first_segment(index) ⇒ Object


160
161
162
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 160

def relative_in_first_segment(index)
  index
end

#relative_in_first_segment?(index) ⇒ Boolean

Returns:

  • (Boolean)

147
148
149
150
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 147

def relative_in_first_segment?(index)
  index >= 0 &&
    (@segments.one? || index < @segments.first.text.length)
end

#relative_in_last_segment(index) ⇒ Object


164
165
166
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 164

def relative_in_last_segment(index)
  index - @segments.first.text.length
end

#relative_text_position(index) ⇒ Object

Returns the relative position within the appropriate segment for index in the overall DSL text


137
138
139
140
141
142
143
144
145
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 137

def relative_text_position(index)
  if at_end?(index)
    relative_end_position
  elsif relative_in_first_segment?(index)
    relative_in_first_segment(index)
  else
    relative_in_last_segment(index)
  end
end

#results_in_first_segment(text_range) ⇒ Object


114
115
116
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 114

def results_in_first_segment(text_range)
  [[@segments.first, text_range]]
end

#results_in_last_segment(text_range, first_text) ⇒ Object


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

def results_in_last_segment(text_range, first_text)
  range_start = text_range.first - first_text.length
  range_end   = text_range.last - first_text.length
  [[@segments.last, (range_start..range_end)]]
end

#results_spanning_segments(text_range, first_text, slice) ⇒ Object


118
119
120
121
122
123
124
125
126
127
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 118

def results_spanning_segments(text_range, first_text, slice)
  result = []
  result << [@segments.first, (text_range.first..first_text.length)]
  # If first == last, then requested range was longer than our one and
  # only segment, so just stick with full range of the first segment.
  if @segments.first != @segments.last
    result << [@segments.last, (0..text_range.count - slice.length - 1)]
  end
  result
end

#segment_at_text_position(index) ⇒ Object


91
92
93
94
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 91

def segment_at_text_position(index)
  return @segments.last if index.negative?
  segment_ranges(index..index).first.first
end

#segment_ranges(text_range) ⇒ Object

If we've got segments that style us across different ranges, it might be in either, or both, of the segments. This method figures out which segments apply, and what the relative ranges within each segment to use.


99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 99

def segment_ranges(text_range)
  return [] unless text_range.any?

  first_text = @segments.first.text
  slice = first_text[text_range]

  if slice.nil? || slice.empty?
    results_in_last_segment(text_range, first_text)
  elsif slice.length < text_range.count
    results_spanning_segments(text_range, first_text, slice)
  else
    results_in_first_segment(text_range)
  end
end

#style_from(style) ⇒ Object


39
40
41
42
43
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 39

def style_from(style)
  @segments.each do |segment|
    segment.style_from(default_text_styles, style)
  end
end

#style_segment_ranges(elements_by_range) ⇒ Object


55
56
57
58
59
60
61
62
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 55

def style_segment_ranges(elements_by_range)
  elements_by_range.each do |range, elements|
    style = calculate_style(elements)
    segment_ranges(range).each do |segment, inner_range|
      segment.set_style(style, inner_range)
    end
  end
end

#supports_links?(element) ⇒ Boolean

Returns:

  • (Boolean)

85
86
87
88
89
# File 'shoes-swt/lib/shoes/swt/text_block/text_segment_collection.rb', line 85

def supports_links?(element)
  element.respond_to?(:gui) &&
    element.gui &&
    element.gui.respond_to?(:create_links_in)
end