Class: CyberarmEngine::Element::EditBox

Inherits:
EditLine show all
Defined in:
lib/cyberarm_engine/ui/elements/edit_box.rb

Constant Summary

Constants included from Theme

Theme::THEME

Instance Attribute Summary

Attributes inherited from CyberarmEngine::Element

#background_canvas, #border_canvas, #element_visible, #event_handler, #options, #parent, #style, #tip, #x, #y, #z

Instance Method Summary collapse

Methods inherited from EditLine

#begin_drag, #blur, #caret_position, #draggable?, #draw_text, #end_drag, #enter, #focus, #handle_keyboard_shortcuts, #keep_caret_visible, #layout, #leave, #left_mouse_button, #render, #selection_start_position, #value, #value=

Methods inherited from Button

#draw_image, #draw_text, #layout, #render, #value, #value=

Methods inherited from TextBlock

#handle_text_wrapping, #layout, #line_width, #render, #value, #value=

Methods inherited from CyberarmEngine::Element

#background=, #background_image=, #background_nine_slice=, #blur, #child_of?, #clicked_left_mouse_button, #content_height, #content_width, #debug_draw, #default_events, #dimensional_size, #draggable?, #draw, #element_visible?, #enabled=, #enabled?, #enter, #focus, #focused?, #height, #hide, #hit?, #inner_height, #inner_width, #inspect, #is_root?, #layout, #leave, #left_mouse_button, #max_scroll_height, #max_scroll_width, #noncontent_height, #noncontent_width, #outer_height, #outer_width, #parent_of?, #recalculate, #recalculate_if_size_changed, #released_left_mouse_button, #render, #reposition, #root, #safe_style_fetch, #scroll_height, #scroll_width, #set_background, #set_background_image, #set_background_nine_slice, #set_border_color, #set_border_thickness, #set_color, #set_font, #set_margin, #set_padding, #set_static_position, #show, #space_available_height, #space_available_width, #stylize, #to_s, #toggle, #update_background, #update_background_image, #update_background_nine_slice, #update_styles, #value, #value=, #visible?, #width

Methods included from Common

#alt_down?, #control_down?, #current_state, #darken, #draw_rect, #fill, #find_element_by_tag, #get_asset, #get_image, #get_sample, #get_song, #lighten, #opacity, #pop_state, #previous_state, #push_state, #shift_down?, #shift_state, #show_cursor, #show_cursor=, #window

Methods included from CyberarmEngine::Event

#event, #publish, #subscribe, #unsubscribe

Methods included from Theme

#deep_merge, #default, #theme_defaults

Constructor Details

#initialize(*args) ⇒ EditBox

Returns a new instance of EditBox.



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/cyberarm_engine/ui/elements/edit_box.rb', line 4

def initialize(*args)
  super(*args)

  @active_line = 0

  @repeatable_keys = [
    {
      key: Gosu::KB_UP,
      down: false,
      repeat_delay: 50,
      last_repeat: 0,
      action: proc { move(:up) }
    },
    {
      key: Gosu::KB_DOWN,
      down: false,
      repeat_delay: 50,
      last_repeat: 0,
      action: proc { move(:down) }
    }
  ]
end

Instance Method Details

#button_down(id) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/cyberarm_engine/ui/elements/edit_box.rb', line 123

def button_down(id)
  super

  @repeatable_keys.detect do |key|
    next unless key[:key] == id

    key[:down] = true
    key[:last_repeat] = Gosu.milliseconds + key[:repeat_delay]
    return true
  end

  case id
  when Gosu::KB_ENTER, Gosu::KB_RETURN
    caret_pos = @text_input.caret_pos
    @text_input.text = @text_input.text.insert(@text_input.caret_pos, "\n")
    @text_input.caret_pos = @text_input.selection_start = caret_pos + 1
  end
end

#button_up(id) ⇒ Object



142
143
144
145
146
147
148
149
150
151
# File 'lib/cyberarm_engine/ui/elements/edit_box.rb', line 142

def button_up(id)
  super

  @repeatable_keys.detect do |key|
    if key[:key] == id
      key[:down] = false
      return true
    end
  end
end

#calculate_active_lineObject



69
70
71
72
# File 'lib/cyberarm_engine/ui/elements/edit_box.rb', line 69

def calculate_active_line
  sub_text = @text_input.text[0...@text_input.caret_pos]
  @active_line = sub_text.lines.size - 1
end

#caret_position_under_mouse(mouse_x, mouse_y) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/cyberarm_engine/ui/elements/edit_box.rb', line 81

def caret_position_under_mouse(mouse_x, mouse_y)
  active_line = row_at(mouse_y)
  right_offset = column_at(mouse_x, mouse_y)

  buffer = @text_input.text.lines[0..active_line].join if active_line != 0
  buffer = @text_input.text.lines.first if active_line == 0
  line = buffer.lines.last

  if buffer.chars.last == "\n"
    (buffer.length - line.length) + right_offset - 1
  else
    (buffer.length - line.length) + right_offset
  end
end

#caret_stay_left_of_last_newlineObject



74
75
76
77
78
79
# File 'lib/cyberarm_engine/ui/elements/edit_box.rb', line 74

def caret_stay_left_of_last_newline
  @text_input.text += "\n" unless @text_input.text.end_with?("\n")

  eof = @text_input.text.chomp.length
  set_position(eof) if @text_input.caret_pos > eof
end

#column_at(x, y) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/cyberarm_engine/ui/elements/edit_box.rb', line 104

def column_at(x, y)
  row = row_at(y)

  buffer = @text_input.text.lines[0..row].join if row != 0
  buffer = @text_input.text.lines.first if row == 0

  line = @text_input.text.lines[row]
  line ||= ""
  column = 0

  line.length.times do |_i|
    break if @text.textobject.text_width(line[0...column]) >= (x - @text.x).clamp(0.0, Float::INFINITY)

    column += 1
  end

  column
end

#drag_update(_sender, x, y, _button) ⇒ Object



170
171
172
173
174
175
176
# File 'lib/cyberarm_engine/ui/elements/edit_box.rb', line 170

def drag_update(_sender, x, y, _button)
  int = caret_position_under_mouse(x, y)
  int = 0 if int < 0
  @text_input.caret_pos = int

  :handled
end

#draw_caretObject



41
42
43
44
# File 'lib/cyberarm_engine/ui/elements/edit_box.rb', line 41

def draw_caret
  Gosu.draw_rect(caret_position, @text.y + @active_line * @text.textobject.height, @caret_width, @caret_height,
                 @caret_color, @z)
end

#draw_selectionObject



46
47
48
49
50
51
# File 'lib/cyberarm_engine/ui/elements/edit_box.rb', line 46

def draw_selection
  selection_width = caret_position - selection_start_position

  Gosu.draw_rect(selection_start_position, @text.y, selection_width, @text.textobject.height,
                 default(:selection_color), @z)
end

#move(direction) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/cyberarm_engine/ui/elements/edit_box.rb', line 153

def move(direction)
  pos = @text_input.caret_pos
  line = nil

  case direction
  when :up
    return if @active_line == 0
  when :down
    return if @active_line == @text_input.text.chomp.lines

    text = @text_input.text.chomp.lines[0..@active_line].join("\n")
    pos = text.length
  end

  set_position(pos)
end

#move_caret_to_mouse(mouse_x, mouse_y) ⇒ Object



96
97
98
# File 'lib/cyberarm_engine/ui/elements/edit_box.rb', line 96

def move_caret_to_mouse(mouse_x, mouse_y)
  set_position(caret_position_under_mouse(mouse_x, mouse_y))
end

#row_at(y) ⇒ Object



100
101
102
# File 'lib/cyberarm_engine/ui/elements/edit_box.rb', line 100

def row_at(y)
  ((y - @text.y) / @text.textobject.height).floor
end

#set_position(int) ⇒ Object



64
65
66
67
# File 'lib/cyberarm_engine/ui/elements/edit_box.rb', line 64

def set_position(int)
  int = 0 if int < 0
  @text_input.selection_start = @text_input.caret_pos = int
end

#text_input_position_for(_method) ⇒ Object



53
54
55
56
57
58
59
60
61
62
# File 'lib/cyberarm_engine/ui/elements/edit_box.rb', line 53

def text_input_position_for(_method)
  line = @text_input.text[0...@text_input.caret_pos].lines.last
  _x = @text.x + @offset_x

  if @type == :password
    _x + @text.width(default(:password_character) * line.length)
  else
    _x + @text.width(line)
  end
end

#updateObject



27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/cyberarm_engine/ui/elements/edit_box.rb', line 27

def update
  super

  caret_stay_left_of_last_newline
  calculate_active_line

  @repeatable_keys.each do |key|
    if key[:down] && (Gosu.milliseconds > key[:last_repeat] + key[:repeat_delay])
      key[:action].call
      key[:last_repeat] = Gosu.milliseconds
    end
  end
end