184 lines
6.4 KiB
Racket
184 lines
6.4 KiB
Racket
#lang racket
|
|
|
|
(require racket/gui)
|
|
|
|
(provide columns-pane%)
|
|
|
|
(define columns-pane%
|
|
(class vertical-pane%
|
|
(super-new)
|
|
|
|
;; Internal data
|
|
(define hpanes #f)
|
|
(define creating-row #f)
|
|
(define current-col 0)
|
|
(define current-row 0)
|
|
|
|
(define/private (mk-hpane*)
|
|
(set! creating-row #t)
|
|
(let ((new-pane (new horizontal-pane% [parent this]
|
|
[spacing spacing] [horiz-margin horiz-margin] [vert-margin (round (/ spacing 2))]
|
|
[stretchable-height #f])))
|
|
(letrec ((adder (lambda (col)
|
|
(when (< col columns)
|
|
(new horizontal-pane% [parent new-pane] [stretchable-width #t]
|
|
[alignment (list (column-alignment* col) 'center)])
|
|
(adder (+ col 1))))))
|
|
(adder 0))
|
|
(set! creating-row #f)
|
|
new-pane)
|
|
)
|
|
|
|
(define/private (column-alignment* c)
|
|
(let ((align (vector-ref column-aligns c)))
|
|
;(displayln align)
|
|
align))
|
|
|
|
(define/private (get-row* i)
|
|
(when (eq? hpanes #f)
|
|
(set! hpanes (make-vector (+ i 1) #f)))
|
|
(when (>= i (vector-length hpanes))
|
|
(let ((v hpanes))
|
|
(set! hpanes (make-vector (+ i 1) #f))
|
|
(vector-copy! hpanes 0 v)))
|
|
(let ((p (vector-ref hpanes i)))
|
|
(when (eq? p #f)
|
|
(set! p (mk-hpane*))
|
|
(vector-set! hpanes i p))
|
|
p))
|
|
|
|
(define/private (cell* c r)
|
|
(let* ((row (get-row* r))
|
|
(cells (send row get-children)))
|
|
(let ((cell (list-ref cells c)))
|
|
;(call-with-values (lambda () (send cell get-alignment))
|
|
; (lambda (h v) (printf "h=~a, v=~a\n" h v)))
|
|
cell)))
|
|
|
|
(define/private (child* c r)
|
|
(let* ((cell (cell* c r))
|
|
(children (send cell get-children))
|
|
(child (if (null? children) #f (car children)))
|
|
)
|
|
child))
|
|
|
|
(define/private (max-width* c r w)
|
|
(if (< r (vector-length hpanes))
|
|
(let* ((child (child* c r))
|
|
(child-width (if (eq? child #f) 0 (send child get-width))))
|
|
(max-width* c (+ r 1) (if (> child-width w) child-width w)))
|
|
w))
|
|
|
|
(define/private (set-min-width* c r w)
|
|
(when (< r (vector-length hpanes))
|
|
(let ((cell (cell* c r)))
|
|
(unless (eq? cell #f)
|
|
(send cell min-width w))
|
|
(when (eq? (column-alignment* c) 'left)
|
|
(let ((child (child* c r)))
|
|
(unless (eq? child #f)
|
|
(send child min-width w))))
|
|
)
|
|
(set-min-width* c (+ r 1) w)))
|
|
|
|
(define/private (arrange-col* c)
|
|
(let* ((w (max-width* c 0 -1))
|
|
(col-min-width (vector-ref column-min-widths c))
|
|
(w* (if (> col-min-width w) col-min-width w))
|
|
)
|
|
(when (eq? (vector-ref column-keep-min-widths c) #t)
|
|
(vector-set! column-min-widths c w*))
|
|
(set-min-width* c 0 w*)))
|
|
|
|
(define/private (arrange*)
|
|
(letrec ((cols (length (send (vector-ref hpanes 0) get-children)))
|
|
(f (lambda (c)
|
|
(when (< c cols)
|
|
(arrange-col* c)
|
|
(f (+ c 1)))))
|
|
)
|
|
(f 0)))
|
|
|
|
;; Fields that can be given
|
|
(init-field [vert-margin 5] [horiz-margin 5] [spacing 5] [columns 1])
|
|
|
|
;; Internal data
|
|
(define column-min-widths (make-vector columns 0))
|
|
(define column-aligns (make-vector columns 'left))
|
|
(define column-keep-min-widths (make-vector columns #f))
|
|
|
|
;; Public methods
|
|
(define/public (column-min-width c . w)
|
|
(unless (null? w)
|
|
(vector-set! column-min-widths c (car w)))
|
|
(vector-ref column-min-widths c))
|
|
|
|
(define/public (column-align c . a)
|
|
(let ((current-align (vector-ref column-aligns c)))
|
|
(unless (null? a)
|
|
(let ((new-align (car a)))
|
|
(unless (eq? new-align current-align)
|
|
(vector-set! column-aligns c new-align)
|
|
(letrec ((rows (if (eq? hpanes #f) 0 (vector-length hpanes)))
|
|
(f (lambda (r)
|
|
(when (< r rows)
|
|
(let ((cell (cell* c r)))
|
|
(send cell set-alignment (list new-align 'center)))
|
|
(f (+ r 1)))))
|
|
)
|
|
(f 0))))))
|
|
(vector-ref column-aligns c))
|
|
|
|
(define/public (column-keep-min-width c . k)
|
|
(unless (null? k)
|
|
(vector-set! column-keep-min-widths c (car k)))
|
|
(vector-ref column-keep-min-widths c))
|
|
|
|
;; Overridden methods
|
|
(define/override (after-new-child child)
|
|
(super after-new-child child)
|
|
(when (eq? creating-row #f)
|
|
(let ((cell (cell* current-col current-row)))
|
|
(send child reparent cell))
|
|
(set! current-col (+ current-col 1))
|
|
(when (>= current-col columns)
|
|
(set! current-row (+ current-row 1))
|
|
(set! current-col 0))
|
|
))
|
|
|
|
(define/override (place-children info width height)
|
|
(let ((r (super place-children info width height)))
|
|
(arrange*)
|
|
r
|
|
))
|
|
|
|
))
|
|
|
|
|
|
;;; GUI Testing
|
|
|
|
;(define win (new frame% [label "Hi there!"]))
|
|
;(define grid-group (new group-box-panel% [label "My group"] [parent win] [horiz-margin 10] [vert-margin 10]))
|
|
|
|
;(define g (new columns-pane% [parent grid-group] [columns 3]))
|
|
;(send g column-min-width 1 500)
|
|
;(send g column-align 2 'center)
|
|
;(send g column-keep-min-width 2 #t)
|
|
|
|
;(define btn1 (new button% [parent g] [label "Button 1"]
|
|
; [callback (lambda (b e) (send lbl1 set-label "New label"))]))
|
|
;(define g1 (new gauge% [parent g] [stretchable-width #t] [label "gauge 1"] [range 100]))
|
|
;(define lbl1 (new message% [parent g] [label "This is lbl 1 and long"] [auto-resize #t]))
|
|
|
|
;(define btn2 (new button% [parent g] [label "Btn 2"]))
|
|
;(define g2-lbl (new message% [parent g] [label "This is something else then a gauge"]))
|
|
;(define lbl2 (new message% [parent g] [label "This is lbl 2"] [auto-resize #t]))
|
|
|
|
;(define btn3 (new button% [parent g] [label "Btn 3"]
|
|
; [callback (lambda (b e) (send lbl3 set-label "Longer label now"))]))
|
|
;(define g3-lbl (new message% [parent g] [label "This is something else then a gauge, another message"]))
|
|
;(define lbl3 (new message% [parent g] [label "short"] [auto-resize #t]))
|
|
|
|
;(send win show #t)
|
|
|