lib/cyberarm_engine/ui/elements/container.rb in cyberarm_engine-0.19.0 vs lib/cyberarm_engine/ui/elements/container.rb in cyberarm_engine-0.19.1
- old
+ new
@@ -1,256 +1,256 @@
-module CyberarmEngine
- class Element
- class Container < Element
- include Common
-
- attr_accessor :stroke_color, :fill_color
- attr_reader :children, :gui_state, :scroll_position
-
- def initialize(options = {}, block = nil)
- @gui_state = options.delete(:gui_state)
- super
-
- @scroll_position = Vector.new(0, 0)
- @scroll_speed = 40
-
- @text_color = options[:color]
-
- @children = []
-
- event(:window_size_changed)
- end
-
- def build
- @block.call(self) if @block
-
- root.gui_state.request_recalculate
- end
-
- def add(element)
- @children << element
-
- root.gui_state.request_recalculate
- end
-
- def clear(&block)
- @children.clear
-
- old_container = $__current_container__
-
- $__current_container__ = self
- block.call(self) if block
-
- $__current_container__ = old_container
-
- root.gui_state.request_recalculate
- end
-
- def apend(&block)
- old_container = $__current_container__
-
- $__current_container__ = self
- block.call(self) if block
-
- $__current_container__ = old_container
-
- root.gui_state.request_recalculate
- end
-
- def render
- Gosu.clip_to(@x, @y, width, height) do
- @children.each(&:draw)
- end
- end
-
- def debug_draw
- super
-
- @children.each do |child|
- child.debug_draw
- end
- end
-
- def update
- @children.each(&:update)
- end
-
- def hit_element?(x, y)
- return unless hit?(x, y)
-
- @children.reverse_each do |child|
- next unless child.visible?
-
- case child
- when Container
- if element = child.hit_element?(x, y)
- return element
- end
- else
- return child if child.hit?(x, y)
- end
- end
-
- self if hit?(x, y)
- end
-
- def recalculate
- @current_position = Vector.new(@style.margin_left + @style.padding_left, @style.margin_top + @style.padding_top)
- @current_position += @scroll_position
-
- return unless visible?
-
- Stats.increment(:gui_recalculations_last_frame, 1)
-
- stylize
-
- layout
-
- if is_root?
- @width = @style.width = window.width
- @height = @style.height = window.height
- else
- @width = 0
- @height = 0
-
- _width = dimensional_size(@style.width, :width)
- _height = dimensional_size(@style.height, :height)
-
- @width = _width || (@children.map { |c| c.x + c.outer_width }.max || 0).round
- @height = _height || (@children.map { |c| c.y + c.outer_height }.max || 0).round
- end
-
- # Move child to parent after positioning
- @children.each do |child|
- child.x += (@x + @style.border_thickness_left) - style.margin_left
- child.y += (@y + @style.border_thickness_top) - style.margin_top
-
- child.stylize
- child.recalculate
- child.reposition # TODO: Implement top,bottom,left,center, and right positioning
-
- Stats.increment(:gui_recalculations_last_frame, 1)
- end
-
- update_background
- end
-
- def layout
- raise "Not overridden"
- end
-
- def max_width
- _width = dimensional_size(@style.width, :width)
- if _width
- outer_width
- else
- window.width - (@parent ? @parent.style.margin_right + @style.margin_right : @style.margin_right)
- end
- end
-
- def fits_on_line?(element) # Flow
- p [@options[:id], @width] if @options[:id]
- @current_position.x + element.outer_width <= max_width &&
- @current_position.x + element.outer_width <= window.width
- end
-
- def position_on_current_line(element) # Flow
- element.x = element.style.margin_left + @current_position.x
- element.y = element.style.margin_top + @current_position.y
-
- @current_position.x += element.outer_width
- @current_position.x = @style.margin_left if @current_position.x >= max_width
- end
-
- def tallest_neighbor(querier, _y_position) # Flow
- response = querier
- @children.each do |child|
- response = child if child.outer_height > response.outer_height
- break if child == querier
- end
-
- response
- end
-
- def position_on_next_line(child) # Flow
- @current_position.x = @style.margin_left
- @current_position.y += tallest_neighbor(child, @current_position.y).outer_height
-
- child.x = child.style.margin_left + @current_position.x
- child.y = child.style.margin_top + @current_position.y
-
- @current_position.x += child.outer_width
- end
-
- def move_to_next_line(element) # Stack
- element.x = element.style.margin_left + @current_position.x
- element.y = element.style.margin_top + @current_position.y
-
- @current_position.y += element.outer_height
- end
-
- def mouse_wheel_up(sender, x, y)
- return unless @style.scroll
-
- if @scroll_position.y < 0
- @scroll_position.y += @scroll_speed
- @scroll_position.y = 0 if @scroll_position.y > 0
- recalculate
-
- return :handled
- end
- end
-
- def mouse_wheel_down(sender, x, y)
- return unless @style.scroll
-
- return unless height < scroll_height
-
- if @scroll_position.y.abs < max_scroll_height
- @scroll_position.y -= @scroll_speed
- @scroll_position.y = -max_scroll_height if @scroll_position.y.abs > max_scroll_height
- recalculate
-
- return :handled
- end
- end
-
- def scroll_top
- @scroll_position.y
- end
-
- def scroll_top=(n)
- n = 0 if n <= 0
- @scroll_position.y = -n
-
- if max_scroll_height.positive?
- @scroll_position.y = -max_scroll_height if @scroll_position.y.abs > max_scroll_height
- else
- @scroll_position.y = 0
- end
- end
-
- def value
- @children.map { |c| c.class }.join(", ")
- end
-
- def to_s
- "#{self.class} x=#{x} y=#{y} width=#{width} height=#{height} children=#{@children.size}"
- end
-
- def write_tree(indent = "", _index = 0)
- puts self
-
- indent += " "
- @children.each_with_index do |child, i|
- print "#{indent}#{i}: "
-
- if child.is_a?(Container)
- child.write_tree(indent)
- else
- puts child
- end
- end
- end
- end
- end
-end
+module CyberarmEngine
+ class Element
+ class Container < Element
+ include Common
+
+ attr_accessor :stroke_color, :fill_color
+ attr_reader :children, :gui_state, :scroll_position
+
+ def initialize(options = {}, block = nil)
+ @gui_state = options.delete(:gui_state)
+ super
+
+ @scroll_position = Vector.new(0, 0)
+ @scroll_speed = 40
+
+ @text_color = options[:color]
+
+ @children = []
+
+ event(:window_size_changed)
+ end
+
+ def build
+ @block.call(self) if @block
+
+ root.gui_state.request_recalculate
+ end
+
+ def add(element)
+ @children << element
+
+ root.gui_state.request_recalculate
+ end
+
+ def clear(&block)
+ @children.clear
+
+ old_container = $__current_container__
+
+ $__current_container__ = self
+ block.call(self) if block
+
+ $__current_container__ = old_container
+
+ root.gui_state.request_recalculate
+ end
+
+ def apend(&block)
+ old_container = $__current_container__
+
+ $__current_container__ = self
+ block.call(self) if block
+
+ $__current_container__ = old_container
+
+ root.gui_state.request_recalculate
+ end
+
+ def render
+ Gosu.clip_to(@x, @y, width, height) do
+ @children.each(&:draw)
+ end
+ end
+
+ def debug_draw
+ super
+
+ @children.each do |child|
+ child.debug_draw
+ end
+ end
+
+ def update
+ @children.each(&:update)
+ end
+
+ def hit_element?(x, y)
+ return unless hit?(x, y)
+
+ @children.reverse_each do |child|
+ next unless child.visible?
+
+ case child
+ when Container
+ if element = child.hit_element?(x, y)
+ return element
+ end
+ else
+ return child if child.hit?(x, y)
+ end
+ end
+
+ self if hit?(x, y)
+ end
+
+ def recalculate
+ @current_position = Vector.new(@style.margin_left + @style.padding_left, @style.margin_top + @style.padding_top)
+ @current_position += @scroll_position
+
+ return unless visible?
+
+ Stats.increment(:gui_recalculations_last_frame, 1)
+
+ stylize
+
+ layout
+
+ if is_root?
+ @width = @style.width = window.width
+ @height = @style.height = window.height
+ else
+ @width = 0
+ @height = 0
+
+ _width = dimensional_size(@style.width, :width)
+ _height = dimensional_size(@style.height, :height)
+
+ @width = _width || (@children.map { |c| c.x + c.outer_width }.max || 0).round
+ @height = _height || (@children.map { |c| c.y + c.outer_height }.max || 0).round
+ end
+
+ # Move child to parent after positioning
+ @children.each do |child|
+ child.x += (@x + @style.border_thickness_left) - style.margin_left
+ child.y += (@y + @style.border_thickness_top) - style.margin_top
+
+ child.stylize
+ child.recalculate
+ child.reposition # TODO: Implement top,bottom,left,center, and right positioning
+
+ Stats.increment(:gui_recalculations_last_frame, 1)
+ end
+
+ update_background
+ end
+
+ def layout
+ raise "Not overridden"
+ end
+
+ def max_width
+ _width = dimensional_size(@style.width, :width)
+ if _width
+ outer_width
+ else
+ window.width - (@parent ? @parent.style.margin_right + @style.margin_right : @style.margin_right)
+ end
+ end
+
+ def fits_on_line?(element) # Flow
+ p [@options[:id], @width] if @options[:id]
+ @current_position.x + element.outer_width <= max_width &&
+ @current_position.x + element.outer_width <= window.width
+ end
+
+ def position_on_current_line(element) # Flow
+ element.x = element.style.margin_left + @current_position.x
+ element.y = element.style.margin_top + @current_position.y
+
+ @current_position.x += element.outer_width
+ @current_position.x = @style.margin_left if @current_position.x >= max_width
+ end
+
+ def tallest_neighbor(querier, _y_position) # Flow
+ response = querier
+ @children.each do |child|
+ response = child if child.outer_height > response.outer_height
+ break if child == querier
+ end
+
+ response
+ end
+
+ def position_on_next_line(child) # Flow
+ @current_position.x = @style.margin_left
+ @current_position.y += tallest_neighbor(child, @current_position.y).outer_height
+
+ child.x = child.style.margin_left + @current_position.x
+ child.y = child.style.margin_top + @current_position.y
+
+ @current_position.x += child.outer_width
+ end
+
+ def move_to_next_line(element) # Stack
+ element.x = element.style.margin_left + @current_position.x
+ element.y = element.style.margin_top + @current_position.y
+
+ @current_position.y += element.outer_height
+ end
+
+ def mouse_wheel_up(sender, x, y)
+ return unless @style.scroll
+
+ if @scroll_position.y < 0
+ @scroll_position.y += @scroll_speed
+ @scroll_position.y = 0 if @scroll_position.y > 0
+ recalculate
+
+ return :handled
+ end
+ end
+
+ def mouse_wheel_down(sender, x, y)
+ return unless @style.scroll
+
+ return unless height < scroll_height
+
+ if @scroll_position.y.abs < max_scroll_height
+ @scroll_position.y -= @scroll_speed
+ @scroll_position.y = -max_scroll_height if @scroll_position.y.abs > max_scroll_height
+ recalculate
+
+ return :handled
+ end
+ end
+
+ def scroll_top
+ @scroll_position.y
+ end
+
+ def scroll_top=(n)
+ n = 0 if n <= 0
+ @scroll_position.y = -n
+
+ if max_scroll_height.positive?
+ @scroll_position.y = -max_scroll_height if @scroll_position.y.abs > max_scroll_height
+ else
+ @scroll_position.y = 0
+ end
+ end
+
+ def value
+ @children.map { |c| c.class }.join(", ")
+ end
+
+ def to_s
+ "#{self.class} x=#{x} y=#{y} width=#{width} height=#{height} children=#{@children.size}"
+ end
+
+ def write_tree(indent = "", _index = 0)
+ puts self
+
+ indent += " "
+ @children.each_with_index do |child, i|
+ print "#{indent}#{i}: "
+
+ if child.is_a?(Container)
+ child.write_tree(indent)
+ else
+ puts child
+ end
+ end
+ end
+ end
+ end
+end