gui/gui-lib/mred/private/wxlitem.rkt
2014-12-02 02:33:07 -05:00

414 lines
15 KiB
Racket

(module wxlitem racket/base
(require racket/class
racket/file
(only-in racket/base remq)
racket/snip/private/prefs
(prefix-in wx: "kernel.rkt")
"lock.rkt"
"helper.rkt"
"const.rkt"
"wx.rkt"
"check.rkt"
"wxwindow.rkt"
"wxitem.rkt"
"wxpanel.rkt")
(provide (protect-out wx-choice%
wx-list-box%
wx-radio-box%
wx-gauge%
wx-slider%))
;; ----------------------------------------
(define (is-horiz? style parent)
(cond
[(memq 'vertical-label style) #f]
[(memq 'horizontal-label style) #t]
[else (eq? (send (send parent get-window) get-label-position) 'horizontal)]))
(define (make-sub horiz? proxy this ha va)
(if horiz?
(begin
(send this alignment ha va)
this)
(let ([p (make-object wx-vertical-pane% #f proxy this null #f)])
(send p skip-enter-leave-events #t)
(send p skip-subwindow-events? #t)
(send (send p area-parent) add-child p)
(send p alignment ha va)
p)))
(define (make-label label proxy p font)
(and label
(let ([l (make-object wx-message% #f proxy p label -1 -1 null font)])
(send l x-margin 0) (send l y-margin 0)
(send l skip-enter-leave-events #t)
(send l skip-subwindow-events? #t)
l)))
(define (filter-style style)
(remq 'deleted style))
(define-syntax-rule (bounce c (m . args) ...)
(begin
(define/public m (lambda args (send c m . args)))
...))
;; ----------------------------------------
(define wx-label-panel%
(class wx-control-horizontal-panel%
(init proxy parent label style font halign valign)
(inherit area-parent skip-enter-leave-events set-event-positions-wrt)
(define c #f)
(define/override (enable on?) (if c (send c enable on?) (void)))
(define/override (is-enabled?) (if c (send c is-enabled?) #t))
(define/override (is-window-enabled?) (if c (send c is-window-enabled?) #t))
(super-make-object #f proxy parent (if (memq 'deleted style) '(deleted) null) #f)
(skip-enter-leave-events #t)
(unless (memq 'deleted style)
(send (area-parent) add-child this))
(define horiz? (is-horiz? style parent))
(define p (make-sub horiz? proxy this (if horiz? 'left halign) valign))
(define l (make-label label proxy p font))
(define/public (set-label s) (when l (send l set-label s)))
(define/public (get-label) (and l (send l get-label)))
(define/override (client-to-screen x y)
(if c
(send c client-to-screen x y)
(super client-to-screen x y)))
(define/override (screen-to-client x y)
(if c
(send c screen-to-client x y)
(super screen-to-client x y)))
(define/public (get-p) p)
(define/public (set-c v sx? sy?)
(set! c v)
(set-event-positions-wrt c)
(when l (send l set-event-positions-wrt c))
(when p (send p set-event-positions-wrt c))
(send c stretchable-in-x sx?)
(send c stretchable-in-y sy?)
(send c skip-subwindow-events? #t))))
;; ----------------------------------------
(define wx-internal-choice%
(class (make-window-glue% (make-simple-control% wx:choice% 0 0))
(init mred proxy parent cb label x y w h choices style font)
(override*
[handles-key-code
(lambda (x alpha? meta?)
(or (memq x '(up down))
(and alpha? (not meta?))))])
(super-make-object mred proxy style parent cb label x y w h choices (cons 'deleted style) font)))
(define wx-choice%
(class wx-label-panel%
(init mred proxy parent cb label x y w h choices style font)
(inherit stretchable-in-y stretchable-in-x get-p set-c)
(super-make-object proxy parent label style font 'left 'center)
(define c (make-object wx-internal-choice% mred proxy (get-p) cb label x y w h choices
(filter-style style) font))
(set-c c #t #f)
(bounce
c
(set-selection i)
(get-selection)
(number)
(clear)
(append lbl)
(delete i))
(stretchable-in-y #f)
(stretchable-in-x #f)))
;; ----------------------------------------
(define list-box-wheel-step #f)
(define wx-internal-list-box%
(make-window-glue%
(class (make-control% wx:list-box% 0 0 #t #t)
(init parent cb label kind x y w h choices style font
label-font columns column-order)
(inherit get-first-item
set-first-visible-item
number-of-visible-items)
(private*
[scroll (lambda (dir)
(unless list-box-wheel-step
(set! list-box-wheel-step (get-preference* '|GRacket:wheelStep| (lambda () 3)))
(unless (and (number? list-box-wheel-step)
(exact? list-box-wheel-step)
(integer? list-box-wheel-step)
(<= 1 list-box-wheel-step 100))
(set! list-box-wheel-step 3)))
(let ([top (get-first-item)])
(set-first-visible-item
(max 0 (+ top (* (min list-box-wheel-step (number-of-visible-items)) dir))))))])
(override*
[handles-key-code (lambda (x alpha? meta?)
(case x
[(up down) #t]
[else (and alpha? (not meta?))]))]
[pre-on-char (lambda (w e)
(or (super pre-on-char w e)
(and (not (eq? (system-type) 'macosx)) ; scrolling is built into NSListView
(case (send e get-key-code)
[(wheel-up) (scroll -1) #t]
[(wheel-down) (scroll 1) #t]
[else #f]))))])
(super-make-object style parent cb label kind x y w h choices (cons 'deleted style) font
label-font columns column-order))))
(define wx-list-box%
(class wx-label-panel%
(init mred proxy parent cb label kind x y w h choices style font label-font columns column-order)
(inherit get-p set-c)
(super-make-object proxy parent label style font 'left 'top)
(define c (make-object wx-internal-list-box% mred proxy (get-p) cb label kind x y w h choices
(filter-style style) font label-font columns column-order))
(set-c c #t #t)
(bounce
c
(get-label-font)
(set-string i s col)
(set-selection i)
(get-selection)
(get-selections)
(visible-range)
(get-first-item)
(number-of-visible-items)
(set-first-visible-item i)
(number)
(get-row n)
(set-data i v)
(get-data i)
(selected? i)
(delete i)
(clear)
(set choices . more)
(reset)
(get-column-order)
(set-column-order l)
(set-column-label i l)
(set-column-size i w mn mx)
(get-column-size i)
(delete-column i)
(append-column l))
(define/public select
(case-lambda
[(i) (send c select i)]
[(i on?) (send c select i on?)]
[(i on? extend?) (send c select i on? extend?)]))
(define/public append
(case-lambda
[(s) (send c append s)]
[(s v) (send c append s v)]))))
;; ----------------------------------------
(define wx-internal-radio-box%
(make-window-glue%
(class (make-simple-control% wx:radio-box% 0 0)
(init parent cb label x y w h choices major style font)
(inherit number orig-enable set-selection command)
(override*
[enable
(case-lambda
[(on?) (super enable on?)]
[(which on?) (when (< -1 which (number))
(vector-set! enable-vector which (and on? #t))
(orig-enable which on?))])]
[is-enabled?
(case-lambda
[() (super is-enabled?)]
[(which) (and (< -1 which (number))
(vector-ref enable-vector which))])])
(define is-vertical? (memq 'vertical style))
(public*
[vertical? (lambda () is-vertical?)]
[char-to-button (lambda (i)
(as-exit
(lambda ()
(set-selection i)
(command (make-object wx:control-event% 'radio-box)))))])
(super-make-object style parent cb label x y w h choices major (cons 'deleted style) font)
(define enable-vector (make-vector (number) #t)))))
(define wx-radio-box%
(class wx-label-panel%
(init mred proxy parent cb label x y w h choices major style font)
(inherit stretchable-in-y stretchable-in-x get-p set-c)
(super-make-object proxy parent label style font 'left 'center)
(define c (make-object wx-internal-radio-box% mred proxy (get-p) cb label x y w h choices
major (filter-style style) font))
(set-c c #t #t)
(define enable-vector (make-vector (length choices) #t))
(define/override enable
(case-lambda
[(on?) (super enable on?)]
[(i on?)
(when (< -1 i (vector-length enable-vector))
(vector-set! enable-vector i on?)
(send c enable-button i on?))]))
(define/override is-enabled?
(case-lambda
[() (super is-enabled?)]
[(which) (and (< -1 which (vector-length enable-vector))
(vector-ref enable-vector which))]))
(bounce
c
(button-focus i)
(set-selection i)
(get-selection))
(stretchable-in-y #f)
(stretchable-in-x #f)))
;; ----------------------------------------
(define wx-internal-gauge%
(make-window-glue%
(class (make-control% wx:gauge% 0 0 #f #f)
(init parent label range style font)
(inherit get-client-size get-width get-height set-size
stretchable-in-x stretchable-in-y set-min-height set-min-width
get-parent)
(override* [gets-focus? (lambda () #f)])
;; # pixels per unit of value.
(define pixels-per-value 1)
(super-make-object style parent label range -1 -1 -1 -1 (cons 'deleted style) font)
(let-values ([(client-width client-height) (get-two-int-values
(lambda (a b) (get-client-size a b)))])
(let ([delta-w (- (get-width) client-width)]
[delta-h (- (get-height) client-height)]
[vertical-labels? (eq? (send (send (get-parent) get-window) get-label-position) 'vertical)]
[horizontal? (memq 'horizontal style)])
(set-min-width (if horizontal?
(let ([cw (min const-max-gauge-length
(* range pixels-per-value))])
(max (if vertical-labels?
cw
(+ cw delta-w))
(get-width)))
;; client-height is the default
;; dimension in the minor direction.
(+ client-width delta-w)))
(set-min-height (if horizontal?
(+ client-height delta-h)
(let ([ch (min const-max-gauge-length
(* range pixels-per-value))])
(max (if vertical-labels?
(+ ch delta-h)
ch)
(get-height)))))))
(if (memq 'horizontal style)
(begin
(stretchable-in-x #t)
(stretchable-in-y #f))
(begin
(stretchable-in-x #f)
(stretchable-in-y #t))))))
(define wx-gauge%
(class wx-label-panel%
(init mred proxy parent label range style font)
(inherit stretchable-in-y stretchable-in-x get-p set-c)
(super-make-object proxy parent label style font 'center 'center)
(define c (make-object wx-internal-gauge% mred proxy (get-p) label range
(filter-style style) font))
(set-c c
(memq 'horizontal style)
(memq 'vertical style))
(bounce
c
(get-range)
(set-range rng)
(get-value)
(set-value v))
(let ([h? (and (memq 'horizontal style) #t)])
(stretchable-in-x h?)
(stretchable-in-y (not h?)))))
;; ----------------------------------------
(define wx-internal-slider%
(make-window-glue%
(class (make-control% wx:slider% 0 0 #f #f)
(init parent func label value min-val max-val style font)
(inherit set-min-width set-min-height stretchable-in-x stretchable-in-y
get-client-size get-width get-height get-parent)
;; # pixels per possible setting.
(define pixels-per-value 3)
;; 3 is good because with horizontal sliders under Xt, with 1 or 2
;; pixels per value, the thumb is too small to display the number,
;; which looks bad.
(super-make-object style parent func label value min-val max-val -1 -1 -1 (cons 'deleted style) font)
(let-values ([(client-w client-h) (get-two-int-values (lambda (a b)
(get-client-size a b)))])
(let* ([horizontal? (memq 'horizontal style)]
[vertical-labels? (eq? (send (send (get-parent) get-window) get-label-position) 'vertical)]
[range (+ (* pixels-per-value (add1 (- max-val min-val)))
(cond
[(and horizontal? (not vertical-labels?)) (- (get-width) client-w)]
[(and (not horizontal?) vertical-labels?) (- (get-height) client-h)]
[else 0]))])
((if horizontal? (lambda (v) (set-min-width v)) (lambda (v) (set-min-height v)))
(max ((if horizontal? (lambda () (get-width)) (lambda () (get-height))))
(min const-max-gauge-length range)))
(stretchable-in-x horizontal?)
(stretchable-in-y (not horizontal?)))))))
(define wx-slider%
(class wx-label-panel%
(init mred proxy parent func label value min-val max-val style font)
(inherit stretchable-in-y stretchable-in-x get-p set-c)
(super-make-object proxy parent label style font 'center 'center)
(define c (make-object wx-internal-slider% mred proxy (get-p) func label value min-val max-val
(filter-style style) font))
(set-c c
(memq 'horizontal style)
(memq 'vertical style))
(bounce
c
(get-value)
(set-value v))
(let ([h? (and (memq 'horizontal style) #t)])
(stretchable-in-x h?)
(stretchable-in-y (not h?)))))
)