[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: catch-cancel



In article <korcuska-3005951056520001@korcuska.ils.nwu.edu>,
korcuska@ils.nwu.edu (Michael Korcuska) wrote:

> In article <korcuska-2805950935540001@korcuska.ils.nwu.edu>,
> korcuska@ils.nwu.edu (Michael Korcuska) wrote:
> 
> > We ran into a strange problem the other day with catch-cancel and
> > throw-cancel.  Inside a catch-cancel we create a window with a button
> > which, when clicked, calls throw-cancel.  Unfortunately the throw wasn't
> > being caught by the catch we set up.
> > 

I belive the problem is that the scope that (throw *tag* "Cancelled") is
different from the scope that (catch *tag ...) is set up in. The throw is
called from low level event handling code which is different from where
the loop is running. I also think that the throw-cancel/catch-cancel
mechanism is reserved for modal-dialogs. (i'm relatively new to MCL so I
could be wrong about this.) So how do you write code like this:

(defparameter *tag* :cancel)

(let* ((btn (make-instance 'button-dialog-item
              :view-size #@(60 20)
              :view-position #@(20 40)
              :dialog-item-text "Cancel"
              :dialog-item-action #'(lambda (item)
                                      (declare (ignore item))
                                      (throw *tag* "Cancelled")))
            )
       (wind (make-instance 'window
               :window-type :single-edge-box
               :view-position :centered
               :view-size #@(100 100)
               :window-show nil
               :view-subviews (list btn))))
  (princ
   (catch *tag*
     (window-show wind)
     (princ "Looping until cancel button clicked")
     (loop for i from 1 to 500
           do (princ ".")
           finally (return "finished"))))
  (window-close wind)
  )

Like this.

(defparameter *tag* :cancel)

(defun do-something ()
  (princ ".")
  nil)

(let* ((btn (make-instance 'button-dialog-item
              :view-size #@(60 20)
              :view-position #@(20 40)
              :dialog-item-text "Cancel"
              :dialog-item-action #'(lambda (item)
                                      (declare (ignore item))
                                      (return-from-modal-dialog :cancel)))
            )
       (wind (make-instance 'window
               :window-type :single-edge-box
               :view-position :centered
               :view-size #@(100 100)
               :window-show nil
               :view-subviews (list btn))))
  (princ
    (catch-cancel
     (princ "Looping until cancel button clicked")
      (modal-dialog wind t #'do-something))))

If you take out the catch-cancel the Listener's catch-cancel is where the
thow cancel is caught. (return-from-modal-dialog calls throw-cancel in the
correct scope.) do-something is set up as an *eventhook* which is the good
Macintosh doobie way of doing two things at once.

-- 
geoff                                           Geoffrey P. Clements
Senior Software Engineer                            Mac Software Guy
Kodak Electronic Printing Systems                         KEPS, Inc.
gclements@keps.com                             Voice: (508) 670-6812