[plt-scheme] MrEd: how can I _cleanly_ keep the states of various widgets in sync?

From: Gregory Cooper (greg at cs.brown.edu)
Date: Fri Nov 30 08:55:05 EST 2007

Here's how I would write something along those lines in FrTime:

(require (lib "simple.ss" "frtime" "demos" "gui"))

(define frame (new ft-frame% [shown #t]))

(define check-box (new ft-check-box% [parent frame] [label "Enable the
button?"]))
(define enabled? (send check-box get-value-b))

(define button (new ft-button% [parent frame] [label "Click me!"]
[enabled enabled?]))
(define clicks (send button get-value-e))

(define message (new ft-message% [parent frame]
                     [label (format "~a clicks so far"
                                    (accum-b (map-e (lambda (_) add1)
clicks) 0))]))

Greg

On Nov 29, 2007 6:53 PM, Eric Hanchrow <offby1 at blarg.net> wrote:
> I'll let the comments in my example program speak for themselves:
>
> #! /bin/sh
> #| Hey Emacs, this is -*-scheme-*- code!
> #$Id: gui-constraints.ss 5286 2007-11-29 23:51:36Z erich $
> exec mred --no-init-file --mute-banner --version --require "$0"
> |#
> (module gui-constraints mzscheme
> (require (lib "class.ss")
>          (lib "mred.ss" "mred"))
>
> ;; Trying to use MrEd to solve a problem that is easily solved in
> ;; Delphi 6, and presumably other sophisticated GUI builders: we have
> ;; a couple of widgets, and we'd like the state of each of those
> ;; widgets to be determined by the states of some of the others.
> ;; Imagine a button and a radio-box, where the button is enabled if
> ;; and only if certain items are selected in the radio box.  Now, we
> ;; could certainly add code to the callback for _the radio box_ that
> ;; fiddles the enabled state of the button, but imagine that we
> ;; actually have lots of widgets, not just two, and their
> ;; interrelationships are complex.  It seems to me that it's easier to
> ;; put the code that enables a widget right "next to" that widget, and
> ;; have that code refer to all the things that affect it, than the
> ;; other way around, namely, having each widget "know" about those
> ;; that it -affects-.
>
> ;; So my solution is to write a background thread that runs all the
> ;; "update me" processes.  This code here does just that, for a very
> ;; simple case.  Alas the background thread burns up all the CPU
> ;; without that ugly "sleep" call; I haven't yet figured out how to
> ;; make it run only when it needs to run (i.e., when some state in the
> ;; GUI has changed).
>
> ;; * I think Kenny Tilton's "Cells"
> ;;   (http://common-lisp.net/project/cells/) are a sophisticated way
> ;;   to solve this problem (probably without threads)
>
> ;; * Java's "Swing" GUI thingy has something called "Actions" that
> ;;   might solve the same problem:
> ;;   http://java.sun.com/docs/books/tutorial/uiswing/misc/action.html;
> ;;   "hotblack23" on #scheme suggests that
> ;;   java.beans.PropertyChangeListener is the relevant class
>
> ;; * C-sharp has some documentation on "Event-based Asynchronous
> ;;   Pattern", which _might_ be relevant (but in typical M$ style,
> ;;   it's very hard to understand):
> ;;   http://msdn2.microsoft.com/en-us/library/wewwczdw.aspx
>
> (define frame (new frame% (label "Constraint Testing")))
>
> (define button
>   (new button% (parent frame) (label "Click me!")
>        (callback (lambda (item event)
>                    (message-box "OK" "Now what?")))))
>
> (define radio-box
>   (new radio-box% (label "Pick one")
>        (choices '("Disable that button there" "Let it be enabled"))
>        (parent frame)))
>
> (thread
>  (lambda ()
>    (let loop ()
>      (sync (system-idle-evt))
>      (send button enable
>            (not (zero? (send radio-box get-selection))))
>      (sleep 1/10)
>      (loop))))
>
> (send frame show #t)
>
> )
>
>
> --
> If you're trying to choose between two theories and one gives
> you an excuse for being lazy, the other one is probably right.
>         -- Paul Graham
> _________________________________________________
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>


Posted on the users mailing list.