Class: Arrolio::Flowables::ListFlowable

Inherits:
Arrolio::Flowable show all
Defined in:
lib/arrolio/flowables/list_flowable.rb

Overview

Hanging-indent list. Each item has a marker column (fixed width) and a body column (wraps under body, not marker).

Direct Known Subclasses

NoteFlowable

Instance Attribute Summary collapse

Attributes inherited from Arrolio::Flowable

#style

Instance Method Summary collapse

Methods inherited from Arrolio::Flowable

#keep_together?, #keep_with_next?, #page_break_after?, #page_break_before?, #space_after, #space_before, #split

Constructor Details

#initialize(items, kind: :bullet, style: Style::Definition.new, marker_width: 18.0, body_indent: 6.0, marker_indent: 0.0, item_spacing: 0.0) ⇒ ListFlowable

Returns a new instance of ListFlowable.



11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/arrolio/flowables/list_flowable.rb', line 11

def initialize(items, kind: :bullet, style: Style::Definition.new,
               marker_width: 18.0, body_indent: 6.0,
               marker_indent: 0.0, item_spacing: 0.0)
  super(style: style)
  @kind = kind.to_sym
  @marker_width = marker_width.to_f
  @body_indent = body_indent.to_f
  @marker_indent = marker_indent.to_f
  @item_spacing = item_spacing.to_f
  @items = items
  freeze
end

Instance Attribute Details

#body_indentObject (readonly)

Returns the value of attribute body_indent.



8
9
10
# File 'lib/arrolio/flowables/list_flowable.rb', line 8

def body_indent
  @body_indent
end

#item_spacingObject (readonly)

Returns the value of attribute item_spacing.



8
9
10
# File 'lib/arrolio/flowables/list_flowable.rb', line 8

def item_spacing
  @item_spacing
end

#itemsObject (readonly)

Returns the value of attribute items.



8
9
10
# File 'lib/arrolio/flowables/list_flowable.rb', line 8

def items
  @items
end

#kindObject (readonly)

Returns the value of attribute kind.



8
9
10
# File 'lib/arrolio/flowables/list_flowable.rb', line 8

def kind
  @kind
end

#marker_indentObject (readonly)

Returns the value of attribute marker_indent.



8
9
10
# File 'lib/arrolio/flowables/list_flowable.rb', line 8

def marker_indent
  @marker_indent
end

#marker_widthObject (readonly)

Returns the value of attribute marker_width.



8
9
10
# File 'lib/arrolio/flowables/list_flowable.rb', line 8

def marker_width
  @marker_width
end

Instance Method Details

#do_split(width, remaining_height, context = nil) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/arrolio/flowables/list_flowable.rb', line 88

def do_split(width, remaining_height, context = nil)
  head_items = []
  tail_items = []
  used = 0.0

  @items.each do |item|
    _, body_flowables = item
    item_h = body_flowables.sum { |f| f.height(body_width(width), context) }
    if used + item_h <= remaining_height || head_items.empty?
      head_items << item
      used += item_h
    else
      tail_items << item
    end
  end

  head = if head_items.empty?
  nil
else
  self.class.new(head_items, kind: @kind, style: @style,
                       marker_width: @marker_width,
                       body_indent: @body_indent,
                       marker_indent: @marker_indent,
                       item_spacing: @item_spacing)
end
  tail = if tail_items.empty?
  nil
else
  self.class.new(tail_items, kind: @kind, style: @style,
                       marker_width: @marker_width,
                       body_indent: @body_indent,
                       marker_indent: @marker_indent,
                       item_spacing: @item_spacing)
end
  [head, tail]
end

#emit(x, y, width, context = nil) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/arrolio/flowables/list_flowable.rb', line 42

def emit(x, y, width, context = nil)
  boxes = []
  consumed = 0.0
  cursor = y
  marker_x = x + @marker_indent
  body_x = x + @marker_indent + @marker_width + @body_indent

  @items.each_with_index do |item, idx|
    marker_text, body_flowables = item
    marker = marker_text || default_marker(idx)

    if marker.is_a?(String)
      unless marker.empty?
        mboxes, = marker_flowable(marker, marker_x, cursor, width, context)
                           .emit(marker_x, cursor, width, context)
        boxes.concat(mboxes)
      end
    elsif marker
      # marker is a Flowable (e.g. NoteFlowable passes a TextFlowable)
      mboxes, = marker.emit(marker_x, cursor, width, context)
      boxes.concat(mboxes)
    end

    item_h = 0.0
    body_flowables.each do |f|
      fh = f.height(body_width(width), context)
      fboxes, = f.emit(body_x, cursor, body_width(width), context)
      boxes.concat(fboxes)
      cursor -= fh
      item_h += fh
    end

    if idx < @items.length - 1 && @item_spacing.positive?
      cursor -= @item_spacing
      item_h += @item_spacing
    end
    consumed += item_h
  end

  [boxes, consumed]
end

#height(width, context = nil) ⇒ Object



24
25
26
27
28
29
30
# File 'lib/arrolio/flowables/list_flowable.rb', line 24

def height(width, context = nil)
  body_h = @items.sum do |item|
    _, body_flowables = item
    body_flowables.sum { |f| f.height(body_width(width), context) }
  end
  body_h + ([@items.length - 1, 0].max * @item_spacing)
end

#min_keep_height(width, context = nil) ⇒ Object

What must stay with a preceding keep-with-next flowable: the first item — the lead-in paragraph keeps with the list's first line, not the whole list.



35
36
37
38
39
40
# File 'lib/arrolio/flowables/list_flowable.rb', line 35

def min_keep_height(width, context = nil)
  _, body_flowables = @items.first
  return 0.0 unless body_flowables&.any?

  body_flowables.sum { |f| f.height(body_width(width), context) }
end

#splittable?Boolean

Returns:

  • (Boolean)


84
85
86
# File 'lib/arrolio/flowables/list_flowable.rb', line 84

def splittable?
  true
end