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