From: bill@cambridge.apple.com (Bill St. Clair)
Newsgroups: comp.lang.lisp.mcl
Subject: Re: cell-select in sequence-dialog-items
Date: 20 Aug 92 21:05:38 GMT
Full-Name: Bill St. Clair
Original-To: owens@jonquil.uchicago.edu (Christopher Owens)
Original-Cc: info-mcl

>I'm noticing that, contrary to my intuitive expectations,
>sequence-dialog-items in MCL 2.0 do not call CELL-SELECT when the user
>selects a cell by clicking on it.  Cells become highlighted and added
>to the list returned by SELECTED-CELLS, but the CELL-SELECT method
>itself does not appear to be called.
>
>I had hoped to specialize an :after method for this generic function
>(and for cell-deselect) on a subclass of sequence-dialog-item that
>would accomplish the behavior of activating a few buttons when and
>only when one or more items in a table were selected.  It seems like
>CELL-SELECT and CELL-DESELECT are a more logical place to put this
>behavior than on VIEW-CLICK-EVENT-HANDLER, since sometimes cells might
>be selected or deselected other than by clicking. (i.e. by typing
>characters as in the select file dialog, or by program action)

Sorry for not answering you the first time.

This is not as easy as you think. The VIEW-CLICK-EVENT-HANDLER method
for TABLE-DIALOG-ITEM calls #_LClick which tracks the mouse, taking into
consideration the states of the shift and command keys (depending on
the :SELECTION-TYPE). When the user releases the mouse button, #_LClick
returns, possibly having changed the selection state of some of the
cells. Since most people do not share your desire to have CELL-SELECT
and CELL-DESELECT called at this time (which would redo what has
already been done by the ROM), MCL doesn't bother to record which
cells were selected before #_LClick, compare it with which cells are
selected after #_LClick, and make appropriate calls to CELL-SELECT
and CELL-DESELECT.

It seems to me that you can easily do the following:

(defclass my-sequence-dialog-item (sequence-dialog-item) 
  ((action-buttons :initarg :action-buttons :accessor action-buttons)))

(defmethod view-click-event-handler :after ((d my-sequence-dialog-item) where)
  (declare (ignore where))
  (fixup-buttons d))

(defmethod cell-deselect :after ((d my-sequence-dialog-item) h &optional v)
  (declare (ignore h v))
  (fixup-buttons d))

(defmethod cell-select :after ((d my-sequence-dialog-item) h &optional v)
  (declare (ignore h v))
  (fixup-buttons d))

; This is so we can prevent flashing when arrow keys are typed
; to an arrow dialog.
(defvar *ignore-fixup* nil)

(defmethod fixup-buttons ((d my-sequence-dialog-item))
  (unless (eq *ignore-fixup* d)
    (let ((buttons (action-buttons d))
          (enabler (if (selected-cells d)
                     'dialog-item-enable
                     'dialog-item-disable)))
      (dolist (button buttons)
        (funcall enabler button)))))

; a ccl::arrow-dialog moves the selection in its first sequence-dialog-item
; when an arrow key is typed.
(defclass my-arrow-dialog (ccl::arrow-dialog) ())

(defmethod view-key-event-handler ((d my-arrow-dialog) key)
  (declare (ignore key))
    (let* ((table (view-named :table d))
           (*ignore-fixup* table))
      (prog1 (call-next-method)
        (when table (fixup-buttons table)))))

(defun test-dialog ()
  (let* ((d (make-instance 'my-arrow-dialog
              :view-size #@(160 200)
              :window-show nil))
         (button (make-instance 'button-dialog-item
                   :dialog-item-text "Do something"
                   :view-position #@(10 160)
                   :view-container d))
         (table (make-instance 'my-sequence-dialog-item
                  :table-sequence '(one two three four five six seven eight nine ten)
                  :view-position #@(10 10)
                  :view-size #@(140 130)
                  :view-container d
                  :view-nick-name :table
                  :action-buttons (list button))))
    (fixup-buttons table)
    (window-show d)))

#|
(test-dialog)
|#