aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/layout.nim122
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