From 8664c90de71922819150f137a88ba399b9cb9b1a Mon Sep 17 00:00:00 2001 From: Cyberarm Date: Fri, 1 Mar 2019 10:27:29 -0600 Subject: [PATCH] Made Container less independant of Element, events are now fired. --- lib/cyberarm_engine/ui/container.rb | 30 ++---------------- lib/cyberarm_engine/ui/element.rb | 47 +++++++++++++++++++++++------ lib/cyberarm_engine/ui/event.rb | 31 +++++++++++++++++-- lib/cyberarm_engine/ui/gui_state.rb | 8 +++-- 4 files changed, 75 insertions(+), 41 deletions(-) diff --git a/lib/cyberarm_engine/ui/container.rb b/lib/cyberarm_engine/ui/container.rb index b93331a..8a3b623 100644 --- a/lib/cyberarm_engine/ui/container.rb +++ b/lib/cyberarm_engine/ui/container.rb @@ -3,48 +3,24 @@ module CyberarmEngine include Common attr_accessor :stroke_color, :fill_color, :background_color, :x, :y, :z, :width, :height - attr_reader :children, :options, :parent + attr_reader :children attr_reader :scroll_x, :scroll_y def initialize(options = {}, block = nil) - @parent = options[:parent] || nil + super + # @current_position = Vector.new(@x, @y) - options = { - x: 0, y: 0, z: 0, - width: 0, height: 0 - }.merge(options) - - x = options.dig(:x) - y = options.dig(:y) - z = options.dig(:z) - - width = options.dig(:width) - height = options.dig(:height) - - raise "#{self.class} 'x' must be a number" unless x.is_a?(Numeric) - raise "#{self.class} 'y' must be a number" unless y.is_a?(Numeric) - raise "#{self.class} 'z' must be a number" unless z.is_a?(Numeric) - raise "#{self.class} 'width' must be a number" unless width.is_a?(Numeric) - raise "#{self.class} 'height' must be a number" unless height.is_a?(Numeric) - raise "#{self.class} 'options' must be a Hash" unless options.is_a?(Hash) - - @x, @y, @z, @width, @height, = x, y, z, width, height @origin_x, @origin_x = @x, @x @origin_width, @origin_height = @width, @height @scroll_x, @scroll_y = 0, 0 @scroll_speed = 10 - @block = block - @options = options - @text_color = options[:text_color] || Element::THEME[:stroke] @background_color = Element::THEME[:background] @children = [] @theme = {} - - return self end def build diff --git a/lib/cyberarm_engine/ui/element.rb b/lib/cyberarm_engine/ui/element.rb index 0360356..85b6cea 100644 --- a/lib/cyberarm_engine/ui/element.rb +++ b/lib/cyberarm_engine/ui/element.rb @@ -4,30 +4,59 @@ module CyberarmEngine include Event attr_accessor :x, :y, :z, :width, :height, :padding, :margin, :enabled + attr_reader :parent, :options, :event_handler def initialize(options = {}, block = nil) @parent = options[:parent] # parent Container (i.e. flow/stack) - options = (THEME).merge(DEFAULTS).merge(@parent.theme).merge(options) + parent_theme = @parent ? @parent.theme : {} + options = (THEME).merge(DEFAULTS).merge(parent_theme).merge(options) @options = options @block = block - @x = options[:x] - @y = options[:y] - @z = options[:z] + @x = options.dig(:x) + @y = options.dig(:y) + @z = options.dig(:z) @fixed_x = @x if @x != 0 @fixed_y = @y if @y != 0 - @width = options[:width] - @height = options[:width] + @width = options.dig(:width) + @height = options.dig(:height) + + @padding = options.dig(:padding) + @margin = options.dig(:margin) + + raise "#{self.class} 'x' must be a number" unless @x.is_a?(Numeric) + raise "#{self.class} 'y' must be a number" unless @y.is_a?(Numeric) + raise "#{self.class} 'z' must be a number" unless @z.is_a?(Numeric) + raise "#{self.class} 'width' must be a number" unless @width.is_a?(Numeric) + raise "#{self.class} 'height' must be a number" unless @height.is_a?(Numeric) + raise "#{self.class} 'options' must be a Hash" unless @options.is_a?(Hash) + + raise "#{self.class} 'padding' must be a number" unless @padding.is_a?(Numeric) + raise "#{self.class} 'margin' must be a number" unless @margin.is_a?(Numeric) @max_width = @width if @width != 0 @max_height = @height if @height != 0 - @padding = options[:padding] - @margin = options[:margin] - @enabled = true + + default_events + end + + def default_events + [:left, :middle, :right].each do |button| + event(:"#{button}_mouse_button") + event(:"released_#{button}_mouse_button") + event(:"holding_#{button}_mouse_button") + end + + event(:mouse_wheel_up) + event(:mouse_wheel_down) + + event(:enter) + event(:hover) + event(:leave) end def enabled? diff --git a/lib/cyberarm_engine/ui/event.rb b/lib/cyberarm_engine/ui/event.rb index 55d727b..354b2ad 100644 --- a/lib/cyberarm_engine/ui/event.rb +++ b/lib/cyberarm_engine/ui/event.rb @@ -1,13 +1,29 @@ module CyberarmEngine - module Event + module Event # Gets included into Element def subscribe(event, method = nil, &block) + handler = method || block + @event_handler[event] << handler + + Subscription.new(self, event, handler) end - def unsubscribe(event) + def unsubscribe(subscription) end def publish(event, *args) - # block.call(*args) + raise ArgumentError, "#{self.class} does not handle #{event.inspect}" unless @event_handler.include?(event) + + return unless enabled? + + if respond_to?(event) + return :handled if send(event, self, *args) == :handled + end + + @event_handler[event].reverse_each do |handler| + return :handled if handler.call(self, *args) == :handled + end + + return nil end def event(event) @@ -17,5 +33,14 @@ module CyberarmEngine end class Subscription + attr_reader :publisher, :event, :handler + + def initialize(publisher, event, handler) + @publisher, @event, @handler = publisher, event, handler + end + + def unsubscribe + @publisher.unsubscribe(self) + 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 9f71140..a93b82f 100644 --- a/lib/cyberarm_engine/ui/gui_state.rb +++ b/lib/cyberarm_engine/ui/gui_state.rb @@ -30,6 +30,10 @@ module CyberarmEngine super new_mouse_over = @root_container.hit_element?(window.mouse_x, window.mouse_y) + if new_mouse_over + new_mouse_over.publish(:enter) if new_mouse_over != @mouse_over + new_mouse_over.publish(:hover, window.mouse_x, window.mouse_y) + end @mouse_over.publish(:leave) if @mouse_over && new_mouse_over != @mouse_over @mouse_over = new_mouse_over @@ -69,7 +73,7 @@ module CyberarmEngine end def redirect_mouse_button(button) - @mouse_over.publish(:"released_#{button}_mouse_button", window.mouse_x, window.mouse_y) if @mouse_over + @mouse_over.publish(:"#{button}_mouse_button", window.mouse_x, window.mouse_y) if @mouse_over end def redirect_released_mouse_button(button) @@ -81,7 +85,7 @@ module CyberarmEngine end def redirect_mouse_wheel(button) - @mouse_over.publish(:"scroll_#{button}", window.mouse_x, window.mouse_y) if @mouse_over + @mouse_over.publish(:"mouse_wheel_#{button}", window.mouse_x, window.mouse_y) if @mouse_over end end end \ No newline at end of file