(module (s9fes char-canvas shape vgroup) (;export ; real-shape-vgroup ; shape-vgroup) (import scheme utf8) (import (chicken base)) (import (chicken fixnum)) (import (chicken type)) (import record-variants) (import (s9fes char-canvas) (s9fes char-canvas rect) (s9fes char-canvas shape shape)) (include-relative "s9fes.char-canvas.types") (include-relative "s9fes.char-canvas.inlines") (: real-shape-vgroup (#!rest real-shape-plotter -> real-shape-plotter)) (: shape-vgroup (#!rest shape-plotter -> shape-plotter)) ;; Private (define (*info-elements info) (the (list-of shape-plotter) (@info 0 info))) (define (*new-vgroup info elms) (case (@info-coords info) ((real) (real-shape-vgroup elms)) (else (shape-vgroup elms))) ) (define (*canvas-draw-vgroup cv x0 y0 shps) ;FIXME (define (next shp x y) (receive (w h) (shape-size shp) (values x (fx+ y h)))) (let loop ((shps (reverse shps)) (x x0) (y y0)) (unless (null? shps) (let ((shp (car shps))) (shp cv x y) (receive (x y) (next shp x y) (loop (cdr shps) x y)) ) ) ) cv ) (define (*canvas-plot-vgroup cv x0 y0 shps) ;FIXME (define (next shp x y) (receive (w h) (shape-size shp) (values x (+ y h)))) (let loop ((shps (reverse shps)) (x x0) (y y0)) (unless (null? shps) (let ((shp (car shps))) (shp cv x y) (receive (x y) (next shp x y) (loop (cdr shps) x y)) ) ) ) cv ) ;; Public (define ((real-shape-vgroup #!rest shps) #!optional cv x0 y0) (if cv (*canvas-draw-vgroup cv x0 y0 shps) (^real-info vgroup shps) ) ) ;; (define ((shape-vgroup #!rest shps) #!optional cv x0 y0) (if cv (*canvas-plot-vgroup cv 0 y0 shps) (^virtual-info vgroup shps) ) ) ;; (define (class-shape-size shp info) (let* ((shps (*info-elements info)) (sizs (map (lambda (shp) (receive (shape-size shp))) shps)) ) (values (apply max (map car sizs)) (apply + (map cadr sizs))) ) ) ;FIXME layout should take wd & ht (as original, dip) (define (class-shape-layout shp info bb) ;FIXME finish apportionment - rqr-wd rqr-ht (let-values (((rqr-wd rqr-ht) (class-shape-size shp info))) ; v is bottom to top (let* ((shps (reverse (*info-elements info))) (ht-per (/ (%rect-ht bb) (length shps))) (rem-x (%rect-x bb)) (rem-wd (%rect-wd bb)) ) (if (or (< (%rect-wd bb) rqr-wd) (< (%rect-ht bb) rqr-ht)) ;then can't fit ;FIXME should error? or just stack (let ((outs (map (cut shape-layout <> bb) shps))) (*new-vgroup info outs) ) ;else try to fit (let loop ((shps shps) (new-y (%rect-y bb)) (rem-ht (%rect-ht bb)) (jsts '())) ;FIXME what if out of room (if (null? shps) (*new-vgroup info jsts) (let ((shp (car shps))) ;FIXME new-ht negotiated how? (let* ((this-ht ht-per) ;FIXME !!!!!! (this-bb (%rect rem-x new-y rem-wd this-ht)) ) (loop (cdr shps) (+ new-y this-ht) (- rem-ht this-ht) (cons (shape-layout shp this-bb) jsts) ) ) ) ) ) ) ) ) ) (define (class-shape-justified? shp info) (let loop ((shps (*info-elements info))) (or (null? shps) (let ((shp (car shps))) (and (shape-justified? shp) (loop (cdr shps))) ) ) ) ) (register-shape-method 'vgroup 'size class-shape-size) (register-shape-method 'vgroup 'cardinality (lambda (shp info) (length (*info-elements info)))) (register-shape-method 'vgroup 'elements (lambda (shp info) (*info-elements info))) (register-shape-method 'vgroup 'layout class-shape-layout) (register-shape-method 'vgroup 'justified? class-shape-justified?) ) ;module (s9fes char-canvas shape vgroup)