[plt-scheme] MrEd: how can I _cleanly_ keep the states of various widgets in sync?
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
>