diff options
-rw-r--r-- | src/layout.nim | 122 |
1 files changed, 16 insertions, 106 deletions
diff --git a/src/layout.nim b/src/layout.nim index 41f48cc..cfec966 100644 --- a/src/layout.nim +++ b/src/layout.nim @@ -19,6 +19,9 @@ const block_elements = [ "legend", "details", "summary" ] +# Will expand to cover flexbox and grid in the future. +# The Document layout is included because pages can +# have multiple Documents through the use of iframes. type LayoutKind = enum Inline, Block, Document @@ -30,7 +33,7 @@ type Layout = ref object previous: Option[Layout] x, y, width, height: float cursorX, cursorY: float - case kind*: LayoutKind: + case kind: LayoutKind: of Inline: weight: int of Block: @@ -68,34 +71,30 @@ func populate_tree(self: Layout, parent: Option[Layout] = none(Layout), previous child.populate_tree(parent=some(self), previous=prevchild) prevchild = some(child) -# Overload the `get(value, otherwise)` function for brevity +# Overload the `value.get(otherwise)` function for brevity. func get(self: Option[Layout]): auto = - self.get(Layout(x: 22, y: 22, width: 22, height: 22)) + self.get(Layout()) # This function does a third pass through the layout tree to calculate positions. func calculate_position(self: Layout) = case self.kind: + of Document: + self.x = 1 + self.y = 1 + self.width = 500 + self.height = 500 of Inline: self.x = self.parent.get.x # every object starts at its parent's left edge... self.y = # if there is no previous sibiling, they start at their parent's top edge... - if self.previous.isSome(): - self.previous.get.y + self.previous.get.height - else: - self.parent.get.y + if self.previous.isSome(): self.previous.get.y + self.previous.get.height + else: self.parent.get.y self.width = self.parent.get.width # by default, objects are greedy and take up all the space they can get... of Block: self.x = self.parent.get.x self.y = - if self.previous.isSome(): - self.previous.get.y + self.previous.get.height - else: - self.parent.get.y + if self.previous.isSome(): self.previous.get.y + self.previous.get.height + else: self.parent.get.y self.width = self.parent.get.width - of Document: - self.x = 1 - self.y = 1 - self.width = 500 - self.height = 500 for child in self.children: calculate_position(child) @@ -107,9 +106,7 @@ func calculate_position(self: Layout) = self.height = # height calculation must come after the recursive call if self.children.len != 0: self.children.map(x => x.height).foldl(a + b) else: 0 - of Document: - discard # really should refactor the document layout out of here - + else: discard # the Document layout doesn't matter # These implicitly-mutating parameters are a bit gross, but # really seem like the best way to build this layout tree. @@ -125,93 +122,6 @@ func layout(html: Html): Layout = self.calculate_position() return self -# TODO: change Html into a distinct Node and adjust layout accordingly -type DocumentLayout = ref object - node: Node - children: seq[Layout] - -# Layout function that mutates a previously constructed layout object, -# so that we can make valid references to parent nodes. Not great. -# FIXME: Mutable cases within an object cause problems -#[func layout(self: var Layout, node: Node, parent: Option[Layout], previous: Option[Layout]) = - var children: seq[Layout] = @[] - var prevchild: Option[Layout] = none(Layout) - var kind: LayoutKind = Inline - case node.kind: - of Element: - for child in node.children: - var mutable = Layout() - mutable.layout(child, parent=some(self), previous=prevchild) - children.add(mutable) - prevchild = some(mutable) - if kind == Inline and child.kind == Element and child.tag in block_elements: - kind = Block - if node.children.len == 0: - kind = Block - of Text: - discard - self.node = node - self.parent = parent - self.previous = previous - self.children = children - self.kind = kind]# - -# I need to come up with a better way to generate a parent-child tree... -#[func layout(html: Html): Layout = - result = Layout(kind: Document, node: html[0], parent: none(Layout), previous: none(Layout), children: @[]) - for child in html[0].children: - var mutable = Layout() - mutable.layout(child, none(Layout), none(Layout)) - result.children.add(mutable)]# - -# Recursively construct the layout tree -#[func layout(node: Node, parent: Option[Layout], previous: Option[Layout]): Layout = - result = Layout() # !!! ref types are nil by default :-( - var children: seq[Layout] = @[] - var prevchild: Option[Layout] = none(Layout) - var kind: LayoutKind = Inline - case node.kind: - of Element: - for child in node.children: - # FIXME: parent nodes are broken. we pass a ref to result, which is different from the returned layout. - let current = child.layout(parent=some(result), previous=prevchild) - children.add(current) - prevchild = some(current) - if kind == Inline and child.kind == Element and child.tag in block_elements: - kind = Block - if node.children.len == 0: - kind = Block - of Text: - discard - return Layout(node: node, parent: parent, previous: previous, children: children, kind: kind)]# - -#[func layout_mode(node: Node): LayoutKind = - if node.kind == Text: - return Inline - elif node.children.len > 0: - for child in node.children: - if child.kind == Text: continue - if child.tag in block_elements: - return Block - return Inline - else: - return Block]# - -#[func layout(node: Node, parent: Layout, previous: Layout = nil): Layout = - if node.kind == Element and node.children.len > 0: - var previous: Layout = previous - var current: Layout - for child in node.children: - if previous == nil: - current = child.layout(result) - result.children.add(current) - else: - current = child.layout(result, previous) - result.children.add(current) - previous = current - else: - result = Layout(node: node, parent: parent, previous: previous, children: @[])]# - when isMainModule: import formats/uri, protocols/http, std/strutils |