diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buffer/buffer.nim | 1 | ||||
-rw-r--r-- | src/css/values.nim | 23 | ||||
-rw-r--r-- | src/display/pager.nim | 3 | ||||
-rw-r--r-- | src/io/term.nim | 5 | ||||
-rw-r--r-- | src/layout/box.nim | 7 | ||||
-rw-r--r-- | src/layout/engine.nim | 88 |
6 files changed, 88 insertions, 39 deletions
diff --git a/src/buffer/buffer.nim b/src/buffer/buffer.nim index b8e2d69f..685fa4db 100644 --- a/src/buffer/buffer.nim +++ b/src/buffer/buffer.nim @@ -285,6 +285,7 @@ proc gotoAnchor(buffer: Buffer) = inc i proc windowChange(buffer: Buffer) = + buffer.viewport = Viewport(window: buffer.attrs) buffer.width = buffer.attrs.width buffer.height = buffer.attrs.height - 1 buffer.reshape = true diff --git a/src/css/values.nim b/src/css/values.nim index 1d28484c..67200532 100644 --- a/src/css/values.nim +++ b/src/css/values.nim @@ -322,6 +322,29 @@ func cssLength(val: float64, unit: string): CSSLength = else: raise newException(CSSValueError, "Invalid unit") +func parseDimensionValues*(s: string): Option[CSSLength] = + if s == "": return + var i = 0 + while s[i] in AsciiWhitespace: inc i + if i >= s.len or s[i] notin AsciiDigit: return + var n: float64 + while s[i] in AsciiDigit: + n *= 10 + n += float64(decValue(s[i])) + inc i + if i >= s.len: return some(CSSLength(num: n, unit: UNIT_PX)) + if s[i] == '.': + inc i + if i >= s.len: return some(CSSLength(num: n, unit: UNIT_PX)) + var d = 1 + while i < s.len and s[i] in AsciiDigit: + n += float64(decValue(s[i])) / float64(d) + inc d + inc i + if i >= s.len: return some(CSSLength(num: n, unit: UNIT_PX)) + if s[i] == '%': return some(CSSLength(num: n, unit: UNIT_PERC)) + return some(CSSLength(num: n, unit: UNIT_PX)) + func color(r, g, b: int): CSSColor = return CSSColor(rgba: rgba(r, g, b, 256)) diff --git a/src/display/pager.nim b/src/display/pager.nim index 4d1d56e4..62137805 100644 --- a/src/display/pager.nim +++ b/src/display/pager.nim @@ -423,6 +423,9 @@ proc toggleSource*(pager: Pager) {.jsfunc.} = proc windowChange*(pager: Pager, attrs: WindowAttributes) = pager.attrs = attrs + pager.display = newFixedGrid(attrs.width, attrs.height - 1) + pager.statusmsg = newFixedGrid(attrs.width) + pager.term.windowChange(attrs) for container in pager.containers: container.windowChange(attrs) diff --git a/src/io/term.nim b/src/io/term.nim index e80eff29..0406907d 100644 --- a/src/io/term.nim +++ b/src/io/term.nim @@ -239,8 +239,9 @@ proc processFormat*(term: Terminal, format: var Format, cellf: Format): string = format = cellf -proc updateWindow*(term: Terminal) = - term.attrs = getWindowAttributes(term.outfile) +proc windowChange*(term: Terminal, attrs: WindowAttributes) = + term.attrs = attrs + term.cleared = false proc getCursorPos(term: Terminal): (int, int) = term.write(CSI("6n")) diff --git a/src/layout/box.nim b/src/layout/box.nim index bf6026da..ef4f7e8a 100644 --- a/src/layout/box.nim +++ b/src/layout/box.nim @@ -57,6 +57,7 @@ type TableBoxBuilder* = ref object of BlockBoxBuilder rowgroups*: seq[TableRowGroupBoxBuilder] + width*: Option[CSSLength] # WIDTH property InlineAtom* = ref object of RootObj offset*: Offset @@ -129,10 +130,8 @@ type ListItemBox* = ref object of BlockBox marker*: InlineContext - TableCellBox* = ref object of BlockBox - colspan*: int - CellWrapper* = object + builder*: TableCellBoxBuilder box*: BlockBox colspan*: int @@ -143,6 +142,8 @@ type TableContext* = object colwidths*: seq[int] + reflow*: seq[bool] + colwidths_specified*: seq[int] rows*: seq[RowContext] InlineBlockBox* = ref object of InlineAtom diff --git a/src/layout/engine.nim b/src/layout/engine.nim index 4ef81812..866fd786 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -366,14 +366,10 @@ proc setPreferredDimensions(bctx: BlockBox, width: int, height: Option[int]) = bctx.margin_left = preferred.margin_left bctx.margin_right = preferred.margin_right -proc newBlockBox_common2(bctx: BlockBox, parent: BlockBox, box: BoxBuilder) {.inline.} = - bctx.viewport = parent.viewport - bctx.computed = box.computed - bctx.setPreferredDimensions(parent.compwidth, parent.compheight) - -proc newBlockBox_common(parent: BlockBox, box: BoxBuilder): BlockBox {.inline.} = - new(result) - result.newBlockBox_common2(parent, box) +proc newBlockBox_common2(box: BlockBox, parent: BlockBox, builder: BoxBuilder) {.inline.} = + box.viewport = parent.viewport + box.computed = builder.computed + box.setPreferredDimensions(parent.compwidth, parent.compheight) proc newFlowRootBox(viewport: Viewport, box: BoxBuilder, parentWidth: int, parentHeight = none(int)): BlockBox {.inline.} = new(result) @@ -382,32 +378,29 @@ proc newFlowRootBox(viewport: Viewport, box: BoxBuilder, parentWidth: int, paren result.setPreferredDimensions(parentWidth, parentHeight) result.shrink = result.computed{"width"}.auto -proc newBlockBox(parent: BlockBox, box: BlockBoxBuilder): BlockBox = - result = newBlockBox_common(parent, box) - result.shrink = result.computed{"width"}.auto and parent.shrink - -proc newTableCellBox(parent: BlockBox, box: TableCellBoxBuilder): BlockBox = +proc newBlockBox(parent: BlockBox, box: BoxBuilder, ignore_parent_shrink = false): BlockBox = new(result) result.newBlockBox_common2(parent, box) - result.shrink = result.computed{"width"}.auto + result.shrink = result.computed{"width"}.auto and (ignore_parent_shrink or parent.shrink) + +proc newTableCellBox(parent: BlockBox, box: TableCellBoxBuilder): BlockBox = + return newBlockBox(parent, box, true) proc newTableRowBox(parent: BlockBox, box: TableRowBoxBuilder): BlockBox = - new(result) - result.newBlockBox_common2(parent, box) - result.shrink = result.computed{"width"}.auto and parent.shrink + return newBlockBox(parent, box) proc newTableBox(parent: BlockBox, box: TableBoxBuilder): BlockBox = - new(result) - result.newBlockBox_common2(parent, box) - result.shrink = result.computed{"width"}.auto and parent.shrink + let table = newBlockBox(parent, box) + if box.width.isSome: + table.compwidth = box.width.get.px(parent.viewport, parent.compwidth) + return table proc newListItem(parent: BlockBox, builder: ListItemBoxBuilder): ListItemBox = new(result) result.newBlockBox_common2(parent, builder.content) - result.shrink = result.computed{"width"}.auto and parent.shrink proc newBlockBox(viewport: Viewport, box: BlockBoxBuilder): BlockBox = - result = newFlowRootBox(viewport, box, viewport.window.width_px) + return newFlowRootBox(viewport, box, viewport.window.width_px) proc newInlineBlock(viewport: Viewport, builder: InlineBlockBoxBuilder, parentWidth: int, parentHeight = none(int)): InlineBlockBox = new(result) @@ -628,8 +621,11 @@ proc positionBlocks(bctx: BlockBox) = bctx.width += bctx.padding_left bctx.width += bctx.padding_right -proc buildTableCell(box: TableCellBoxBuilder, parent: BlockBox): BlockBox = +proc buildTableCell(box: TableCellBoxBuilder, parent: BlockBox, cellwidth = none(int)): BlockBox = result = parent.newTableCellBox(box) + if cellwidth.isSome: + result.compwidth = cellwidth.get + result.shrink = true if box.inlinelayout: result.buildInlineLayout(box.children) else: @@ -646,11 +642,17 @@ proc preBuildTableRow(pctx: var TableContext, box: TableRowBoxBuilder, parent: B assert child.computed{"display"} == DISPLAY_TABLE_CELL let cellbuilder = TableCellBoxBuilder(child) let cell = buildTableCell(cellbuilder, parent) - ctx.cells[i] = CellWrapper(box: cell, colspan: cellbuilder.colspan) + ctx.cells[i] = CellWrapper(box: cell, builder: cellbuilder, colspan: cellbuilder.colspan) + let pwidth = cellbuilder.computed{"width"} if pctx.colwidths.len <= n: pctx.colwidths.setLen(n + 1) + if pctx.colwidths_specified.len <= n: + if not pwidth.auto: + pctx.colwidths_specified.setLen(n + 1) for i in n ..< n + cellbuilder.colspan: pctx.colwidths[i] = max(cell.width div cellbuilder.colspan, pctx.colwidths[i]) + if not pwidth.auto: + pctx.colwidths_specified[i] = cell.compwidth n += cellbuilder.colspan ctx.width += cell.width inc i @@ -661,15 +663,20 @@ proc buildTableRow(pctx: TableContext, ctx: RowContext, parent: BlockBox, builde var n = 0 let row = newTableRowBox(parent, builder) for cellw in ctx.cells: - let cell = cellw.box + var cell = cellw.box cell.offset.x += x - let colspan = cellw.colspan - for i in n ..< n + colspan: - x += pctx.colwidths[i] - n += colspan + var w = 0 + for i in n ..< n + cellw.colspan: + w += pctx.colwidths[i] + x += w + if pctx.reflow.len > n: + for i in n ..< min(n + cellw.colspan, pctx.reflow.len): + if pctx.reflow[i]: + cell = buildTableCell(cellw.builder, parent, some(w)) + n += cellw.colspan row.nested.add(cell) row.height = max(row.height, cell.height) - row.width = ctx.width + row.width = x return row iterator rows(builder: TableBoxBuilder): TableRowBoxBuilder = @@ -687,16 +694,25 @@ iterator rows(builder: TableBoxBuilder): TableRowBoxBuilder = proc buildTable(box: TableBoxBuilder, parent: BlockBox): BlockBox = let table = parent.newTableBox(box) var ctx: TableContext + var maxw = 0 for row in box.rows: - ctx.rows.add(ctx.preBuildTableRow(row, table)) + let rctx = ctx.preBuildTableRow(row, table) + ctx.rows.add(rctx) + maxw = max(rctx.width, maxw) + if maxw > table.compwidth and false: #TODO + for n in ctx.colwidths_specified: + maxw -= n + ctx.reflow.setLen(ctx.colwidths.len) + for i in 0 ..< ctx.colwidths.len: + if ctx.colwidths[i] != 0: + ctx.colwidths[i] -= (maxw - table.compwidth) div ctx.colwidths[i] + ctx.reflow[i] = true for roww in ctx.rows: - var x = 0 - var n = 0 let row = ctx.buildTableRow(roww, table, roww.builder) row.offset.y += table.height table.height += row.height - table.width = max(row.width, table.width) table.nested.add(row) + table.width = max(row.width, table.width) return table proc buildBlocks(bctx: BlockBox, blocks: seq[BoxBuilder], node: StyledNode) = @@ -1050,6 +1066,10 @@ proc generateTableChildWrappers(box: TableBoxBuilder) = proc generateTableBox(styledNode: StyledNode, viewport: Viewport): TableBoxBuilder = let box = getTableBox(styledNode.computed) var blockgroup = newBlockGroup(box) #TODO this probably shouldn't exist + if styledNode.node != nil and styledNode.node.nodeType == ELEMENT_NODE: + #TODO put this in dom or something + let s = Element(styledNode.node).attr("width") + box.width = parseDimensionValues(s) var ibox: InlineBoxBuilder = nil var listItemCounter = 1 for child in styledNode.children: |