home *** CD-ROM | disk | FTP | other *** search
- (in-package :oou)
- (oou-provide :selectable-svm)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; selectable-svm.Lisp
- ;;
- ;; Copyright ⌐ 1992 Northwestern University Institute for the Learning Sciences
- ;; All Rights Reserved
- ;;
- ;; author: Michael S. Engber
- ;;
- ;; mixins for selecting views
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (oou-dependencies
- :simple-view-ce)
-
-
- (export '(selectable-svm selectable-rb-svm selectable-cb-svm
- selected-items hilite-selected-item
- ))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (defclass selectable-svm ()
- ((selection-cluster :initarg :selection-cluster
- :accessor selection-cluster)
- (selected-p :initarg :selected-p
- :accessor selected-p)
- (all-drag-actions-p :initarg :all-drag-actions-p
- :accessor all-drag-actions-p)
- (all-drag-end-actions-p :initarg :all-drag-end-actions-p
- :accessor all-drag-end-actions-p)
- (all-drop-actions-p :initarg :all-drop-actions-p
- :accessor all-drop-actions-p))
- (:default-initargs
- :selection-cluster nil
- :selected-p nil
- :all-drag-actions-p t
- :all-drag-end-actions-p t
- :all-drop-actions-p t
- ))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; click handling
-
- (defmethod view-click-event-handler :before ((sv selectable-svm) where)
- (declare (ignore where))
- (with-focused-view (focusing-view sv)
- (if (selected-p sv)
- (click-selected-item sv (shift-key-p))
- (click-unselected-item sv (shift-key-p)))))
-
- (defmethod click-unselected-item ((sv selectable-svm) shift-p)
- (unless shift-p (deselect-all sv :draw-now-p t))
- (select-item sv :draw-now-p t))
-
- (defmethod click-selected-item ((sv selectable-svm) shift-p)
- (when shift-p (deselect-item sv :draw-now-p t)))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; drawing (hiliting)
-
- (defmethod view-draw-contents :after ((sv selectable-svm))
- (when (selected-p sv) (hilite-selected-item sv t)))
-
- (defmethod hilite-selected-item ((sv selectable-svm) hilite-flag)
- (with-focused-view (focusing-view sv)
- (hilite-view sv hilite-flag)))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; handling the current selection
-
- (defmethod mapc-selectable-cluster ((sv selectable-svm) fn &optional selected-only-p)
- ;;search starts from the item's container
- (with-slots (selection-cluster) sv
- (flet ((map-fn (i) (when (and (eq (selection-cluster i) selection-cluster)
- (or (selected-p i) (not selected-only-p)))
- (funcall fn i))))
- (declare (dynamic-extent #'map-fn))
- (map-subviews (view-container sv) #'map-fn 'selectable-svm))))
-
-
- (defmethod selected-items ((sv selectable-svm))
- ;;Returns a list of all the selected items in di's cluster
- (let ((item-list nil))
- (flet ((fn (i) (push i item-list)))
- (declare (dynamic-extent #'fn))
- (mapc-selectable-cluster sv #'fn t)
- (nreverse item-list))))
-
- (defmethod (setf selected-items) (items (sv selectable-svm))
- (without-interrupts
- (deselect-all sv)
- (dolist (i items) (select-item i))))
-
- ;;;;;;;;;;
- ;;Note: the draw-now-p is provided for using these methods at
- ;;interrupt time (e.g. during click event handling). Normally you
- ;;should let draw-now-p default to nil. If you use a non-nil
- ;;draw-now-p, make sure the current view is focused to the item's
- ;;container.
-
- (defmethod select-item ((sv selectable-svm) &key draw-now-p)
- (unless (selected-p sv)
- (setf (selected-p sv) t)
- (if draw-now-p
- (hilite-selected-item sv t)
- (invalidate-view sv t))))
-
- (defmethod deselect-item ((sv selectable-svm) &key draw-now-p)
- (when (selected-p sv)
- (setf (selected-p sv) nil)
- (if draw-now-p
- (hilite-selected-item sv nil)
- (invalidate-view sv t))))
-
- (defmethod deselect-all ((sv selectable-svm) &key draw-now-p)
- (flet ((fn (i) (deselect-item i :draw-now-p draw-now-p)))
- (declare (dynamic-extent #'fn))
- (mapc-selectable-cluster sv #'fn t)))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;specializations for handling dragging selections
-
- (declaim (ftype (function (&rest t) t)
- drop-action
- drag-action
- drag-end-action
- set-drag-outline-rgn))
-
- (defmethod set-DragGrayRgn-areas :after ((sv selectable-svm) where drag-rgn limitRect slopRect)
- ;;specialize the drag-rgn to be the union of all selected items
- (declare (ignore where limitRect slopRect))
- (with-macptrs ((temp-rgn (#_NewRgn)))
- (flet ((add-rgn (i)
- (set-drag-outline-rgn i temp-rgn)
- (#_UnionRgn temp-rgn drag-rgn drag-rgn)))
- (declare (dynamic-extent #'add-rgn))
- (mapc-selectable-cluster sv #'add-rgn t))
- (#_DisposeRgn temp-rgn)))
-
- (defmethod draggable-p ((sv selectable-svm))
- ;;Must check if the item is selected before allowing dragging. Normally this
- ;;isn't needed cause the click selects the item, but a shift-click can de-select.
- (and (selected-p sv) (call-next-method)))
-
- (defmethod pre-drag-hilite ((sv selectable-svm) hilite-flag)
- ;;selectable items already hilite when clicked - so do nothing
- (declare (ignore sv hilite-flag)))
-
- (defmethod drag-item ((sv selectable-svm) where)
- ;;*current-drag-selection* is bound for the duration of the drag,
- ;;so droppable-p won't have to repeatedly compute the current selection.
- (declare (ignore where))
- (let ((*current-drag-selection* (selected-items sv)))
- (declare (special *current-drag-selection*))
- (call-next-method)))
-
- (defmethod droppable-p ((sv selectable-svm) (target simple-view))
- ;;disallow dropping on any member of current selection
- (declare (special *current-drag-selection*))
- (unless (find target *current-drag-selection*)
- (call-next-method)))
-
- ;;;;;;;;;;
- ;;3 call action functions specialized to use entire selection
-
- (defmethod call-drag-action ((sv selectable-svm))
- (declare (special *current-drag-selection*))
- (if (slot-value sv 'all-drag-actions-p)
- (dolist (i *current-drag-selection*) (drag-action i))
- (drag-action sv)))
-
- (defmethod call-drag-end-action ((sv selectable-svm) drag-offset dest-point)
- (if (slot-value sv 'all-drag-end-actions-p)
- (flet ((fn (i) (drag-end-action i drag-offset dest-point)))
- (declare (dynamic-extent #'fn))
- (mapc-selectable-cluster sv #'fn t))
- (drag-end-action sv drag-offset dest-point)))
-
- (defmethod call-drop-action ((sv selectable-svm) (target simple-view) drag-offset dest-point)
- (if (slot-value sv 'all-drag-end-actions-p)
- (flet ((fn (i) (drop-action i target drag-offset dest-point)))
- (declare (dynamic-extent #'fn))
- (mapc-selectable-cluster sv #'fn t))
- (drop-action sv target drag-offset dest-point)))
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; selectable views with radio button behavior
-
- (defclass selectable-rb-svm (selectable-svm) ())
-
- (defmethod click-unselected-item ((sv selectable-rb-svm) shift-p)
- (declare (ignore shift-p))
- (deselect-all sv :draw-now-p t)
- (select-item sv :draw-now-p t))
-
- (defmethod click-selected-item ((sv selectable-rb-svm) shift-p)
- (declare (ignore sv shift-p)))
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; selectable views with check box behavior
-
- (defclass selectable-cb-svm (selectable-svm) ())
-
- (defmethod click-unselected-item ((sv selectable-cb-svm) shift-p)
- (declare (ignore shift-p))
- (select-item sv :draw-now-p t))
-
- (defmethod click-selected-item ((sv selectable-cb-svm) shift-p)
- (declare (ignore shift-p))
- (deselect-item sv :draw-now-p t))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- #|
-
- ;;; a modest example - adding select behavior to static text dialog items
-
- (defclass stsel (selectable-svm static-text-dialog-item) ())
- ;(defclass stsel (selectable-rb-svm static-text-dialog-item) ())
- ;(defclass stsel (selectable-cb-svm static-text-dialog-item) ())
-
- (setf *test-w*
- (make-instance 'dialog
- :window-type :document
- :view-position :centered
- :view-size #@(200 100)
- :window-title "selectable-svm demo"
- :close-box-p t
- :color-p t
- :view-subviews
- (list (make-instance 'stsel
- :view-position #@(20 20)
- :dialog-item-text "item 1"
- :view-nick-name :i1
- :selection-cluster 1
- )
- (make-instance 'stsel
- :view-position #@(20 40)
- :dialog-item-text "item 2"
- :view-nick-name :i2
- :selection-cluster 1
- )
- (make-instance 'stsel
- :view-position #@(20 60)
- :dialog-item-text "Item 3"
- :view-nick-name :i2
- :selection-cluster 1
- )
-
- )))
-
- ;(selected-items (view-named :i1 *test-w*))
-
- |#