Class: SilkLayout::Layout::BlockLayout
- Inherits:
-
Object
- Object
- SilkLayout::Layout::BlockLayout
- Defined in:
- lib/silk_layout/layout/block_layout.rb
Class Method Summary collapse
- .auto_content_width(box, available_width) ⇒ Object
- .border_box_sizing?(box) ⇒ Boolean
- .constrain_css_width(box, width, available_width) ⇒ Object
- .content_height_from_css_height(box, height) ⇒ Object
- .content_width_from_css_width(box, width) ⇒ Object
- .declared_height(box) ⇒ Object
- .declared_width(box, available_width) ⇒ Object
- .horizontal_box_edges(box) ⇒ Object
- .layout(box, context, cursor_y = 0, parent_x = 0, containing_width = nil) ⇒ Object
- .optional_width(box, property, available_width) ⇒ Object
- .preserve_assigned_width?(box, raw_width, available_width) ⇒ Boolean
- .resolve_spacing(box, available_width) ⇒ Object
- .resolved_content_width(box, available_width) ⇒ Object
- .resolved_edge(style, property, side, values, available_width, fallback) ⇒ Object
- .resolved_edges(box, property, available_width, fallback) ⇒ Object
- .style_value(box, property) ⇒ Object
- .vertical_box_edges(box) ⇒ Object
Class Method Details
.auto_content_width(box, available_width) ⇒ Object
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/silk_layout/layout/block_layout.rb', line 134 def self.auto_content_width(box, available_width) content_width = available_width - box.margin[:left] - box.margin[:right] - box.border[:left] - box.border[:right] - box.padding[:left] - box.padding[:right] constrained_width = if border_box_sizing?(box) constrain_css_width(box, content_width + horizontal_box_edges(box), available_width) else constrain_css_width(box, content_width, available_width) end content_width_from_css_width(box, constrained_width) end |
.border_box_sizing?(box) ⇒ Boolean
186 187 188 |
# File 'lib/silk_layout/layout/block_layout.rb', line 186 def self.border_box_sizing?(box) style_value(box, "box-sizing") == "border-box" end |
.constrain_css_width(box, width, available_width) ⇒ Object
151 152 153 154 155 156 157 158 |
# File 'lib/silk_layout/layout/block_layout.rb', line 151 def self.constrain_css_width(box, width, available_width) min_width = optional_width(box, "min-width", available_width) max_width = optional_width(box, "max-width", available_width) width = [width, min_width].max if min_width width = [width, max_width].min if max_width width end |
.content_height_from_css_height(box, height) ⇒ Object
180 181 182 183 184 |
# File 'lib/silk_layout/layout/block_layout.rb', line 180 def self.content_height_from_css_height(box, height) content_height = border_box_sizing?(box) ? height - vertical_box_edges(box) : height [content_height, 0].max end |
.content_width_from_css_width(box, width) ⇒ Object
167 168 169 170 171 |
# File 'lib/silk_layout/layout/block_layout.rb', line 167 def self.content_width_from_css_width(box, width) return width unless border_box_sizing?(box) width - horizontal_box_edges(box) end |
.declared_height(box) ⇒ Object
173 174 175 176 177 178 |
# File 'lib/silk_layout/layout/block_layout.rb', line 173 def self.declared_height(box) raw = style_value(box, "height") return box.height if raw.nil? || raw == "auto" CSS::Values.resolve_length(raw, default: box.height) end |
.declared_width(box, available_width) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/silk_layout/layout/block_layout.rb', line 122 def self.declared_width(box, available_width) raw = style_value(box, "width") width = if raw && raw != "auto" && !preserve_assigned_width?(box, raw, available_width) CSS::Values.resolve_length(raw, reference: available_width, default: box.width) else box.width end constrain_css_width(box, width, available_width) end |
.horizontal_box_edges(box) ⇒ Object
190 191 192 |
# File 'lib/silk_layout/layout/block_layout.rb', line 190 def self.horizontal_box_edges(box) box.border[:left] + box.border[:right] + box.padding[:left] + box.padding[:right] end |
.layout(box, context, cursor_y = 0, parent_x = 0, containing_width = nil) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 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 83 84 85 |
# File 'lib/silk_layout/layout/block_layout.rb', line 6 def self.layout(box, context, cursor_y = 0, parent_x = 0, containing_width = nil) available_width = containing_width || context.width resolve_spacing(box, available_width) return FlexLayout.layout(box, context, cursor_y, parent_x, containing_width) if box.is_a?(FlexBox) box.x = parent_x + box.margin[:left] box.y = cursor_y + box.margin[:top] content_x = box.x + box.border[:left] + box.padding[:left] content_y = box.y + box.border[:top] + box.padding[:top] content_width = resolved_content_width(box, available_width) current_y = content_y new_children = [] inline_buffer = [] box.children.each do |child| if child.is_a?(InlineBox) inline_buffer << child next end if inline_buffer.any? lines = InlineFormatter.layout(inline_buffer, content_width, content_x, current_y) lines.each do |line| line.x = content_x line.y = current_y current_y += line.height new_children << line end inline_buffer.clear end layout(child, context, current_y, content_x, content_width) current_y += child.height + child.margin[:top] + child.margin[:bottom] new_children << child end if inline_buffer.any? lines = InlineFormatter.layout(inline_buffer, content_width, content_x, current_y) lines.each do |line| line.x = content_x line.y = current_y current_y += line.height new_children << line end end box.children = new_children content_height = current_y - content_y if box.explicit_height content_height = [content_height, content_height_from_css_height(box, declared_height(box))].max end max_child_width = box.children.map(&:width).max || 0 content_width = max_child_width if !box.explicit_width && content_width == 0 box.width = content_width + box.padding[:left] + box.padding[:right] + box.border[:left] + box.border[:right] box.height = content_height + box.padding[:top] + box.padding[:bottom] + box.border[:top] + box.border[:bottom] end |
.optional_width(box, property, available_width) ⇒ Object
160 161 162 163 164 165 |
# File 'lib/silk_layout/layout/block_layout.rb', line 160 def self.optional_width(box, property, available_width) raw = style_value(box, property) return nil if raw.nil? || raw == "none" || raw == "auto" CSS::Values.resolve_length(raw, reference: available_width, default: 0) end |
.preserve_assigned_width?(box, raw_width, available_width) ⇒ Boolean
198 199 200 201 202 |
# File 'lib/silk_layout/layout/block_layout.rb', line 198 def self.preserve_assigned_width?(box, raw_width, available_width) return false if CSS::Values.reference_relative?(raw_width) available_width && box.width == available_width end |
.resolve_spacing(box, available_width) ⇒ Object
87 88 89 90 |
# File 'lib/silk_layout/layout/block_layout.rb', line 87 def self.resolve_spacing(box, available_width) box.margin = resolved_edges(box, "margin", available_width, box.margin) box.padding = resolved_edges(box, "padding", available_width, box.padding) end |
.resolved_content_width(box, available_width) ⇒ Object
111 112 113 114 115 116 117 118 119 120 |
# File 'lib/silk_layout/layout/block_layout.rb', line 111 def self.resolved_content_width(box, available_width) content_width = if box.explicit_width content_width_from_css_width(box, declared_width(box, available_width)) else auto_content_width(box, available_width) end [content_width, 0].max end |
.resolved_edge(style, property, side, values, available_width, fallback) ⇒ Object
104 105 106 107 108 109 |
# File 'lib/silk_layout/layout/block_layout.rb', line 104 def self.resolved_edge(style, property, side, values, available_width, fallback) raw = style&.[]("#{property}-#{side}") || values[side] return fallback unless raw CSS::Values.resolve_length(raw, reference: available_width, default: fallback) end |
.resolved_edges(box, property, available_width, fallback) ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/silk_layout/layout/block_layout.rb', line 92 def self.resolved_edges(box, property, available_width, fallback) style = box.node&.computed_style values = CSS::Values.(style&.[](property)) { top: resolved_edge(style, property, :top, values, available_width, fallback[:top]), right: resolved_edge(style, property, :right, values, available_width, fallback[:right]), bottom: resolved_edge(style, property, :bottom, values, available_width, fallback[:bottom]), left: resolved_edge(style, property, :left, values, available_width, fallback[:left]) } end |
.style_value(box, property) ⇒ Object
204 205 206 207 208 209 |
# File 'lib/silk_layout/layout/block_layout.rb', line 204 def self.style_value(box, property) value = box.node&.computed_style&.[](property) return nil if value.to_s.strip.empty? value end |
.vertical_box_edges(box) ⇒ Object
194 195 196 |
# File 'lib/silk_layout/layout/block_layout.rb', line 194 def self.vertical_box_edges(box) box.border[:top] + box.border[:bottom] + box.padding[:top] + box.padding[:bottom] end |