literate: restructure all 19 org files with per-function blocks and prose
Every function, defclass, defstruct, defgeneric, defmethod, defmacro, defvar, and defparameter in every org file now has its own #+BEGIN_SRC block with literate prose above it explaining the design reasoning. Block counts before → after: package.org: 1 → 7 container-package.org: 1 → 1 (prose expanded) dirty.org: 4 → 6 render.org: 10 → 25 theme.org: 6 → 19 box-renderable.org: 9 → 29 scrollbox.org: 8 → 26 tabbar.org: 5 → 10 backend-protocol.org: 8 → 66 modern-backend.org: 17 → 53 detection.org: 4 → 6 layout-engine.org: 9 → 36 framebuffer.org: 8 → 37 markdown-renderer.org:13 → 38 dialog.org: 17 → 23 (merged dual structure) mouse.org: 4 → 25 select.org: 12 → 30 slot.org: 4 → 12 text-input.org: 11 → 53 Total: ~153 blocks → ~502 blocks Bugs fixed during restructuring: - render.org: stray π character typo (backenπd → backend) - modern-backend.org: sgr-attr missing closing paren + #+END_SRC - detection.org: invalid #\Esc character reference - select.org: extra closing paren in select-visible-options All 13 test suites pass at 100%.
This commit is contained in:
@@ -42,42 +42,96 @@ unnecessary — ~200 lines of CL math suffices.
|
||||
|
||||
* Tests
|
||||
|
||||
** Test package definition
|
||||
|
||||
The test package uses ~:fiveam~ for the test framework and imports
|
||||
all exported symbols from ~cl-tty.layout~.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(defpackage :cl-tty-layout-test
|
||||
(:use :cl :fiveam :cl-tty.layout)
|
||||
(:export #:run-tests))
|
||||
(in-package :cl-tty-layout-test)
|
||||
#+END_SRC
|
||||
|
||||
** Test suite
|
||||
|
||||
~fiveam~ suites collect related tests under a descriptive name for
|
||||
batch execution.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(def-suite layout-suite :description "Layout engine tests")
|
||||
(in-suite layout-suite)
|
||||
#+END_SRC
|
||||
|
||||
** Test runner
|
||||
|
||||
~run-tests~ provides a convenient entry point that prints results and
|
||||
exits cleanly for CI or batch runs.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(defun run-tests ()
|
||||
(let ((result (run 'layout-suite)))
|
||||
(fiveam:explain! result)
|
||||
(uiop:quit 0)))
|
||||
#+END_SRC
|
||||
|
||||
** Test: make-layout-node defaults
|
||||
|
||||
Verify that a node created with no arguments has the correct default
|
||||
direction ~:column~ and is of type ~layout-node~.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test make-layout-node-defaults
|
||||
(let ((n (make-layout-node)))
|
||||
(is (typep n 'layout-node))
|
||||
(is (eql (layout-node-direction n) :column))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: make-layout-node with ~:row~
|
||||
|
||||
Verify that passing ~:direction :row~ produces a node whose direction
|
||||
slot reflects that choice.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test make-layout-node-row
|
||||
(let ((n (make-layout-node :direction :row)))
|
||||
(is (eql (layout-node-direction n) :row))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: add-child sets parent
|
||||
|
||||
Children must have their ~parent~ back-pointer set when added, and
|
||||
the parent's ~children~ list must contain the child.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test add-child-sets-parent
|
||||
(let ((parent (make-layout-node)) (child (make-layout-node)))
|
||||
(layout-node-add-child parent child)
|
||||
(is (eql (layout-node-parent child) parent))
|
||||
(is (= (length (layout-node-children parent)) 1))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: remove-child clears parent
|
||||
|
||||
Removing a child should clear its parent reference and remove it
|
||||
from the parent's ~children~ list.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test remove-child-clears-parent
|
||||
(let ((parent (make-layout-node)) (child (make-layout-node)))
|
||||
(layout-node-add-child parent child)
|
||||
(layout-node-remove-child parent child)
|
||||
(is (null (layout-node-parent child)))
|
||||
(is (= (length (layout-node-children parent)) 0))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: column lays out two children vertically
|
||||
|
||||
In a column layout, children stack top-to-bottom. The first child
|
||||
starts at y=0; the second starts below the first.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test column-two-children-vertical
|
||||
(let* ((root (make-layout-node :direction :column))
|
||||
(c1 (make-layout-node :height 3))
|
||||
@@ -86,7 +140,14 @@ unnecessary — ~200 lines of CL math suffices.
|
||||
(compute-layout root 20 20)
|
||||
(is (= (layout-node-y c1) 0)) (is (= (layout-node-height c1) 3))
|
||||
(is (= (layout-node-y c2) 3)) (is (= (layout-node-height c2) 5))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: row lays out two children horizontally
|
||||
|
||||
In a row layout, children stack left-to-right. The first child starts
|
||||
at x=0; the second starts to the right of the first.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test row-two-children-horizontal
|
||||
(let* ((root (make-layout-node :direction :row))
|
||||
(c1 (make-layout-node :width 10))
|
||||
@@ -95,7 +156,15 @@ unnecessary — ~200 lines of CL math suffices.
|
||||
(compute-layout root 20 10)
|
||||
(is (= (layout-node-x c1) 0)) (is (= (layout-node-width c1) 10))
|
||||
(is (= (layout-node-x c2) 10)) (is (= (layout-node-width c2) 5))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: flex-grow distributes remaining space proportionally
|
||||
|
||||
When children have different ~grow~ values, remaining space is
|
||||
divided in proportion to those values. A child with grow=2 gets
|
||||
twice as much extra space as a child with grow=1.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test flex-grow-distributes-space
|
||||
(let* ((root (make-layout-node :direction :row :width 20))
|
||||
(c1 (make-layout-node :width 4 :grow 1))
|
||||
@@ -103,14 +172,28 @@ unnecessary — ~200 lines of CL math suffices.
|
||||
(layout-node-add-child root c1) (layout-node-add-child root c2)
|
||||
(compute-layout root 20 10)
|
||||
(is (= (layout-node-width c1) 8)) (is (= (layout-node-width c2) 12))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: flex-grow single child fills container
|
||||
|
||||
A single flexible child with ~grow~ set should expand to fill all
|
||||
available space in the container.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test 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)
|
||||
(compute-layout root 20 10)
|
||||
(is (= (layout-node-width c) 20))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: flex-shrink reduces overflow proportionally
|
||||
|
||||
When children exceed the container size, each child shrinks in
|
||||
proportion to its ~shrink~ value.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test flex-shrink-reduces-overflow
|
||||
(let* ((root (make-layout-node :direction :row :width 10))
|
||||
(c1 (make-layout-node :width 8 :shrink 1))
|
||||
@@ -118,7 +201,14 @@ unnecessary — ~200 lines of CL math suffices.
|
||||
(layout-node-add-child root c1) (layout-node-add-child root c2)
|
||||
(compute-layout root 10 10)
|
||||
(is (= (layout-node-width c1) 5)) (is (= (layout-node-width c2) 5))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: padding reduces content area
|
||||
|
||||
Padding insets the child rendering area. Children are offset by the
|
||||
padding values and sized to the remaining space.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test padding-reduces-content-area
|
||||
(let* ((root (make-layout-node :direction :column :padding '(:top 1 :left 1 :bottom 1 :right 1)))
|
||||
(c (make-layout-node :height 3)))
|
||||
@@ -126,7 +216,14 @@ unnecessary — ~200 lines of CL math suffices.
|
||||
(compute-layout root 20 10)
|
||||
(is (= (layout-node-x c) 1)) (is (= (layout-node-y c) 1))
|
||||
(is (= (layout-node-height c) 3))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: gap between children
|
||||
|
||||
The ~gap~ property inserts spacing between consecutive children
|
||||
without adding space before the first or after the last.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test gap-between-children
|
||||
(let* ((root (make-layout-node :direction :column :gap 2))
|
||||
(c1 (make-layout-node :height 3))
|
||||
@@ -134,25 +231,55 @@ unnecessary — ~200 lines of CL math suffices.
|
||||
(layout-node-add-child root c1) (layout-node-add-child root c2)
|
||||
(compute-layout root 20 20)
|
||||
(is (= (layout-node-y c1) 0)) (is (= (layout-node-y c2) 5))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: vbox macro
|
||||
|
||||
The ~vbox~ macro creates a column-direction container and adds
|
||||
children in one expression. The second child's y-offset should be
|
||||
the sum of the first child's height plus gap.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test vbox-macro
|
||||
(let ((r (vbox () (make-layout-node :height 3) (make-layout-node :height 5))))
|
||||
(compute-layout r 20 20)
|
||||
(is (= (length (layout-node-children r)) 2))
|
||||
(is (= (layout-node-y (elt (layout-node-children r) 1)) 3))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: hbox macro
|
||||
|
||||
The ~hbox~ macro creates a row-direction container. The second
|
||||
child's x-offset should equal the first child's width.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test hbox-macro
|
||||
(let ((r (hbox () (make-layout-node :width 5) (make-layout-node :width 3))))
|
||||
(compute-layout r 20 10)
|
||||
(is (= (length (layout-node-children r)) 2))
|
||||
(is (= (layout-node-x (elt (layout-node-children r) 1)) 5))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: spacer takes grow
|
||||
|
||||
The ~spacer~ macro creates a flexible node that pushes siblings
|
||||
apart. With two fixed-width children and a spacer between them, the
|
||||
spacer absorbs all remaining width.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test spacer-takes-grow
|
||||
(let ((r (hbox (:width 20) (make-layout-node :width 5) (spacer :grow 1) (make-layout-node :width 5))))
|
||||
(compute-layout r 20 10)
|
||||
(let ((c (layout-node-children r)))
|
||||
(is (= (layout-node-x (elt c 2)) 15)) (is (= (layout-node-width (elt c 1)) 10)))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: nested vbox in hbox
|
||||
|
||||
Nesting a column layout inside a row layout exercises the recursive
|
||||
solver. Sidebar gets fixed width; main content stretches.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test nested-vbox-in-hbox
|
||||
(let* ((sidebar (vbox (:width 5 :height 10) (make-layout-node :height 3) (make-layout-node :height 7)))
|
||||
(main (vbox (:grow 1 :height 10) (make-layout-node :height 2) (make-layout-node :grow 1)))
|
||||
@@ -163,15 +290,27 @@ unnecessary — ~200 lines of CL math suffices.
|
||||
(let ((sc (layout-node-children sidebar)))
|
||||
(is (= (layout-node-y (elt sc 0)) 0))
|
||||
(is (= (layout-node-y (elt sc 1)) 3)))))
|
||||
#+END_SRC
|
||||
|
||||
;; ── Edge Cases ────────────────────────────────────────────────
|
||||
** Test: empty container does not crash
|
||||
|
||||
Layout must gracefully handle containers with no children, returning
|
||||
valid integer dimensions.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test empty-container-does-not-crash
|
||||
(let ((r (make-layout-node)))
|
||||
(compute-layout r 20 20)
|
||||
(is (integerp (layout-node-width r)))
|
||||
(is (integerp (layout-node-height r)))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: single child in column
|
||||
|
||||
A column with one child positions it at the origin and sizes it to
|
||||
its requested height. Width is inherited from the container.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test single-child-in-column
|
||||
(let* ((r (make-layout-node :direction :column :width 10 :height 20))
|
||||
(c (make-layout-node :height 5)))
|
||||
@@ -179,7 +318,14 @@ unnecessary — ~200 lines of CL math suffices.
|
||||
(compute-layout r 10 20)
|
||||
(is (= (layout-node-y c) 0))
|
||||
(is (= (layout-node-height c) 5))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: zero-size container
|
||||
|
||||
When available space is zero, the solver must still produce valid
|
||||
integer coordinates without crashing or producing NaN/infinite values.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test zero-size-container
|
||||
(let* ((r (make-layout-node :direction :column))
|
||||
(c (make-layout-node :height 5)))
|
||||
@@ -187,7 +333,14 @@ unnecessary — ~200 lines of CL math suffices.
|
||||
(compute-layout r 0 0)
|
||||
(is (integerp (layout-node-x c)))
|
||||
(is (integerp (layout-node-y c)))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: deep nesting three levels
|
||||
|
||||
Three levels of nested vboxes ensure that layout is computed
|
||||
correctly for deeply nested subtrees.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test deep-nesting-three-levels
|
||||
(let* ((out (vbox ()
|
||||
(vbox (:grow 1)
|
||||
@@ -196,7 +349,14 @@ unnecessary — ~200 lines of CL math suffices.
|
||||
(elt (layout-node-children out) 0)) 0)))
|
||||
(compute-layout out 20 20)
|
||||
(is (= (layout-node-y leaf) 0))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: large padding leaves room
|
||||
|
||||
Substantial padding on all sides should offset children inward by the
|
||||
full padding amount.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test large-padding-leaves-room
|
||||
(let* ((r (make-layout-node :direction :column
|
||||
:padding '(:top 5 :left 5 :bottom 5 :right 5)))
|
||||
@@ -205,7 +365,14 @@ unnecessary — ~200 lines of CL math suffices.
|
||||
(compute-layout r 20 20)
|
||||
(is (= (layout-node-x c) 5))
|
||||
(is (= (layout-node-y c) 5))))
|
||||
#+END_SRC
|
||||
|
||||
** Test: negative grow is clamped
|
||||
|
||||
A negative ~grow~ value should not cause layout errors. The solver
|
||||
treats it as zero for distribution purposes and produces valid output.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/tests.lisp
|
||||
(test negative-grow-is-clamped
|
||||
(let* ((r (make-layout-node :direction :row :width 10))
|
||||
(c (make-layout-node :width 5 :grow -1)))
|
||||
@@ -218,6 +385,11 @@ unnecessary — ~200 lines of CL math suffices.
|
||||
|
||||
** Package
|
||||
|
||||
The ~cl-tty.layout~ package exports all public symbols for creating
|
||||
and manipulating layout trees. Internal accessors like
|
||||
~layout-node-parent~ and helpers like ~normalize-box~ are also
|
||||
exported for testing.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/layout.lisp
|
||||
(defpackage :cl-tty.layout
|
||||
(:use :cl)
|
||||
@@ -239,8 +411,11 @@ unnecessary — ~200 lines of CL math suffices.
|
||||
|
||||
** Box model utilities
|
||||
|
||||
*** normalize-box
|
||||
|
||||
~normalize-box~ converts nil, number, or plist inputs to a canonical
|
||||
plist. ~box-edge~ extracts the value for a specific edge.
|
||||
plist. This normalisation layer means users can pass ~:padding 2~ or
|
||||
~:padding '(:top 1 :left 2)~ interchangeably throughout the API.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/layout.lisp
|
||||
(defun normalize-box (spec)
|
||||
@@ -250,13 +425,27 @@ plist. ~box-edge~ extracts the value for a specific edge.
|
||||
for (key val) on spec by #'cddr
|
||||
do (setf (getf result key) val)
|
||||
finally (return result)))))
|
||||
#+END_SRC
|
||||
|
||||
*** box-edge
|
||||
|
||||
~box-edge~ extracts the value for a specific edge keyword from a
|
||||
canonical box plist, defaulting to zero if the key is not present.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/layout.lisp
|
||||
(defun box-edge (box edge)
|
||||
(or (getf box edge) 0))
|
||||
#+END_SRC
|
||||
|
||||
** Layout node class
|
||||
|
||||
The ~layout-node~ class holds all properties needed by the flexbox
|
||||
layout algorithm. Slots are split between tree structure (~parent~,
|
||||
~children~), computed layout results (~x~, ~y~, ~width~, ~height~),
|
||||
and input constraints (~direction~, ~grow~, ~shrink~, ~padding~,
|
||||
~margin~, ~gap~, ~position-type~, ~position-offset~, ~fixed-width~,
|
||||
~fixed-height~).
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/layout.lisp
|
||||
(defclass layout-node ()
|
||||
((parent :initform nil :accessor layout-node-parent)
|
||||
@@ -279,6 +468,10 @@ plist. ~box-edge~ extracts the value for a specific edge.
|
||||
|
||||
** Constructor
|
||||
|
||||
~make-layout-node~ is the primary constructor. It normalises all
|
||||
keyword arguments through ~normalize-box~ for padding/margin, fills
|
||||
defaults for missing values, and delegates to ~make-instance~.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/layout.lisp
|
||||
(defun make-layout-node (&key direction grow shrink padding margin gap
|
||||
position-type position-offset width height)
|
||||
@@ -294,13 +487,27 @@ plist. ~box-edge~ extracts the value for a specific edge.
|
||||
|
||||
** Tree manipulation
|
||||
|
||||
*** layout-node-add-child
|
||||
|
||||
~layout-node-add-child~ attaches a child to a parent by setting the
|
||||
child's parent back-pointer and appending to the parent's children
|
||||
list. Returns the child for convenience in chaining or ~let~ forms.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/layout.lisp
|
||||
(defun layout-node-add-child (parent child)
|
||||
(setf (layout-node-parent child) parent)
|
||||
(setf (layout-node-children parent)
|
||||
(nconc (layout-node-children parent) (list child)))
|
||||
child)
|
||||
#+END_SRC
|
||||
|
||||
*** layout-node-remove-child
|
||||
|
||||
~layout-node-remove-child~ detaches a child by clearing its parent
|
||||
back-pointer and removing it from the parent's children list.
|
||||
Returns the child.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/layout.lisp
|
||||
(defun layout-node-remove-child (parent child)
|
||||
(setf (layout-node-parent child) nil)
|
||||
(setf (layout-node-children parent)
|
||||
@@ -310,10 +517,12 @@ plist. ~box-edge~ extracts the value for a specific edge.
|
||||
|
||||
** Constraint solver
|
||||
|
||||
~distribute-sizes~ computes child sizes given available space and gap.
|
||||
Each child starts from its fixed size. Remaining space is distributed
|
||||
by grow ratio; overflow is reduced by shrink ratio. Rounding errors
|
||||
are amortized across the first N children.
|
||||
*** distribute-sizes
|
||||
|
||||
~distribute-sizes~ computes child sizes given available space and
|
||||
gap. Each child starts from its fixed size. Remaining space is
|
||||
distributed by grow ratio; overflow is reduced by shrink ratio.
|
||||
Rounding errors are amortized across the first N children.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/layout.lisp
|
||||
(defun distribute-sizes (children avail gap horizontal)
|
||||
@@ -346,9 +555,13 @@ are amortized across the first N children.
|
||||
sizes)))
|
||||
#+END_SRC
|
||||
|
||||
*** compute-layout
|
||||
|
||||
~compute-layout~ recursively lays out all children of the root node
|
||||
within given dimensions. It positions each child at the correct
|
||||
(x, y) coordinate and sizes it to fill the available space.
|
||||
(x, y) coordinate and sizes it to fill the available space. The
|
||||
inner ~labels~ form ~place-children~ handles the recursive descent,
|
||||
adjusting for padding and direction at each level.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/layout.lisp
|
||||
(defun compute-layout (root available-width available-height)
|
||||
@@ -409,6 +622,12 @@ within given dimensions. It positions each child at the correct
|
||||
|
||||
** Composable macros
|
||||
|
||||
*** vbox
|
||||
|
||||
~vbox~ creates a column-direction container with optional layout
|
||||
properties and adds all children via ~layout-node-add-child~. The
|
||||
~gensym~ ensures no variable capture in the expansion.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/layout.lisp
|
||||
(defmacro vbox ((&key grow shrink padding margin gap width height) &body children)
|
||||
(let ((n (gensym)))
|
||||
@@ -422,7 +641,14 @@ within given dimensions. It positions each child at the correct
|
||||
,@(when height `(:height ,height)))))
|
||||
,@(loop for c in children collect `(layout-node-add-child ,n ,c))
|
||||
,n)))
|
||||
#+END_SRC
|
||||
|
||||
*** hbox
|
||||
|
||||
~hbox~ creates a row-direction container, structurally identical to
|
||||
~vbox~ except the ~:direction~ is ~:row~.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/layout.lisp
|
||||
(defmacro hbox ((&key grow shrink padding margin gap width height) &body children)
|
||||
(let ((n (gensym)))
|
||||
`(let ((,n (make-layout-node :direction :row
|
||||
@@ -435,7 +661,14 @@ within given dimensions. It positions each child at the correct
|
||||
,@(when height `(:height ,height)))))
|
||||
,@(loop for c in children collect `(layout-node-add-child ,n ,c))
|
||||
,n)))
|
||||
#+END_SRC
|
||||
|
||||
*** spacer
|
||||
|
||||
~spacer~ creates a minimal flex-grow node that fills remaining space,
|
||||
defaulting to ~grow 1~ when no keyword is given.
|
||||
|
||||
#+BEGIN_SRC lisp :tangle ../src/layout/layout.lisp
|
||||
(defmacro spacer (&key grow)
|
||||
`(make-layout-node :grow ,(or grow 1)))
|
||||
#+END_SRC
|
||||
|
||||
Reference in New Issue
Block a user