;;;-*- Mode:Common-Lisp; Package:PICTURES; Base:10 -*- ;;; ;;; ;;; ;;; TEXAS INSTRUMENTS INCORPORATED ;;; P.O. BOX 149149 ;;; AUSTIN, TEXAS 78714-9149 ;;; ;;; Copyright (C)1987,1988,1989,1990 Texas Instruments Incorporated. ;;; ;;; Permission is granted to any individual or institution to use, copy, modify, ;;; and distribute this software, provided that this complete copyright and ;;; permission notice is maintained, intact, in all copies and supporting ;;; documentation. ;;; ;;; Texas Instruments Incorporated provides this software "as is" without ;;; express or implied warranty. ;;; ;;; Authors: Delmar Hager, James Dutton, Teri Crowe ;;; Contributors: Kerry Kimbrough, Patrick Hogan, Eric Mielke (in-package "PICTURES") (DEFPARAMETER grabber-side-size 6 "This is the size of the width and the height of the grabber") (export '( make-selection-scene view-transform-graphic view-move-graphic view-scale-graphic view-rotate-graphic ) 'pictures) (DEFUN round-vector (VECTOR) "round all of the values of a vector" (DOTIMES (pointer (FILL-POINTER vector) nil) (SETF (ELT vector pointer) (FLOOR (ELT vector pointer) )))) (defclass selection-scene (scene) ( (grabber-size :type integer :initform grabber-side-size :accessor grabber-size :documentation "The size of the grabber for the grabber-rect") ) (:documentation "The graphic class for representing the selection scene")) (DEFMACRO scene-visible-p (graphic) `(AND (NOT (AND (and min-x min-y width height) ; Was optional rect given (not (graphic-within-p ,graphic min-x min-y width height)) (not (graphic-intersects-p ,graphic min-x min-y width height)))) (viewable-p ,graphic))) (defmethod draw-graphic ((scene selection-scene) (view view) &optional min-x min-y width height) (DECLARE (IGNORE min-x min-y width height)) (with-slots (elements extent) scene (WHEN (viewable-p scene) (graphic-world-transform scene) ; Cache our transform (DOTIMES (position (length elements)) (draw-graphic (ELT elements position) view ) )))) (DEFUN make-selection-scene ( &rest options ) (APPLY #'MAKE-INSTANCE 'selection-scene :sensitivity :subselectable options)) (defclass grabber (filled-rectangle) ( (name :type (OR null symbol) :initarg :grabber-name :accessor grabber-name :documentation "the position name of the grabber in the the grabber-rect") (opposing :initform nil :accessor opposing-grabber :documentation "the grabber that is opposite of this instance of grabber") ) (:documentation "This is special class of filled rectangle to represent the grabbers of the extent rectangle")) (defmethod scene-insert ((scene selection-scene) graphic &optional pos ) (DECLARE (IGNORE pos)) (declare (values graphic)) (with-slots (elements parent) scene ;to a scene (VECTOR-PUSH-EXTEND graphic elements 1) ;insert after last graphic ) ; Set its new parent graphic) (DEFUN normalize-transform (transform) (WHEN transform (with-slots (t11 t12 t21 t22 t31 t32) transform (SETF t11 1 t12 0 t21 0 t22 1 t31 0 t32 0)))) (defmethod draw-graphic ((rectangle grabber) (view view) &optional min-x min-y width height) (declare (IGNORE min-x min-y width height)) (WHEN (viewable-p rectangle) (LET ((grabber-rect-transform (grabber-rect-transform view))) (with-slots (vertices transform) rectangle (with-vector temp-vertices (copy-to-vector vertices temp-vertices) (normalize-transform transform) (scale-transform transform (t11 grabber-rect-transform) (t22 grabber-rect-transform ) (rectangle-origin-x rectangle)(rectangle-origin-y rectangle) ) (transform-point-seq transform temp-vertices) (view-draw-filled-polygon view ; No, use draw-polygon to draw it temp-vertices (graphic-gstate rectangle))))))) (defclass grabber-rect (scene) ( (graphic :type (OR null graphic) :initform nil :accessor grabber-graphic :documentation "the graphic the grabber-rect is attached to") (north-grabber :type (OR null grabber) :initform nil :accessor north-grabber :documentation "the north grabber of the grabber-rect") (south-grabber :type (OR null grabber) :initform nil :accessor south-grabber :documentation "the south grabber of the grabber-rect") (east-grabber :type (OR null grabber) :initform nil :accessor east-grabber :documentation "the east grabber of the grabber-rect") (west-grabber :type (OR null grabber) :initform nil :accessor west-grabber :documentation "the west grabber of the grabber-rect") (northwest-grabber :type (OR null grabber) :initform nil :accessor northwest-grabber :documentation "the northwest grabber of the grabber-rect") (northeast-grabber :type (OR null grabber) :initform nil :accessor northeast-grabber :documentation "the northeast grabber of the grabber-rect") (southwest-grabber :type (OR null grabber) :initform nil :accessor southwest-grabber :documentation "the southwest grabber of the grabber-rect") (southeast-grabber :type (OR null grabber) :initform nil :accessor southeast-grabber :documentation "the southeast grabber of the grabber-rect") (background-grabber :type (OR null grabber) :initform nil :accessor background-grabber :documentation "the background grabber of the grabber-rect") ) (:documentation "The graphic class for representing the grabber rectangle")) (defmethod draw-graphic ((scene grabber-rect) (view view) &optional min-x min-y width height) (declare (type (or null wcoord) min-x min-y width height)) (with-slots (elements extent) scene (WHEN (viewable-p scene) (graphic-world-transform scene) ; Cache our transform (DOTIMES (position (length elements)) (draw-graphic (ELT elements position) view min-x min-y width height) )))) (defclass background-grabber ( grabber) () (:documentation "This is special class of rectangle to represent the background grabber")) ;Define a graphic-contains-p method for the background-grabber that will use the graphic-contains-p ;method of the the selected graphic (defmethod graphic-contains-p ((grabber background-grabber) x y &optional pixel) (declare (type wcoord x y )) (declare (values boolean)) (graphic-contains-p (grabber-graphic (graphic-parent grabber)) x y pixel)) (DEFMETHOD graphic-contains-p ((filled-polygon grabber) x y &optional pixel) (DECLARE (IGNORE pixel)) (DECLARE (type wcoord x y)) ; (WHEN (point-in-extents-p filled-polygon x y) (with-slots (vertices) filled-polygon (with-vector temp-vertices (copy-to-vector vertices temp-vertices) (transform-point-seq (graphic-world-transform filled-polygon) temp-vertices) (WHEN (inside-p temp-vertices (make-point :x x :y y)) t )) ) ) (defun make-background-grabber (name x y width height transform) (declare (type wcoord x y )) (FUNCALL #'make-instance 'background-grabber :allow-other-keys t :grabber-name name :vertices (complete-rectangle x y (+ x width) (+ y height)) :transform transform )) (DEFMETHOD initialize-instance :after ((background-grabber background-grabber) &key vertices) (SETF (vertices background-grabber) vertices)) (defun make-grabber (name x y width height transform &rest options &key &allow-other-keys) (declare (type wcoord x y )) (declare (values rectangle)) (apply #'make-instance 'grabber :allow-other-keys t :grabber-name name :vertices (complete-rectangle x y (+ x width) (+ y height)) :transform transform :gstate (make-gstate :function boole-xor) options)) (DEFMETHOD initialize-instance :after ((grabber grabber) &key vertices) (SETF (vertices grabber) vertices)) (DEFMETHOD (SETF grabber-graphic) (agraphic (grabber-rect grabber-rect)) (with-slots (graphic transform extent sensitivity) grabber-rect (SETF graphic agraphic) (IF agraphic (PROGN (extent-compute grabber-rect) (SETF sensitivity :subselectable)) (SETF sensitivity :hidden) ))) (DEFMACRO scale-value (fixed-p p1 p2) `(IF (EQ ,fixed-p ,p1) 0.000001 (/ (- ,fixed-p ,p2) (- ,fixed-p ,p1)))) (DEFMACRO grabber-corner-p (grabber-name) `(OR (EQ ,grabber-name 'northwest-grabber) (EQ ,grabber-name 'southwest-grabber) (EQ ,grabber-name 'northeast-grabber) (EQ ,grabber-name 'southeast-grabber))) (DEFMACRO grabber-north-south-p (grabber-name) `(OR (EQ ,grabber-name 'north-grabber) (EQ ,grabber-name 'south-grabber))) (DEFMACRO grabber-east-west-p (grabber-name) `(OR (EQ ,grabber-name 'east-grabber) (EQ ,grabber-name 'west-grabber))) (defun make-grabber-rect (view &key (highlight 1) parent ) (LET* ((size (grabber-size (view-selection-scene view)))) (FUNCALL #'MAKE-INSTANCE 'grabber-rect :sensitivity :subselectable :gstate (make-gstate :foreground highlight :function boole-xor ) ;the function is set for Xor :size size :parent parent :view view ))) (DEFMACRO grabber-transform () `(copy-transform transform (make-transform))) (DEFMETHOD initialize-instance :after ((grabber-rect grabber-rect) &key size view) (LET* ((sign-x (SIGNUM (view-scale-x view))) (sign-y (SIGNUM (view-scale-y view))) (negsize (- size)) (width (* sign-x size)) (negwidth (* sign-x negsize)) (heigth (* sign-y size)) (negheigth (* sign-y negsize)) (transform (grabber-rect-transform view))) (with-slots (north-grabber northwest-grabber northeast-grabber south-grabber southwest-grabber southeast-grabber east-grabber west-grabber center-grabber background-grabber) grabber-rect (scene-insert grabber-rect (SETF background-grabber (MAKE-background-GRABBER 'background-grabber 0 0 0 0 (grabber-transform) ))) (scene-insert grabber-rect (SETF northwest-grabber (MAKE-GRABBER 'northwest-grabber 0 0 width negheigth (grabber-transform) ))) (scene-insert grabber-rect (SETF north-grabber (MAKE-GRABBER 'north-grabber 0 0 width negheigth (grabber-transform) ))) (scene-insert grabber-rect (SETF west-grabber (MAKE-GRABBER 'west-grabber 0 0 width heigth (grabber-transform) ))) (scene-insert grabber-rect (SETF east-grabber (MAKE-GRABBER 'east-grabber 0 0 negwidth heigth (grabber-transform)) )) (scene-insert grabber-rect (SETF south-grabber (MAKE-GRABBER 'south-grabber 0 0 width heigth (grabber-transform) ))) (scene-insert grabber-rect (SETF southwest-grabber (MAKE-GRABBER 'southwest-grabber 0 0 width heigth (grabber-transform) ))) (scene-insert grabber-rect (SETF southeast-grabber (MAKE-GRABBER 'southeast-grabber 0 0 negwidth heigth (grabber-transform) ))) (scene-insert grabber-rect (SETF northeast-grabber (MAKE-GRABBER 'northeast-grabber 0 0 negwidth negheigth (grabber-transform)))) (SETF (opposing-grabber northwest-grabber) southeast-grabber (opposing-grabber northeast-grabber) southwest-grabber (opposing-grabber north-grabber) south-grabber (opposing-grabber south-grabber) north-grabber (opposing-grabber east-grabber) west-grabber (opposing-grabber west-grabber) east-grabber (opposing-grabber southeast-grabber) northwest-grabber (opposing-grabber southwest-grabber) northeast-grabber (opposing-grabber background-grabber) northeast-grabber)) grabber-rect )) (DEFMACRO get-motion-notify-event (grabber-name fixed-x fixed-y px py) `(COND ((grabber-corner-p ,grabber-name) (LIST 'scale-rubberband ,fixed-x ,fixed-y)) ((grabber-north-south-p ,grabber-name) (LIST 'scale-rubberband-fixed-width ,fixed-x ,fixed-y ,px)) ((grabber-east-west-p ,grabber-name) (LIST 'scale-rubberband-fixed-height ,fixed-x ,fixed-y ,py)) ((EQ ,grabber-name 'background-grabber) '(move-box)))) (DEFMACRO grabber-x (grabber-name grabber view) `(COND ((grabber-north-south-p ,grabber-name) (transform-x ,view (rectangle-origin-x (east-grabber (graphic-parent ,grabber)))) ) ((EQ 'background-grabber grabber-name) (transform-x ,view (rectangle-origin-x ,grabber))) (t (transform-x ,view (rectangle-origin-x ,grabber))))) (DEFMACRO grabber-y (grabber-name grabber view) `(COND ((grabber-east-west-p ,grabber-name) (transform-y ,view (rectangle-origin-y (north-grabber (graphic-parent ,grabber)))) ) ((EQ 'background-grabber grabber-name) (transform-y ,view (rectangle-origin-y ,grabber))) (t (transform-y ,view (rectangle-origin-y ,grabber))))) (DEFMETHOD view-transform-graphic ((grabber grabber) (view view) &key (event :button-1)) (LET* ((pixel-size (view-pixel-size view)) (grabber-name (grabber-name grabber)) (opposing (opposing-grabber grabber)) (fixed-x (fixed-x opposing view )) (fixed-y (fixed-y opposing view)) (px1 (grabber-x grabber-name grabber view)) (py1 (grabber-y grabber-name grabber view)) (highlight-color (view-highlight-color view)) (selection-elements (scene-elements (view-selection-scene view))) ) (when (editable-p (grabber-graphic (graphic-parent grabber))) (with-event (x y display) (LET* ((*px* px1 ) ( *py* py1) (*fixed-x* fixed-x) (*fixed-y* fixed-y) (*delta-fx* (- fixed-x x )) ( *delta-fy* (- fixed-y y)) (*delta-px* (- x *px* )) (*delta-py* (- y *py*)) ) (DECLARE (SPECIAL *px* *py* *fixed-x* *fixed-y* *delta-fx* *delta-fy* *delta-px* *delta-py* *transform*)) (with-event-mode (view (LIST `(:motion-notify ,event)(get-motion-notify-event grabber-name fixed-x fixed-y px1 py1)) `((:button-release ,event) (view-button-release t))) (WHEN (EQL (FIRST (get-motion-notify-event grabber-name fixed-x fixed-y px1 py1)) 'move-box) (WHEN (= *px* *fixed-x*) (SETF *px* (FLOOR (+ *px* pixel-size)) *delta-px* (FLOOR (+ *delta-px* pixel-size)))) (WHEN (= *py* *fixed-y*) (SETF *py* (FLOOR (+ *py* pixel-size)) *delta-py* (FLOOR (+ *delta-py* pixel-size)))) ) (process-motion-notify-events view display *fixed-x* *fixed-y* *px* *py* highlight-color) (erase-grabber-rects view selection-elements (FILL-POINTER selection-elements)) (repair-view view) (if (EQ grabber-name 'background-grabber) (move-selected-graphics view selection-elements (FILL-POINTER selection-elements) (- (view-untransform-x view *fixed-x*) (view-untransform-x view fixed-x )) (- (view-untransform-y view *fixed-y*) (view-untransform-y view fixed-y))) (scale-selected-graphics view selection-elements (FILL-POINTER selection-elements) (scale-value *fixed-x* px1 *px*) (scale-value *fixed-y* py1 *py*) (grabber-name opposing)) ) ))) (repair-view view)))) (DEFMETHOD view-move-graphic ((grabber grabber) (view view) &key (event :button-1)) (LET* ((pixel-size (view-pixel-size view)) (grabber-name (grabber-name grabber)) (opposing (opposing-grabber grabber)) (fixed-x (fixed-x opposing view )) (fixed-y (fixed-y opposing view)) (px1 (grabber-x grabber-name grabber view)) (py1 (grabber-y grabber-name grabber view)) (highlight-color (view-highlight-color view)) (selection-elements (scene-elements (view-selection-scene view))) ) (with-event (x y display) (LET* ((*px* px1 ) ( *py* py1) (*fixed-x* fixed-x) (*fixed-y* fixed-y) (*delta-fx* (- fixed-x x )) ( *delta-fy* (- fixed-y y)) (*delta-px* (- x *px* )) (*delta-py* (- y *py*)) ) (DECLARE (SPECIAL *px* *py* *fixed-x* *fixed-y* *delta-fx* *delta-fy* *delta-px* *delta-py* *transform*)) (WHEN (= *px* *fixed-x*) (SETF *px* (FLOOR (+ *px* pixel-size)) *delta-px* (FLOOR (+ *delta-px* pixel-size)))) (WHEN (= *py* *fixed-y*) (SETF *py* (FLOOR (+ *py* pixel-size)) *delta-py* (FLOOR (+ *delta-py* pixel-size)))) (with-event-mode (view `((:motion-notify ,event) (move-box)) `((:button-release ,event) (view-button-release t))) (process-motion-notify-events view display *fixed-x* *fixed-y* *px* *py* highlight-color) (erase-grabber-rects view selection-elements (FILL-POINTER selection-elements)) (repair-view view) (move-selected-graphics view selection-elements (FILL-POINTER selection-elements) (- (view-untransform-x view *fixed-x*) (view-untransform-x view fixed-x )) (- (view-untransform-y view *fixed-y*) (view-untransform-y view fixed-y)))))) (repair-view view))) (DEFMETHOD view-scale-graphic ((grabber grabber) (view view) &key uniform (event :button-1)) (LET* ( (grabber-name (grabber-name grabber)) (opposing (opposing-grabber grabber)) (fixed-x (fixed-x opposing view )) (fixed-y (fixed-y opposing view)) (px1 (grabber-x grabber-name grabber view)) (py1 (grabber-y grabber-name grabber view)) (highlight-color (view-highlight-color view)) (selection-elements (scene-elements (view-selection-scene view))) ) (when (editable-p (grabber-graphic (graphic-parent grabber))) (with-event (x y display) (LET* ((*px* px1 ) ( *py* py1) (*fixed-x* fixed-x) (*fixed-y* fixed-y) (*delta-fx* (- fixed-x x )) ( *delta-fy* (- fixed-y y)) (*delta-px* (- x *px* )) (*delta-py* (- y *py*)) ) (DECLARE (SPECIAL *px* *py* *fixed-x* *fixed-y* *delta-fx* *delta-fy* *delta-px* *delta-py* *transform*)) (with-event-mode (view (LIST `(:motion-notify ,event)(get-motion-notify-event grabber-name fixed-x fixed-y px1 py1)) `((:button-release ,event) (view-button-release t))) (UNLESS (EQ grabber-name 'background-grabber) (process-motion-notify-events view display *fixed-x* *fixed-y* *px* *py* highlight-color)) (erase-grabber-rects view selection-elements (FILL-POINTER selection-elements)) (repair-view view) (scale-selected-graphics view selection-elements (FILL-POINTER selection-elements) (scale-value *fixed-x* px1 *px*) (IF uniform (scale-value *fixed-x* px1 *px*) (scale-value *fixed-y* py1 *py*)) (grabber-name opposing)) ))))) (repair-view view)) (DEFUN fixed-x (opposing view) (LET ((grabber-class-name (grabber-name opposing)) (parent (graphic-parent opposing))) (COND ((grabber-corner-p grabber-class-name) (transform-x view (rectangle-origin-x opposing))) ((EQ 'west-grabber grabber-class-name) (transform-x view (rectangle-origin-x (west-grabber parent)))) ((EQ 'east-grabber grabber-class-name) (transform-x view (rectangle-origin-x (east-grabber parent)))) ((EQ 'north-grabber grabber-class-name) (transform-x view (rectangle-origin-x (west-grabber parent)))) ((EQ 'south-grabber grabber-class-name) (transform-x view (rectangle-origin-x (west-grabber parent))))))) (DEFUN fixed-y (opposing view) (LET ((grabber-class-name (grabber-name opposing)) (parent (graphic-parent opposing))) (COND ((grabber-corner-p grabber-class-name) (transform-y view (rectangle-origin-y opposing))) ((EQ 'west-grabber grabber-class-name) (transform-y view (rectangle-origin-y (southwest-grabber parent)))) ((EQ 'east-grabber grabber-class-name) (transform-y view (rectangle-origin-y (southeast-grabber parent)))) ((EQ 'north-grabber grabber-class-name) (transform-y view (rectangle-origin-y (north-grabber parent)))) ((EQ 'south-grabber grabber-class-name) (transform-y view (rectangle-origin-y (south-grabber parent))))))) (DEFUN erase-grabber-rects ( view selection-elements selection-length ) (DOTIMES (pos SELECTION-LENGTH) (LET* ((highlight (ELT selection-elements pos)) (graphic (grabber-graphic highlight))) (UNLESS (EQ (graphic-sensitivity highlight) :hidden) ;Is the grabber-rect being used? (graphic-damage graphic) (draw-graphic highlight view)))) (repair-view view) ) (DEFUN scale-selected-graphics (view selection-elements selection-length x-scale y-scale fixed-point) (DECLARE (IGNORE view)) (DOTIMES (pos SELECTION-LENGTH) (LET* ((highlight (ELT selection-elements pos)) (graphic (grabber-graphic highlight)) ) (UNLESS (EQ (graphic-sensitivity highlight) :hidden) ;Is the grabber-rect being used? (MULTIPLE-VALUE-BIND (fx fy) (graphic-fixed-point graphic fixed-point) (scale-transform graphic x-scale y-scale fx fy) (graphic-extent graphic) (extent-compute highlight )))))) (DEFUN move-selected-graphics (view selection-elements selection-length delta-x delta-y) (DECLARE (IGNORE view)) (DOTIMES (pos SELECTION-LENGTH) ;Move the graphics in the scene (LET* ((highlight (ELT selection-elements pos)) (graphic (grabber-graphic highlight)) ) (WHEN (EQ (graphic-sensitivity highlight) :hidden) (RETURN)) (WHEN graphic ;Is the graphic attached to a grabber rectangle. (move-transform graphic ; Yes, move the graphic. delta-x delta-y) (graphic-extent graphic) (extent-compute highlight ))))) (DEFMETHOD view-rotate-graphic ((grabber grabber) (view view) &key (event :button-3)) (UNLESS (OR (grabber-north-south-p (grabber-name grabber))(grabber-east-west-p (grabber-name grabber))) (LET* ( (selection-elements (scene-elements (view-selection-scene view))) (highlight-color (view-highlight-color view)) (opposing (opposing-grabber grabber)) (fixed-x (fixed-x opposing view )) (fixed-y (fixed-y opposing view)) (px1 (transform-x view (rectangle-origin-x grabber))) (py1 (transform-y view (rectangle-origin-y grabber)))) (when (editable-p (grabber-graphic (graphic-parent grabber))) (UNWIND-PROTECT (progn (grab-pointer view #.(make-event-mask :button-release) :owner-p t) (with-event (x y display) (LET ((*px* px1 ) ( *py* py1 ) (*fixed-x* fixed-x)(*fixed-y* fixed-y) (*transform* (make-transform))) (DECLARE (SPECIAL *px* *py* *fixed-x* *fixed-y* *delta-fx* *delta-fy* *delta-px* *delta-py* *transform*)) (with-special-vector *rotate-vector* (SETF (display-after-function display) #'display-force-output) (SETF (FILL-POINTER *rotate-vector*) 10) (SETF (ELT *rotate-vector* 0) *fixed-x* (ELT *rotate-vector* 1) *fixed-y* (ELT *rotate-vector* 2) *px* (ELT *rotate-vector* 3) *fixed-Y* (ELT *rotate-vector* 4) *px* (ELT *rotate-vector* 5) *py* (ELT *rotate-vector* 6) *fixed-x* (ELT *rotate-vector* 7) *py* (ELT *rotate-vector* 8) *fixed-x* (ELT *rotate-vector* 9) *fixed-y*) (with-event-mode (view `((:motion-notify ,event) (rotate-box)) `((:button-release ,event) (view-button-release t))) (drawlines-with-gc view highlight-color *rotate-vector* ) (CATCH :release (LOOP (process-next-event display ))) (transform-point-seq *transform* *rotate-vector*) (round-vector *rotate-vector*) (drawlines-with-gc view highlight-color *rotate-vector*) (SETF (display-after-function display) nil) (erase-grabber-rects view selection-elements (FILL-POINTER selection-elements)) (repair-view view) )) (rotate-selected-graphics view selection-elements (FILL-POINTER selection-elements) (rotation (view-untransform-x view *fixed-x*)(view-untransform-y view *fixed-y*) (rectangle-origin-x grabber)(rectangle-origin-y grabber) (view-untransform-x view *px*)(view-untransform-y view *py*)) (grabber-name opposing))))) (ungrab-pointer (contact-display view)))) (repair-view view)))) (DEFUN rotation (fixed-x fixed-y x y x2 y2) "Determine the difference in the angle between FIXED-X:FIXED-Y X1:Y1 and FIXED-X:FIXED-Y X2:Y2." (- (IF (= x2 fixed-x) (radians 0) (+ (ATAN (/ (- y2 fixed-y) (- x2 fixed-x ))) (IF (< (* (SIGNUM (- x fixed-x ))(- x2 fixed-x )) 0) (radians 180) 0))) (IF (= fixed-x x) 0 (ATAN (/ (- y fixed-y ) (- x fixed-x )))))) (DEFUN rotate-selected-graphics (view selection-elements selection-length rotation fixed-point) (DECLARE (IGNORE view)) (DOTIMES (pos SELECTION-LENGTH) ;Rotate the graphics in the scene (LET* ((highlight (ELT selection-elements pos)) (graphic (grabber-graphic highlight)) ) (WHEN (EQ (graphic-sensitivity highlight) :hidden) (RETURN)) (WHEN graphic ;Is the graphic attached to a grabber rectangle? (MULTIPLE-VALUE-BIND (fx fy) (graphic-fixed-point graphic fixed-point) (rotate-transform graphic ; Yes, rotate the graphic. rotation fx fy) (extent-compute highlight ) ))))) ;Method: extent-compute ; Compute the extent rectangle for the GRAPHIC. The method should be defined ; for each derived graphic class. The primary method returns nil, meaning ; "undefined extent." ; Note: A graphic's extent rectangle is defined in the local coordinate system. This ; means that each graphic should apply its own transform to its computed extent ; before returning it. To obtain the extent of a graphic in the world coordinate system, ; call the world-extent method (defined below). (defmethod extent-compute ((grabber-rect grabber-rect)) (declare (values (or null extent-rect))) (with-slots (graphic extent) grabber-rect (WHEN graphic (LET* ((graphic-extent (world-extent graphic)) (view (FIRST (graphic-views graphic))) (size (* -1 (/ (grabber-size (view-selection-scene view)) (view-scale view) 2.0)))) (extent-copy graphic-extent extent) (LET* ((xmax (extent-rect-xmax extent)) (xmin (extent-rect-xmin extent)) (ymin (extent-rect-ymin extent)) (ymax (extent-rect-ymax extent))) (DOLIST (grab '(northwest-grabber north-grabber east-grabber northeast-grabber southwest-grabber south-grabber west-grabber southeast-grabber)) (SETF (graphic-sensitivity (FUNCALL grab grabber-rect)) :editable)) (when (= xmax xmin) (SETF xmax (+ xmin (view-pixel-size view))) (DOLIST (grab '(north-grabber east-grabber northeast-grabber southwest-grabber west-grabber south-grabber)) (SETF (graphic-sensitivity (FUNCALL grab grabber-rect)) :hidden))) (when (= ymax ymin) (SETF ymax (+ ymin (view-pixel-size view))) (DOLIST (grab '(north-grabber east-grabber northeast-grabber southwest-grabber west-grabber south-grabber)) (SETF (graphic-sensitivity (FUNCALL grab grabber-rect)) :hidden))) (LET* ((width (/ (- xmax xmin) 2.0)) (height (/ (- ymax ymin) 2.0))) (SETF (rectangle-origin-x (northwest-grabber grabber-rect)) xmin) (SETF (rectangle-origin-y (northwest-grabber grabber-rect)) ymax) (SETF (rectangle-origin-x (southwest-grabber grabber-rect)) xmin) (SETF (rectangle-origin-y (southwest-grabber grabber-rect)) ymin) (SETF (rectangle-origin-x (northeast-grabber grabber-rect)) xmax) (SETF (rectangle-origin-y (northeast-grabber grabber-rect)) ymax) (SETF (rectangle-origin-x (southeast-grabber grabber-rect)) xmax) (SETF (rectangle-origin-y (southeast-grabber grabber-rect)) ymin) (SETF (rectangle-origin-x (north-grabber grabber-rect)) (+ xmin width size)) (SETF (rectangle-origin-y (north-grabber grabber-rect)) ymax) (SETF (rectangle-origin-x (south-grabber grabber-rect)) (+ xmin width size)) (SETF (rectangle-origin-y (south-grabber grabber-rect)) ymin) (SETF (rectangle-origin-x (east-grabber grabber-rect)) xmax) (SETF (rectangle-origin-y (east-grabber grabber-rect)) (+ ymin height size)) (SETF (rectangle-origin-x (west-grabber grabber-rect)) xmin) (SETF (rectangle-origin-y (west-grabber grabber-rect)) (+ ymin height size)) (SETF (rectangle-origin-x (background-grabber grabber-rect)) xmin) (SETF (rectangle-origin-y (background-grabber grabber-rect)) ymin) )))) extent)) (defmethod extent-compute ((grabber grabber)) (declare (values (or null extent-rect))) (with-slots (vertices) grabber (LET ((x-min (rectangle-origin-x grabber)) (y-min (rectangle-origin-y grabber))) (multiple-value-setq (x-min y-min ) (transform-point (graphic-transform grabber) x-min y-min )) (SETF (rectangle-origin-x grabber) x-min) (SETF (rectangle-origin-y grabber) y-min) (make-extent-rect :xmin (point-seq-x-min vertices) :ymin (point-seq-y-min vertices) :xmax (point-seq-x-max vertices) :ymax (point-seq-y-max vertices)) )))