mirror of
https://github.com/cyberarm/cyberarm_engine.git
synced 2025-12-16 05:02:34 +00:00
298 lines
7.6 KiB
Ruby
298 lines
7.6 KiB
Ruby
module CyberarmEngine
|
|
class Element
|
|
class EditLine < Button
|
|
class TextInput < Gosu::TextInput
|
|
def filter=(filter)
|
|
@filter = filter
|
|
end
|
|
|
|
def filter(text_in)
|
|
if @filter
|
|
@filter.call(text_in)
|
|
else
|
|
text_in
|
|
end
|
|
end
|
|
end
|
|
|
|
def initialize(text, options = {}, block = nil)
|
|
@filter = options.delete(:filter)
|
|
super(text, options, block)
|
|
|
|
@type = default(:type)
|
|
|
|
@caret_width = default(:caret_width)
|
|
@caret_height = @text.textobject.height
|
|
@caret_color = default(:caret_color)
|
|
@caret_interval = default(:caret_interval)
|
|
@caret_last_interval = Gosu.milliseconds
|
|
@show_caret = true
|
|
|
|
@text_input = TextInput.new
|
|
@text_input.filter = @filter
|
|
@text_input.text = text
|
|
@last_text_value = text
|
|
@last_caret_position = @text_input.caret_pos
|
|
|
|
@offset_x = 0
|
|
@offset_y = 0
|
|
|
|
event(:begin_drag)
|
|
event(:drag_update)
|
|
event(:end_drag)
|
|
end
|
|
|
|
def render
|
|
Gosu.clip_to(@text.x, @text.y, @width, @height) do
|
|
Gosu.translate(-@offset_x, -@offset_y) do
|
|
draw_selection
|
|
draw_caret if @focus && @show_caret
|
|
draw_text
|
|
end
|
|
end
|
|
end
|
|
|
|
def draw_text
|
|
@text.draw(:draw_text)
|
|
end
|
|
|
|
def draw_caret
|
|
Gosu.draw_rect(caret_position, @text.y, @caret_width, @caret_height, @caret_color, @z)
|
|
end
|
|
|
|
def draw_selection
|
|
selection_width = caret_position - selection_start_position
|
|
|
|
Gosu.draw_rect(selection_start_position, @text.y, selection_width, @text.height, default(:selection_color), @z)
|
|
end
|
|
|
|
def update
|
|
@style_event = :active if @focus
|
|
|
|
@text.text = if @type == :password
|
|
default(:password_character) * @text_input.text.length
|
|
else
|
|
@text_input.text
|
|
end
|
|
|
|
if @last_text_value != value
|
|
@last_text_value = value
|
|
@show_caret = true
|
|
@caret_last_interval = Gosu.milliseconds
|
|
|
|
root.gui_state.request_repaint
|
|
|
|
publish(:changed, value)
|
|
end
|
|
|
|
if @last_caret_position != @text_input.caret_pos
|
|
@last_caret_position = @text_input.caret_pos
|
|
root.gui_state.request_repaint
|
|
|
|
@show_caret = true
|
|
@caret_last_interval = Gosu.milliseconds
|
|
end
|
|
|
|
if Gosu.milliseconds >= @caret_last_interval + @caret_interval
|
|
root.gui_state.request_repaint
|
|
|
|
@caret_last_interval = Gosu.milliseconds
|
|
|
|
@show_caret = !@show_caret
|
|
end
|
|
|
|
keep_caret_visible
|
|
end
|
|
|
|
def button_down(id)
|
|
handle_keyboard_shortcuts(id)
|
|
end
|
|
|
|
def handle_keyboard_shortcuts(id)
|
|
return unless @focus && @enabled
|
|
|
|
if Gosu.button_down?(Gosu::KB_LEFT_CONTROL) || Gosu.button_down?(Gosu::KB_RIGHT_CONTROL)
|
|
case id
|
|
when Gosu::KB_A
|
|
@text_input.selection_start = 0
|
|
@text_input.caret_pos = @text_input.text.length
|
|
|
|
when Gosu::KB_C
|
|
Gosu.clipboard = if @text_input.selection_start < @text_input.caret_pos
|
|
@text_input.text[@text_input.selection_start...@text_input.caret_pos]
|
|
else
|
|
@text_input.text[@text_input.caret_pos...@text_input.selection_start]
|
|
end
|
|
|
|
when Gosu::KB_X
|
|
chars = @text_input.text.chars
|
|
|
|
if @text_input.selection_start < @text_input.caret_pos
|
|
Gosu.clipboard = @text_input.text[@text_input.selection_start...@text_input.caret_pos]
|
|
chars.slice!(@text_input.selection_start, @text_input.caret_pos)
|
|
else
|
|
Gosu.clipboard = @text_input.text[@text_input.caret_pos...@text_input.selection_start]
|
|
chars.slice!(@text_input.caret_pos, @text_input.selection_start)
|
|
end
|
|
|
|
@text_input.text = chars.join
|
|
|
|
when Gosu::KB_V
|
|
if instance_of?(EditLine) # EditLine assumes a single line of text
|
|
@text_input.insert_text(Gosu.clipboard.gsub("\n", ""))
|
|
else
|
|
@text_input.insert_text(Gosu.clipboard)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def caret_position_under_mouse(mouse_x)
|
|
1.upto(@text.text.length) do |i|
|
|
return i - 1 if mouse_x < @text.x - @offset_x + @text.width(@text.text[0...i])
|
|
end
|
|
|
|
@text_input.text.length
|
|
end
|
|
|
|
def move_caret_to_mouse(mouse_x, _mouse_y)
|
|
@text_input.caret_pos = @text_input.selection_start = caret_position_under_mouse(mouse_x)
|
|
end
|
|
|
|
def keep_caret_visible
|
|
caret_pos = (caret_position - @text.x) + @caret_width
|
|
|
|
@last_text ||= "/\\"
|
|
@last_pos ||= -1
|
|
|
|
@last_text = @text.text
|
|
@last_pos = caret_pos
|
|
|
|
if caret_pos.between?(@offset_x, @width + @offset_x)
|
|
# Do nothing
|
|
|
|
elsif caret_pos < @offset_x
|
|
@offset_x = if caret_pos > @width
|
|
caret_pos + @width
|
|
else
|
|
0
|
|
end
|
|
|
|
elsif caret_pos > @width
|
|
@offset_x = caret_pos - @width
|
|
|
|
else
|
|
# Reset to Zero
|
|
@offset_x = 0
|
|
end
|
|
end
|
|
|
|
def caret_position
|
|
text_input_position_for(:caret_pos)
|
|
end
|
|
|
|
def selection_start_position
|
|
text_input_position_for(:selection_start)
|
|
end
|
|
|
|
def text_input_position_for(method)
|
|
if @type == :password
|
|
@text.x + @text.width(default(:password_character) * @text_input.text[0...@text_input.send(method)].length)
|
|
else
|
|
@text.x + @text.width(@text_input.text[0...@text_input.send(method)]) - @style.border_thickness_left
|
|
end
|
|
end
|
|
|
|
def left_mouse_button(sender, x, y)
|
|
super
|
|
window.text_input = @text_input
|
|
|
|
@caret_last_interval = Gosu.milliseconds
|
|
@show_caret = true
|
|
|
|
move_caret_to_mouse(x, y)
|
|
|
|
:handled
|
|
end
|
|
|
|
def focus(sender)
|
|
@focus = true
|
|
window.text_input = @text_input
|
|
@text_input.caret_pos = @text_input.selection_start = @text_input.text.length
|
|
|
|
update_styles(:active)
|
|
|
|
:handled
|
|
end
|
|
|
|
def enter(sender)
|
|
if @enabled && @focus
|
|
update_styles(:active)
|
|
elsif @enabled && !@focus
|
|
update_styles(:hover)
|
|
else
|
|
update_styles(:disabled)
|
|
end
|
|
|
|
:handled
|
|
end
|
|
|
|
def leave(sender)
|
|
if @enabled && @focus
|
|
update_styles(:active)
|
|
elsif @enabled && !@focus
|
|
update_styles
|
|
else
|
|
update_styles(:disabled)
|
|
end
|
|
|
|
:handled
|
|
end
|
|
|
|
def blur(_sender)
|
|
super
|
|
window.text_input = nil
|
|
|
|
:handled
|
|
end
|
|
|
|
def draggable?(button)
|
|
button == :left
|
|
end
|
|
|
|
def begin_drag(_sender, x, _y, _button)
|
|
@drag_start = x
|
|
@offset_drag_start = @offset_x
|
|
@drag_caret_position = @text_input.caret_pos
|
|
|
|
:handled
|
|
end
|
|
|
|
def drag_update(_sender, x, _y, _button)
|
|
@text_input.caret_pos = caret_position_under_mouse(x)
|
|
|
|
:handled
|
|
end
|
|
|
|
def end_drag(_sender, _x, _y, _button)
|
|
:handled
|
|
end
|
|
|
|
def layout
|
|
super
|
|
|
|
@width = dimensional_size(@style.width, :width) || default(:width)
|
|
update_background
|
|
end
|
|
|
|
def value
|
|
@text_input.text
|
|
end
|
|
|
|
def value=(string)
|
|
@text_input.text = string
|
|
end
|
|
end
|
|
end
|
|
end
|