Class: Fidgit::TextArea

Inherits:
Element show all
Defined in:
lib/fidgit/elements/text_area.rb

Constant Summary

Constants inherited from Element

Element::DEFAULT_SCHEMA_FILE, Element::VALID_ALIGN_H, Element::VALID_ALIGN_V

Instance Attribute Summary collapse

Attributes inherited from Element

#align_h, #align_v, #background_color, #border_thickness, #font_size, #padding_bottom, #padding_left, #padding_right, #padding_top, #parent, #tip, #z

Instance Method Summary collapse

Methods inherited from Element

#default, #drag?, #draw, #draw_frame, #draw_rect, #enabled=, #enabled?, #font, #height, #height=, #hit?, #max_width, #min_width, new, original_new, #outer_height, #outer_width, #recalc, schema, #update, #width, #width=, #with, #x, #x=, #y, #y=

Methods included from Event

#events, included, #publish, #subscribe

Constructor Details

#initialize(options = {}, &block) ⇒ TextArea

Returns a new instance of TextArea.

Options Hash (options):

  • :text (String) — default: ""
  • :height (Integer)

    Sets both min and max height at once.

  • :min_height (Integer)
  • :max_height (Integer) — default: Infinite
  • :line_spacing (Number) — default: 0


87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/fidgit/elements/text_area.rb', line 87

def initialize(options = {}, &block)
  options = {
    text: '',
    max_height: Float::INFINITY,
    line_spacing: default(:line_spacing),
    background_color: default(:background_color),
    border_color: default(:border_color),
    caret_color: default(:caret_color),
    caret_period: default(:caret_period),
    focused_border_color: default(:focused, :border_color),
    selection_color: default(:selection_color),
  }.merge! options

  @line_spacing = options[:line_spacing]
  @caret_color = options[:caret_color].dup
  @caret_period = options[:caret_period]
  @focused_border_color = options[:focused_border_color].dup
  @selection_color = options[:selection_color].dup

  @lines = [''] # List of lines of wrapped text.

  @caret_positions = [[0, 0]] # [x, y] of each position the caret can be in.

  @char_widths = [] # Width of each character in the text.

  @text_input = Gosu::TextInput.new
  @old_text = ''
  @old_caret_position = 0
  @old_selection_start = 0

  @text_input.text = options[:text].dup

  super(options)

  min_height = padding_left + padding_right + font_size
  if options[:height]
    @max_height = @min_height = [options[:height], min_height].max
  else
    @max_height = [options[:max_height], min_height].max
    @min_height = options[:min_height] ? [options[:min_height], min_height].max : min_height
  end
  rect.height = [padding_left + padding_right + font_size, @min_height].max

  subscribe :left_mouse_button, method(:click_in_text)
  subscribe :right_mouse_button, method(:click_in_text)
end

Instance Attribute Details

#editable=(value) ⇒ Boolean (writeonly)



15
16
17
# File 'lib/fidgit/elements/text_area.rb', line 15

def editable=(value)
  @editable = value
end

#line_spacingNumber (readonly)



11
12
13
# File 'lib/fidgit/elements/text_area.rb', line 11

def line_spacing
  @line_spacing
end

#max_heightNumber (readonly)



8
9
10
# File 'lib/fidgit/elements/text_area.rb', line 8

def max_height
  @max_height
end

#min_heightNumber (readonly)



6
7
8
# File 'lib/fidgit/elements/text_area.rb', line 6

def min_height
  @min_height
end

Instance Method Details

#blur(sender) ⇒ nil



161
162
163
164
165
166
167
168
169
170
# File 'lib/fidgit/elements/text_area.rb', line 161

def blur(sender)
  if focused?
    $window.current_game_state.focus = nil
    $window.text_input = nil
  end

  @focused = false

  nil
end

#caret_positionInteger

Position of the caret.



52
53
54
# File 'lib/fidgit/elements/text_area.rb', line 52

def caret_position
  @text_input.caret_pos
end

#caret_position=(position) ⇒ Integer

Position of the caret.

Raises:

  • (ArgumentError)


60
61
62
63
64
65
# File 'lib/fidgit/elements/text_area.rb', line 60

def caret_position=(position)
  raise ArgumentError, "Caret position must be in the range 0 to the length of the text (inclusive)" unless position.between?(0, text.length)
  @text_input.caret_pos = position

  position
end

#click_in_text(sender, x, y) ⇒ nil



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/fidgit/elements/text_area.rb', line 132

def click_in_text(sender, x, y)
  publish :focus unless focused?

  # Move caret to position the user clicks on.

  mouse_x, mouse_y = x - (self.x + padding_left), y - (self.y + padding_top)
  @char_widths.each_with_index do |width, i|
    char_x, char_y = @caret_positions[i]
    if mouse_x.between?(char_x, char_x + width) and mouse_y.between?(char_y, char_y + font_size)
      self.caret_position = @text_input.selection_start = i
      break
    end
  end

  nil
end

#draw_foregroundnil

Draw the text area.



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/fidgit/elements/text_area.rb', line 175

def draw_foreground
  # Always roll back changes made by the user unless the text is editable.

  if not editable? and text != @old_text
    @text_input.text = @old_text
    @text_input.selection_start = @old_selection_start
    self.caret_position = @old_caret_position
  else
    recalc if focused? # Workaround for Windows draw/update bug.

    @old_caret_position = caret_position
    @old_selection_start = @text_input.selection_start
  end

  # Draw the selection.

  selection_range.each do |pos|
    char_x, char_y = @caret_positions[pos]
    char_width = @char_widths[pos]
    left, top = x + padding_left + char_x, y + padding_top + char_y
    draw_rect left, top, char_width, font_size, z, @selection_color
  end

  # Draw text.

  @lines.each_with_index do |line, index|
    font.draw(line, x + padding_left, y + padding_top + y_at_line(index), z)
  end

  # Draw the caret.

  if focused? and ((Gosu::milliseconds / @caret_period) % 2 == 0)
    caret_x, caret_y = @caret_positions[caret_position]
    left, top = x + padding_left + caret_x, y + padding_top + caret_y
    draw_rect left, top, 1, font_size, z, @caret_color
  end
end

#editable?Boolean

Is the area editable?



22
23
24
# File 'lib/fidgit/elements/text_area.rb', line 22

def editable?
  enabled?
end

#focus(sender) ⇒ nil



152
153
154
155
156
157
158
# File 'lib/fidgit/elements/text_area.rb', line 152

def focus(sender)
  @focused = true
  $window.current_game_state.focus = self
  $window.text_input = @text_input

  nil
end

#focused?Boolean

Does the element have the focus?



149
# File 'lib/fidgit/elements/text_area.rb', line 149

def focused?; @focused; end

#selection_rangeRange

Returns the range of the selection.



35
36
37
38
39
40
# File 'lib/fidgit/elements/text_area.rb', line 35

def selection_range
  from = [@text_input.selection_start, caret_position].min
  to = [@text_input.selection_start, caret_position].max

  (from...to)
end

#selection_textString

Returns the text within the selection.



45
46
47
# File 'lib/fidgit/elements/text_area.rb', line 45

def selection_text
  text[selection_range]
end

#textString

Text within the element.



28
29
30
# File 'lib/fidgit/elements/text_area.rb', line 28

def text
  @text_input.text.force_encoding 'UTF-8'
end

#text=(text) ⇒ String

Sets caret to the end of the text.



71
72
73
74
75
76
# File 'lib/fidgit/elements/text_area.rb', line 71

def text=(text)
  @text_input.text = text
  recalc # This may roll back the text if it is too long.

  publish :changed, self.text
  self.text
end