class HexaPDF::Layout::ColumnBox

arguments are ignored.
frame into account. This also means that the available_width and available_height
If this is set to :flow, the frames created for the columns will take the shape of the
Style#position::
The following style properties are used (additionally to those used by the parent class):
each column.
box. This means they are around all columns and their contents and are not used separately for
If the column box has padding and/or borders specified, they are handled like with any other
columns can be made equally high.
modified. Additionally, the contents can either fill the columns one after the other or the
The number and width of the columns as well as the size of the gap between the columns can be
A ColumnBox arranges boxes in one or more columns.

def calculate_columns(width)

If it is not possible to fit all columns into the given +width+, an empty array is returned.

width.
Calculates the x-coordinates and widths of all columns based on the given total available
def calculate_columns(width)
  number_of_columns = @columns.size
  gaps = @gaps.cycle.take(number_of_columns - 1)
  fixed_width, variable_width = @columns.partition(&:positive?).map {|c| c.sum(&:abs) }
  rest_width = width - fixed_width - gaps.sum
  return [] if rest_width <= 0
  variable_width_unit = rest_width / variable_width.to_f
  position = 0
  @columns.map.with_index do |column, index|
    result = if column > 0
               [position, column]
             else
               [position, column.abs * variable_width_unit]
             end
    position += result[1] + (gaps[index] || 0)
    result
  end
end

def draw_content(canvas, x, y)

Draws the child boxes onto the canvas at position [x, y].
def draw_content(canvas, x, y)
  if style.position != :flow && (x != @fit_x || y != @fit_y)
    canvas.translate(x - @fit_x, y - @fit_y) do
      @box_fitter.fit_results.each {|result| result.draw(canvas) }
    end
  else
    @box_fitter.fit_results.each {|result| result.draw(canvas) }
  end
end

def empty?

Returns +true+ if no box was fitted into the columns.
def empty?
  super && (!@box_fitter || @box_fitter.fit_results.empty?)
end

def fit_content(_available_width, _available_height, frame)


Fits the column box into the current region of the frame.
def fit_content(_available_width, _available_height, frame)
  initial_fit_successful = (@equal_height && @columns.size > 1 ? nil : false)
  tries = 0
  width = @width - reserved_width
  height = @height - reserved_height
  columns = calculate_columns(width)
  return if columns.empty?
  left = (style.position == :flow ? frame.left : frame.x) + reserved_width_left
  top = frame.y - reserved_height_top
  successful_height = height
  unsuccessful_height = 0
  while true
    @box_fitter = BoxFitter.new
    columns.each do |col_x, column_width|
      column_left = left + col_x
      column_bottom = top - height
      if style.position == :flow
        rect = Geom2D::Polygon([column_left, column_bottom],
                               [column_left + column_width, column_bottom],
                               [column_left + column_width, column_bottom + height],
                               [column_left, column_bottom + height])
        shape = Geom2D::Algorithms::PolygonOperation.run(frame.shape, rect, :intersection)
      end
      column_frame = frame.child_frame(column_left, column_bottom, column_width, height,
                                       shape: shape, box: self)
      @box_fitter << column_frame
    end
    children.each {|box| @box_fitter.fit(box) }
    fit_successful = @box_fitter.success?
    initial_fit_successful = fit_successful if initial_fit_successful.nil?
    if fit_successful
      successful_height = height if successful_height > height
    elsif unsuccessful_height < height
      unsuccessful_height = height
    end
    break if !initial_fit_successful || tries > 40 ||
      (fit_successful && successful_height - unsuccessful_height < 10)
    height = if successful_height - unsuccessful_height <= 5
               successful_height
             else
               (successful_height + unsuccessful_height) / 2.0
             end
    tries += 1
  end
  update_content_width { columns[-1].sum }
  update_content_height { @box_fitter.content_heights.max }
  if @box_fitter.success?
    fit_result.success!
  elsif !@box_fitter.fit_results.empty?
    fit_result.overflow!
  end
end

def initialize(children: [], columns: 2, gaps: 36, equal_height: true, **kwargs)

Otherwise the columns are filled from the left.
If +true+, the #fit method tries to balance the columns in terms of their height.
+equal_height+::

definition (see #gap for details).
Can either be a simply integer specifying the width between two columns or a full gap
+gaps+::

(see #columns for details).
Can either simply integer specify the number of columns or be a full column definition

+columns+::

Creates a new ColumnBox object for the given child boxes in +children+.
def initialize(children: [], columns: 2, gaps: 36, equal_height: true, **kwargs)
  super(**kwargs)
  @children = children
  @columns = (columns.kind_of?(Array) ? columns : [-1] * columns)
  @gaps = (gaps.kind_of?(Array) ? gaps : [gaps])
  @equal_height = equal_height
end

def split_content

Splits the content of the column box. This method is called from Box#split.
def split_content
  box = create_split_box
  box.instance_variable_set(:@children, @box_fitter.remaining_boxes)
  [self, box]
end

def supports_position_flow?

Returns +true+ as the 'position' style property value :flow is supported.
def supports_position_flow?
  true
end