New module: src/rendering/framebuffer.lisp (tangled from org/framebuffer.org) - framebuffer-backend class: implements backend protocol by writing to 2D cell array instead of emitting escape sequences - cell struct: per-cell state (char, fg, bg, bold, italic, underline, link-url) - make-framebuffer / framebuffer-width / framebuffer-height - draw-text, draw-rect, draw-border, draw-link, draw-ellipsis methods - diff-framebuffers: compares two framebuffers, returns changed cells - flush-framebuffer: diff + output changes to real backend - with-scissor macro: clip drawing operations to rectangle - cursor-move: added default no-op method for all backends - 20 new tests, all passing (372 total) Version bumped from 0.11.0 to 0.13.0. License field set to GPL-3.0 in ASDF.
95 lines
4.8 KiB
Common Lisp
95 lines
4.8 KiB
Common Lisp
(load "~/quicklisp/setup.lisp")
|
|
(ql:quickload :cl-tty :silent t)
|
|
(in-package :cl-tty.layout)
|
|
|
|
(defun trace-layout (root aw ah)
|
|
"Run compute-layout with detailed traces"
|
|
(labels ((p (node x y max-w max-h depth)
|
|
(let* ((children (layout-node-children node))
|
|
(is-row (eql (layout-node-direction node) :row))
|
|
(pl (box-edge (layout-node-padding node) :left))
|
|
(pt (box-edge (layout-node-padding node) :top))
|
|
(pr (box-edge (layout-node-padding node) :right))
|
|
(pb (box-edge (layout-node-padding node) :bottom))
|
|
(cw (max 0 (- max-w pl pr)))
|
|
(ch (max 0 (- max-h pt pb)))
|
|
(gap (layout-node-gap node))
|
|
(sizes (distribute-sizes children (if is-row cw ch) gap is-row)))
|
|
(format t "~v,0Tp~A: xy=~A,~A mw=~A mh=~A pl=~A pt=~A cw=~A ch=~A gap=~A sizes=~A~%"
|
|
(* depth 2) (if is-row 'ROW 'COL)
|
|
x y max-w max-h pl pt cw ch gap sizes)
|
|
(setf (layout-node-x node) (+ x pl)
|
|
(layout-node-y node) (+ y pt))
|
|
(loop :with pos = 0
|
|
:for child :in children
|
|
:for size :in sizes
|
|
:for i :from 0
|
|
:do (if is-row
|
|
(setf (layout-node-width child) size
|
|
(layout-node-x child) (+ x pl pos)
|
|
(layout-node-height child) ch
|
|
(layout-node-y child) (+ y pt))
|
|
(setf (layout-node-height child) size
|
|
(layout-node-y child) (+ y pt pos)
|
|
(layout-node-width child) cw
|
|
(layout-node-x child) (+ x pl)))
|
|
(format t "~v,0T~A#~D: placed pos=~A size=~A xy=~A,~A wh=~A,~A~%"
|
|
(* (1+ depth) 2) (if is-row 'H 'V) i pos size
|
|
(layout-node-x child) (layout-node-y child)
|
|
(layout-node-width child) (layout-node-height child))
|
|
(p child
|
|
(layout-node-x child) (layout-node-y child)
|
|
(if is-row size cw) (if is-row ch size)
|
|
(1+ depth))
|
|
(incf pos (+ size gap)))
|
|
(let ((last-child (car (last children))))
|
|
(if is-row
|
|
(setf (layout-node-width node)
|
|
(or (layout-node-fixed-width node)
|
|
(if last-child
|
|
(+ (layout-node-x node)
|
|
(layout-node-width last-child)
|
|
pr)
|
|
max-w))
|
|
(layout-node-height node)
|
|
max-h)
|
|
(setf (layout-node-height node)
|
|
(or (layout-node-fixed-height node)
|
|
(if last-child
|
|
(let ((last-y (layout-node-y last-child))
|
|
(last-h (layout-node-height last-child)))
|
|
(+ last-y last-h pb))
|
|
max-h))
|
|
(layout-node-width node)
|
|
max-w))
|
|
(format t "~v,0Tresult: node wh=~A,~A (fixed-w=~A fixed-h=~A)~%"
|
|
(* depth 2)
|
|
(layout-node-width node) (layout-node-height node)
|
|
(layout-node-fixed-width node) (layout-node-fixed-height node))))))
|
|
(p root 0 0 aw ah 0)
|
|
root))
|
|
|
|
(format t "~%=== 1. SINGLE-CHILD-IN-COLUMN ===~%~%")
|
|
(let* ((r (make-layout-node :direction :column :width 10 :height 20))
|
|
(c (make-layout-node :height 5)))
|
|
(layout-node-add-child r c)
|
|
(trace-layout r 10 20)
|
|
(format t "~%child final: x=~A (exp 0) y=~A (exp 0) w=~A h=~A (exp 5)~%~%"
|
|
(layout-node-x c) (layout-node-y c) (layout-node-width c) (layout-node-height c)))
|
|
|
|
(format t "=== 2. PADDING-REDUCES-CONTENT-AREA ===~%~%")
|
|
(let* ((r (make-layout-node :direction :column :padding '(:top 1 :left 1 :bottom 1 :right 1)))
|
|
(c (make-layout-node :height 3)))
|
|
(layout-node-add-child r c)
|
|
(trace-layout r 20 10)
|
|
(format t "~%child final: x=~A (exp 1) y=~A (exp 1)~%~%"
|
|
(layout-node-x c) (layout-node-y c)))
|
|
|
|
(format t "=== 3. FLEX-GROW-SINGLE-CHILD ===~%~%")
|
|
(let* ((root (make-layout-node :direction :row :width 20))
|
|
(c (make-layout-node :width 5 :grow 1)))
|
|
(layout-node-add-child root c)
|
|
(trace-layout root 20 10)
|
|
(format t "~%child final: w=~A (exp 20)~%~%"
|
|
(layout-node-width c)))
|