mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-06 06:01:46 +00:00
214 lines
7.5 KiB
Ruby
214 lines
7.5 KiB
Ruby
#===============================================================================
|
|
# Also known as a Combo Box.
|
|
# NOTE: This control lets you type in whatever text you want. The dropdown list
|
|
# only offers autocomplete-like suggestions, but you don't need to match
|
|
# any of them.
|
|
#===============================================================================
|
|
class UIControls::TextBoxDropdownList < UIControls::TextBox
|
|
attr_accessor :max_rows
|
|
|
|
TEXT_BOX_WIDTH = 200 - TEXT_BOX_HEIGHT
|
|
BUTTON_X = TEXT_BOX_X + TEXT_BOX_WIDTH
|
|
BUTTON_WIDTH = TEXT_BOX_HEIGHT
|
|
BUTTON_HEIGHT = TEXT_BOX_HEIGHT
|
|
MAX_LIST_ROWS = 8
|
|
|
|
def initialize(width, height, viewport, options, value = "")
|
|
super(width, height, viewport, value)
|
|
@box_width = TEXT_BOX_WIDTH
|
|
@options = options
|
|
@toggling_dropdown_list = false
|
|
@max_rows = MAX_LIST_ROWS
|
|
end
|
|
|
|
def dispose
|
|
remove_dropdown_menu
|
|
super
|
|
end
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
def values=(new_vals)
|
|
@options = new_vals
|
|
@dropdown_menu.values = @options if @dropdown_menu
|
|
end
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
def busy?
|
|
return true if @dropdown_menu || @toggling_dropdown_list
|
|
return super
|
|
end
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
def set_interactive_rects
|
|
@text_box_rect = Rect.new(TEXT_BOX_X, (height - TEXT_BOX_HEIGHT) / 2,
|
|
[@box_width, width - (TEXT_BOX_X * 2) - BUTTON_WIDTH].min, TEXT_BOX_HEIGHT)
|
|
@button_rect = Rect.new(BUTTON_X, @text_box_rect.y, BUTTON_WIDTH, BUTTON_HEIGHT)
|
|
@interactions = {
|
|
:text_box => @text_box_rect,
|
|
:button => @button_rect
|
|
}
|
|
end
|
|
|
|
def make_dropdown_menu
|
|
menu_height = (UIControls::List::ROW_HEIGHT * [@options.length, @max_rows].min) + (UIControls::List::BORDER_THICKNESS * 2)
|
|
# Draw menu's background
|
|
@dropdown_menu_bg = BitmapSprite.new(@text_box_rect.width + @button_rect.width, menu_height, self.viewport)
|
|
@dropdown_menu_bg.x = self.x + @text_box_rect.x
|
|
@dropdown_menu_bg.y = self.y + @text_box_rect.y + @text_box_rect.height
|
|
@dropdown_menu_bg.z = self.z + 1
|
|
@dropdown_menu_bg.bitmap.fill_rect(0, 0, @dropdown_menu_bg.width, @dropdown_menu_bg.height, background_color)
|
|
# Create menu
|
|
@dropdown_menu = UIControls::List.new(@text_box_rect.width + @button_rect.width, menu_height, self.viewport, @options)
|
|
@dropdown_menu.x = @dropdown_menu_bg.x
|
|
@dropdown_menu.y = @dropdown_menu_bg.y
|
|
@dropdown_menu.z = self.z + 2
|
|
@dropdown_menu.color_scheme = @color_scheme
|
|
@dropdown_menu.set_interactive_rects
|
|
@dropdown_menu.repaint
|
|
end
|
|
|
|
def remove_dropdown_menu
|
|
@dropdown_menu_bg&.dispose
|
|
@dropdown_menu_bg = nil
|
|
@dropdown_menu&.dispose
|
|
@dropdown_menu = nil
|
|
@captured_area = nil
|
|
@applied_filter = false
|
|
end
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
def draw_area_highlight
|
|
highlight_color = nil
|
|
if @captured_area == :text_box && !@hover_area && Input.press?(Input::MOUSELEFT)
|
|
highlight_color = capture_color
|
|
elsif !@captured_area && [:text_box, :button].include?(@hover_area)
|
|
# Draw mouse hover over area highlight
|
|
highlight_color = hover_color
|
|
end
|
|
return if !highlight_color
|
|
[:text_box, :button].each do |area|
|
|
rect = @interactions[area]
|
|
self.bitmap.fill_rect(rect.x, rect.y, rect.width, rect.height, highlight_color) if rect
|
|
end
|
|
end
|
|
|
|
def refresh
|
|
@dropdown_menu&.refresh
|
|
super
|
|
# Draw disabled colour in button
|
|
if disabled?
|
|
self.bitmap.fill_rect(@button_rect.x, @button_rect.y,
|
|
@button_rect.width, @button_rect.height,
|
|
disabled_fill_color)
|
|
end
|
|
# Draw button outline
|
|
self.bitmap.outline_rect(@button_rect.x, @button_rect.y,
|
|
@button_rect.width, @button_rect.height,
|
|
line_color)
|
|
# Draw down arrow
|
|
arrow_area_x = @button_rect.x + @button_rect.width - @button_rect.height + 1
|
|
arrow_area_width = @button_rect.height - 2
|
|
arrow_color = (disabled?) ? disabled_text_color : text_color
|
|
# self.bitmap.fill_rect(arrow_area_x, @button_rect.y + 1, arrow_area_width, arrow_area_width,
|
|
# (@hover_area && @captured_area != :button) ? hover_color : background_color)
|
|
6.times do |i|
|
|
self.bitmap.fill_rect(arrow_area_x + (arrow_area_width / 2) - 5 + i,
|
|
@button_rect.y + (arrow_area_width / 2) - 1 + i,
|
|
11 - (2 * i), 1, arrow_color)
|
|
end
|
|
end
|
|
|
|
#-----------------------------------------------------------------------------
|
|
|
|
def on_mouse_press
|
|
mouse_x, mouse_y = mouse_pos
|
|
return if !mouse_x || !mouse_y
|
|
if @dropdown_menu
|
|
if @text_box_rect.contains?(mouse_x, mouse_y)
|
|
# Clicked into the text box; put the text cursor in there
|
|
@captured_area = :text_box
|
|
@cursor_pos = get_cursor_index_from_mouse_position
|
|
@cursor_timer = System.uptime
|
|
invalidate
|
|
elsif !@dropdown_menu.mouse_in_control?
|
|
@value.strip! if @value.respond_to?("strip!")
|
|
@value = @initial_value.dup if disabled?
|
|
set_changed if @initial_value && @value != @initial_value
|
|
reset_interaction
|
|
remove_dropdown_menu
|
|
@toggling_dropdown_list = true
|
|
end
|
|
else
|
|
@captured_area = nil
|
|
super
|
|
if @captured_area
|
|
make_dropdown_menu
|
|
@toggling_dropdown_list = true
|
|
end
|
|
end
|
|
end
|
|
|
|
def on_mouse_release
|
|
return if !@captured_area && !@dropdown_menu && !@toggling_dropdown_list
|
|
if @toggling_dropdown_list
|
|
@toggling_dropdown_list = false
|
|
mouse_x, mouse_y = mouse_pos
|
|
if mouse_x && mouse_y && @interactions[:text_box].contains?(mouse_x, mouse_y)
|
|
@initial_value = @value.dup
|
|
Input.text_input = true
|
|
invalidate
|
|
end
|
|
return
|
|
end
|
|
if @dropdown_menu
|
|
if @dropdown_menu.changed?
|
|
new_val = @dropdown_menu.value
|
|
new_val = @options[new_val] if new_val.is_a?(Integer)
|
|
if new_val && new_val != @value
|
|
self.value = new_val
|
|
set_changed
|
|
end
|
|
@value.strip! if @value.respond_to?("strip!")
|
|
reset_interaction
|
|
remove_dropdown_menu
|
|
@captured_area = nil
|
|
elsif @captured_area
|
|
mouse_x, mouse_y = mouse_pos
|
|
if mouse_x && mouse_y && @interactions[:text_box].contains?(mouse_x, mouse_y)
|
|
@captured_area = :text_box
|
|
@initial_value = @value.dup
|
|
Input.text_input = true
|
|
end
|
|
elsif !mouse_in_control? && !@dropdown_menu.mouse_in_control?
|
|
@value.strip! if @value.respond_to?("strip!")
|
|
self.value = @initial_value if disabled?
|
|
set_changed if @initial_value && @value != @initial_value
|
|
reset_interaction
|
|
remove_dropdown_menu
|
|
@captured_area = nil
|
|
end
|
|
else
|
|
super
|
|
end
|
|
invalidate
|
|
end
|
|
|
|
def update
|
|
@dropdown_menu&.update
|
|
@dropdown_menu&.repaint
|
|
super
|
|
# Filter the dropdown menu options based on @value if it changes
|
|
if @dropdown_menu && @initial_value && (@applied_filter || @value != @initial_value)
|
|
filtered_options = @options.select do |key, val|
|
|
key.downcase.include?(@value.downcase) || val.downcase.include?(@value.downcase)
|
|
end
|
|
@dropdown_menu.values = filtered_options
|
|
@applied_filter = true
|
|
end
|
|
end
|
|
end
|