Added header variant of Label control, makde DropdownList control

This commit is contained in:
Maruno17
2023-11-04 23:12:25 +00:00
parent 64890f3c9e
commit ab2d2c1356
12 changed files with 209 additions and 10 deletions

View File

@@ -46,6 +46,16 @@ class UIControls::BaseControl < BitmapSprite
@interactions = {}
end
def mouse_in_control?
return false if !@interactions || @interactions.empty?
mouse_x, mouse_y = mouse_pos
return false if !mouse_x || !mouse_y
@interactions.each_pair do |area, rect|
return true if rect.contains?(mouse_x, mouse_y)
end
return false
end
#-----------------------------------------------------------------------------
def invalid?

View File

@@ -10,6 +10,7 @@ class UIControls::Label < UIControls::BaseControl
def initialize(width, height, viewport, label)
super(width, height, viewport)
@label = label
@header = false
end
def label=(value)
@@ -17,8 +18,19 @@ class UIControls::Label < UIControls::BaseControl
refresh
end
def header=(val)
@header = val
refresh
end
def refresh
super
draw_text(self.bitmap, 4, TEXT_OFFSET_Y, @label)
if @header
draw_text_centered(self.bitmap, 0, TEXT_OFFSET_Y, width, @label)
text_size = self.bitmap.text_size(@label)
self.bitmap.fill_rect((width - text_size.width) / 2, TEXT_OFFSET_Y + text_size.height, text_size.width, 1, TEXT_COLOR)
else
draw_text(self.bitmap, 4, TEXT_OFFSET_Y, @label)
end
end
end

View File

@@ -4,6 +4,8 @@
# decide which characters are selected. Maybe? Note that this method
# is only triggered upon the initial mouse press, and isn't repeated
# while it's still held down.
# TODO: Add a blacklist array. Can't type in any values in this array. Disable
# this control if @value is in this array.
#===============================================================================
class UIControls::TextBox < UIControls::BaseControl
TEXT_BOX_X = 2

View File

@@ -66,7 +66,7 @@ class UIControls::Button < UIControls::BaseControl
# Change this control's value
if @captured_area == :button
mouse_x, mouse_y = mouse_pos
if mouse_x && mouse_y && @interactions[@captured_area].contains?(mouse_x, mouse_y)
if mouse_x && mouse_y && @interactions[@captured_area].contains?(mouse_x, mouse_y)
set_changed
end
end

View File

@@ -43,6 +43,11 @@ class UIControls::List < UIControls::BaseControl
@scrollbar.y = new_val + LIST_Y
end
def z=(new_val)
super(new_val)
@scrollbar.z = new_val + 1
end
# Each value in @values is an array: [id, text].
def values=(new_vals)
@values = new_vals
@@ -77,7 +82,18 @@ class UIControls::List < UIControls::BaseControl
# Returns the ID of the selected row.
def value
return nil if @selected < 0
return @values[@selected][0]
if @values.is_a?(Array)
return (@values[@selected].is_a?(Array)) ? @values[@selected][0] : @selected
elsif @values.is_a?(Hash)
return @values.keys[@selected]
end
return nil
end
def mouse_in_control?
return true if super
return true if @scrollbar.mouse_in_control?
return false
end
def set_interactive_rects
@@ -202,6 +218,17 @@ class UIControls::List < UIControls::BaseControl
# Set the selected row to the row the mouse is over, if clicked on
if @captured_area
@selected = @hover_area if @hover_area.is_a?(Integer)
elsif @hover_area
wheel_v = Input.scroll_v
if wheel_v > 0 # Scroll up
@scrollbar.slider_top -= UIControls::Scrollbar::SCROLL_DISTANCE
elsif wheel_v < 0 # Scroll down
@scrollbar.slider_top += UIControls::Scrollbar::SCROLL_DISTANCE
end
if wheel_v != 0
self.top_row = (@scrollbar.position.to_f / ROW_HEIGHT).round
update_hover_highlight
end
end
end
end

View File

@@ -1,9 +1,147 @@
#===============================================================================
# TODO
#
#===============================================================================
class UIControls::DropdownList < UIControls::BaseControl
TEXT_BOX_X = 2
TEXT_BOX_WIDTH = 172
TEXT_BOX_HEIGHT = 24
TEXT_BOX_PADDING = 4 # Gap between sides of text box and text
TEXT_OFFSET_Y = 5
MAX_LIST_ROWS = 8
def initialize(width, height, viewport, options, value)
# NOTE: options is a hash: keys are symbols, values are display names.
super(width, height, viewport)
@options = options
@value = value
@toggling_dropdown_list = false
end
def dispose
remove_dropdown_menu
super
end
def value=(new_value)
return if @value == new_value
@value = new_value
invalidate
end
def set_interactive_rects
@button_rect = Rect.new(TEXT_BOX_X, (height - TEXT_BOX_HEIGHT) / 2,
[TEXT_BOX_WIDTH, width].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_LIST_ROWS].min
# Draw menu's background
@dropdown_menu_bg = BitmapSprite.new(@button_rect.width, menu_height + 4, self.viewport)
@dropdown_menu_bg.x = self.x + @button_rect.x
@dropdown_menu_bg.y = self.y + @button_rect.y + @button_rect.height
@dropdown_menu_bg.z = self.z + 1
@dropdown_menu_bg.bitmap.outline_rect(0, 0, @dropdown_menu_bg.width, @dropdown_menu_bg.height, Color.black)
@dropdown_menu_bg.bitmap.fill_rect(1, 1, @dropdown_menu_bg.width - 2, @dropdown_menu_bg.height - 2, Color.white)
# Create menu
@dropdown_menu = UIControls::List.new(@button_rect.width - 4, menu_height, self.viewport, @options)
@dropdown_menu.x = @dropdown_menu_bg.x + 2
@dropdown_menu.y = @dropdown_menu_bg.y + 2
@dropdown_menu.z = self.z + 2
@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
end
#-----------------------------------------------------------------------------
def draw_area_highlight
return if @captured_area == :button
super
end
def refresh
@dropdown_menu&.refresh
super
# Draw button outline
self.bitmap.outline_rect(@button_rect.x, @button_rect.y,
@button_rect.width, @button_rect.height,
Color.black)
# 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, Color.black)
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