Files
infinitefusion-e18/Data/Scripts/801_UI controls/Control elements/010_DropdownList.rb
2024-04-04 22:39:01 +01:00

153 lines
4.6 KiB
Ruby

#===============================================================================
#
#===============================================================================
class UIControls::DropdownList < UIControls::BaseControl
attr_accessor :box_width
attr_accessor :max_rows
TEXT_BOX_X = 2
TEXT_BOX_WIDTH = 200
TEXT_BOX_HEIGHT = 24
TEXT_BOX_PADDING = 4 # Gap between sides of text box and text
MAX_LIST_ROWS = 10
# NOTE: options is a hash: keys are symbols, values are display names.
def initialize(width, height, viewport, options, value)
super(width, height, viewport)
@options = options
@value = value
@box_width = TEXT_BOX_WIDTH
@toggling_dropdown_list = false
@max_rows = MAX_LIST_ROWS
end
def dispose
remove_dropdown_menu
super
end
def value=(new_value)
return if @value == new_value
@value = new_value
invalidate
end
def values=(new_vals)
@options = new_vals
@dropdown_menu.values = @options if @dropdown_menu
end
def set_interactive_rects
@button_rect = Rect.new(TEXT_BOX_X, (height - TEXT_BOX_HEIGHT) / 2,
[@box_width, width - (TEXT_BOX_X * 2)].min, TEXT_BOX_HEIGHT)
@interactions = {
:button => @button_rect
}
end
#-----------------------------------------------------------------------------
def busy?
return true if @dropdown_menu || @toggling_dropdown_list
return super
end
#-----------------------------------------------------------------------------
def make_dropdown_menu
menu_height = (UIControls::List::ROW_HEIGHT * [@options.length, @max_rows].min) + (UIControls::List::BORDER_THICKNESS * 2)
@dropdown_menu = UIControls::List.new(@button_rect.width, menu_height, self.viewport, @options)
@dropdown_menu.x = self.x + @button_rect.x
@dropdown_menu.y = self.y + @button_rect.y + @button_rect.height
@dropdown_menu.z = self.z + 2
@dropdown_menu.set_interactive_rects
@dropdown_menu.repaint
end
def remove_dropdown_menu
@dropdown_menu&.dispose
@dropdown_menu = nil
@captured_area = nil
end
#-----------------------------------------------------------------------------
def draw_area_highlight
return if @captured_area == :button
super
end
def refresh
@dropdown_menu&.refresh
super
# Draw disabled colour
if disabled?
self.bitmap.fill_rect(@button_rect.x, @button_rect.y,
@button_rect.width, @button_rect.height,
DISABLED_COLOR)
end
# Draw button outline
self.bitmap.outline_rect(@button_rect.x, @button_rect.y,
@button_rect.width, @button_rect.height,
self.bitmap.font.color)
# Draw value
draw_text(self.bitmap, @button_rect.x + TEXT_BOX_PADDING, TEXT_OFFSET_Y, @options[@value] || "???")
# Draw down arrow
arrow_area_x = @button_rect.x + @button_rect.width - @button_rect.height + 1
arrow_area_width = @button_rect.height - 2
self.bitmap.fill_rect(arrow_area_x, @button_rect.y + 1, arrow_area_width, arrow_area_width,
(@hover_area && @captured_area != :button) ? HOVER_COLOR : Color.white)
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, (disabled?) ? DISABLED_COLOR_DARK : self.bitmap.font.color)
end
end
#-----------------------------------------------------------------------------
def on_mouse_press
if @dropdown_menu
if !@dropdown_menu.mouse_in_control?
remove_dropdown_menu
@toggling_dropdown_list = true
end
else
@captured_area = nil
super
if @captured_area == :button
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
return
end
if @dropdown_menu
if @dropdown_menu.changed?
new_val = @dropdown_menu.value
if new_val && new_val != @value
@value = new_val
set_changed
end
remove_dropdown_menu
super # Make this control not busy again
elsif !@dropdown_menu.mouse_in_control?
remove_dropdown_menu
super # Make this control not busy again
end
end
end
def update
@dropdown_menu&.update
@dropdown_menu&.repaint
super
end
end