-- Compiler ObjectXForms
-- Stone May 2, 1981 1:09 PM
-- Last Edited by: Stone, January 28, 1983 6:43 pm

DIRECTORY
 ObjectDefs: FROM "ObjectDefs",
 PointDefs: FROM "PointDefs",
 EncodingDefs: FROM "EncodingDefs",
 MenuDefs: FROM "MenuDefs",
 XFormDefs: FROM "XFormDefs",
 GriffinMemoryDefs USING [CZone];

ObjectXForms: PROGRAM
IMPORTS ObjectDefs,XFormDefs,PointDefs,MenuDefs, GriffinMemoryDefs
EXPORTS ObjectDefs =
BEGIN OPEN ObjectDefs,XFormDefs,GriffinMemoryDefs,PointDefs;

--does a translation on all control points and on the encoding
MoveObject: PUBLIC PROCEDURE[object: ObjectHandle, from,to: ScrPt]=
BEGIN
token: ObjectHandle ← ReturnSelected[object];
Move[object,from,to];
IF token # NIL THEN Move[token,from,to];
END;

Move: PROCEDURE[object: ObjectHandle, from,to: ScrPt]=
BEGIN
transmatrix: XFMDescriptor ← CZone.NEW[XFormMatrix];
hgrid,vgrid: BOOLEANFALSE;
objfrom,objto,dist: ObjPt;
dx,dy: INTEGER;
dx ← to[X]-from[X];
dy ← to[Y]-from[Y];
--move bounding box
--bounding boxes on the grid move only in one dimension
WITH objtype: object SELECT FROM
 token => {hgrid ← objtype.tokenType=hgrid;
  vgrid ← objtype.tokenType=vgrid};
ENDCASE;
IF ~hgrid THEN object.tl[X] ← object.tl[X]+dx;
IF ~vgrid THEN object.tl[Y] ← object.tl[Y]+dy;
IF ~hgrid THEN object.br[X] ← object.br[X]+dx;
IF ~vgrid THEN object.br[Y] ← object.br[Y]+dy;
--move encoding in screen space
WITH objtype: object SELECT FROM
 shape => BEGIN
  cptr: EncodingDefs.ChainHandle;
  aptr: EncodingDefs.AreaHandle;
  FOR cptr ← objtype.chainEncoding, cptr.link UNTIL cptr=NIL DO
   cptr.p0[X] ← cptr.p0[X]+dx; cptr.p0[Y] ← cptr.p0[Y]+dy;
   cptr.tl[X] ← cptr.tl[X]+dx; cptr.tl[Y] ← cptr.tl[Y]+dy;
   cptr.br[X] ← cptr.br[X]+dx; cptr.br[Y] ← cptr.br[Y]+dy;
   ENDLOOP;
  FOR aptr ← objtype.areaEncoding, aptr.link UNTIL aptr=NIL DO
   aptr.tl[X] ← aptr.tl[X]+dx; aptr.tl[Y] ← aptr.tl[Y]+dy;
   aptr.br[X] ← aptr.br[X]+dx; aptr.br[Y] ← aptr.br[Y]+dy;
   ENDLOOP;
  END;
 menu => BEGIN OPEN MenuDefs;
   MoveMenuItem: MenuProc =
    BEGIN
    item.tl [X] ← item.tl [X] + dx;
    item.tl [Y] ← item.tl [Y] + dy;
    item.br [X] ← item.br [X] + dx;
    item.br [Y] ← item.br [Y] + dy;
    END;
   ForAllMenuItems [@objtype, MoveMenuItem];
   END;
  ENDCASE;
--move the object in object space
objfrom ← ScrToObj[from];
objto ← ScrToObj[to];
dist[X] ← objto[X]-objfrom[X];
dist[Y] ← objto[Y]-objfrom[Y];
InitXForms[transmatrix];
Translate[dist,transmatrix];
XForm[object,transmatrix];
END;

XFormObject: PUBLIC PROCEDURE [object: ObjectHandle,matrix: XFMDescriptor] =
BEGIN
token: ObjectHandle ← ReturnSelected[object];
XForm[object,matrix];
IF token # NIL THEN BEGIN
 XForm[token,matrix];
 token.validEncoding ← FALSE;
END;
object.validEncoding ← FALSE;
END;

XForm: PROCEDURE [object: ObjectHandle,matrix: XFMDescriptor] =
BEGIN
WITH objtype: object SELECT FROM
 shape => WITH traj: objtype.trajectory SELECT FROM
  linked => BEGIN
   link: REF Link ← traj.links;
   UNTIL link=NIL
    DO
    XFormArray[link.knots,matrix];
    link ← link.link;
    ENDLOOP;
   END;
  cyclic => XFormArray[traj.knots,matrix];
  ENDCASE;
--captions and tokens don't do much except on translate
 caption => objtype.p0 ← XFormPt[objtype.p0,matrix]; 
 token => objtype.p0 ← XFormPt[objtype.p0,matrix]; 
ENDCASE;
END;

XFormArray: PROCEDURE [array: PointDefs.ObjPtSequence,xform: XFMDescriptor] =
BEGIN
i: INTEGER;
FOR i IN [0..array.length) DO
 array[i] ← XFormPt[array[i],xform];
ENDLOOP;
END;
END.