Compiler DrawOps/n
m.stone December 2, 1981 11:24 PM
Tiberi December 11, 1979 8:42 PM
Last Edited by: Stone, December 29, 1983 11:15 am
DIRECTORY
GriffinDefs: FROM "GriffinDefs",
MenuDefs: FROM "MenuDefs",
ObjectDefs: FROM "ObjectDefs",
GriffinText USING [GetCaption, GetBoundingBox],
RefreshDefs: FROM "RefreshDefs",
StyleDefs USING [StyleHandle],
GriffinStyle USING [SetCurrentStyle, CopyCurrentStyle],
PointDefs: FROM "PointDefs",
GriffinMemoryDefs USING [CZone],
CubicSplines USING [SplineType],
Rope USING [ROPE, Equal],
GriffinEncoding USING [Link, EncodeArea],
GriffinMenusInterface,
ControllerMenuDefs;
DrawOps: CEDAR PROGRAM
IMPORTS GriffinDefs, MenuDefs, ObjectDefs, ControllerMenuDefs, GriffinMemoryDefs, PointDefs, RefreshDefs, Rope, GriffinStyle, GriffinText, GriffinEncoding
EXPORTS GriffinDefs, GriffinMenusInterface =
BEGIN OPEN ObjectDefs,PointDefs,GriffinMemoryDefs;
newObj: REF shape Object ← NIL;
spline: CubicSplines.SplineType ← naturalAL;
Fitting: TYPE = {lines,curve};
fitting: Fitting;
ROPE: TYPE = Rope.ROPE;
BugItemByString: PROCEDURE[menu: MenuDefs.MenuHandle, string: ROPE]=
BEGIN OPEN MenuDefs;
menuItem: MenuItemHandle ← NARROW[menu.head];
IsThisItem: MenuProc = {
IF Rope.Equal[MenuString[item], string, FALSE] THEN menuItem ← item};
ForAllMenuItems[menu, IsThisItem];
BugItem[menuItem]
END;
ExpandShape: PUBLIC MenuDefs.MenuProc =
BEGIN OPEN ControllerMenuDefs;
IF MenuDefs.IsSelected[item] THEN ControllerMenuDefs.UnDisplayShapeMenu[]
ELSE ControllerMenuDefs.DisplayShapeMenu[];
IF MenuDefs.IsSelected[item] THEN MenuDefs.Deselect[item] ELSE MenuDefs.Select[item];
RefreshDefs.RestoreScreen;
END;
ExpandColor: PUBLIC MenuDefs.MenuProc =
BEGIN OPEN ControllerMenuDefs;
IF MenuDefs.IsSelected[item] THEN ControllerMenuDefs.UnDisplayColorMenu[]
ELSE ControllerMenuDefs.DisplayColorMenu[];
IF MenuDefs.IsSelected[item] THEN MenuDefs.Deselect[item] ELSE MenuDefs.Select[item];
RefreshDefs.RestoreScreen;
END;
ExpandText: PUBLIC MenuDefs.MenuProc =
BEGIN OPEN ControllerMenuDefs;
IF MenuDefs.IsSelected[item] THEN ControllerMenuDefs.UnDisplayCaptionMenu[]
ELSE ControllerMenuDefs.DisplayCaptionMenu[];
IF MenuDefs.IsSelected[item] THEN MenuDefs.Deselect[item] ELSE MenuDefs.Select[item];
RefreshDefs.RestoreScreen;
END;
ApplyStyle: PUBLIC MenuDefs.MenuProc =
BEGIN OPEN ControllerMenuDefs;
called with a selected object
new: StyleDefs.StyleHandle ← GriffinStyle.CopyCurrentStyle[];
ChangeObj: ObjectProc=BEGIN
oldTL: ScrPt ← obj.tl;
oldBR: ScrPt ← obj.br;
tl, br: ScrPt;
obj.style ← new;
AdjustBoxForStyle[obj];
tl[X] ← MIN[oldTL[X], obj.tl[X]];
br[X] ← MAX[oldBR[X], obj.br[X]];
tl[Y] ← MAX[oldTL[Y], obj.tl[Y]];
br[Y] ← MIN[oldBR[Y], obj.br[Y]];
RefreshDefs.EraseAndSaveBox[tl, br]
END;
ForAllSelectedDo[ChangeObj];
RefreshDefs.RestoreScreen[];
END;
IndicateStyle: PUBLIC MenuDefs.MenuProc =
BEGIN
style: StyleDefs.StyleHandle ← NIL;
SetSelectedStyle: ObjectProc =
BEGIN style ← obj.style END;
ObjectDefs.ForAllSelectedDo [SetSelectedStyle];
IF style#NIL THEN {
ControllerMenuDefs.SetStyleMenus[style];
GriffinStyle.SetCurrentStyle[style];
};
END;
FittingType: PUBLIC MenuDefs.MenuProc =
BEGIN
string: ROPE ← MenuDefs.MenuString[item];
fitting ← SELECT TRUE FROM
Rope.Equal[string,"Straight",FALSE] => lines,
Rope.Equal[string,"Curved",FALSE] => curve,
ENDCASE => ERROR;
MenuDefs.SelectOnly[item];
END;
ExpandSplines: PUBLIC MenuDefs.MenuProc =
BEGIN
IF MenuDefs.IsSelected[item] THEN MenuDefs.HideMenu[splineMenu]
ELSE MenuDefs.ShowMenu[splineMenu];
IF MenuDefs.IsSelected[item] THEN MenuDefs.Deselect[item] ELSE MenuDefs.Select[item];
RefreshDefs.RestoreScreen;
END;
SplineType: PUBLIC MenuDefs.MenuProc =
BEGIN
string: ROPE ← MenuDefs.MenuString[item];
IF newObj#NIL THEN GriffinDefs.UserMessage["Only one spline type per object"];
spline ← SELECT TRUE FROM
Rope.Equal[string,"Natural: Arc Length",FALSE] => naturalAL,
Rope.Equal[string,"Natural: Unit Length",FALSE] => naturalUM,
Rope.Equal[string,"Bezier Curve",FALSE] => bezier,
Rope.Equal[string,"B-Spline",FALSE] => bspline,
Rope.Equal[string,"Catmull-Rom Curve",FALSE] => crspline,
ENDCASE => ERROR;
MenuDefs.SelectOnly[item];
END;
SetSplineType: PROCEDURE[splinetype: CubicSplines.SplineType] =
BEGIN
string: ROPESELECT splinetype FROM
naturalAL => "Natural: Arc Length",
naturalUM => "Natural: Unit Length",
bezier => "Bezier Curve",
bspline => "B-Spline",
crspline => "Catmull-Rom Curve",
ENDCASE => ERROR;
BugItemByString[splineMenu, string];
END;
NewLink: PUBLIC MenuDefs.MenuProc =
BEGIN
tempLink: REF Link ← NIL;
lastPt: PointDefs.ScrPt;
cps: PointDefs.ObjPtSequence;
encoding: GriffinEncoding.Link;
IF spline=bspline OR spline=crspline THEN
GriffinDefs.UserMessage["B-Splines and Catmull-Rom Curves cannot be used in linked objects"];
cps ← ReadCPs[];
IF cps=NIL OR cps.length <=1 THEN RETURN;
lastPt ← PointDefs.ObjToScr[cps[cps.length-1]];
tempLink ← MakeLink[fitting=lines,cps];
IF newObj=NIL THEN newObj ← StartShapeObject[closed: FALSE, linked: TRUE];
encoding ← ObjectDefs.AppendLink[newObj,tempLink];
RefreshDefs.EraseAndSaveAllCPs[];
DeleteAllCPs[];
PlotLink[encoding, NIL];
AddToken[lastPt,open];
RefreshDefs.RestoreScreen[];
END;
MakeLink: PROCEDURE[isLines: BOOLEAN,cps: PointDefs.ObjPtSequence]RETURNS[newLink: REF Link] =
BEGIN
newLink ← CZone.NEW[Link];
newLink^ ← [NIL, (IF isLines THEN D1 ELSE D3), cps];
END;
BackLink: PUBLIC MenuDefs.MenuProc =
BEGIN
lastLink: REF Link ← GetNewObjectLinks[];
RefreshDefs.EraseAndSaveAllCPs[];
DeleteAllCPs[];
case of nil object. Shouldn't happen;
IF lastLink = NIL THEN BEGIN
[] ← DeleteObject[newObj];
newObj ← NIL;
RefreshDefs.RestoreScreen[];
RETURN;
END;
case of one link
IF lastLink.link = NIL THEN BEGIN
ShowKnots[lastLink.knots,FALSE];
RefreshDefs.EraseAndSave[newObj];
[] ← DeleteObject[newObj];
newObj ← NIL;
RefreshDefs.RestoreScreen[];
RETURN;
END;
UNTIL lastLink.link=NIL DO lastLink ← lastLink.link; ENDLOOP;
ShowLinkKnots[lastLink.knots,FALSE];
EraseLink[RemoveLastLink[newObj]];
RefreshDefs.RestoreScreen[];
END;
ShowLinkKnots: PROCEDURE[knots: PointDefs.ObjPtSequence, exceptLast: BOOLEAN] =
BEGIN
i: CARDINAL;
lastknot: CARDINAL ← knots.length-1;
cps: PointDefs.ObjPtSequence ← ReadCPs[];
DeleteAllCPs[];
IF exceptLast THEN lastknot ← lastknot-1;
AddToken[ObjToScr[knots[0]], open];
FOR i IN [1..lastknot] DO
AddToken[ObjToScr[knots[i]], CP];
ENDLOOP;
IF cps#NIL THEN BEGIN
FOR i IN [0..cps.length) DO
AddToken[ObjToScr[cps[i]], CP];
ENDLOOP;
END;
END;
GetNewObjectLinks: PROCEDURE RETURNS [link: REF Link]=
TRUSTED BEGIN
IF newObj=NIL THEN RETURN[NIL];
WITH traj: newObj.trajectory SELECT FROM
linked => link ← traj.links;
ENDCASE => ERROR;
RETURN;
END;
Draw: PUBLIC MenuDefs.MenuProc =
BEGIN
DrawObject[newObj,FALSE];
END;
Close: PUBLIC MenuDefs.MenuProc =
BEGIN
DrawObject[newObj,TRUE];
END;
Box: PUBLIC MenuDefs.MenuProc =
BEGIN
cps: PointDefs.ObjPtSequence;
pt: ObjPt;
cps ← ReadCPs[];
IF cps=NIL OR cps.length #2 THEN SIGNAL GriffinDefs.UserMessage["Exactly 2 points for a box"];
DeleteAllCPs[];
AddToken[ObjToScr[cps[0]],CP];
pt ← [cps[0][X],cps[1][Y]];
AddToken[ObjToScr[pt],CP];
AddToken[ObjToScr[cps[1]],CP];
pt ← [cps[1][X],cps[0][Y]];
AddToken[ObjToScr[pt],CP];
BugItemByString[shapeMenu,"Straight"];
DrawObject[newObj,TRUE];
END;
Caption: PUBLIC MenuDefs.MenuProc = {
cps: PointDefs.ObjPtSequence ← ObjectDefs.ReadCPs[];
text: ROPE ← GriffinText.GetCaption[];
IF cps=NIL OR cps.length # 1 THEN
SIGNAL GriffinDefs.UserMessage["Place exactly one control point for caption."];
IF text=NIL THEN SIGNAL GriffinDefs.UserMessage["Please select the text for the caption in a Tioga viewer."]
ELSE BEGIN
caption: REF Object[caption] ← NARROW[ObjectDefs.StartObject[caption]];
caption.text ← text;
caption.style ← GriffinStyle.CopyCurrentStyle[];
caption.p0 ← cps[0];
[caption.tl, caption.br] ← GriffinText.GetBoundingBox[text, caption.style, caption.p0];
caption.validEncoding ← TRUE;
caption.cluster ← 0;
[] ← ObjectDefs.SelectObject[caption];
RefreshDefs.EraseAndSaveAllCPs;
ObjectDefs.DeleteAllCPs[];
RefreshDefs.MarkObject[caption];
RefreshDefs.RestoreScreen[];
END;
};
Modify: PUBLIC MenuDefs.MenuProc =
BEGIN
selected: ObjectHandle ← NIL;
FindLastSelected: ObjectProc=BEGIN
selected ← obj;
END;
IF newObj#NIL THEN RETURN; --don't modify while drawing or modifying
ForAllSelectedDo[FindLastSelected];
IF selected=NIL THEN RETURN;
WITH selected SELECT FROM
obj: REF Object[shape] => BEGIN
GriffinStyle.SetCurrentStyle[selected.style];
SetSplineType[obj.trajectory.splineType];
EraseObject[selected];
DeSelectObject[selected]; --will get selected again when finished
OpenObject[obj]; --remove link, show cps, plot remaining object
END;
obj: REF Object[caption] => BEGIN
EraseObject[selected];
DeSelectObject[selected]; --will get selected again when finished
GriffinStyle.SetCurrentStyle[selected.style];
GriffinText.EditCaption[obj.text];
GriffinDefs.UserMessage["You must delete the caption and start over"];
END;
ENDCASE => RETURN;
END;
OpenObject: PROCEDURE[obj: REF Object[shape]] =
TRUSTED BEGIN
WITH traj: obj.trajectory SELECT FROM
linked => BEGIN
link: REF Link ← traj.links;
IF link = NIL THEN ERROR;
object with one link
IF link.link=NIL THEN BEGIN
ShowKnots[link.knots,obj.closed];
IF link.degree=D1 THEN BugItemByString[shapeMenu,"Straight"]
ELSE BugItemByString[shapeMenu,"Curved"];
[] ← DeleteObject[obj];
END
multiple links. Order here is important
ELSE BEGIN
closed: BOOLEAN ← obj.closed;
newObj ← obj;
newObj.closed ← FALSE;
newObj.cluster ← OpenCluster;
delete last link
FOR link ← traj.links , link.link UNTIL link.link=NIL DO ENDLOOP;
link is now last link in the object
ShowLinkKnots[link.knots,closed];
IF link.degree=D1 THEN BugItemByString[shapeMenu,"Straight"]
ELSE BugItemByString[shapeMenu,"Curved"];
[] ← ObjectDefs.RemoveLastLink[obj];
plot the rest
PlotOneObject[newObj];
END;
END;
cyclic =>
BEGIN
ShowKnots[traj.knots, FALSE];
BugItemByString[shapeMenu,"Curved"];
[] ← DeleteObject[obj];
END;
ENDCASE;
END;
ShowKnots: PROCEDURE[knots: PointDefs.ObjPtSequence, exceptLast: BOOLEAN] =
BEGIN
i: CARDINAL;
lastknot: CARDINAL ← knots.length-1;
IF exceptLast THEN lastknot ← lastknot-1;
FOR i IN [0..lastknot] DO
AddToken[ObjToScr[knots[i]], CP];
ENDLOOP;
END;
StartShapeObject: PROC [closed: BOOLEAN, linked: BOOLEAN] RETURNS [REF Object[shape]] ~ {
shape: REF Object[shape] ← NARROW[StartObject[shape]];
shape.closed ← closed;
shape.edgeEncoding ← NIL;
shape.areaEncoding ← NIL;
shape.style ← GriffinStyle.CopyCurrentStyle[];
shape.cluster ← OpenCluster;
IF linked THEN shape.trajectory ← CZone.NEW[Trajectory[linked] ← [spline,linked[NIL]]]
ELSE shape.trajectory ← CZone.NEW[Trajectory[cyclic] ← [spline,cyclic[NIL]]];
RETURN[shape];
};
DrawObject: PROCEDURE[shapeObj: REF shape Object, closed: BOOLEAN] =
TRUSTED BEGIN
cps: PointDefs.ObjPtSequence ← ReadCPs[];
IF shapeObj=NIL AND (cps=NIL OR cps.length<1) THEN RETURN;
IF shapeObj = NIL THEN shapeObj ←
StartShapeObject[closed: closed, linked: NOT (closed AND fitting=curve)];
shapeObj.closed ← closed;
IF shapeObj.closed THEN {
WITH traj: shapeObj.trajectory SELECT FROM
cyclic => AddToken[ObjToScr[cps[0]],CP];
linked => IF traj.links=NIL THEN AddToken[ObjToScr[cps[0]],CP]
ELSE AddToken[ObjToScr[traj.links.knots[0]],CP];
ENDCASE => ERROR;
cps ← ReadCPs[]; --reread them with new cp
};
WITH traj: shapeObj.trajectory SELECT FROM
cyclic => {
traj.splineType ← SELECT traj.splineType FROM
naturalUM => cyclicUM, naturalAL => cyclicAL, ENDCASE => traj.splineType;
traj.knots ← cps;
EncodeObject[shapeObj]; --makes edge and area encoding
};
linked => {
link: REF Link;
link ← MakeLink[fitting=lines,cps];
PlotLink[AppendLink[shapeObj,link], shapeObj.style];
The edge encoding has been built up incrementally by making links
Make the area encoding here
IF shapeObj.closed THEN
shapeObj.areaEncoding ← GriffinEncoding.EncodeArea[shapeObj.edgeEncoding];
};
ENDCASE;
shapeObj.cluster ← 0;
[] ← ObjectDefs.SelectObject[shapeObj];
AdjustBoxForStyle[shapeObj];
RefreshDefs.EraseAndSaveAllCPs[];
DeleteAllCPs[];
RefreshDefs.MarkObject[shapeObj];
RefreshDefs.RestoreScreen[];
newObj ← NIL;
END;
editMenu: MenuDefs.MenuHandle←NIL;
styleMenu: MenuDefs.MenuHandle←NIL;
shapeMenu: MenuDefs.MenuHandle←NIL;
splineMenu: MenuDefs.MenuHandle←NIL;
default: MenuDefs.MenuItemHandle←NIL;
showstyle: MenuDefs.MenuItemHandle←NIL;
newLink: MenuDefs.MenuItemHandle←NIL;
ToggleEditMenus: PUBLIC PROC = { --edit and spline menus
IF editMenu.visible THEN {
IF splineMenu.visible THEN MenuDefs.HideMenu[splineMenu];
MenuDefs.HideMenu[shapeMenu];
MenuDefs.HideMenu[editMenu];
}
ELSE {
item: MenuDefs.MenuItemHandle;
MenuDefs.ShowMenu[editMenu];
MenuDefs.ShowMenu[shapeMenu];
item ← FindItemByString[editMenu,"Spline Type"];
IF MenuDefs.IsSelected[item] THEN MenuDefs.BugItem[item];  --show spline menu
};
RefreshDefs.RestoreScreen[];
};
ToggleStyleMenu: PUBLIC PROC = { -- the top level style menu
IF styleMenu.visible THEN {
ControllerMenuDefs routines are smart enough to do nothing if menus not displayed
ControllerMenuDefs.UnDisplayColorMenu[];
ControllerMenuDefs.UnDisplayCaptionMenu[];
ControllerMenuDefs.UnDisplayShapeMenu[];
MenuDefs.HideMenu[styleMenu];
}
ELSE {
item: MenuDefs.MenuItemHandle;
MenuDefs.ShowMenu[styleMenu];
item ← FindItemByString[styleMenu,"Text Style"];
IF MenuDefs.IsSelected[item] THEN MenuDefs.BugItem[item];
item ← FindItemByString[styleMenu,"Color Style"];
IF MenuDefs.IsSelected[item] THEN MenuDefs.BugItem[item];
item ← FindItemByString[styleMenu,"Shape Style"];
IF MenuDefs.IsSelected[item] THEN MenuDefs.BugItem[item];
};
RefreshDefs.RestoreScreen[];
};
FindItemByString: PROCEDURE[menu: MenuDefs.MenuHandle,string: ROPE] RETURNS [mitem: MenuDefs.MenuItemHandle]= BEGIN OPEN MenuDefs;
IsItem: MenuDefs.MenuProc = BEGIN
IF Rope.Equal[MenuDefs.MenuString[item],string] THEN mitem ← item;
END;
MenuDefs.ForAllMenuItems[menu,IsItem];
END;
StartDrawMenus: PUBLIC PROC = {
editMenu ← MenuDefs.CreateMenu[horizontal, [100,500], NIL];
[]←MenuDefs.AddMenuItem[editMenu,"Draw",Draw];
[]←MenuDefs.AddMenuItem[editMenu,"Close",Close];
[]←MenuDefs.AddMenuItem[editMenu,"Draw link",NewLink];
[]←MenuDefs.AddMenuItem[editMenu,"Modify",Modify];
[]←MenuDefs.AddMenuItem[editMenu,"Back link",BackLink];
[]←MenuDefs.AddMenuItem[editMenu,"Box",Box];
[]←MenuDefs.AddMenuItem[editMenu,"Caption",Caption];
[]←MenuDefs.AddMenuItem[editMenu,"Spline Type",ExpandSplines];
shapeMenu ← MenuDefs.CreateMenu[vertical, [100,550], NIL];
default ←MenuDefs.AddMenuItem[shapeMenu,"Straight",FittingType];
[]←MenuDefs.AddMenuItem[shapeMenu,"Curved",FittingType];
MenuDefs.BugItem[default];
splineMenu ← MenuDefs.CreateMenu[vertical, [200,550], NIL];
default ←MenuDefs.AddMenuItem[splineMenu,"Natural: Arc Length",SplineType];
[]←MenuDefs.AddMenuItem[splineMenu,"Natural: Unit Length",SplineType];
[]←MenuDefs.AddMenuItem[splineMenu,"Bezier Curve",SplineType];
[]←MenuDefs.AddMenuItem[splineMenu,"B-Spline",SplineType];
[]←MenuDefs.AddMenuItem[splineMenu,"Catmull-Rom Curve",SplineType];
MenuDefs.BugItem[default];
styleMenu ← MenuDefs.CreateMenu[vertical, [400,200], NIL];
[]←MenuDefs.AddMenuItem [styleMenu, "Indicate", IndicateStyle];
[]←MenuDefs.AddMenuItem [styleMenu, "Apply", ApplyStyle];
[]←MenuDefs.AddMenuItem [styleMenu, "Shape Style", ExpandShape];
[]←MenuDefs.AddMenuItem [styleMenu, "Color Style", ExpandColor];
[]←MenuDefs.AddMenuItem [styleMenu, "Text Style", ExpandText];
};
END.