racket/collects/mred/private/mrpanel.rkt
2011-02-24 13:23:51 -07:00

255 lines
10 KiB
Racket

(module mrpanel mzscheme
(require mzlib/class
mzlib/class100
(prefix wx: "kernel.ss")
"lock.ss"
"const.ss"
"check.ss"
"helper.ss"
"wx.ss"
"kw.ss"
"wxpanel.ss"
"mrwindow.ss"
"mrcontainer.ss")
(provide pane%
vertical-pane%
horizontal-pane%
grow-box-spacer-pane%
panel%
vertical-panel%
horizontal-panel%
tab-panel%
group-box-panel%)
(define-keywords pane%-keywords
subarea%-keywords
container%-keywords
area%-keywords)
(define-local-member-name get-initial-label)
(define pane%
(class100*/kw (make-subarea% (make-container% area%)) ()
[(parent) pane%-keywords]
(private-field [wx #f])
(sequence
(let* ([who (cond ; yuck! - we do this to make h-p and v-p subclasses of p
[(is-a? this vertical-pane%) 'vertical-pane]
[(is-a? this horizontal-pane%) 'horizontal-pane]
[(is-a? this grow-box-spacer-pane%) 'grow-box-spacer-pane]
[else 'pane])]
[cwho `(constructor ,who)])
(check-container-parent cwho parent)
(as-entry
(lambda ()
(super-init (lambda ()
(set! wx (make-object (case who
[(vertical-pane) wx-vertical-pane%]
[(horizontal-pane) wx-horizontal-pane%]
[(grow-box-spacer-pane) wx-grow-box-pane%]
[else wx-pane%])
this this (mred->wx-container parent) null
#f))
wx)
(lambda () wx)
(lambda () wx)
(lambda ()
(check-container-ready cwho parent))
parent)
(send (send wx area-parent) add-child wx)))
(send parent after-new-child this)))))
(define vertical-pane% (class100*/kw pane% () [(parent) pane%-keywords] (sequence (super-init parent))))
(define horizontal-pane% (class100*/kw pane% () [(parent) pane%-keywords] (sequence (super-init parent))))
(define grow-box-spacer-pane% (class100*/kw pane% () [(parent) pane%-keywords] (sequence (super-init parent))))
(define-keywords panel%-keywords
window%-keywords
subarea%-keywords
container%-keywords
area%-keywords)
(define panel%
(class100*/kw (make-subwindow%
(make-area-container-window%
(make-window% #f (make-subarea% (make-container% area%)))) )
(subwindow<%>)
[(parent [style null]) panel%-keywords]
(private-field [wx #f])
(public [get-initial-label (lambda () #f)])
(sequence
(let* ([who (cond ; yuck! - we do this to make h-p and v-p subclasses of p
[(is-a? this tab-panel%) 'tab-panel]
[(is-a? this group-box-panel%) 'group-box-panel]
[(is-a? this vertical-panel%) 'vertical-panel]
[(is-a? this horizontal-panel%) 'horizontal-panel]
[else 'panel])]
[cwho `(constructor ,who)]
[can-canvas? (memq who '(vertical-panel
horizontal-panel
panel))]
[as-canvas? (lambda () (or (memq 'vscroll style)
(memq 'auto-vscroll style)
(memq 'hscroll style)
(memq 'auto-hscroll style)))])
(check-container-parent cwho parent)
(check-style cwho #f (append '(border deleted)
(if can-canvas?
'(hscroll vscroll auto-hscroll auto-vscroll)
null))
style)
(as-entry
(lambda ()
(super-init (lambda () (set! wx (make-object (case who
[(vertical-panel)
(if (as-canvas?)
wx-vertical-canvas-panel%
wx-vertical-panel%)]
[(tab-panel) wx-vertical-tab-panel%]
[(group-box-panel) wx-vertical-group-panel%]
[(horizontal-panel)
(if (as-canvas?)
wx-horizontal-canvas-panel%
wx-horizontal-panel%)]
[else (if (as-canvas?)
wx-canvas-panel%
wx-panel%)])
this this (mred->wx-container parent)
(cons 'transparent style)
(get-initial-label)))
wx)
(lambda () wx)
(lambda () wx)
(lambda () (check-container-ready cwho parent))
#f parent #f)
(unless (memq 'deleted style)
(send (send wx area-parent) add-child wx))))
(send parent after-new-child this)))))
(define vertical-panel%
(class100*/kw panel% ()
[(parent [style null]) panel%-keywords]
(sequence (super-init parent style))
(public [set-orientation (λ (x) (send (mred->wx this) set-orientation x))]
[get-orientation (λ () (send (mred->wx this) get-orientation))])))
(define horizontal-panel%
(class100*/kw panel% ()
[(parent [style null]) panel%-keywords]
(sequence (super-init parent style))
(public [set-orientation (λ (x) (send (mred->wx this) set-orientation x))]
[get-orientation (λ () (send (mred->wx this) get-orientation))])))
(define list-append append)
(define tab-panel%
(class100*/kw vertical-panel% ()
[(choices parent [callback (lambda (b e) (void))] [style null] [font no-val]) panel%-keywords]
(private-field [save-choices choices])
(override [get-initial-label (lambda () save-choices)])
(sequence
(let ([cwho '(constructor tab-panel)])
(unless (and (list? choices) (andmap label-string? choices))
(raise-type-error (who->name cwho) "list of strings (up to 200 characters)" choices))
(check-callback cwho callback)
(check-container-parent cwho parent)
(check-style cwho #f '(deleted no-border) style)
(check-font cwho font))
(super-init parent (if (memq 'no-border style)
(if (eq? (car style) 'no-border)
(cdr style)
(list (car style)))
(cons 'border style)))
(send (mred->wx this) set-callback (lambda (wx e) (callback (wx->mred wx) e))))
(public
[get-number (lambda () (length save-choices))]
[append (entry-point
(lambda (n)
(check-label-string '(method tab-panel% append) n)
(let ([n (string->immutable-string n)])
(set! save-choices (list-append save-choices (list n)))
(send (mred->wx this) append n))))]
[get-selection (lambda () (and (pair? save-choices)
(send (mred->wx this) get-selection)))]
[set-selection (entry-point
(lambda (i)
(check-item 'set-selection i)
(send (mred->wx this) set-selection i)))]
[delete (entry-point
(lambda (i)
(check-item 'delete i)
(set! save-choices (let loop ([p 0][l save-choices])
(if (= p i)
(cdr l)
(cons (car l) (loop (add1 p) (cdr l))))))
(send (mred->wx this) delete i)))]
[set-item-label (entry-point
(lambda (i s)
(check-item 'set-item-label i)
(check-label-string '(method tab-panel% set-item-label) s)
(let ([s (string->immutable-string s)])
(set! save-choices (let loop ([save-choices save-choices][i i])
(if (zero? i)
(cons s (cdr save-choices))
(cons (car save-choices) (loop (cdr save-choices) (sub1 i))))))
(send (mred->wx this) set-label i s))))]
[set
(entry-point (lambda (l)
(unless (and (list? l) (andmap label-string? l))
(raise-type-error (who->name '(method tab-panel% set))
"list of strings (up to 200 characters)" l))
(set! save-choices (map string->immutable-string l))
(send (mred->wx this) set l)))]
[get-item-label (entry-point
(lambda (i)
(check-item 'get-item-label i)
(list-ref save-choices i)))])
(private
[check-item
(lambda (method n)
(check-non-negative-integer `(method tab-panel% ,method) n)
(let ([m (length save-choices)])
(unless (< n m)
(raise-mismatch-error (who->name `(method tab-panel% ,method))
(if (zero? m)
"panel has no tabs; given index: "
(format "panel has only ~a tabs, indexed 0 to ~a; given out-of-range index: "
m (sub1 m)))
n))))])))
(define group-box-panel%
(class100*/kw vertical-panel% ()
[(label parent [style null] [font no-val]) panel%-keywords]
(private-field
[lbl label])
(override [get-initial-label (lambda () lbl)])
(sequence
(let ([cwho '(constructor group-box-panel)])
(check-label-string cwho label)
(check-container-parent cwho parent)
(check-style cwho #f '(deleted) style)
(check-font cwho font))
;; Technically a bad way to change margin defaults, since it's
;; implemented with an update after creation:
(when (eq? horiz-margin no-val) (set! horiz-margin 2))
(when (eq? vert-margin no-val) (set! vert-margin 2))
(super-init parent (if (memq 'deleted style)
'(deleted)
null)))
(override
[set-label (entry-point
(lambda (s)
(check-label-string '(method group-box-panel% set-label) s)
(set! lbl (if (immutable? s)
s
(string->immutable-string s)))
(send (mred->wx this) set-label s)))]
[get-label (lambda () lbl)]))))