class MiniGL::TextField
This class represents a text field (input).
Attributes
Whether the text field is focused (accepting input)
The current ‘locale’ used for detecting the keys. THIS FEATURE IS INCOMPLETE!
Public Class Methods
Creates a new text field.
Parameters:
- x
-
The x-coordinate where the text field will be drawn in the screen.
- y
-
The y-coordinate where the text field will be drawn in the screen.
- font
-
The
Gosu::Font
object that will be used to draw the text inside the field. - img
-
The image of the text field. For a good result, you would likely want something like a rectangle, horizontally wide, vertically short, and with a color that contrasts with the
text_color
. - cursor_img
-
An image for the blinking cursor that stands in the point where text will be inserted. If
nil
, a simple black line will be drawn instead. - disabled_img
-
Image for the text field when it’s disabled. If
nil
, a darkened version ofimg
will be used. - text_color
-
Color of the button text, in hexadecimal RRGGBB format.
- margin_x
-
The x offset, from the field x-coordinate, to draw the text.
- margin_y
-
The y offset, from the field y-coordinate, to draw the text.
- max_length
-
The maximum length of the text inside the field.
- focused
-
Whether the text field must be focused by default. If
false
, focus can be granted by clicking inside the text field or by calling thefocus
method. - text
-
The starting text. Must not be
nil
. - allowed_chars
-
A string containing all characters that can be typed inside the text field. The complete set of supported characters is given by the string
"abcdefghijklmnopqrstuvwxyz1234567890 ABCDEFGHIJKLMNOPQRSTUVWXYZ'-=/[]\\,.;\"_+?{}|<>:!@#$%¨&*()"
. - text_color
-
The color with which the text will be drawn, in hexadecimal RRGGBB format.
- disabled_text_color
-
The color with which the text will be drawn, when the text field is disabled, in hexadecimal RRGGBB format.
- selection_color
-
The color of the rectangle highlighting selected text, in hexadecimal RRGGBB format. The rectangle will always be drawn with 50% of opacity.
- locale
-
The locale to be used when detecting keys. By now, only ‘en-US’ and ‘pt-BR’ are partially supported. Default is ‘en-US’. If any different value is supplied, all typed characters will be mapped to ‘#’.
- params
-
An object containing any parameters you want passed to the
on_text_changed
block. When the text of the text field is changed, the following is called:@on_text_changed.call @text, @params
Thus,
params
will be the second parameter. Note that this doesn’t force you to declare a block that takes parameters. - retro
-
Whether the images should be loaded with the ‘retro’ option set (see
Gosu::Image
for details). If the value is omitted, theRes.retro_images
value will be used. - scale_x
-
Horizontal scale to draw the component with.
- scale_y
-
Vertical scale to draw the component with.
- anchor
-
See parameter with the same name in
Panel#initialize
for details. - on_text_changed
-
The block of code executed when the text in the text field is changed, either by user input or by calling
text=
. The new text is passed as a first parameter to this block, followed byparams
. Can benil
.
Obs.: This method accepts named parameters, but x
, y
, font
and img
are mandatory.
# File lib/minigl/forms.rb, line 630 def initialize(x, y = nil, font = nil, img = nil, cursor_img = nil, disabled_img = nil, margin_x = 0, margin_y = 0, max_length = 100, focused = false, text = '', allowed_chars = nil, text_color = 0, disabled_text_color = 0, selection_color = 0, locale = 'en-us', params = nil, retro = nil, scale_x = 1, scale_y = 1, anchor = nil, &on_text_changed) if x.is_a? Hash y = x[:y] font = x[:font] img = x[:img] cursor_img = x.fetch(:cursor_img, nil) disabled_img = x.fetch(:disabled_img, nil) margin_x = x.fetch(:margin_x, 0) margin_y = x.fetch(:margin_y, 0) max_length = x.fetch(:max_length, 100) focused = x.fetch(:focused, false) text = x.fetch(:text, '') allowed_chars = x.fetch(:allowed_chars, nil) text_color = x.fetch(:text_color, 0) disabled_text_color = x.fetch(:disabled_text_color, 0) selection_color = x.fetch(:selection_color, 0) locale = x.fetch(:locale, 'en-us') params = x.fetch(:params, nil) retro = x.fetch(:retro, nil) scale_x = x.fetch(:scale_x, 1) scale_y = x.fetch(:scale_y, 1) anchor = x.fetch(:anchor, nil) x = x[:x] end retro = Res.retro_images if retro.nil? @scale_x = scale_x @scale_y = scale_y @img = Res.img img, false, false, '.png', retro @w = @img.width * @scale_x @h = @img.height * @scale_y @anchor_offset_x = x; @anchor_offset_y = y @anchor, x, y = FormUtils.check_anchor(anchor, x, y, @w, @h) super x, y, font, text, text_color, disabled_text_color @cursor_img = Res.img(cursor_img, false, false, '.png', retro) if cursor_img @disabled_img = Res.img(disabled_img, false, false, '.png', retro) if disabled_img @max_length = max_length @focused = focused @text_x = x + margin_x * @scale_x @text_y = y + margin_y * @scale_y @selection_color = selection_color @nodes = [@text_x] send(:text=, text, false) if text @cur_node = 0 @cursor_visible = false @cursor_timer = 0 @k = [ Gosu::KbA, Gosu::KbB, Gosu::KbC, Gosu::KbD, Gosu::KbE, Gosu::KbF, Gosu::KbG, Gosu::KbH, Gosu::KbI, Gosu::KbJ, Gosu::KbK, Gosu::KbL, Gosu::KbM, Gosu::KbN, Gosu::KbO, Gosu::KbP, Gosu::KbQ, Gosu::KbR, Gosu::KbS, Gosu::KbT, Gosu::KbU, Gosu::KbV, Gosu::KbW, Gosu::KbX, Gosu::KbY, Gosu::KbZ, Gosu::Kb1, Gosu::Kb2, Gosu::Kb3, Gosu::Kb4, Gosu::Kb5, Gosu::Kb6, Gosu::Kb7, Gosu::Kb8, Gosu::Kb9, Gosu::Kb0, Gosu::KbNumpad1, Gosu::KbNumpad2, Gosu::KbNumpad3, Gosu::KbNumpad4, Gosu::KbNumpad5, Gosu::KbNumpad6, Gosu::KbNumpad7, Gosu::KbNumpad8, Gosu::KbNumpad9, Gosu::KbNumpad0, Gosu::KbSpace, Gosu::KbBackspace, Gosu::KbDelete, Gosu::KbLeft, Gosu::KbRight, Gosu::KbHome, Gosu::KbEnd, Gosu::KbLeftShift, Gosu::KbRightShift, Gosu::KbBacktick, Gosu::KbMinus, Gosu::KbEqual, Gosu::KbBracketLeft, Gosu::KbBracketRight, Gosu::KbBackslash, Gosu::KbSemicolon, Gosu::KbApostrophe, Gosu::KbComma, Gosu::KbPeriod, Gosu::KbSlash, Gosu::KbNumpadAdd, Gosu::KbNumpadSubtract, Gosu::KbNumpadMultiply, Gosu::KbNumpadDivide ] @user_allowed_chars = allowed_chars self.locale = locale @on_text_changed = on_text_changed @params = params end
Public Instance Methods
Draws the text field in the screen.
Parameters:
- alpha
-
The opacity with which the text field will be drawn. Allowed values vary between 0 (fully transparent) and 255 (fully opaque).
- z_index
-
The z-order to draw the object. Objects with larger z-orders will be drawn on top of the ones with smaller z-orders.
- color
-
Color to apply a filter to the image.
- disabled_color
-
Color to apply a filter to the image when the field is disabled.
# File lib/minigl/forms.rb, line 965 def draw(alpha = 0xff, z_index = 0, color = 0xffffff, disabled_color = 0x808080) @z_index = z_index return unless @visible color = (alpha << 24) | ((@enabled or @disabled_img) ? color : disabled_color) text_color = (alpha << 24) | (@enabled ? @text_color : @disabled_text_color) img = ((@enabled or @disabled_img.nil?) ? @img : @disabled_img) img.draw @x, @y, z_index, @scale_x, @scale_y, color @font.draw_text @text, @text_x, @text_y, z_index, @scale_x, @scale_y, text_color if @anchor1 and @anchor2 selection_color = ((alpha / 2) << 24) | @selection_color G.window.draw_quad @nodes[@anchor1], @text_y, selection_color, @nodes[@anchor2] + 1, @text_y, selection_color, @nodes[@anchor2] + 1, @text_y + @font.height * @scale_y, selection_color, @nodes[@anchor1], @text_y + @font.height * @scale_y, selection_color, z_index end if @cursor_visible if @cursor_img @cursor_img.draw @nodes[@cur_node] - (@cursor_img.width * @scale_x) / 2, @text_y, z_index, @scale_x, @scale_y else cursor_color = alpha << 24 G.window.draw_quad @nodes[@cur_node], @text_y, cursor_color, @nodes[@cur_node] + 1, @text_y, cursor_color, @nodes[@cur_node] + 1, @text_y + @font.height * @scale_y, cursor_color, @nodes[@cur_node], @text_y + @font.height * @scale_y, cursor_color, z_index end end end
Grants focus to the text field, so that it allows keyboard input.
# File lib/minigl/forms.rb, line 922 def focus @focused = true set_node_by_mouse @anchor2 = nil @double_clicked = false set_cursor_visible end
Sets the locale used by the text field to detect keys. Only ‘en-us’ and ‘pt-br’ are partially supported. If any different value is supplied, all typed characters will be mapped to ‘#’.
# File lib/minigl/forms.rb, line 897 def locale=(value) @locale = value.downcase @chars = case @locale when 'en-us' then "abcdefghijklmnopqrstuvwxyz1234567890 ABCDEFGHIJKLMNOPQRSTUVWXYZ`-=[]\\;',./~_+{}|:\"<>?!@#$%^&*()+-*/" when 'pt-br' then "abcdefghijklmnopqrstuvwxyz1234567890 ABCDEFGHIJKLMNOPQRSTUVWXYZ'-=/[]ç~,.;\"_+?{}Ç^<>:!@#$%¨&*()+-*/" else '###################################################################################################' end @allowed_chars = if @user_allowed_chars @user_allowed_chars else @chars end end
Returns the currently selected text.
# File lib/minigl/forms.rb, line 914 def selected_text return '' if @anchor2.nil? min = @anchor1 < @anchor2 ? @anchor1 : @anchor2 max = min == @anchor1 ? @anchor2 : @anchor1 @text[min..max] end
Sets the position of the text field in the screen.
Parameters:
- x
-
The new x-coordinate for the text field.
- y
-
The new y-coordinate for the text field.
# File lib/minigl/forms.rb, line 944 def set_position(x, y) d_x = x - @x d_y = y - @y @x = x; @y = y @text_x += d_x @text_y += d_y @nodes.map! do |n| n + d_x end end
Sets the text of the text field to the specified value.
Parameters:
- value
-
The new text to be set. If it’s longer than the
max_length
parameter used in the constructor, it will be truncated tomax_length
characters.
# File lib/minigl/forms.rb, line 879 def text=(value, trigger_changed = true) @text = value[0...@max_length] @nodes.clear; @nodes << @text_x x = @nodes[0] @text.chars.each { |char| x += @font.text_width(char) * @scale_x @nodes << x } @cur_node = @nodes.size - 1 @anchor1 = nil @anchor2 = nil set_cursor_visible @on_text_changed.call @text, @params if trigger_changed && @on_text_changed end
Removes focus from the text field, so that no keyboard input will be accepted.
# File lib/minigl/forms.rb, line 932 def unfocus @anchor1 = @anchor2 = nil @cursor_visible = false @cursor_timer = 0 @focused = false end
Updates the text field, checking for mouse events and keyboard input.
# File lib/minigl/forms.rb, line 710 def update return unless @enabled and @visible ################################ Mouse ################################ if Mouse.over? @x, @y, @w, @h if not @focused and Mouse.button_pressed? :left Mouse.add_click(@z_index || 0, method(:focus)) end elsif Mouse.button_pressed? :left unfocus end return unless @focused if Mouse.double_click? :left if @nodes.size > 1 @anchor1 = 0 @anchor2 = @nodes.size - 1 @cur_node = @anchor2 @double_clicked = true end set_cursor_visible elsif Mouse.button_pressed? :left Mouse.add_click(@z_index || 0, method(:focus_and_set_anchor)) elsif Mouse.button_down? :left if @anchor1 and not @double_clicked set_node_by_mouse if @cur_node != @anchor1; @anchor2 = @cur_node else; @anchor2 = nil; end set_cursor_visible end elsif Mouse.button_released? :left if @anchor1 and not @double_clicked if @cur_node != @anchor1; @anchor2 = @cur_node else; @anchor1 = nil; end end end @cursor_timer += 1 if @cursor_timer >= 30 @cursor_visible = (not @cursor_visible) @cursor_timer = 0 end ############################### Keyboard ############################## shift = (KB.key_down?(@k[53]) or KB.key_down?(@k[54])) if KB.key_pressed?(@k[53]) or KB.key_pressed?(@k[54]) # shift @anchor1 = @cur_node if @anchor1.nil? elsif KB.key_released?(@k[53]) or KB.key_released?(@k[54]) @anchor1 = nil if @anchor2.nil? end inserted = false for i in 0..46 # alnum if KB.key_pressed?(@k[i]) or KB.key_held?(@k[i]) remove_interval true if @anchor1 and @anchor2 if i < 26 if shift insert_char @chars[i + 37] else insert_char @chars[i] end elsif i < 36 if shift; insert_char @chars[i + 59] else; insert_char @chars[i]; end elsif shift insert_char(@chars[i + 49]) else insert_char(@chars[i - 10]) end inserted = true break end end return if inserted for i in 55..65 # special if KB.key_pressed?(@k[i]) or KB.key_held?(@k[i]) remove_interval true if @anchor1 and @anchor2 if shift; insert_char @chars[i + 19] else; insert_char @chars[i + 8]; end inserted = true break end end return if inserted for i in 66..69 # numpad operators if KB.key_pressed?(@k[i]) or KB.key_held?(@k[i]) remove_interval true if @anchor1 and @anchor2 insert_char @chars[i + 19] inserted = true break end end return if inserted if KB.key_pressed?(@k[47]) or KB.key_held?(@k[47]) # back if @anchor1 and @anchor2 remove_interval elsif @cur_node > 0 remove_char true end elsif KB.key_pressed?(@k[48]) or KB.key_held?(@k[48]) # del if @anchor1 and @anchor2 remove_interval elsif @cur_node < @nodes.size - 1 remove_char false end elsif KB.key_pressed?(@k[49]) or KB.key_held?(@k[49]) # left if @anchor1 if shift if @cur_node > 0 @cur_node -= 1 @anchor2 = @cur_node set_cursor_visible end elsif @anchor2 @cur_node = @anchor1 < @anchor2 ? @anchor1 : @anchor2 @anchor1 = nil @anchor2 = nil set_cursor_visible end elsif @cur_node > 0 @cur_node -= 1 set_cursor_visible end elsif KB.key_pressed?(@k[50]) or KB.key_held?(@k[50]) # right if @anchor1 if shift if @cur_node < @nodes.size - 1 @cur_node += 1 @anchor2 = @cur_node set_cursor_visible end elsif @anchor2 @cur_node = @anchor1 > @anchor2 ? @anchor1 : @anchor2 @anchor1 = nil @anchor2 = nil set_cursor_visible end elsif @cur_node < @nodes.size - 1 @cur_node += 1 set_cursor_visible end elsif KB.key_pressed?(@k[51]) # home @cur_node = 0 if shift; @anchor2 = @cur_node else @anchor1 = nil @anchor2 = nil end set_cursor_visible elsif KB.key_pressed?(@k[52]) # end @cur_node = @nodes.size - 1 if shift; @anchor2 = @cur_node else @anchor1 = nil @anchor2 = nil end set_cursor_visible end end
Private Instance Methods
# File lib/minigl/forms.rb, line 1008 def focus_and_set_anchor focus @anchor1 = @cur_node end
# File lib/minigl/forms.rb, line 1033 def insert_char(char) return unless @allowed_chars.index char and @text.length < @max_length @text.insert @cur_node, char @nodes.insert @cur_node + 1, @nodes[@cur_node] + @font.text_width(char) * @scale_x for i in (@cur_node + 2)..(@nodes.size - 1) @nodes[i] += @font.text_width(char) * @scale_x end @cur_node += 1 set_cursor_visible @on_text_changed.call @text, @params if @on_text_changed end
# File lib/minigl/forms.rb, line 1064 def remove_char(back) @cur_node -= 1 if back char_width = @font.text_width(@text[@cur_node]) * @scale_x @text[@cur_node] = '' @nodes.delete_at @cur_node + 1 for i in (@cur_node + 1)..(@nodes.size - 1) @nodes[i] -= char_width end set_cursor_visible @on_text_changed.call @text, @params if @on_text_changed end
# File lib/minigl/forms.rb, line 1045 def remove_interval(will_insert = false) min = @anchor1 < @anchor2 ? @anchor1 : @anchor2 max = min == @anchor1 ? @anchor2 : @anchor1 interval_width = 0 for i in min...max interval_width += @font.text_width(@text[i]) * @scale_x @nodes.delete_at min + 1 end @text[min...max] = '' for i in (min + 1)..(@nodes.size - 1) @nodes[i] -= interval_width end @cur_node = min @anchor1 = nil @anchor2 = nil set_cursor_visible @on_text_changed.call @text, @params if @on_text_changed and not will_insert end
# File lib/minigl/forms.rb, line 1013 def set_cursor_visible @cursor_visible = true @cursor_timer = 0 end
# File lib/minigl/forms.rb, line 1018 def set_node_by_mouse index = @nodes.size - 1 @nodes.each_with_index do |n, i| if n >= Mouse.x index = i break end end if index > 0 d1 = @nodes[index] - Mouse.x; d2 = Mouse.x - @nodes[index - 1] index -= 1 if d1 > d2 end @cur_node = index end