class WindowBlock < Node attr_accessor :children, :direction, :size, :x, :y, :width, :height def initialize(direction = :horizontal) @children = [] @direction = direction super() end def add_node(node) @children << node end def each_leaf(&block) @children.each { |child| child.each_leaf(&block) } end def each_node(&block) block.call(self) @children.each { |child| child.each_node(&block) if child.is_a? WindowBlock } end def compute_geometry! return if @children.empty? horizontal = @direction == :horizontal total_percent = @children.map { |c| c.size.to_i > 0 ? c.size.to_i : 0 }.sum flex_count = @children.count { |c| c.size.to_i <= 0 } total_space = horizontal ? @width : @height total_percent = [total_percent, 100].min remaining_percent = 100 - total_percent flex_percent = flex_count > 0 ? remaining_percent / flex_count : 0 pos = horizontal ? @x : @y @children.each do |child| percent = child.size.to_i > 0 ? child.size.to_i : flex_percent child_size = (total_space * percent) / 100.0 if horizontal child.x = pos child.y = @y child.width = child_size child.height = @height else child.x = @x child.y = pos child.width = @width child.height = child_size end child.compute_geometry! if child.is_a?(WindowBlock) child.apply_geometry! if child.is_a?(Window) pos += child_size end end end class RootWindowBlock < WindowBlock def initialize(workspace) super(:horizontal) @x = workspace.x @y = workspace.y @width = workspace.width @height = workspace.height end end