diff --git a/lib/cyberarm_engine.rb b/lib/cyberarm_engine.rb index f33f1c5..39b0a63 100644 --- a/lib/cyberarm_engine.rb +++ b/lib/cyberarm_engine.rb @@ -37,9 +37,9 @@ require_relative "cyberarm_engine/ui/style" require_relative "cyberarm_engine/ui/border_canvas" require_relative "cyberarm_engine/ui/element" require_relative "cyberarm_engine/ui/elements/label" -require_relative "cyberarm_engine/ui/elements/list_box" require_relative "cyberarm_engine/ui/elements/button" require_relative "cyberarm_engine/ui/elements/toggle_button" +require_relative "cyberarm_engine/ui/elements/list_box" require_relative "cyberarm_engine/ui/elements/edit_line" require_relative "cyberarm_engine/ui/elements/edit_box" require_relative "cyberarm_engine/ui/elements/image" diff --git a/lib/cyberarm_engine/ui/dsl.rb b/lib/cyberarm_engine/ui/dsl.rb index 272e7de..cefb3fe 100644 --- a/lib/cyberarm_engine/ui/dsl.rb +++ b/lib/cyberarm_engine/ui/dsl.rb @@ -22,6 +22,13 @@ module CyberarmEngine add_element( Element::Button.new(text, options, block) { if block.is_a?(Proc); block.call; end } ) end + def list_box(options = {}, &block) + options[:parent] = element_parent + options[:theme] = current_theme + + add_element( Element::ListBox.new(options, block) { if block.is_a?(Proc); block.call; end } ) + end + def edit_line(text, options = {}, &block) options[:parent] = element_parent options[:theme] = current_theme diff --git a/lib/cyberarm_engine/ui/elements/list_box.rb b/lib/cyberarm_engine/ui/elements/list_box.rb index 076ddfa..b14aac1 100644 --- a/lib/cyberarm_engine/ui/elements/list_box.rb +++ b/lib/cyberarm_engine/ui/elements/list_box.rb @@ -1,6 +1,66 @@ module CyberarmEngine class Element - class ListBox < Element + class ListBox < Button + attr_accessor :items + attr_reader :choose + + def initialize(options = {}, block = nil) + @items = options[:items] ? options[:items] : [] + @choose = options[:choose] ? options[:choose] : @items.first + + super(@choose, options, block) + + @style.background_canvas.background = default(:background) + + # TODO: "Clean Up" into own class? + @menu = Stack.new(parent: parent, width: @options[:width], theme: @options[:theme]) + @menu.define_singleton_method(:recalculate_menu) do + @x = @__list_box.x + @y = @__list_box.y + @__list_box.height + end + @menu.instance_variable_set(:"@__list_box", self) + + def @menu.recalculate + super + recalculate_menu + end + end + + def choose=(item) + valid = @items.detect { |i| i == item } + return unless valid # TODO: Throw an error? + @choose = item + + self.value = item.to_s + + recalculate + end + + def released_left_mouse_button(sender, x, y) + show_menu + + return :handled + end + + def show_menu + @menu.clear + @items.each do |item| + [ @block] + block = proc { self.choose = item; @block.call(item) if @block } + b = Button.new(item, { parent: @menu, width: 1.0, theme: @options[:theme], margin: 0, border_color: 0x00ffffff }, block) + + @menu.add(b) + end + recalculate + + root.gui_state.show_menu(@menu) + end + + def recalculate + super + + @menu.recalculate + end end end end \ No newline at end of file diff --git a/lib/cyberarm_engine/ui/gui_state.rb b/lib/cyberarm_engine/ui/gui_state.rb index 39c8ef7..37585c4 100644 --- a/lib/cyberarm_engine/ui/gui_state.rb +++ b/lib/cyberarm_engine/ui/gui_state.rb @@ -17,6 +17,7 @@ module CyberarmEngine @active_width = window.width @active_height = window.height + @menu = nil @focus = nil @mouse_over = nil @mouse_down_on = {} @@ -45,6 +46,11 @@ module CyberarmEngine def draw super + if @menu + Gosu.flush + @menu.draw + end + if @tip.text.length > 0 Gosu.draw_rect(@tip.x - 2, @tip.y - 2, @tip.width + 4, @tip.height + 4, 0xff020202, Float::INFINITY) @tip.draw @@ -60,9 +66,12 @@ module CyberarmEngine @pending_recalculate_request = false end + @menu.update if @menu super - new_mouse_over = @root_container.hit_element?(window.mouse_x, window.mouse_y) + new_mouse_over = @menu.hit_element?(window.mouse_x, window.mouse_y) if @menu + new_mouse_over = @root_container.hit_element?(window.mouse_x, window.mouse_y) unless new_mouse_over + if new_mouse_over new_mouse_over.publish(:enter) if new_mouse_over != @mouse_over new_mouse_over.publish(:hover) @@ -136,6 +145,8 @@ module CyberarmEngine end def redirect_mouse_button(button) + hide_menu unless @menu and (@menu == @mouse_over) or (@mouse_over.parent == @menu) + if @focus && @mouse_over != @focus @focus.publish(:blur) @focus = nil @@ -153,6 +164,8 @@ module CyberarmEngine end def redirect_released_mouse_button(button) + hide_menu if @menu and (@menu == @mouse_over) or (@mouse_over.parent == @menu) + if @mouse_over @mouse_over.publish(:"released_#{button}_mouse_button", window.mouse_x, window.mouse_y) @mouse_over.publish(:"clicked_#{button}_mouse_button", window.mouse_x, window.mouse_y) if @mouse_over == @mouse_down_on[button] @@ -188,5 +201,13 @@ module CyberarmEngine def request_recalculate @pending_recalculate_request = true end + + def show_menu(list_box) + @menu = list_box + end + + def hide_menu + @menu = nil + end end end \ No newline at end of file