;;;-*- Mode:Common-Lisp; Package:PICTURES; Fonts:(CPTFONT HL12B HL12BI HL12BI CPTFONTB); Base:10 -*- ;1;;* ;1;; Description:* ;1;;* 1Picture objects allow graphic objects to be arranged in hierarchical structures.* ;1;;* 1A graphic is a "child" of a picture (its "parent") if the graphic is a* ;1;;* 1member of the picture's list of elements. A picture is an "ancestor" of a* ;1;;* 1graphic (its "descendant") if it is the graphic's parent or an ancestor of its* ;1;;* 1parent. A "top-level" graphic is one whose parent is nil.* ;1;;* 1Read-access to the list of picture elements is given by the picture-elements* ;1;;* 1method. Modification of the list of picture elements is supported by the* ;1;;* 1picture-insert/delete methods. These methods are responsible for reporting the* ;1;;* 1appropriate damaged regions to any view containing the picture.* ;1;;* ;1;; History:* ;1;;* 18/24/89* 1 Jim Dutton* 1Created* ;1;;* 19/05/89* 1 Jim Dutton* 1Added graphic-normalize method* ;1;;* 19/14/89* 1 Jim Dutton Reversed order of compose in graphic-normalize* ;1;;* 19/19/89* 1 Jim Dutton* 1Changed graphic-draw to only draw children* ;1;;* 1that intersect the optional limit rectangle.* ;1;;* ;1;; * ;1;; * 1 RESTRICTED RIGHTS LEGEND * ;1;; * ;1;; Use, duplication, or disclosure by the Government is subject to restrictions as set* ;1;; forth in subdivision (b)(3)(ii) of the Rights in Technical Data and Computer* ;1;; Software clause at 52.227-7013. * ;1;; * ;1;; TEXAS INSTRUMENTS INCORPORATED, P.O. BOX 149149 AUSTIN, TEXAS 78714-9149* ;1;; Copyright (C) 1989, Texas Instruments Incorporated. All rights reserved.* ;1;; * (in-package "2PICTURES*") (USE-PACKAGE '(common-lisp clos)) ;1Picture Class Definition:* (defclass 4picture *(extent-cache graphic) ( (elements :type list :initarg :elements :initform nil :documentation "3The graphic objects in the picture(mR)*") (views :type list :initform nil :documentation "3The views to which the picture is attached(mR)*") ) (:documentation "3Base class for composite graphical objects*")) ;1Type: picture-position* (deftype 4picture-position *() '(or graphic (member :first :last))) ;1Function: make-picture* ;1 Return a new picture object with no elements.* (defun 4make-picture* (&rest initargs &key &allow-other-keys) (declare (values picture)) (apply #'make-instance 'picture initargs)) ;1Method: graphic-draw* ;1 Draw the PICTURE object in the given VIEW. If MIN-X, MIN-Y, WIDTH, and HEIGHT* ;1 are given, then only parts of the object that lie within the given rectangle* ;1 need to be drawn.* ;1 For pictures, just draw each of the child graphics.* (defmethod 4graphic-draw* ((picture picture) (view view) &optional min-x min-y width height) (declare (type (or null wcoord) min-x min-y width height)) (with-slots (elements sensitivity) picture (world-transform picture) ;1 Cache our transform* (combined-gstate picture) ;1 Cache our gstate* (UNLESS (EQUAL sensitivity :hidden) (if (and min-x min-y width height) ;1 Was optional rect is given* (dolist (child elements) ;1 Yes, conditionally draw children* (when (graphic-intersects-p child min-x min-y width height) (graphic-draw child view min-x min-y width height))) (dolist (child elements) ;1 No, unconditionally draw children* (graphic-draw child view)))))) ;1Method: graphic-normalize* ;1 Normalize the PICTURE by applying its transform and then calling* ;1 graphic-normalize on each of its children.* ;1 Nothing of value is returned.* (defmethod 4graphic-normalize *:before ((picture picture)) (with-slots ((parent-transform transform) elements) picture (dolist (child elements) (with-slots ((child-transform transform)) child (setf child-transform (compose-transform child-transform parent-transform child-transform))) (graphic-normalize child)))) ;1Method: graphic-views* ;1 Return a list of all the views to which the GRAPHIC is attached.* (defmethod 4graphic-views *((picture picture)) (with-slots (views) picture views)) ;1Method: extent-compute* ;1 Compute the extent rectangle for the PICTURE. This is done by combining the extents* ;1 of each of the elements in PICTURE and then applying the PICTURE's transform to the* ;1 resulting extent.* (defmethod 4extent-compute *((picture picture)) (declare (values (or null extent-rect))) (with-slots (elements) picture (when elements ;1 Is this an empty picture?* (let ((first-child-extent ;1 No, get the first child's extent* (extent-rectangle (first elements)))) (when first-child-extent ;1 Is it defined?* (let ((temp-extent ;1 Yes, make a copy in a temp* (extent-copy first-child-extent (make-extent-rect)))) (dolist (child (cdr elements)) ;1 For all the other children...* (extent-combine (extent-rectangle child) ;1 Combine their extents* temp-extent)) (extent-transform (graphic-transform picture) ;1 Apply our transform to the result* temp-extent temp-extent) temp-extent)))))) ;1 Return the computed extent* ;1Method: picture-delete* ;1 Removes the graphic at the given POSition from the PICTURE.* ;1 If POS is :FIRST or :LAST, the first or last object in the PICTURE is* ;1 deleted. If POS is a graphic, then that graphic is deleted.* ;1 The deleted graphic is returned with its parent slot set to nil.* (defmethod 4picture-delete* ((picture picture) pos) (declare (type picture-position pos)) (declare (values graphic)) (with-slots (elements) picture (when elements (let ((dead-graphic ;1 Remember who was killed* (case pos (:first (pop elements)) ;1 Delete first graphic on list* (:last (prog1 (car (last elements)) ;1 Delete last graphic* (nbutlast elements))) (t (progn (setf elements ;1 Delete the given graphic* (delete pos elements :test 'eq)) pos))))) (when dead-graphic ;1 If we killed something,* (graphic-stack-purge *transform-stack* dead-graphic) ;1 Notify the transform stack* (graphic-stack-purge *gstate-stack* dead-graphic) ;1 Notify the gstate stack* (setf (graphic-parent dead-graphic) nil)) ;1 Clear its parent slot* dead-graphic)))) ;1 Return the dead guy* ;1Method: picture-elements* ;1 Return the list of elements contained by PICTURE.* (defmethod 4picture-elements* ((picture picture)) (declare (values elements)) (slot-value picture 'elements)) ;1Function: picture-group* ;1 Create a new picture and reparent the given elements to it.* ;1 Return the new picture.* (defun 4picture-group* (&rest elements) (declare (type list elements)) (picture-reparent (make-picture) elements)) ;1 Reparent all elements using a new picture* ;1Method: picture-insert* ;1 Inserts the GRAPHIC at the given POSITION in the PICTURE. If POSITION is a* ;1 graphic, then GRAPHIC is inserted immediately after it. If POSITION is :FIRST* ;1 or :LAST, then GRAPHIC is inserted at the beginning or the end of the elements* ;1 list respectively. The parent slot of GRAPHIC is changed to point to PICTURE* ;1 and the GRAPHIC is returned.* (defmethod 4picture-insert* ((picture picture) graphic &optional (pos :last)) (declare (type picture-position pos)) (declare (values graphic)) (with-slots (elements) picture (case pos (:first (push graphic elements)) ;1 Push graphic onto front of list* (:last (if elements ;1 Glue graphic onto the end* (rplacd (last elements) (list graphic)) (push graphic elements))) (t (let ((pos-n (position pos elements))) ;1 Insert after pos on the list* (if pos-n (LET ((a (nthcdr (+ pos-n 1) elements))) (push graphic a)) (error "3Graphic not found in picture*")))))) (setf (graphic-parent graphic) picture) ;1 Set its new parent* graphic) ;1 Return the inserted graphic* ;1Method: picture-reparent* ;1 Move each of the ELEMENTS into the PICTURE.* ;1 Return the new parent picture.* (defmethod 4picture-reparent* ((picture picture) elements) (declare (type list elements)) (dolist (child elements) ;1 Go through the list* (when (graphic-parent child) ;1 If graphic has a parent* (picture-delete (graphic-parent child) child)) ;1 remove it from its parent's list* (picture-insert picture child)) ;1 Add it to the new picture* picture) ;1 Return the picture now containing graphic* ;1Method: picture-restack* ;1 For the given PICTURE, delete the graphic in OLD-POSITION and re-insert it* ;1 in NEW-POSITION.* (defmethod 4picture-restack* ((picture picture) old-position new-position) (declare (type picture-position old-position new-position)) (picture-insert picture (picture-delete picture old-position) new-position)) ;1Method: picture-ungroup* ;1 Reparent all elements of PICTURE to the parent of PICTURE.* ;1 Delete PICTURE from its parent.* (defmethod 4picture-ungroup* ((picture picture)) (with-slots (elements) picture (let ((grand-parent (graphic-parent picture))) (if grand-parent ;1 Is there a grand parent?* (prog1 (picture-reparent grand-parent elements) ;1 Yes, make it the parent* (picture-delete grand-parent picture)) ;1 and delete the picture* (dolist (child elements) ;1 No, make them all independent* (picture-delete picture child)))))) ;1 i.e., they have no parent