#lang syndicate (require "../../widgets.rkt") (require/activate syndicate/drivers/timestate) ;; notes on MF impl: ;; - reset button doesn't do anything if duration is at 0 ;; - duration is meant to update as slider is moved, not just when released ;; a timer that permits the continuous setting of a new interval, plusanything if duration is at 0 ;; - duration is meant to update as slider is moved, not just when released ;; a gauge and a text field that display the fraction of the elapsed time ;; a reset button that sends the elapsed time back to 0 (define INTERVAL 100) (define (next-time) (+ (current-milliseconds) INTERVAL)) (define frame (spawn-frame #:label "timer")) (define elapsed (spawn-gauge #:label "elapsed" #:parent frame #:enabled #f #:range 100)) (define text (spawn-text-field #:parent frame #:init-value "0" #:label "")) (define slider (spawn-slider #:label "duration" #:parent frame #:min-value 0 #:max-value 100)) (define button (spawn-button #:label "reset" #:parent frame)) (spawn (field [*elapsed 0] ;; INTERVAL/1000 ms accumulated elapsed time [*duration 0] ;; INTERVAL/1000 ms set duration interval [t (next-time)]) (define (timer-cb) (unless (>= (*elapsed) (*duration)) (*elapsed (+ (*elapsed) 1)) (t (next-time)) (elapsed-cb))) (define (elapsed-cb) (send! (set-text-field text (format "elapsed ~a" (*elapsed)))) (unless (zero? (*duration)) (define r (quotient (* 100 (*elapsed)) (*duration))) (send! (set-gauge-value elapsed r)))) (define (reset-cb) (*elapsed 0) (timer-cb)) (define (duration-cb new-duration) (unless (= new-duration (*duration)) (*duration new-duration) (timer-cb))) (on (asserted (later-than (t))) (timer-cb)) (on (message (button-press button)) (reset-cb)) (on (message (slider-update slider $val)) (duration-cb val)) (on-start (elapsed-cb) (send! (show frame #t))))