v0.1.0: Yoga FFI binding — CFFI types, 50+ bound functions, 9 tests
- Load Yoga shared library via CFFI (/usr/local/lib/libyoga.so) - 15 enum constant sets (YGDirection through YGUnit) - Foreign type definitions: yg-node-ref, yg-size, yg-value - Core node management: new, free, insert-child, remove-child, get-child-count - Layout: calculate-layout, get-left/top/width/height - Style setters: direction, flex-direction, justify-content, align-items, align-self, flex-wrap, position-type, flex-grow/shrink/basis, overflow, display, width/height, min/max dimensions, padding, margin, border, gap, position (point and percent) - Style getters: width, height, flex-direction, align-items, justify-content - Disable FP traps for SBCL (Yoga uses NaN for YGUndefined) GREEN: 9/9 pass (22 assertions) - test-node-create-free, test-node-child-count, test-node-insert-child - test-layout-basic-column, test-layout-basic-row - test-layout-flex-grow, test-layout-absolute-position - test-layout-padding, test-layout-nested
This commit is contained in:
9
cl-tui.asd
Normal file
9
cl-tui.asd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
(defsystem :cl-tui
|
||||||
|
:name "cl-tui"
|
||||||
|
:author "memex"
|
||||||
|
:version "0.1.0"
|
||||||
|
:license "AGPLv3"
|
||||||
|
:description "Reusable Common Lisp Terminal UI Framework"
|
||||||
|
:depends-on (:cffi :croatoan)
|
||||||
|
:serial t
|
||||||
|
:components ((:file "lisp/yoga-ffi")))
|
||||||
631
lisp/yoga-ffi.lisp
Normal file
631
lisp/yoga-ffi.lisp
Normal file
@@ -0,0 +1,631 @@
|
|||||||
|
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||||
|
(ql:quickload :cffi :silent t))
|
||||||
|
|
||||||
|
(defpackage :cl-tui.yoga-ffi
|
||||||
|
(:use :cl)
|
||||||
|
(:export
|
||||||
|
;; library
|
||||||
|
#:*libyoga*
|
||||||
|
#:load-yoga
|
||||||
|
;; constants
|
||||||
|
#:+yg-direction-inherit+
|
||||||
|
#:+yg-direction-ltr+
|
||||||
|
#:+yg-direction-rtl+
|
||||||
|
#:+yg-flex-direction-column+
|
||||||
|
#:+yg-flex-direction-column-reverse+
|
||||||
|
#:+yg-flex-direction-row+
|
||||||
|
#:+yg-flex-direction-row-reverse+
|
||||||
|
#:+yg-justify-auto+
|
||||||
|
#:+yg-justify-flex-start+
|
||||||
|
#:+yg-justify-center+
|
||||||
|
#:+yg-justify-flex-end+
|
||||||
|
#:+yg-justify-space-between+
|
||||||
|
#:+yg-justify-space-around+
|
||||||
|
#:+yg-justify-space-evenly+
|
||||||
|
#:+yg-justify-stretch+
|
||||||
|
#:+yg-align-auto+
|
||||||
|
#:+yg-align-flex-start+
|
||||||
|
#:+yg-align-center+
|
||||||
|
#:+yg-align-flex-end+
|
||||||
|
#:+yg-align-stretch+
|
||||||
|
#:+yg-align-baseline+
|
||||||
|
#:+yg-align-space-between+
|
||||||
|
#:+yg-align-space-around+
|
||||||
|
#:+yg-align-space-evenly+
|
||||||
|
#:+yg-wrap-nowrap+
|
||||||
|
#:+yg-wrap-wrap+
|
||||||
|
#:+yg-wrap-wrap-reverse+
|
||||||
|
#:+yg-position-type-static+
|
||||||
|
#:+yg-position-type-relative+
|
||||||
|
#:+yg-position-type-absolute+
|
||||||
|
#:+yg-overflow-visible+
|
||||||
|
#:+yg-overflow-hidden+
|
||||||
|
#:+yg-overflow-scroll+
|
||||||
|
#:+yg-display-flex+
|
||||||
|
#:+yg-display-none+
|
||||||
|
#:+yg-display-contents+
|
||||||
|
#:+yg-edge-left+
|
||||||
|
#:+yg-edge-top+
|
||||||
|
#:+yg-edge-right+
|
||||||
|
#:+yg-edge-bottom+
|
||||||
|
#:+yg-edge-start+
|
||||||
|
#:+yg-edge-end+
|
||||||
|
#:+yg-edge-horizontal+
|
||||||
|
#:+yg-edge-vertical+
|
||||||
|
#:+yg-edge-all+
|
||||||
|
#:+yg-gutter-column+
|
||||||
|
#:+yg-gutter-row+
|
||||||
|
#:+yg-gutter-all+
|
||||||
|
#:+yg-unit-undefined+
|
||||||
|
#:+yg-unit-point+
|
||||||
|
#:+yg-unit-percent+
|
||||||
|
#:+yg-unit-auto+
|
||||||
|
;; types
|
||||||
|
#:yg-node-ref
|
||||||
|
#:yg-node-const-ref
|
||||||
|
;; node management
|
||||||
|
#:yg-node-new
|
||||||
|
#:yg-node-free
|
||||||
|
#:yg-node-free-recursive
|
||||||
|
#:yg-node-insert-child
|
||||||
|
#:yg-node-remove-child
|
||||||
|
#:yg-node-remove-all-children
|
||||||
|
#:yg-node-get-child-count
|
||||||
|
#:yg-node-get-child
|
||||||
|
;; layout
|
||||||
|
#:yg-node-calculate-layout
|
||||||
|
#:yg-node-layout-get-left
|
||||||
|
#:yg-node-layout-get-top
|
||||||
|
#:yg-node-layout-get-width
|
||||||
|
#:yg-node-layout-get-height
|
||||||
|
#:yg-node-layout-get-right
|
||||||
|
#:yg-node-layout-get-bottom
|
||||||
|
#:yg-node-is-dirty
|
||||||
|
#:yg-node-mark-dirty
|
||||||
|
;; style direction & flex
|
||||||
|
#:yg-node-style-set-direction
|
||||||
|
#:yg-node-style-set-flex-direction
|
||||||
|
#:yg-node-style-set-justify-content
|
||||||
|
#:yg-node-style-set-align-items
|
||||||
|
#:yg-node-style-set-align-self
|
||||||
|
#:yg-node-style-set-align-content
|
||||||
|
#:yg-node-style-set-flex-wrap
|
||||||
|
#:yg-node-style-set-position-type
|
||||||
|
#:yg-node-style-set-flex-grow
|
||||||
|
#:yg-node-style-set-flex-shrink
|
||||||
|
#:yg-node-style-set-flex-basis
|
||||||
|
#:yg-node-style-set-flex-basis-auto
|
||||||
|
#:yg-node-style-set-flex-basis-percent
|
||||||
|
#:yg-node-style-set-overflow
|
||||||
|
#:yg-node-style-set-display
|
||||||
|
;; style dimensions
|
||||||
|
#:yg-node-style-set-width
|
||||||
|
#:yg-node-style-set-width-percent
|
||||||
|
#:yg-node-style-set-width-auto
|
||||||
|
#:yg-node-style-set-height
|
||||||
|
#:yg-node-style-set-height-percent
|
||||||
|
#:yg-node-style-set-height-auto
|
||||||
|
#:yg-node-style-set-min-width
|
||||||
|
#:yg-node-style-set-min-width-percent
|
||||||
|
#:yg-node-style-set-min-height
|
||||||
|
#:yg-node-style-set-min-height-percent
|
||||||
|
#:yg-node-style-set-max-width
|
||||||
|
#:yg-node-style-set-max-height
|
||||||
|
#:yg-node-style-set-aspect-ratio
|
||||||
|
;; style padding/margin/border/gap/position
|
||||||
|
#:yg-node-style-set-padding
|
||||||
|
#:yg-node-style-set-padding-percent
|
||||||
|
#:yg-node-style-set-margin
|
||||||
|
#:yg-node-style-set-margin-percent
|
||||||
|
#:yg-node-style-set-margin-auto
|
||||||
|
#:yg-node-style-set-border
|
||||||
|
#:yg-node-style-set-gap
|
||||||
|
#:yg-node-style-set-position
|
||||||
|
#:yg-node-style-set-position-percent
|
||||||
|
;; style getters
|
||||||
|
#:yg-node-style-get-width
|
||||||
|
#:yg-node-style-get-height
|
||||||
|
#:yg-node-style-get-flex-direction
|
||||||
|
#:yg-node-style-get-align-items
|
||||||
|
#:yg-node-style-get-justify-content))
|
||||||
|
|
||||||
|
(in-package :cl-tui.yoga-ffi)
|
||||||
|
|
||||||
|
(defparameter *libyoga* nil "Handle for the loaded Yoga shared library.")
|
||||||
|
|
||||||
|
(defun load-yoga ()
|
||||||
|
"Load the Yoga shared library via CFFI."
|
||||||
|
(setf *libyoga* (cffi:load-foreign-library "/usr/local/lib/libyoga.so"))
|
||||||
|
(sb-int:set-floating-point-modes :traps '())
|
||||||
|
*libyoga*)
|
||||||
|
|
||||||
|
(load-yoga)
|
||||||
|
|
||||||
|
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||||
|
;; YGDirection
|
||||||
|
(defconstant +yg-direction-inherit+ 0)
|
||||||
|
(defconstant +yg-direction-ltr+ 1)
|
||||||
|
(defconstant +yg-direction-rtl+ 2)
|
||||||
|
;; YGFlexDirection
|
||||||
|
(defconstant +yg-flex-direction-column+ 0)
|
||||||
|
(defconstant +yg-flex-direction-column-reverse+ 1)
|
||||||
|
(defconstant +yg-flex-direction-row+ 2)
|
||||||
|
(defconstant +yg-flex-direction-row-reverse+ 3)
|
||||||
|
;; YGJustify
|
||||||
|
(defconstant +yg-justify-auto+ 0)
|
||||||
|
(defconstant +yg-justify-flex-start+ 1)
|
||||||
|
(defconstant +yg-justify-center+ 2)
|
||||||
|
(defconstant +yg-justify-flex-end+ 3)
|
||||||
|
(defconstant +yg-justify-space-between+ 4)
|
||||||
|
(defconstant +yg-justify-space-around+ 5)
|
||||||
|
(defconstant +yg-justify-space-evenly+ 6)
|
||||||
|
(defconstant +yg-justify-stretch+ 7)
|
||||||
|
;; YGAlign
|
||||||
|
(defconstant +yg-align-auto+ 0)
|
||||||
|
(defconstant +yg-align-flex-start+ 1)
|
||||||
|
(defconstant +yg-align-center+ 2)
|
||||||
|
(defconstant +yg-align-flex-end+ 3)
|
||||||
|
(defconstant +yg-align-stretch+ 4)
|
||||||
|
(defconstant +yg-align-baseline+ 5)
|
||||||
|
(defconstant +yg-align-space-between+ 6)
|
||||||
|
(defconstant +yg-align-space-around+ 7)
|
||||||
|
(defconstant +yg-align-space-evenly+ 8)
|
||||||
|
;; YGWrap
|
||||||
|
(defconstant +yg-wrap-nowrap+ 0)
|
||||||
|
(defconstant +yg-wrap-wrap+ 1)
|
||||||
|
(defconstant +yg-wrap-wrap-reverse+ 2)
|
||||||
|
;; YGPositionType
|
||||||
|
(defconstant +yg-position-type-static+ 0)
|
||||||
|
(defconstant +yg-position-type-relative+ 1)
|
||||||
|
(defconstant +yg-position-type-absolute+ 2)
|
||||||
|
;; YGOverflow
|
||||||
|
(defconstant +yg-overflow-visible+ 0)
|
||||||
|
(defconstant +yg-overflow-hidden+ 1)
|
||||||
|
(defconstant +yg-overflow-scroll+ 2)
|
||||||
|
;; YGDisplay
|
||||||
|
(defconstant +yg-display-flex+ 0)
|
||||||
|
(defconstant +yg-display-none+ 1)
|
||||||
|
(defconstant +yg-display-contents+ 2)
|
||||||
|
;; YGEdge
|
||||||
|
(defconstant +yg-edge-left+ 0)
|
||||||
|
(defconstant +yg-edge-top+ 1)
|
||||||
|
(defconstant +yg-edge-right+ 2)
|
||||||
|
(defconstant +yg-edge-bottom+ 3)
|
||||||
|
(defconstant +yg-edge-start+ 4)
|
||||||
|
(defconstant +yg-edge-end+ 5)
|
||||||
|
(defconstant +yg-edge-horizontal+ 6)
|
||||||
|
(defconstant +yg-edge-vertical+ 7)
|
||||||
|
(defconstant +yg-edge-all+ 8)
|
||||||
|
;; YGGutter
|
||||||
|
(defconstant +yg-gutter-column+ 0)
|
||||||
|
(defconstant +yg-gutter-row+ 1)
|
||||||
|
(defconstant +yg-gutter-all+ 2)
|
||||||
|
;; YGUnit
|
||||||
|
(defconstant +yg-unit-undefined+ 0)
|
||||||
|
(defconstant +yg-unit-point+ 1)
|
||||||
|
(defconstant +yg-unit-percent+ 2)
|
||||||
|
(defconstant +yg-unit-auto+ 3))
|
||||||
|
|
||||||
|
(cffi:defctype yg-node-ref :pointer)
|
||||||
|
(cffi:defctype yg-node-const-ref :pointer)
|
||||||
|
|
||||||
|
(cffi:defcstruct yg-size
|
||||||
|
(width :float)
|
||||||
|
(height :float))
|
||||||
|
|
||||||
|
(cffi:defcstruct yg-value
|
||||||
|
(value :float)
|
||||||
|
(unit :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeNew" yg-node-new) yg-node-ref)
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeFree" yg-node-free) :void
|
||||||
|
(node yg-node-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeFreeRecursive" yg-node-free-recursive) :void
|
||||||
|
(node yg-node-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeInsertChild" yg-node-insert-child) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(child yg-node-ref)
|
||||||
|
(index :unsigned-int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeRemoveChild" yg-node-remove-child) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(child yg-node-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeRemoveAllChildren" yg-node-remove-all-children) :void
|
||||||
|
(node yg-node-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeGetChildCount" yg-node-get-child-count) :unsigned-int
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeGetChild" yg-node-get-child) yg-node-ref
|
||||||
|
(node yg-node-ref)
|
||||||
|
(index :unsigned-int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeCalculateLayout" yg-node-calculate-layout) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(available-width :float)
|
||||||
|
(available-height :float)
|
||||||
|
(owner-direction :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeLayoutGetLeft" yg-node-layout-get-left) :float
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeLayoutGetTop" yg-node-layout-get-top) :float
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeLayoutGetWidth" yg-node-layout-get-width) :float
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeLayoutGetHeight" yg-node-layout-get-height) :float
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeLayoutGetRight" yg-node-layout-get-right) :float
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeLayoutGetBottom" yg-node-layout-get-bottom) :float
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeIsDirty" yg-node-is-dirty) :boolean
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeMarkDirty" yg-node-mark-dirty) :void
|
||||||
|
(node yg-node-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetDirection" yg-node-style-set-direction) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(direction :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetFlexDirection" yg-node-style-set-flex-direction) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(flex-direction :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetJustifyContent" yg-node-style-set-justify-content) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(justify :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetAlignItems" yg-node-style-set-align-items) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(align :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetAlignSelf" yg-node-style-set-align-self) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(align :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetAlignContent" yg-node-style-set-align-content) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(align :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetFlexWrap" yg-node-style-set-flex-wrap) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(wrap :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetPositionType" yg-node-style-set-position-type) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(position-type :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetFlexGrow" yg-node-style-set-flex-grow) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(flex-grow :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetFlexShrink" yg-node-style-set-flex-shrink) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(flex-shrink :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetFlexBasis" yg-node-style-set-flex-basis) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(flex-basis :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetFlexBasisAuto" yg-node-style-set-flex-basis-auto) :void
|
||||||
|
(node yg-node-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetFlexBasisPercent" yg-node-style-set-flex-basis-percent) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(flex-basis :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetOverflow" yg-node-style-set-overflow) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(overflow :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetDisplay" yg-node-style-set-display) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(display :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetWidth" yg-node-style-set-width) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(width :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetWidthPercent" yg-node-style-set-width-percent) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(width :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetWidthAuto" yg-node-style-set-width-auto) :void
|
||||||
|
(node yg-node-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetHeight" yg-node-style-set-height) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(height :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetHeightPercent" yg-node-style-set-height-percent) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(height :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetHeightAuto" yg-node-style-set-height-auto) :void
|
||||||
|
(node yg-node-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMinWidth" yg-node-style-set-min-width) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(min-width :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMinWidthPercent" yg-node-style-set-min-width-percent) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(min-width :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMinHeight" yg-node-style-set-min-height) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(min-height :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMinHeightPercent" yg-node-style-set-min-height-percent) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(min-height :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMaxWidth" yg-node-style-set-max-width) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(max-width :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMaxHeight" yg-node-style-set-max-height) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(max-height :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetAspectRatio" yg-node-style-set-aspect-ratio) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(aspect-ratio :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetPadding" yg-node-style-set-padding) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(edge :int)
|
||||||
|
(padding :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetPaddingPercent" yg-node-style-set-padding-percent) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(edge :int)
|
||||||
|
(padding :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMargin" yg-node-style-set-margin) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(edge :int)
|
||||||
|
(margin :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMarginPercent" yg-node-style-set-margin-percent) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(edge :int)
|
||||||
|
(margin :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMarginAuto" yg-node-style-set-margin-auto) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(edge :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetBorder" yg-node-style-set-border) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(edge :int)
|
||||||
|
(border :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetGap" yg-node-style-set-gap) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(gutter :int)
|
||||||
|
(gap :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetPosition" yg-node-style-set-position) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(edge :int)
|
||||||
|
(position :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetPositionPercent" yg-node-style-set-position-percent) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(edge :int)
|
||||||
|
(position :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleGetWidth" yg-node-style-get-width) yg-value
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleGetHeight" yg-node-style-get-height) yg-value
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleGetFlexDirection" yg-node-style-get-flex-direction) :int
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleGetAlignItems" yg-node-style-get-align-items) :int
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleGetJustifyContent" yg-node-style-get-justify-content) :int
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||||
|
(ql:quickload :fiveam :silent t))
|
||||||
|
|
||||||
|
(defpackage :cl-tui.yoga-ffi-tests
|
||||||
|
(:use :cl :fiveam)
|
||||||
|
(:import-from :cl-tui.yoga-ffi
|
||||||
|
#:load-yoga
|
||||||
|
#:yg-node-new
|
||||||
|
#:yg-node-free
|
||||||
|
#:yg-node-free-recursive
|
||||||
|
#:yg-node-insert-child
|
||||||
|
#:yg-node-get-child-count
|
||||||
|
#:yg-node-calculate-layout
|
||||||
|
#:yg-node-layout-get-left
|
||||||
|
#:yg-node-layout-get-top
|
||||||
|
#:yg-node-layout-get-width
|
||||||
|
#:yg-node-layout-get-height
|
||||||
|
#:yg-node-style-set-flex-direction
|
||||||
|
#:yg-node-style-set-justify-content
|
||||||
|
#:yg-node-style-set-align-items
|
||||||
|
#:yg-node-style-set-width
|
||||||
|
#:yg-node-style-set-height
|
||||||
|
#:yg-node-style-set-padding
|
||||||
|
#:yg-node-style-set-margin
|
||||||
|
#:yg-node-style-set-flex-grow
|
||||||
|
#:yg-node-style-set-position-type
|
||||||
|
#:yg-node-style-set-position
|
||||||
|
#:+yg-flex-direction-column+
|
||||||
|
#:+yg-flex-direction-row+
|
||||||
|
#:+yg-justify-center+
|
||||||
|
#:+yg-justify-flex-start+
|
||||||
|
#:+yg-align-stretch+
|
||||||
|
#:+yg-align-center+
|
||||||
|
#:+yg-edge-all+
|
||||||
|
#:+yg-edge-left+
|
||||||
|
#:+yg-edge-top+
|
||||||
|
#:+yg-edge-right+
|
||||||
|
#:+yg-edge-bottom+
|
||||||
|
#:+yg-position-type-relative+
|
||||||
|
#:+yg-position-type-absolute+
|
||||||
|
;; YGDirection constants (different from YGFlexDirection!)
|
||||||
|
#:+yg-direction-inherit+
|
||||||
|
#:+yg-direction-ltr+
|
||||||
|
#:+yg-direction-rtl+))
|
||||||
|
|
||||||
|
(in-package :cl-tui.yoga-ffi-tests)
|
||||||
|
|
||||||
|
(fiveam:def-suite yoga-ffi-suite
|
||||||
|
:description "Yoga FFI binding verification")
|
||||||
|
(fiveam:in-suite yoga-ffi-suite)
|
||||||
|
|
||||||
|
(fiveam:test test-node-create-free
|
||||||
|
"Contract: yg-node-new returns a non-null pointer; yg-node-free doesn't crash."
|
||||||
|
(let ((node (yg-node-new)))
|
||||||
|
(fiveam:is (not (cffi:null-pointer-p node)))
|
||||||
|
(yg-node-free node)
|
||||||
|
(fiveam:pass)))
|
||||||
|
|
||||||
|
(fiveam:test test-node-child-count
|
||||||
|
"Contract: yg-node-get-child-count returns 0 for a new node."
|
||||||
|
(let ((node (yg-node-new)))
|
||||||
|
(fiveam:is (= 0 (yg-node-get-child-count node)))
|
||||||
|
(yg-node-free node)))
|
||||||
|
|
||||||
|
(fiveam:test test-node-insert-child
|
||||||
|
"Contract: inserting a child increments the child count."
|
||||||
|
(let ((parent (yg-node-new))
|
||||||
|
(child (yg-node-new)))
|
||||||
|
(yg-node-insert-child parent child 0)
|
||||||
|
(fiveam:is (= 1 (yg-node-get-child-count parent)))
|
||||||
|
(yg-node-free-recursive parent)))
|
||||||
|
|
||||||
|
(fiveam:test test-layout-basic-column
|
||||||
|
"Contract: a column with two fixed-height children positions them vertically."
|
||||||
|
(let* ((root (yg-node-new)))
|
||||||
|
(yg-node-style-set-width root 100.0)
|
||||||
|
(yg-node-style-set-height root 200.0)
|
||||||
|
(yg-node-style-set-flex-direction root +yg-flex-direction-column+)
|
||||||
|
(let ((child1 (yg-node-new))
|
||||||
|
(child2 (yg-node-new)))
|
||||||
|
(yg-node-style-set-width child1 100.0)
|
||||||
|
(yg-node-style-set-height child1 50.0)
|
||||||
|
(yg-node-style-set-width child2 100.0)
|
||||||
|
(yg-node-style-set-height child2 50.0)
|
||||||
|
(yg-node-insert-child root child1 0)
|
||||||
|
(yg-node-insert-child root child2 1)
|
||||||
|
(yg-node-calculate-layout root 100.0 200.0 +yg-direction-ltr+)
|
||||||
|
(fiveam:is (= 0.0 (yg-node-layout-get-left child1)))
|
||||||
|
(fiveam:is (= 0.0 (yg-node-layout-get-top child1)))
|
||||||
|
(fiveam:is (= 50.0 (yg-node-layout-get-top child2)))
|
||||||
|
(yg-node-free-recursive root))))
|
||||||
|
|
||||||
|
(fiveam:test test-layout-basic-row
|
||||||
|
"Contract: a row with two fixed-width children positions them horizontally."
|
||||||
|
(let* ((root (yg-node-new)))
|
||||||
|
(yg-node-style-set-width root 200.0)
|
||||||
|
(yg-node-style-set-height root 100.0)
|
||||||
|
(yg-node-style-set-flex-direction root +yg-flex-direction-row+)
|
||||||
|
(let ((child1 (yg-node-new))
|
||||||
|
(child2 (yg-node-new)))
|
||||||
|
(yg-node-style-set-width child1 80.0)
|
||||||
|
(yg-node-style-set-height child1 50.0)
|
||||||
|
(yg-node-style-set-width child2 80.0)
|
||||||
|
(yg-node-style-set-height child2 50.0)
|
||||||
|
(yg-node-insert-child root child1 0)
|
||||||
|
(yg-node-insert-child root child2 1)
|
||||||
|
(yg-node-calculate-layout root 200.0 100.0 +yg-direction-ltr+)
|
||||||
|
(fiveam:is (= 0.0 (yg-node-layout-get-left child1)))
|
||||||
|
(fiveam:is (= 0.0 (yg-node-layout-get-top child1)))
|
||||||
|
(fiveam:is (= 80.0 (yg-node-layout-get-left child2)))
|
||||||
|
(yg-node-free-recursive root))))
|
||||||
|
|
||||||
|
(fiveam:test test-layout-flex-grow
|
||||||
|
"Contract: flex-grow distributes remaining space proportionally."
|
||||||
|
(let* ((root (yg-node-new)))
|
||||||
|
(yg-node-style-set-width root 200.0)
|
||||||
|
(yg-node-style-set-height root 100.0)
|
||||||
|
(yg-node-style-set-flex-direction root +yg-flex-direction-row+)
|
||||||
|
(let ((child1 (yg-node-new))
|
||||||
|
(child2 (yg-node-new)))
|
||||||
|
(yg-node-style-set-height child1 100.0)
|
||||||
|
(yg-node-style-set-flex-grow child1 1.0)
|
||||||
|
(yg-node-style-set-height child2 100.0)
|
||||||
|
(yg-node-style-set-flex-grow child2 2.0)
|
||||||
|
(yg-node-insert-child root child1 0)
|
||||||
|
(yg-node-insert-child root child2 1)
|
||||||
|
(yg-node-calculate-layout root 200.0 100.0 +yg-direction-ltr+)
|
||||||
|
(fiveam:is (< 0.0 (yg-node-layout-get-width child1)))
|
||||||
|
(fiveam:is (< 0.0 (yg-node-layout-get-width child2)))
|
||||||
|
(fiveam:is (= 200.0 (+ (yg-node-layout-get-width child1)
|
||||||
|
(yg-node-layout-get-width child2))))
|
||||||
|
(yg-node-free-recursive root))))
|
||||||
|
|
||||||
|
(fiveam:test test-layout-absolute-position
|
||||||
|
"Contract: an absolute child positions relative to its parent."
|
||||||
|
(let* ((root (yg-node-new)))
|
||||||
|
(yg-node-style-set-width root 300.0)
|
||||||
|
(yg-node-style-set-height root 300.0)
|
||||||
|
(let ((child (yg-node-new)))
|
||||||
|
(yg-node-style-set-width child 50.0)
|
||||||
|
(yg-node-style-set-height child 50.0)
|
||||||
|
(yg-node-style-set-position-type child +yg-position-type-absolute+)
|
||||||
|
(yg-node-style-set-position child +yg-edge-left+ 100.0)
|
||||||
|
(yg-node-style-set-position child +yg-edge-top+ 50.0)
|
||||||
|
(yg-node-insert-child root child 0)
|
||||||
|
(yg-node-calculate-layout root 300.0 300.0 +yg-direction-ltr+)
|
||||||
|
(fiveam:is (= 100.0 (yg-node-layout-get-left child)))
|
||||||
|
(fiveam:is (= 50.0 (yg-node-layout-get-top child)))
|
||||||
|
(fiveam:is (= 50.0 (yg-node-layout-get-width child)))
|
||||||
|
(fiveam:is (= 50.0 (yg-node-layout-get-height child)))
|
||||||
|
(yg-node-free-recursive root))))
|
||||||
|
|
||||||
|
(fiveam:test test-layout-padding
|
||||||
|
"Contract: padding reduces the available space for children."
|
||||||
|
(let* ((root (yg-node-new)))
|
||||||
|
(yg-node-style-set-width root 200.0)
|
||||||
|
(yg-node-style-set-height root 100.0)
|
||||||
|
(yg-node-style-set-padding root +yg-edge-all+ 10.0)
|
||||||
|
(let ((child (yg-node-new)))
|
||||||
|
(yg-node-style-set-width child 180.0)
|
||||||
|
(yg-node-style-set-height child 80.0)
|
||||||
|
(yg-node-insert-child root child 0)
|
||||||
|
(yg-node-calculate-layout root 200.0 100.0 +yg-direction-ltr+)
|
||||||
|
(fiveam:is (= 10.0 (yg-node-layout-get-left child)))
|
||||||
|
(fiveam:is (= 10.0 (yg-node-layout-get-top child)))
|
||||||
|
(yg-node-free-recursive root))))
|
||||||
|
|
||||||
|
(fiveam:test test-layout-nested
|
||||||
|
"Contract: nested containers produce correct leaf positions."
|
||||||
|
(let* ((root (yg-node-new)))
|
||||||
|
(yg-node-style-set-width root 400.0)
|
||||||
|
(yg-node-style-set-height root 400.0)
|
||||||
|
(yg-node-style-set-flex-direction root +yg-flex-direction-column+)
|
||||||
|
(let ((outer (yg-node-new)))
|
||||||
|
(yg-node-style-set-width outer 400.0)
|
||||||
|
(yg-node-style-set-height outer 200.0)
|
||||||
|
(yg-node-style-set-flex-direction outer +yg-flex-direction-row+)
|
||||||
|
(let ((inner (yg-node-new)))
|
||||||
|
(yg-node-style-set-width inner 100.0)
|
||||||
|
(yg-node-style-set-height inner 100.0)
|
||||||
|
(yg-node-insert-child outer inner 0)
|
||||||
|
(yg-node-insert-child root outer 0)
|
||||||
|
(yg-node-calculate-layout root 400.0 400.0 +yg-direction-ltr+)
|
||||||
|
(fiveam:is (= 0.0 (yg-node-layout-get-left inner)))
|
||||||
|
(fiveam:is (= 100.0 (yg-node-layout-get-width inner)))
|
||||||
|
(fiveam:is (= 100.0 (yg-node-layout-get-height inner)))
|
||||||
|
(yg-node-free-recursive root)))))
|
||||||
755
org/yoga-ffi.org
Normal file
755
org/yoga-ffi.org
Normal file
@@ -0,0 +1,755 @@
|
|||||||
|
#+TITLE: Yoga FFI Binding
|
||||||
|
#+STARTUP: content
|
||||||
|
#+FILETAGS: :cl-tui:yoga-ffi:v010:
|
||||||
|
|
||||||
|
* Yoga FFI Binding
|
||||||
|
|
||||||
|
CFFI bindings for Facebook's Yoga Flexbox layout engine. Provides raw access
|
||||||
|
to the C library — node management, style setters, layout calculation, and
|
||||||
|
layout getters. The next file (=layout-primitives.org=) wraps these in CLOS.
|
||||||
|
|
||||||
|
The Yoga shared library is at =/usr/local/lib/libyoga.so=, built from
|
||||||
|
=facebook/yoga= with C++17.
|
||||||
|
|
||||||
|
** Contract
|
||||||
|
|
||||||
|
- =(load-yoga)= :: loads the shared library via CFFI. Signal an error if the
|
||||||
|
library cannot be found.
|
||||||
|
- =(yg-node-new)= → YGNodeRef :: wraps =YGNodeNew=. Allocates a new Yoga node.
|
||||||
|
- =(yg-node-free node)= :: wraps =YGNodeFree=. Frees a node and detaches it
|
||||||
|
from its owner and children.
|
||||||
|
- =(yg-node-free-recursive node)= :: wraps =YGNodeFreeRecursive=. Frees the
|
||||||
|
entire subtree.
|
||||||
|
- =(yg-node-insert-child node child index)= :: wraps =YGNodeInsertChild=.
|
||||||
|
Inserts a child at the given index.
|
||||||
|
- =(yg-node-remove-child node child)= :: wraps =YGNodeRemoveChild=.
|
||||||
|
- =(yg-node-get-child-count node)= → integer :: wraps =YGNodeGetChildCount=.
|
||||||
|
- =(yg-node-calculate-layout node width height direction)= ::
|
||||||
|
wraps =YGNodeCalculateLayout=. Runs the layout algorithm.
|
||||||
|
- =(yg-node-layout-get-left node)= → float :: wraps =YGNodeLayoutGetLeft=.
|
||||||
|
Returns the computed X position.
|
||||||
|
- =(yg-node-layout-get-top node)= → float :: wraps =YGNodeLayoutGetTop=.
|
||||||
|
Returns the computed Y position.
|
||||||
|
- =(yg-node-layout-get-width node)= → float :: wraps =YGNodeLayoutGetWidth=.
|
||||||
|
Returns the computed width.
|
||||||
|
- =(yg-node-layout-get-height node)= → float :: wraps =YGNodeLayoutGetHeight=.
|
||||||
|
Returns the computed height.
|
||||||
|
- =(yg-node-style-set-direction node dir)= :: sets the text direction.
|
||||||
|
- =(yg-node-style-set-flex-direction node dir)= :: sets the flex direction.
|
||||||
|
- =(yg-node-style-set-justify-content node justify)= :: sets main-axis
|
||||||
|
alignment.
|
||||||
|
- =(yg-node-style-set-align-items node align)= :: sets cross-axis alignment.
|
||||||
|
- =(yg-node-style-set-align-self node align)= :: sets self alignment.
|
||||||
|
- =(yg-node-style-set-flex-wrap node wrap)= :: sets wrapping mode.
|
||||||
|
- =(yg-node-style-set-flex-grow node value)= :: sets the flex grow factor.
|
||||||
|
- =(yg-node-style-set-flex-shrink node value)= :: sets the flex shrink factor.
|
||||||
|
- =(yg-node-style-set-position-type node type)= :: sets positioning type.
|
||||||
|
- =(yg-node-style-set-width node points)= :: sets width in points.
|
||||||
|
- =(yg-node-style-set-width-percent node pct)= :: sets width as percentage.
|
||||||
|
- =(yg-node-style-set-width-auto node)= :: sets width to auto.
|
||||||
|
- =(yg-node-style-set-height node points)= :: sets height in points.
|
||||||
|
- =(yg-node-style-set-height-percent node pct)= :: sets height as percentage.
|
||||||
|
- =(yg-node-style-set-height-auto node)= :: sets height to auto.
|
||||||
|
- =(yg-node-style-set-padding node edge points)= :: sets padding on an edge.
|
||||||
|
- =(yg-node-style-set-margin node edge points)= :: sets margin on an edge.
|
||||||
|
- =(yg-node-style-set-border node edge points)= :: sets border on an edge.
|
||||||
|
- =(yg-node-style-set-gap node gutter length)= :: sets gap between children.
|
||||||
|
- =(yg-node-style-set-overflow node overflow)= :: sets overflow mode.
|
||||||
|
- =(yg-node-style-set-display node display)= :: sets display mode.
|
||||||
|
- =(yg-node-style-set-position-percent node edge pct)= :: sets position as
|
||||||
|
percentage.
|
||||||
|
- =(yg-node-style-set-position node edge points)= :: sets position in points.
|
||||||
|
|
||||||
|
Enum keywords (mapping C enum → Lisp keyword):
|
||||||
|
- YGDirection: :inherit (0), :ltr (1), :rtl (2)
|
||||||
|
- YGFlexDirection: :column (0), :column-reverse (1), :row (2), :row-reverse (3)
|
||||||
|
- YGJustify: :auto (0), :flex-start (1), :center (2), :flex-end (3),
|
||||||
|
:space-between (4), :space-around (5), :space-evenly (6), :stretch (7)
|
||||||
|
- YGAlign: :auto (0), :flex-start (1), :center (2), :flex-end (3),
|
||||||
|
:stretch (4), :baseline (5), :space-between (6), :space-around (7),
|
||||||
|
:space-evenly (8)
|
||||||
|
- YGWrap: :nowrap (0), :wrap (1), :wrap-reverse (2)
|
||||||
|
- YGPositionType: :static (0), :relative (1), :absolute (2)
|
||||||
|
- YGOverflow: :visible (0), :hidden (1), :scroll (2)
|
||||||
|
- YGDisplay: :flex (0), :none (1), :contents (2)
|
||||||
|
- YGEdge: :left (0), :top (1), :right (2), :bottom (3), :start (4), :end (5),
|
||||||
|
:horizontal (6), :vertical (7), :all (8)
|
||||||
|
- YGGutter: :column (0), :row (1), :all (2)
|
||||||
|
- YGUnit: :undefined (0), :point (1), :percent (2), :auto (3)
|
||||||
|
|
||||||
|
* Application-Level Package
|
||||||
|
|
||||||
|
#+begin_src lisp
|
||||||
|
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||||
|
(ql:quickload :cffi :silent t))
|
||||||
|
|
||||||
|
(defpackage :cl-tui.yoga-ffi
|
||||||
|
(:use :cl)
|
||||||
|
(:export
|
||||||
|
;; library
|
||||||
|
#:*libyoga*
|
||||||
|
#:load-yoga
|
||||||
|
;; constants
|
||||||
|
#:+yg-direction-inherit+
|
||||||
|
#:+yg-direction-ltr+
|
||||||
|
#:+yg-direction-rtl+
|
||||||
|
#:+yg-flex-direction-column+
|
||||||
|
#:+yg-flex-direction-column-reverse+
|
||||||
|
#:+yg-flex-direction-row+
|
||||||
|
#:+yg-flex-direction-row-reverse+
|
||||||
|
#:+yg-justify-auto+
|
||||||
|
#:+yg-justify-flex-start+
|
||||||
|
#:+yg-justify-center+
|
||||||
|
#:+yg-justify-flex-end+
|
||||||
|
#:+yg-justify-space-between+
|
||||||
|
#:+yg-justify-space-around+
|
||||||
|
#:+yg-justify-space-evenly+
|
||||||
|
#:+yg-justify-stretch+
|
||||||
|
#:+yg-align-auto+
|
||||||
|
#:+yg-align-flex-start+
|
||||||
|
#:+yg-align-center+
|
||||||
|
#:+yg-align-flex-end+
|
||||||
|
#:+yg-align-stretch+
|
||||||
|
#:+yg-align-baseline+
|
||||||
|
#:+yg-align-space-between+
|
||||||
|
#:+yg-align-space-around+
|
||||||
|
#:+yg-align-space-evenly+
|
||||||
|
#:+yg-wrap-nowrap+
|
||||||
|
#:+yg-wrap-wrap+
|
||||||
|
#:+yg-wrap-wrap-reverse+
|
||||||
|
#:+yg-position-type-static+
|
||||||
|
#:+yg-position-type-relative+
|
||||||
|
#:+yg-position-type-absolute+
|
||||||
|
#:+yg-overflow-visible+
|
||||||
|
#:+yg-overflow-hidden+
|
||||||
|
#:+yg-overflow-scroll+
|
||||||
|
#:+yg-display-flex+
|
||||||
|
#:+yg-display-none+
|
||||||
|
#:+yg-display-contents+
|
||||||
|
#:+yg-edge-left+
|
||||||
|
#:+yg-edge-top+
|
||||||
|
#:+yg-edge-right+
|
||||||
|
#:+yg-edge-bottom+
|
||||||
|
#:+yg-edge-start+
|
||||||
|
#:+yg-edge-end+
|
||||||
|
#:+yg-edge-horizontal+
|
||||||
|
#:+yg-edge-vertical+
|
||||||
|
#:+yg-edge-all+
|
||||||
|
#:+yg-gutter-column+
|
||||||
|
#:+yg-gutter-row+
|
||||||
|
#:+yg-gutter-all+
|
||||||
|
#:+yg-unit-undefined+
|
||||||
|
#:+yg-unit-point+
|
||||||
|
#:+yg-unit-percent+
|
||||||
|
#:+yg-unit-auto+
|
||||||
|
;; types
|
||||||
|
#:yg-node-ref
|
||||||
|
#:yg-node-const-ref
|
||||||
|
;; node management
|
||||||
|
#:yg-node-new
|
||||||
|
#:yg-node-free
|
||||||
|
#:yg-node-free-recursive
|
||||||
|
#:yg-node-insert-child
|
||||||
|
#:yg-node-remove-child
|
||||||
|
#:yg-node-remove-all-children
|
||||||
|
#:yg-node-get-child-count
|
||||||
|
#:yg-node-get-child
|
||||||
|
;; layout
|
||||||
|
#:yg-node-calculate-layout
|
||||||
|
#:yg-node-layout-get-left
|
||||||
|
#:yg-node-layout-get-top
|
||||||
|
#:yg-node-layout-get-width
|
||||||
|
#:yg-node-layout-get-height
|
||||||
|
#:yg-node-layout-get-right
|
||||||
|
#:yg-node-layout-get-bottom
|
||||||
|
#:yg-node-is-dirty
|
||||||
|
#:yg-node-mark-dirty
|
||||||
|
;; style direction & flex
|
||||||
|
#:yg-node-style-set-direction
|
||||||
|
#:yg-node-style-set-flex-direction
|
||||||
|
#:yg-node-style-set-justify-content
|
||||||
|
#:yg-node-style-set-align-items
|
||||||
|
#:yg-node-style-set-align-self
|
||||||
|
#:yg-node-style-set-align-content
|
||||||
|
#:yg-node-style-set-flex-wrap
|
||||||
|
#:yg-node-style-set-position-type
|
||||||
|
#:yg-node-style-set-flex-grow
|
||||||
|
#:yg-node-style-set-flex-shrink
|
||||||
|
#:yg-node-style-set-flex-basis
|
||||||
|
#:yg-node-style-set-flex-basis-auto
|
||||||
|
#:yg-node-style-set-flex-basis-percent
|
||||||
|
#:yg-node-style-set-overflow
|
||||||
|
#:yg-node-style-set-display
|
||||||
|
;; style dimensions
|
||||||
|
#:yg-node-style-set-width
|
||||||
|
#:yg-node-style-set-width-percent
|
||||||
|
#:yg-node-style-set-width-auto
|
||||||
|
#:yg-node-style-set-height
|
||||||
|
#:yg-node-style-set-height-percent
|
||||||
|
#:yg-node-style-set-height-auto
|
||||||
|
#:yg-node-style-set-min-width
|
||||||
|
#:yg-node-style-set-min-width-percent
|
||||||
|
#:yg-node-style-set-min-height
|
||||||
|
#:yg-node-style-set-min-height-percent
|
||||||
|
#:yg-node-style-set-max-width
|
||||||
|
#:yg-node-style-set-max-height
|
||||||
|
#:yg-node-style-set-aspect-ratio
|
||||||
|
;; style padding/margin/border/gap/position
|
||||||
|
#:yg-node-style-set-padding
|
||||||
|
#:yg-node-style-set-padding-percent
|
||||||
|
#:yg-node-style-set-margin
|
||||||
|
#:yg-node-style-set-margin-percent
|
||||||
|
#:yg-node-style-set-margin-auto
|
||||||
|
#:yg-node-style-set-border
|
||||||
|
#:yg-node-style-set-gap
|
||||||
|
#:yg-node-style-set-position
|
||||||
|
#:yg-node-style-set-position-percent
|
||||||
|
;; style getters
|
||||||
|
#:yg-node-style-get-width
|
||||||
|
#:yg-node-style-get-height
|
||||||
|
#:yg-node-style-get-flex-direction
|
||||||
|
#:yg-node-style-get-align-items
|
||||||
|
#:yg-node-style-get-justify-content))
|
||||||
|
|
||||||
|
(in-package :cl-tui.yoga-ffi)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
|
||||||
|
* Foreign Library Loading
|
||||||
|
|
||||||
|
#+begin_src lisp
|
||||||
|
(defparameter *libyoga* nil "Handle for the loaded Yoga shared library.")
|
||||||
|
|
||||||
|
(defun load-yoga ()
|
||||||
|
"Load the Yoga shared library via CFFI."
|
||||||
|
(setf *libyoga* (cffi:load-foreign-library "/usr/local/lib/libyoga.so"))
|
||||||
|
(sb-int:set-floating-point-modes :traps '())
|
||||||
|
*libyoga*)
|
||||||
|
|
||||||
|
(load-yoga)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Enum Constants
|
||||||
|
|
||||||
|
#+begin_src lisp
|
||||||
|
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||||
|
;; YGDirection
|
||||||
|
(defconstant +yg-direction-inherit+ 0)
|
||||||
|
(defconstant +yg-direction-ltr+ 1)
|
||||||
|
(defconstant +yg-direction-rtl+ 2)
|
||||||
|
;; YGFlexDirection
|
||||||
|
(defconstant +yg-flex-direction-column+ 0)
|
||||||
|
(defconstant +yg-flex-direction-column-reverse+ 1)
|
||||||
|
(defconstant +yg-flex-direction-row+ 2)
|
||||||
|
(defconstant +yg-flex-direction-row-reverse+ 3)
|
||||||
|
;; YGJustify
|
||||||
|
(defconstant +yg-justify-auto+ 0)
|
||||||
|
(defconstant +yg-justify-flex-start+ 1)
|
||||||
|
(defconstant +yg-justify-center+ 2)
|
||||||
|
(defconstant +yg-justify-flex-end+ 3)
|
||||||
|
(defconstant +yg-justify-space-between+ 4)
|
||||||
|
(defconstant +yg-justify-space-around+ 5)
|
||||||
|
(defconstant +yg-justify-space-evenly+ 6)
|
||||||
|
(defconstant +yg-justify-stretch+ 7)
|
||||||
|
;; YGAlign
|
||||||
|
(defconstant +yg-align-auto+ 0)
|
||||||
|
(defconstant +yg-align-flex-start+ 1)
|
||||||
|
(defconstant +yg-align-center+ 2)
|
||||||
|
(defconstant +yg-align-flex-end+ 3)
|
||||||
|
(defconstant +yg-align-stretch+ 4)
|
||||||
|
(defconstant +yg-align-baseline+ 5)
|
||||||
|
(defconstant +yg-align-space-between+ 6)
|
||||||
|
(defconstant +yg-align-space-around+ 7)
|
||||||
|
(defconstant +yg-align-space-evenly+ 8)
|
||||||
|
;; YGWrap
|
||||||
|
(defconstant +yg-wrap-nowrap+ 0)
|
||||||
|
(defconstant +yg-wrap-wrap+ 1)
|
||||||
|
(defconstant +yg-wrap-wrap-reverse+ 2)
|
||||||
|
;; YGPositionType
|
||||||
|
(defconstant +yg-position-type-static+ 0)
|
||||||
|
(defconstant +yg-position-type-relative+ 1)
|
||||||
|
(defconstant +yg-position-type-absolute+ 2)
|
||||||
|
;; YGOverflow
|
||||||
|
(defconstant +yg-overflow-visible+ 0)
|
||||||
|
(defconstant +yg-overflow-hidden+ 1)
|
||||||
|
(defconstant +yg-overflow-scroll+ 2)
|
||||||
|
;; YGDisplay
|
||||||
|
(defconstant +yg-display-flex+ 0)
|
||||||
|
(defconstant +yg-display-none+ 1)
|
||||||
|
(defconstant +yg-display-contents+ 2)
|
||||||
|
;; YGEdge
|
||||||
|
(defconstant +yg-edge-left+ 0)
|
||||||
|
(defconstant +yg-edge-top+ 1)
|
||||||
|
(defconstant +yg-edge-right+ 2)
|
||||||
|
(defconstant +yg-edge-bottom+ 3)
|
||||||
|
(defconstant +yg-edge-start+ 4)
|
||||||
|
(defconstant +yg-edge-end+ 5)
|
||||||
|
(defconstant +yg-edge-horizontal+ 6)
|
||||||
|
(defconstant +yg-edge-vertical+ 7)
|
||||||
|
(defconstant +yg-edge-all+ 8)
|
||||||
|
;; YGGutter
|
||||||
|
(defconstant +yg-gutter-column+ 0)
|
||||||
|
(defconstant +yg-gutter-row+ 1)
|
||||||
|
(defconstant +yg-gutter-all+ 2)
|
||||||
|
;; YGUnit
|
||||||
|
(defconstant +yg-unit-undefined+ 0)
|
||||||
|
(defconstant +yg-unit-point+ 1)
|
||||||
|
(defconstant +yg-unit-percent+ 2)
|
||||||
|
(defconstant +yg-unit-auto+ 3))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* CFFI Foreign Type Definitions
|
||||||
|
|
||||||
|
#+begin_src lisp
|
||||||
|
(cffi:defctype yg-node-ref :pointer)
|
||||||
|
(cffi:defctype yg-node-const-ref :pointer)
|
||||||
|
|
||||||
|
(cffi:defcstruct yg-size
|
||||||
|
(width :float)
|
||||||
|
(height :float))
|
||||||
|
|
||||||
|
(cffi:defcstruct yg-value
|
||||||
|
(value :float)
|
||||||
|
(unit :int))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Node Management
|
||||||
|
|
||||||
|
#+begin_src lisp
|
||||||
|
(cffi:defcfun ("YGNodeNew" yg-node-new) yg-node-ref)
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeFree" yg-node-free) :void
|
||||||
|
(node yg-node-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeFreeRecursive" yg-node-free-recursive) :void
|
||||||
|
(node yg-node-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeInsertChild" yg-node-insert-child) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(child yg-node-ref)
|
||||||
|
(index :unsigned-int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeRemoveChild" yg-node-remove-child) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(child yg-node-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeRemoveAllChildren" yg-node-remove-all-children) :void
|
||||||
|
(node yg-node-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeGetChildCount" yg-node-get-child-count) :unsigned-int
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeGetChild" yg-node-get-child) yg-node-ref
|
||||||
|
(node yg-node-ref)
|
||||||
|
(index :unsigned-int))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Layout Calculation
|
||||||
|
|
||||||
|
#+begin_src lisp
|
||||||
|
(cffi:defcfun ("YGNodeCalculateLayout" yg-node-calculate-layout) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(available-width :float)
|
||||||
|
(available-height :float)
|
||||||
|
(owner-direction :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeLayoutGetLeft" yg-node-layout-get-left) :float
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeLayoutGetTop" yg-node-layout-get-top) :float
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeLayoutGetWidth" yg-node-layout-get-width) :float
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeLayoutGetHeight" yg-node-layout-get-height) :float
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeLayoutGetRight" yg-node-layout-get-right) :float
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeLayoutGetBottom" yg-node-layout-get-bottom) :float
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeIsDirty" yg-node-is-dirty) :boolean
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeMarkDirty" yg-node-mark-dirty) :void
|
||||||
|
(node yg-node-ref))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Style Setters — Direction and Flex
|
||||||
|
|
||||||
|
#+begin_src lisp
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetDirection" yg-node-style-set-direction) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(direction :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetFlexDirection" yg-node-style-set-flex-direction) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(flex-direction :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetJustifyContent" yg-node-style-set-justify-content) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(justify :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetAlignItems" yg-node-style-set-align-items) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(align :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetAlignSelf" yg-node-style-set-align-self) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(align :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetAlignContent" yg-node-style-set-align-content) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(align :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetFlexWrap" yg-node-style-set-flex-wrap) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(wrap :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetPositionType" yg-node-style-set-position-type) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(position-type :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetFlexGrow" yg-node-style-set-flex-grow) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(flex-grow :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetFlexShrink" yg-node-style-set-flex-shrink) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(flex-shrink :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetFlexBasis" yg-node-style-set-flex-basis) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(flex-basis :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetFlexBasisAuto" yg-node-style-set-flex-basis-auto) :void
|
||||||
|
(node yg-node-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetFlexBasisPercent" yg-node-style-set-flex-basis-percent) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(flex-basis :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetOverflow" yg-node-style-set-overflow) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(overflow :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetDisplay" yg-node-style-set-display) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(display :int))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Style Setters — Dimensions
|
||||||
|
|
||||||
|
#+begin_src lisp
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetWidth" yg-node-style-set-width) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(width :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetWidthPercent" yg-node-style-set-width-percent) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(width :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetWidthAuto" yg-node-style-set-width-auto) :void
|
||||||
|
(node yg-node-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetHeight" yg-node-style-set-height) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(height :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetHeightPercent" yg-node-style-set-height-percent) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(height :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetHeightAuto" yg-node-style-set-height-auto) :void
|
||||||
|
(node yg-node-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMinWidth" yg-node-style-set-min-width) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(min-width :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMinWidthPercent" yg-node-style-set-min-width-percent) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(min-width :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMinHeight" yg-node-style-set-min-height) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(min-height :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMinHeightPercent" yg-node-style-set-min-height-percent) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(min-height :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMaxWidth" yg-node-style-set-max-width) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(max-width :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMaxHeight" yg-node-style-set-max-height) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(max-height :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetAspectRatio" yg-node-style-set-aspect-ratio) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(aspect-ratio :float))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Style Setters — Padding, Margin, Border, Gap, Position
|
||||||
|
|
||||||
|
#+begin_src lisp
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetPadding" yg-node-style-set-padding) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(edge :int)
|
||||||
|
(padding :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetPaddingPercent" yg-node-style-set-padding-percent) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(edge :int)
|
||||||
|
(padding :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMargin" yg-node-style-set-margin) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(edge :int)
|
||||||
|
(margin :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMarginPercent" yg-node-style-set-margin-percent) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(edge :int)
|
||||||
|
(margin :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetMarginAuto" yg-node-style-set-margin-auto) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(edge :int))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetBorder" yg-node-style-set-border) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(edge :int)
|
||||||
|
(border :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetGap" yg-node-style-set-gap) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(gutter :int)
|
||||||
|
(gap :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetPosition" yg-node-style-set-position) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(edge :int)
|
||||||
|
(position :float))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleSetPositionPercent" yg-node-style-set-position-percent) :void
|
||||||
|
(node yg-node-ref)
|
||||||
|
(edge :int)
|
||||||
|
(position :float))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Style Getters
|
||||||
|
|
||||||
|
#+begin_src lisp
|
||||||
|
(cffi:defcfun ("YGNodeStyleGetWidth" yg-node-style-get-width) yg-value
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleGetHeight" yg-node-style-get-height) yg-value
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleGetFlexDirection" yg-node-style-get-flex-direction) :int
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleGetAlignItems" yg-node-style-get-align-items) :int
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
|
||||||
|
(cffi:defcfun ("YGNodeStyleGetJustifyContent" yg-node-style-get-justify-content) :int
|
||||||
|
(node yg-node-const-ref))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Test Suite
|
||||||
|
|
||||||
|
#+begin_src lisp
|
||||||
|
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||||
|
(ql:quickload :fiveam :silent t))
|
||||||
|
|
||||||
|
(defpackage :cl-tui.yoga-ffi-tests
|
||||||
|
(:use :cl :fiveam)
|
||||||
|
(:import-from :cl-tui.yoga-ffi
|
||||||
|
#:load-yoga
|
||||||
|
#:yg-node-new
|
||||||
|
#:yg-node-free
|
||||||
|
#:yg-node-free-recursive
|
||||||
|
#:yg-node-insert-child
|
||||||
|
#:yg-node-get-child-count
|
||||||
|
#:yg-node-calculate-layout
|
||||||
|
#:yg-node-layout-get-left
|
||||||
|
#:yg-node-layout-get-top
|
||||||
|
#:yg-node-layout-get-width
|
||||||
|
#:yg-node-layout-get-height
|
||||||
|
#:yg-node-style-set-flex-direction
|
||||||
|
#:yg-node-style-set-justify-content
|
||||||
|
#:yg-node-style-set-align-items
|
||||||
|
#:yg-node-style-set-width
|
||||||
|
#:yg-node-style-set-height
|
||||||
|
#:yg-node-style-set-padding
|
||||||
|
#:yg-node-style-set-margin
|
||||||
|
#:yg-node-style-set-flex-grow
|
||||||
|
#:yg-node-style-set-position-type
|
||||||
|
#:yg-node-style-set-position
|
||||||
|
#:+yg-flex-direction-column+
|
||||||
|
#:+yg-flex-direction-row+
|
||||||
|
#:+yg-justify-center+
|
||||||
|
#:+yg-justify-flex-start+
|
||||||
|
#:+yg-align-stretch+
|
||||||
|
#:+yg-align-center+
|
||||||
|
#:+yg-edge-all+
|
||||||
|
#:+yg-edge-left+
|
||||||
|
#:+yg-edge-top+
|
||||||
|
#:+yg-edge-right+
|
||||||
|
#:+yg-edge-bottom+
|
||||||
|
#:+yg-position-type-relative+
|
||||||
|
#:+yg-position-type-absolute+
|
||||||
|
;; YGDirection constants (different from YGFlexDirection!)
|
||||||
|
#:+yg-direction-inherit+
|
||||||
|
#:+yg-direction-ltr+
|
||||||
|
#:+yg-direction-rtl+))
|
||||||
|
|
||||||
|
(in-package :cl-tui.yoga-ffi-tests)
|
||||||
|
|
||||||
|
(fiveam:def-suite yoga-ffi-suite
|
||||||
|
:description "Yoga FFI binding verification")
|
||||||
|
(fiveam:in-suite yoga-ffi-suite)
|
||||||
|
|
||||||
|
(fiveam:test test-node-create-free
|
||||||
|
"Contract: yg-node-new returns a non-null pointer; yg-node-free doesn't crash."
|
||||||
|
(let ((node (yg-node-new)))
|
||||||
|
(fiveam:is (not (cffi:null-pointer-p node)))
|
||||||
|
(yg-node-free node)
|
||||||
|
(fiveam:pass)))
|
||||||
|
|
||||||
|
(fiveam:test test-node-child-count
|
||||||
|
"Contract: yg-node-get-child-count returns 0 for a new node."
|
||||||
|
(let ((node (yg-node-new)))
|
||||||
|
(fiveam:is (= 0 (yg-node-get-child-count node)))
|
||||||
|
(yg-node-free node)))
|
||||||
|
|
||||||
|
(fiveam:test test-node-insert-child
|
||||||
|
"Contract: inserting a child increments the child count."
|
||||||
|
(let ((parent (yg-node-new))
|
||||||
|
(child (yg-node-new)))
|
||||||
|
(yg-node-insert-child parent child 0)
|
||||||
|
(fiveam:is (= 1 (yg-node-get-child-count parent)))
|
||||||
|
(yg-node-free-recursive parent)))
|
||||||
|
|
||||||
|
(fiveam:test test-layout-basic-column
|
||||||
|
"Contract: a column with two fixed-height children positions them vertically."
|
||||||
|
(let* ((root (yg-node-new)))
|
||||||
|
(yg-node-style-set-width root 100.0)
|
||||||
|
(yg-node-style-set-height root 200.0)
|
||||||
|
(yg-node-style-set-flex-direction root +yg-flex-direction-column+)
|
||||||
|
(let ((child1 (yg-node-new))
|
||||||
|
(child2 (yg-node-new)))
|
||||||
|
(yg-node-style-set-width child1 100.0)
|
||||||
|
(yg-node-style-set-height child1 50.0)
|
||||||
|
(yg-node-style-set-width child2 100.0)
|
||||||
|
(yg-node-style-set-height child2 50.0)
|
||||||
|
(yg-node-insert-child root child1 0)
|
||||||
|
(yg-node-insert-child root child2 1)
|
||||||
|
(yg-node-calculate-layout root 100.0 200.0 +yg-direction-ltr+)
|
||||||
|
(fiveam:is (= 0.0 (yg-node-layout-get-left child1)))
|
||||||
|
(fiveam:is (= 0.0 (yg-node-layout-get-top child1)))
|
||||||
|
(fiveam:is (= 50.0 (yg-node-layout-get-top child2)))
|
||||||
|
(yg-node-free-recursive root))))
|
||||||
|
|
||||||
|
(fiveam:test test-layout-basic-row
|
||||||
|
"Contract: a row with two fixed-width children positions them horizontally."
|
||||||
|
(let* ((root (yg-node-new)))
|
||||||
|
(yg-node-style-set-width root 200.0)
|
||||||
|
(yg-node-style-set-height root 100.0)
|
||||||
|
(yg-node-style-set-flex-direction root +yg-flex-direction-row+)
|
||||||
|
(let ((child1 (yg-node-new))
|
||||||
|
(child2 (yg-node-new)))
|
||||||
|
(yg-node-style-set-width child1 80.0)
|
||||||
|
(yg-node-style-set-height child1 50.0)
|
||||||
|
(yg-node-style-set-width child2 80.0)
|
||||||
|
(yg-node-style-set-height child2 50.0)
|
||||||
|
(yg-node-insert-child root child1 0)
|
||||||
|
(yg-node-insert-child root child2 1)
|
||||||
|
(yg-node-calculate-layout root 200.0 100.0 +yg-direction-ltr+)
|
||||||
|
(fiveam:is (= 0.0 (yg-node-layout-get-left child1)))
|
||||||
|
(fiveam:is (= 0.0 (yg-node-layout-get-top child1)))
|
||||||
|
(fiveam:is (= 80.0 (yg-node-layout-get-left child2)))
|
||||||
|
(yg-node-free-recursive root))))
|
||||||
|
|
||||||
|
(fiveam:test test-layout-flex-grow
|
||||||
|
"Contract: flex-grow distributes remaining space proportionally."
|
||||||
|
(let* ((root (yg-node-new)))
|
||||||
|
(yg-node-style-set-width root 200.0)
|
||||||
|
(yg-node-style-set-height root 100.0)
|
||||||
|
(yg-node-style-set-flex-direction root +yg-flex-direction-row+)
|
||||||
|
(let ((child1 (yg-node-new))
|
||||||
|
(child2 (yg-node-new)))
|
||||||
|
(yg-node-style-set-height child1 100.0)
|
||||||
|
(yg-node-style-set-flex-grow child1 1.0)
|
||||||
|
(yg-node-style-set-height child2 100.0)
|
||||||
|
(yg-node-style-set-flex-grow child2 2.0)
|
||||||
|
(yg-node-insert-child root child1 0)
|
||||||
|
(yg-node-insert-child root child2 1)
|
||||||
|
(yg-node-calculate-layout root 200.0 100.0 +yg-direction-ltr+)
|
||||||
|
(fiveam:is (< 0.0 (yg-node-layout-get-width child1)))
|
||||||
|
(fiveam:is (< 0.0 (yg-node-layout-get-width child2)))
|
||||||
|
(fiveam:is (= 200.0 (+ (yg-node-layout-get-width child1)
|
||||||
|
(yg-node-layout-get-width child2))))
|
||||||
|
(yg-node-free-recursive root))))
|
||||||
|
|
||||||
|
(fiveam:test test-layout-absolute-position
|
||||||
|
"Contract: an absolute child positions relative to its parent."
|
||||||
|
(let* ((root (yg-node-new)))
|
||||||
|
(yg-node-style-set-width root 300.0)
|
||||||
|
(yg-node-style-set-height root 300.0)
|
||||||
|
(let ((child (yg-node-new)))
|
||||||
|
(yg-node-style-set-width child 50.0)
|
||||||
|
(yg-node-style-set-height child 50.0)
|
||||||
|
(yg-node-style-set-position-type child +yg-position-type-absolute+)
|
||||||
|
(yg-node-style-set-position child +yg-edge-left+ 100.0)
|
||||||
|
(yg-node-style-set-position child +yg-edge-top+ 50.0)
|
||||||
|
(yg-node-insert-child root child 0)
|
||||||
|
(yg-node-calculate-layout root 300.0 300.0 +yg-direction-ltr+)
|
||||||
|
(fiveam:is (= 100.0 (yg-node-layout-get-left child)))
|
||||||
|
(fiveam:is (= 50.0 (yg-node-layout-get-top child)))
|
||||||
|
(fiveam:is (= 50.0 (yg-node-layout-get-width child)))
|
||||||
|
(fiveam:is (= 50.0 (yg-node-layout-get-height child)))
|
||||||
|
(yg-node-free-recursive root))))
|
||||||
|
|
||||||
|
(fiveam:test test-layout-padding
|
||||||
|
"Contract: padding reduces the available space for children."
|
||||||
|
(let* ((root (yg-node-new)))
|
||||||
|
(yg-node-style-set-width root 200.0)
|
||||||
|
(yg-node-style-set-height root 100.0)
|
||||||
|
(yg-node-style-set-padding root +yg-edge-all+ 10.0)
|
||||||
|
(let ((child (yg-node-new)))
|
||||||
|
(yg-node-style-set-width child 180.0)
|
||||||
|
(yg-node-style-set-height child 80.0)
|
||||||
|
(yg-node-insert-child root child 0)
|
||||||
|
(yg-node-calculate-layout root 200.0 100.0 +yg-direction-ltr+)
|
||||||
|
(fiveam:is (= 10.0 (yg-node-layout-get-left child)))
|
||||||
|
(fiveam:is (= 10.0 (yg-node-layout-get-top child)))
|
||||||
|
(yg-node-free-recursive root))))
|
||||||
|
|
||||||
|
(fiveam:test test-layout-nested
|
||||||
|
"Contract: nested containers produce correct leaf positions."
|
||||||
|
(let* ((root (yg-node-new)))
|
||||||
|
(yg-node-style-set-width root 400.0)
|
||||||
|
(yg-node-style-set-height root 400.0)
|
||||||
|
(yg-node-style-set-flex-direction root +yg-flex-direction-column+)
|
||||||
|
(let ((outer (yg-node-new)))
|
||||||
|
(yg-node-style-set-width outer 400.0)
|
||||||
|
(yg-node-style-set-height outer 200.0)
|
||||||
|
(yg-node-style-set-flex-direction outer +yg-flex-direction-row+)
|
||||||
|
(let ((inner (yg-node-new)))
|
||||||
|
(yg-node-style-set-width inner 100.0)
|
||||||
|
(yg-node-style-set-height inner 100.0)
|
||||||
|
(yg-node-insert-child outer inner 0)
|
||||||
|
(yg-node-insert-child root outer 0)
|
||||||
|
(yg-node-calculate-layout root 400.0 400.0 +yg-direction-ltr+)
|
||||||
|
(fiveam:is (= 0.0 (yg-node-layout-get-left inner)))
|
||||||
|
(fiveam:is (= 100.0 (yg-node-layout-get-width inner)))
|
||||||
|
(fiveam:is (= 100.0 (yg-node-layout-get-height inner)))
|
||||||
|
(yg-node-free-recursive root)))))
|
||||||
|
#+end_src
|
||||||
Reference in New Issue
Block a user