[plt-scheme] Parameters and Eventspaces Question

From: Doug Williams (m.douglas.williams at gmail.com)
Date: Tue Oct 28 14:41:08 EDT 2008

I am trying to create a parameter, current-frame, that allows me to access
the 'current frame' in a multiple frame environment.  In this case, the
'current frame' is the one under which the user initiated the action which
has caused a particular function to run.  A very simple example might be as
follows:

#lang scheme/gui

(define current-frame
  (make-parameter #f))

(define my-frame%
  (class frame%
    (super-instantiate ())
    (field (text-field
            (instantiate text-field%
              ("Press test button to update:" this))))
    (instantiate button%
      ("Clear" this)
      (callback
       (lambda (b e)
         (send text-field set-value ""))))
    (instantiate button%
      ("Test" this)
      (callback
       (lambda (b e)
         (update-text-field))))))

(define (update-text-field)
  (send (get-field text-field (current-frame))
        set-value (send (current-frame) get-label)))

The update-text-field function will set the value of the text-field field in
the 'current frame' to the label of the 'current frame'.  When
update-text-field is invoked, I want the value of the current-frame
parameter to be the frame where the user clicked the Test button.  So, the
behavior I want is for the text-field in the frame in which the Test button
is clicked to be updated with the label of that frame. [Yes, in this case it
would be easy to just pass the frame to update-text-field or any of several
other trivial solutions.  But, bear with me.]

I have tried various combinations of parameterize and current-frame, with no
success.  For example:

(parameterize ((current-frame (instantiate my-frame%
                                ("Frame 1"))))
  (send (current-frame) show #t)
  (update-text-field))

(parameterize ((current-eventspace (make-eventspace)))
  (parameterize ((current-frame (instantiate my-frame%
                                  ("Frame 2"))))
    (send (current-frame) show #t)
    (update-text-field)))

(parameterize ((current-eventspace (make-eventspace)))
  (let ((frame-3 (instantiate my-frame%
                   ("Frame 3"))))
    (current-frame frame-3)
    (send (current-frame) show #t)
    (update-text-field)))

(let ((frame-4 (instantiate my-frame%
                 ("Frame 4"))))
  (current-frame frame-4)
  (send (current-frame) show #t)
  (update-text-field))

(let ((frame-5 (instantiate my-frame%
                 ("Frame 5"))))
  (current-frame frame-5)
  (send (current-frame) show #t)
  (update-text-field))

If you evaluate all of these, then Frame 1, Frame 4, and Frame 5 all share a
common eventspace.  Clicking the Test button on any of them will result in
"Frame 5" being written in the text-field in Frame 5.  Clicking the Text
button on either Frame 2 or Frame 3, which should be running in their own
eventspaces, both give an error "get-field: expected an object, got #f".  In
all cases, the hard-coded calls to update-text-field that are lexically
within the scope (and eventspace) that instantiated the frame work as
expected.

I assume the problem is with my mental model of parameters and eventspaces.
I had assumed that each eventspace would have, in addition to its event
queues, etc,  its own execution thread, and copies of any parameters.  Since
it allows me to parameterize or set the current-frame in a new eventspace, I
assume the eventspace 'knows about' my current-frame parameter.  What I
don't understand is why a call to update-text-field by a frame that I think
is running under 'new' eventspace doesn't get a value for the current-frame
parameter.  So, I understand the behavior of Frames 1, 4, and 5 - or at
least they fit my (probably flawed) mental model.  But, I don't understand
the behavior of Frames 2 and 3, which seems like they would work if my
mental model were correct.

I tried to use get-top-level-focus-window, but it doesn't work in my case.
This is an analysis application where some functions are very long running
and the focus window at the time something is running isn't necessarily what
I was thinking of as the 'current frame'.

As an aside, I am basically trying to the replicate the functionality of the
*application-frame* (dynamically-scoped) global variable in CLIM.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20081028/3f53fbd7/attachment.html>

Posted on the users mailing list.