(module gui (lib "frtime.ss" "frtime") (require (all-except (lib "etc.ss") rec) (lib "list.ss") (lib "class.ss") (rename (lib "frp-core.ss" "frtime") proc->signal proc->signal) (all-except (lib "mred.ss" "mred") send-event)) (define reactive-control<%> (interface (control<%>) get-event)) (define (insert-in-list list position new-element) (let loop ((list list) (position position)) (cond ((zero? position) (cons new-element list)) ((null? list) '()) (else (cons (car list) (loop (cdr list) (sub1 position))))))) (define (reactive-control-mixin super) (class* super (reactive-control<%>) ; (mixin (control<%>) (reactive-control<%>) (define event (event-receiver)) (define/public (get-event) event) (define/public (extract-value) (error 'extract-value "abstract method")) (super-instantiate () (callback (lambda (self control-event) (send-event event (list self control-event (extract-value)))))))) (define reactive-slider% (class (reactive-control-mixin slider%) (inherit get-value) (define/override (extract-value) (get-value)) (super-instantiate ()))) (define (make-control-behavior reactive-control) (hold ((send reactive-control get-event) . ==> . third) (send reactive-control extract-value))) ;(define (get-button-event reactive-button) ; ((send reactive-button get-event) . -=> . #t)) (define reactive-slider-1d% reactive-slider%) (define make-slider-1d-behavior make-control-behavior) ; (define reactive-slider-2d% ; (class (reactive-control-mixin slider-2d%) ; (inherit get-values) ; (define/override (extract-value) ; (call-with-values (lambda () (get-values)) ; cons)) ; (super-instantiate ()))) ; ; (define (make-slider-2d-behavior reactive-slider) ; (hold ((send reactive-slider get-event) . ==> . third) ; (call-with-values ; (lambda () (send reactive-slider get-values)) ; cons))) ; ; (define reactive-button% (class (reactive-control-mixin button%) (define/override (extract-value) 'button-press) (super-instantiate ()))) (define reactive-check-box% (class (reactive-control-mixin check-box%) (inherit get-value) (define/override (extract-value) (get-value)) (super-instantiate ()))) (define reactive-list-box% (class (reactive-control-mixin list-box%) (inherit get-selections) (define/override (extract-value) (get-selections)) (super-instantiate ()))) (define reactive-choice% (class (reactive-control-mixin choice%) (inherit get-selection) (define/override (extract-value) (get-selection)) (super-instantiate ()))) (define reactive-text-field% (class (reactive-control-mixin text-field%) (inherit get-value) (define/override (extract-value) (get-value)) (super-instantiate ()))) (define view<%> (interface () set-value)) (define reactive-view<%> (interface () set-behavior)) (define (reactive-view-mixin super) (class* super (reactive-view<%>) ; (mixin (view<%>) (reactive-view<%>) (init-field [cell (new-cell undefined)] [updater #f]) (super-instantiate ()) (define/public (set-behavior beh) (unless updater (set! updater (proc->signal (lambda () (send this set-value (value-now cell)) (value-now cell)) cell))) (set-cell! cell beh)))) ; (define (drive-view-thread view event) ; (let ((view-box (make-weak-box view))) ; (set! view (void)) ; (dynamic-disable-break ; (lambda () ; (thread ; (lambda () ; (let/ec k ; (with-handlers ((exn:break? k)) ; (run-callback event ; (lambda (value) ; (cond ; ((weak-box-value view-box) ; => (lambda (view) ; (send view set-value value))) ; (else (k 'fick-dich-ins-knie))))))))))))) ; (define reactive-gauge% (reactive-view-mixin (class* gauge% (view<%>) (override set-value) (inherit show is-shown?) (define (set-value val) (if (undefined? val) (when (is-shown?) (show #f)) (begin (unless (is-shown?) (show #t)) (super set-value val)))) (super-instantiate ())))) (define reactive-message% (reactive-view-mixin (class* message% (view<%>) (inherit set-label) (define/public (set-value label) (if (undefined? label) (set-label "") (set-label label))) (super-instantiate ())))) (define frame (instantiate frame% () (label "GUI") (height 150) (width 200))) (send frame show #t) (define-struct gui-item (builder)) (define (create-gui-item builder) (let ([C false]) (make-gui-item (lambda (p) (cond [(and p C) (error 'create-window "item added to window twice")] [(and p (not C)) (set! C (builder p)) C] [(and (not p) C) C] [(and (not p) (not C)) (error 'gui "gui-items must be added to window before use (see create-window)")]))))) (define (make-button str) (send (instantiate reactive-button% () (label str) (parent frame)) get-event)) (define (make-message str~) (send (instantiate reactive-message% () (label (if (undefined? (value-now str~)) "" (value-now str~))) (parent frame) (stretchable-height #t) (stretchable-width #t)) set-behavior str~)) (define (make-gauge rng val~) (send (instantiate reactive-gauge% () (label "") (range rng) (parent frame) (stretchable-width #t)) set-behavior val~)) (define (make-text str) (make-control-behavior (instantiate reactive-text-field% () (label str) (init-value "") (parent frame)))) (define (make-choice str los) (make-control-behavior (instantiate reactive-choice% () (choices los) (parent frame) (label str)))) (define (make-slider str min max init) (make-control-behavior (instantiate reactive-slider-1d% () (label str) (min-value min) (max-value max) (parent frame) (init-value init) ;(style (list 'plain 'horizontal)) ))) (define make-check-box (opt-lambda (str [val #f]) (make-control-behavior (instantiate reactive-check-box% () (label str) (parent frame) (value val))))) (define fresh-window (let ([first #t]) (lambda () (if first (set! first #f) (begin (set! frame (instantiate frame% () (label "GUI") (height 150) (width 200))) (send frame show #t)))))) (provide (all-defined)))