You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
br-parser-tools/collects/mrdemo/phone.ss

164 lines
5.0 KiB
Scheme

(define lookup-number
(let ([phonebook '(("Mr. Bumpy" "555-BUMP" "555-SNOT")
("Squishington" "555-SQSH" "555-BOWL")
("Miss Molly" "555-MOLL" "555-COMF"))])
(lambda (name home?)
(sleep 2) ; artificial database delay
(let loop ([pb phonebook])
(cond
[(null? pb) #f]
[(regexp-match name (caar pb))
((if home? cadar caddar) pb)]
[else (loop (cdr pb))])))))
(define a-frame
(make-object mred:frame%
null ; No parent frame
"Phone Book")) ; The frame's title
(define a-panel
(make-object mred:vertical-panel%
a-frame)) ; Panel is in a-frame
(define h-panel
(make-object mred:horizontal-panel%
a-panel)) ; Panel is in a-frame
(define name-text
(make-object mred:text%
h-panel
(lambda (self event) (refresh-number-info))
"Name" ; label
"")) ; initial value
(define quit-button
(make-object mred:button%
h-panel
(lambda (self event)
(send a-frame show #f))
"Quit")) ; Button label
(define number-selector
(make-object mred:radio-box%
a-panel
(lambda (self event) (refresh-number-info))
"" ; No label
-1 -1 -1 -1 ; Default position and size
(list "Home Number" "Office Number")))
(define number-text
(make-object mred:text%
a-panel
(lambda (self event) #f) ; No event-handling
"Number"
"(Unknown)"))
(send number-text set-editable #f)
;; First revision: unthreaded
(define refresh-number-info
(lambda ()
(let* ([name (send name-text get-value)]
[home? (zero? (send number-selector get-selection))]
[number (lookup-number name home?)]
[number-string (if number
number
"(Unknown)")])
(send number-text set-value number-string))))
;; Second revision: threaded
(define refresh-number-info
(let ([adj-cancel-sema (make-semaphore 1)]
[previous-cancel (box #f)])
(lambda ()
(let ([this-cancel (box #f)])
(semaphore-wait adj-cancel-sema)
(set-box! previous-cancel #t)
(set! previous-cancel this-cancel)
(semaphore-post adj-cancel-sema)
(thread
(lambda ()
(send number-text set-value "(Searching...)")
(let* ([name (send name-text get-value)]
[home? (zero? (send number-selector get-selection))]
[number (lookup-number name home?)] ; May take a while...
[number-string (if number
number
"(Unknown)")])
(semaphore-wait adj-cancel-sema)
(unless (unbox this-cancel)
(send number-text set-value number-string))
(semaphore-post adj-cancel-sema))))))))
;; Make a class:
(define pb-session%
(class null ()
(public
[refresh-number-info
(let ([adj-cancel-sema (make-semaphore 1)]
[previous-cancel (box #f)])
(lambda ()
(let ([this-cancel (box #f)])
(semaphore-wait adj-cancel-sema)
(set-box! previous-cancel #t)
(set! previous-cancel this-cancel)
(semaphore-post adj-cancel-sema)
(thread
(lambda ()
(send number-text set-value "(Searching...)")
(let* ([name (send name-text get-value)]
[home? (zero? (send number-selector get-selection))]
[number (lookup-number name home?)] ; May take a while...
[number-string (if number
number
"(Unknown)")])
(semaphore-wait adj-cancel-sema)
(unless (unbox this-cancel)
(send number-text set-value number-string))
(semaphore-post adj-cancel-sema)))))))])
(public
(a-frame (make-object mred:frame% null "Phonebook"))
(a-panel (make-object mred:vertical-panel% a-frame)))
(private
(h-panel (make-object mred:horizontal-panel% a-panel))
(name-text (make-object mred:text% h-panel
(lambda (self event) (refresh-number-info))
"Name" ""))
(quit-button (make-object mred:button% h-panel
(lambda (self event) (send a-frame show #f))
"Quit"))
(number-selector (make-object mred:radio-box% a-panel
(lambda (self event) (refresh-number-info))
"" -1 -1 -1 -1 (list "Home Number" "Office Number")))
(number-text (make-object mred:text% a-panel
(lambda (self event) #f)
"Number" "(Unknown)")))
(sequence
(send a-frame show #t)
(send number-text set-editable #f))))
(define pb-counted-session%
(class pb-session% ()
(inherit a-frame a-panel) ; We need to access the panel object...
(rename [basic-refresh-number-info refresh-number-info]) ; and old refresh
(private [search-counter 0]) ; Counter value
(public
[refresh-number-info ; Increment the counter and call old refresh
(lambda ()
(set! search-counter (add1 search-counter))
(send counter-text set-value (number->string search-counter))
(basic-refresh-number-info))])
(sequence
(super-init)) ; Do base class initialization
(private
(counter-text (make-object mred:text% a-panel
(lambda (self event) #f)
"Number of Searches Started"
"0")))
(sequence
(send counter-text set-editable #f))))