Class: EideticRML::LayoutManagers::TableLayout

Inherits:
LayoutManager show all
Defined in:
lib/erml_layout_managers.rb

Instance Method Summary collapse

Methods inherited from LayoutManager

#after_layout, for_name, #initialize, #layout_absolute, #layout_relative, register

Constructor Details

This class inherits a constructor from EideticRML::LayoutManagers::LayoutManager

Instance Method Details

#grid(container) ⇒ Object



564
565
566
567
568
569
570
# File 'lib/erml_layout_managers.rb', line 564

def grid(container)
  if container.order == :rows
    row_grid(container)
  else # container.order == :cols
    col_grid(container)
  end
end

#layout(container, writer) ⇒ Object



572
573
574
575
# File 'lib/erml_layout_managers.rb', line 572

def layout(container, writer)
  layout_grid(grid(container), container, writer)
  super(container, writer)
end

#preferred_height(grid, writer) ⇒ Object



577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
# File 'lib/erml_layout_managers.rb', line 577

def preferred_height(grid, writer)
  # calculate preferred heights, where available
  heights = Support::Grid.new(grid.cols, grid.rows)
  return 0 if heights.cols == 0 or heights.rows == 0
  grid.cols.times do |c|
    grid.col(c).each_with_index do |widget, r|
      next unless widget
      # heights[c, r] = [widget.rowspan, widget.has_height? ? widget.preferred_height(writer) : nil]
      heights[c, r] = [widget.rowspan, widget.preferred_height(writer)]
    end
  end

  heights.rows.times do |r|
    row_heights = (0...heights.cols).map { |c| heights[c,r] }.compact
    min_rowspan = row_heights.map { |rowspan, height| rowspan }.min
    min_rowspan_heights = row_heights.select { |rowspan, height| rowspan == min_rowspan }
    max_height = min_rowspan_heights.map { |rowspan, height| height }.compact.max
    # at least one cell must specify a height
    return nil if max_height.nil?
    heights.cols.times do |c|
      rh = heights[c,r]
      next if rh.nil?
      # carry height in excess of max height of cells with min_rowspan to cell in next row, subtracting vpadding
      if rh[ROW_SPAN] > min_rowspan
        heights[c,r+1] = [rh[ROW_SPAN] - 1, [rh[ROW_HEIGHT] - max_height - @style.vpadding, 0].max]
      end
      rh[ROW_HEIGHT] = max_height
    end
  end

  result = 0
  grid.rows.times do |r|
    max_height = 0
    grid.cols.times do |c|
      if (widget = grid[c, r]) and (rh = heights[c,r])
        height = (0...rh[ROW_SPAN]).inject((rh[ROW_SPAN] - 1) * @style.vpadding) { |height, row_offset| height + heights[c,r+row_offset][ROW_HEIGHT] }
        max_height = [max_height, rh[ROW_HEIGHT]].max if rh[ROW_SPAN] == 1
      end
    end
    result += max_height + @style.vpadding
  end
  result -= @style.vpadding if result > 0
end

#preferred_width(grid, writer) ⇒ Object



621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
# File 'lib/erml_layout_managers.rb', line 621

def preferred_width(grid, writer)
  # calculate preferred widths, where available
  widths = Support::Grid.new(grid.cols, grid.rows)
  return 0 if widths.cols == 0 or widths.rows == 0
  grid.rows.times do |r|
    grid.row(r).each_with_index do |widget, c|
      next unless widget
      # widths[c, r] = [widget.colspan, widget.has_width? ? widget.preferred_width(writer) : nil]
      widths[c, r] = [widget.colspan, widget.preferred_width(writer)]
    end
  end

  widths.cols.times do |c|
    col_widths = (0...widths.rows).map { |r| widths[c,r] }.compact
    min_colspan = col_widths.map { |colspan, width| colspan }.min
    min_colspan_widths = col_widths.select { |colspan, width| colspan == min_colspan }
    max_width = min_colspan_widths.map { |colspan, width| width }.compact.max
    # at least one cell must specify a width
    return nil if max_width.nil?
    widths.rows.times do |r|
      cw = widths[c,r]
      next if cw.nil?
      # carry width in excess of max width of cells with min_colspan to cell in next col, subtracting hpadding
      if cw[COL_SPAN] > min_colspan
        widths[c+1,r] = [cw[COL_SPAN] - 1, [cw[COL_WIDTH] - max_width - @style.hpadding, 0].max]
      end
      cw[COL_WIDTH] = max_width
    end
  end

  result = 0
  grid.cols.times do |c|
    max_width = 0
    grid.rows.times do |r|
      if (widget = grid[c, r]) and (cw = widths[c, r])
        width = (0...cw[COL_SPAN]).inject((cw[COL_SPAN] - 1) * @style.hpadding) { |width, col_offset| width + widths[c+col_offset,r][COL_WIDTH] }
        max_width = [max_width, cw[COL_WIDTH]].max if cw[COL_SPAN] == 1
      end
    end
    result += max_width + @style.hpadding
  end
  result -= @style.hpadding if result > 0
  result
end