lib/cyberarm_engine/ui/elements/container.rb in cyberarm_engine-0.24.2 vs lib/cyberarm_engine/ui/elements/container.rb in cyberarm_engine-0.24.3

- old
+ new

@@ -2,11 +2,11 @@ class Element class Container < Element include Common attr_accessor :stroke_color, :fill_color - attr_reader :children, :gui_state, :scroll_position + attr_reader :children, :gui_state, :scroll_position, :scroll_target_position def self.current_container @@current_container end @@ -47,24 +47,24 @@ def remove(element) root.gui_state.request_recalculate_for(self) if @children.delete(element) end - def clear(&block) - @children.clear - + def append(&block) old_container = CyberarmEngine::Element::Container.current_container CyberarmEngine::Element::Container.current_container = self block.call(self) if block CyberarmEngine::Element::Container.current_container = old_container root.gui_state.request_recalculate_for(self) end - def append(&block) + def clear(&block) + @children.clear + old_container = CyberarmEngine::Element::Container.current_container CyberarmEngine::Element::Container.current_container = self block.call(self) if block @@ -93,11 +93,11 @@ child.debug_draw end end def update - update_scroll + update_scroll if @style.scroll @children.each(&:update) end def hit_element?(x, y) return unless hit?(x, y) @@ -126,27 +126,20 @@ child.element_visible = child.x >= (@x - @scroll_position.x) - child.width && child.x <= (@x - @scroll_position.x) + width && child.y >= (@y - @scroll_position.y) - child.height && child.y <= (@y - @scroll_position.y) + height end def update_scroll - dt = window.dt > 1 ? 1.0 : window.dt + dt = window.dt.clamp(0.000001, 0.025) + @scroll_position.x += (((@scroll_target_position.x - @scroll_position.x) * (@scroll_speed / 4.0) * 0.98) * dt).round + @scroll_position.y += (((@scroll_target_position.y - @scroll_position.y) * (@scroll_speed / 4.0) * 0.98) * dt).round - scroll_x_diff = (@scroll_target_position.x - @scroll_position.x) - scroll_y_diff = (@scroll_target_position.y - @scroll_position.y) - - @scroll_position.x += (scroll_x_diff * @scroll_speed * 0.25 * dt).round - @scroll_position.y += (scroll_y_diff * @scroll_speed * 0.25 * dt).round - - @scroll_position.x = @scroll_target_position.x if scroll_x_diff.abs < 1.0 - @scroll_position.y = @scroll_target_position.y if scroll_y_diff.abs < 1.0 - # Scrolled PAST top if @scroll_position.y > 0 @scroll_target_position.y = 0 # Scrolled PAST bottom - elsif @scroll_position.y.abs > max_scroll_height + elsif @scroll_position.y < -max_scroll_height @scroll_target_position.y = -max_scroll_height end if @last_scroll_position != @scroll_position @children.each { |child| update_child_element_visibity(child) } @@ -156,24 +149,28 @@ @last_scroll_position.x = @scroll_position.x @last_scroll_position.y = @scroll_position.y end def recalculate + return if @in_recalculate + + @in_recalculate = true + @current_position = Vector.new(@style.margin_left + @style.padding_left, @style.margin_top + @style.padding_top) return unless visible? - Stats.frame.increment(:gui_recalculations) + Stats.frame&.increment(:gui_recalculations) - stylize - # s = Gosu.milliseconds + stylize layout - old_width = @width - old_height = @height + # Old sizes MUST be determined AFTER call to layout + old_width = width + old_height = height @cached_scroll_width = nil @cached_scroll_height = nil if is_root? @@ -212,48 +209,44 @@ when :right @x = parent.width - width end end + # t = Gosu.milliseconds # Move children 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.frame.increment(:gui_recalculations) + Stats.frame&.increment(:gui_recalculations) update_child_element_visibity(child) end + # puts "TOOK: #{Gosu.milliseconds - t}ms to recalculate #{self.class}:0x#{self.object_id.to_s(16)}'s #{@children.count} children" - # puts "TOOK: #{Gosu.milliseconds - s}ms to recalculate #{self.class}:0x#{self.object_id.to_s(16)}" - update_background # Fixes resized container scrolled past bottom - self.scroll_top = -@scroll_position.y - @scroll_target_position.y = @scroll_position.y + if old_height != @height + self.scroll_top = -@scroll_position.y + @scroll_target_position.y = @scroll_position.y + end # Fixes resized container that is scrolled down from being stuck overscrolled when resized if scroll_height < height @scroll_target_position.y = 0 end - # NOTE: Experiment for removing need to explicitly call gui_state#recalculate at least 3 times for layout to layout... - if old_width != @width || old_height != @height - if @parent - root.gui_state.request_recalculate_for(@parent) - else - root.gui_state.request_recalculate - end - end - - root.gui_state.request_repaint if @width != old_width || @height != old_height recalculate_if_size_changed + + # puts "TOOK: #{Gosu.milliseconds - s}ms to recalculate #{self.class}:0x#{self.object_id.to_s(16)}" + + @in_recalculate = false end def layout raise "Not overridden" end @@ -331,9 +324,47 @@ if @scroll_target_position.y > 0 @scroll_target_position.y = -@scroll_chunk else @scroll_target_position.y -= @scroll_chunk end + + return :handled + end + + def scroll_jump_to_top(sender, x, y) + return unless @style.scroll + + @scroll_position.y = 0 + @scroll_target_position.y = 0 + + return :handled + end + + def scroll_jump_to_end(sender, x, y) + return unless @style.scroll + + @scroll_position.y = -max_scroll_height + @scroll_target_position.y = -max_scroll_height + + return :handled + end + + def scroll_page_up(sender, x, y) + return unless @style.scroll + + @scroll_position.y += height + @scroll_position.y = 0 if @scroll_position.y > 0 + @scroll_target_position.y = @scroll_position.y + + return :handled + end + + def scroll_page_down(sender, x, y) + return unless @style.scroll + + @scroll_position.y -= height + @scroll_position.y = -max_scroll_height if @scroll_position.y < -max_scroll_height + @scroll_target_position.y = @scroll_position.y return :handled end def scroll_top