-- 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",
GriffinFontDefs: FROM "GriffinFontDefs",
ControllerDefs: FROM "ControllerDefs",
RefreshDefs: FROM "RefreshDefs",
StyleDefs: FROM "StyleDefs",
PointDefs: FROM "PointDefs",
GriffinMemoryDefs USING [CZone],
SplineDefs: FROM "SplineDefs",
Rope USING [ROPE, Equal, Cat],
GriffinColor USING [ColorToString],
GriffinMenusInterface,
ControllerMenuDefs: FROM "ControllerMenuDefs";
DrawOps: PROGRAM
IMPORTS GriffinDefs, MenuDefs, ObjectDefs, ControllerMenuDefs, GriffinMemoryDefs, PointDefs, ControllerDefs,RefreshDefs, Rope, GriffinColor
EXPORTS GriffinDefs, GriffinMenusInterface =
BEGIN OPEN ObjectDefs,PointDefs,GriffinMemoryDefs;
newObj: REF shape Object ← NIL;
spline: SplineDefs.SplineType ← naturalAL;
Fitting: TYPE = {lines,curve};
fitting: Fitting;
ROPE: TYPE = Rope.ROPE;
SetStyle: PROCEDURE[style: StyleDefs.StyleHandle] =
BEGIN
fd: GriffinFontDefs.FontDescriptorHandle;
name: ROPE;
BugItemByString[ControllerMenuDefs.colorMenu, StringOfColor[style.fillcolor]];
BugItemByString[ControllerMenuDefs.lineColorMenu, StringOfColor[style.color]];
BugItemByString[ControllerMenuDefs.colorControlMenu,
SELECT TRUE FROM
style.filled AND style.outlined => "Both",
style.filled => "Filled",
style.outlined => "Outlined",
ENDCASE => ERROR];
BugItemByString[ControllerMenuDefs.textMenu,
SELECT style.orientation FROM
or0 => "0 d",
or90 => "90 d",
or180 => "180 d",
or270 => "270 d",
ENDCASE => ERROR];
fd ← ControllerDefs.FontWithNumber [style.fontid];
BugItemByString[ControllerMenuDefs.charMenu,
SELECT fd.rotation FROM
GriffinFontDefs.Rot0Degrees => "0 char d",
GriffinFontDefs.Rot90Degrees => "90 char d",
GriffinFontDefs.Rot180Degrees => "180 char d",
GriffinFontDefs.Rot270Degrees => "270 char d",
ENDCASE => ERROR];
name ← GriffinDefs.AppendNumber[fd.name, fd.points];
SELECT fd.face FROM
3 => name ← Rope.Cat[name, "BI"];
2 => name ← Rope.Cat[name, "B"];
1 => name ← Rope.Cat[name, "I"];
ENDCASE;
BugItemByString[ControllerMenuDefs.fontMenu, name];
BugItemByString[ControllerMenuDefs.centerMenu,
SELECT style.anchor FROM
left => "left",
center => "centered",
right => "right",
ENDCASE => ERROR];
BugItemByString[ControllerMenuDefs.thickMenu,
SELECT ObjValToScrVal[style.width] FROM
1 => "1 pt",
2 => "2 pt",
3 => "3 pt",
4 => "4 pt",
ENDCASE => ERROR];
END;
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 UnDisplayShapeMenu[]
ELSE 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 UnDisplayColorMenu[]
ELSE 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 UnDisplayCaptionMenu[]
ELSE 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
ChangeObj: PROCEDURE[obj: ObjectHandle]=BEGIN
--if the object doesn't get any bigger, then don't need to erase it first
new: StyleDefs.StyleHandle ← ControllerDefs.CurrentStyle[];
IF Rope.Equal[new.name, obj.style.name, FALSE] THEN RETURN; --same style
IF obj.objectType=caption THEN IF new.anchor#obj.style.anchor
OR new.orientation#obj.style.orientation OR new.fontid#obj.style.fontid
THEN {
obj.validEncoding←FALSE; --flag to recompute bounding box
RefreshDefs.EraseAndSaveBox[obj.tl,obj.br];
};
IF obj.objectType=shape THEN IF new.width > obj.style.width
OR (new.outlined # obj.style.outlined) OR (new.filled # obj.style.filled)
THEN RefreshDefs.EraseAndSaveBox[obj.tl,obj.br];
obj.style ← new;
RefreshDefs.PlotAndMark[obj];
END;
ForAllSelectedDo[ChangeObj];
RefreshDefs.RestoreScreen[];
END;
IndicateStyle: PUBLIC MenuDefs.MenuProc =
BEGIN
style: StyleDefs.StyleHandle ← NIL;
SetSelectedStyle: PROCEDURE [s: ObjectDefs.ObjectHandle] =
BEGIN style ← s.style END;
ObjectDefs.ForAllSelectedDo [SetSelectedStyle];
IF style#NIL THEN SetStyle[style];
END;
StringOfColor: PROCEDURE[color: StyleDefs.Color] RETURNS[ROPE]=
BEGIN
RETURN[GriffinColor.ColorToString[color]];
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: SplineDefs.SplineType] =
BEGIN
string: ROPE ← SELECT 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;
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 BEGIN
newObj ← LOOPHOLE[StartObject[shape]];
newObj.body ← shape[FALSE,CZone.NEW[Trajectory[linked] ← [spline,linked[tempLink]]],NIL,NIL];
newObj.style ← ControllerDefs.CurrentStyle[];
newObj.cluster ← OpenCluster;
END
ELSE AddLink[newObj,tempLink];
RefreshDefs.EraseAndSaveAllCPs[];
DeleteAllCPs[];
WriteLink[newObj,tempLink];
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];
DeleteLink[newObj,lastLink]; --does an erase too
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]=
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;
Modify: PUBLIC MenuDefs.MenuProc =
BEGIN
selected: ObjectHandle ← NIL;
FindLastSelected: PROCEDURE[obj: ObjectHandle]=BEGIN
selected ← obj;
END;
IF newObj#NIL THEN RETURN; --don't modify while drawing or modifying
ForAllSelectedDo[FindLastSelected];
IF selected=NIL THEN RETURN;
WITH obj: selected SELECT FROM
shape => BEGIN
SetStyle[selected.style];
SetSplineType[obj.trajectory.splineType];
DeSelectObject[selected]; --will get selected again when finished
EraseObject[selected];
ShowCPs[selected];
END;
caption => BEGIN
token: ObjectHandle ← ReturnSelected[selected];
IF token#NIL THEN EraseObject[token];
DeSelectObject[selected]; --will get selected again when finished
SetStyle[selected.style];
GriffinDefs.TypeIntoCaption[selected];
END;
ENDCASE => RETURN;
END;
ShowCPs: PROCEDURE[object: ObjectHandle] =
BEGIN
obj: REF shape Object ←NIL;
IF object=NIL THEN RETURN;
WITH foo: object SELECT FROM
shape => obj ← @foo;
ENDCASE => ERROR;
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"];
DeleteLink[obj,link];
--plot the rest
FOR link ← traj.links , link.link UNTIL link=NIL DO
WriteLink[obj,link];
ENDLOOP;
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;
DrawObject: PROCEDURE[object: ObjectHandle, closed: BOOLEAN] =
BEGIN
shapeObj: REF shape Object ← NIL;
cps: PointDefs.ObjPtSequence ← ReadCPs[];
IF object=NIL AND (cps=NIL OR cps.length<1) THEN RETURN;
IF object = NIL THEN BEGIN
object ← StartObject[shape];
object.body ← shape[closed,CZone.NEW[Trajectory[linked] ← [spline,linked[NIL]]],NIL,NIL];
object.style ← ControllerDefs.CurrentStyle[];
END;
--loophole the elegant way
WITH obj: object SELECT FROM
shape => shapeObj ← @obj;
ENDCASE;
shapeObj.closed ← closed;
WITH traj: shapeObj.trajectory SELECT FROM
cyclic => shapeObj.trajectory 𡤌Zone.NEW[Trajectory[cyclic] ← [spline,cyclic[cps]]];
linked =>
IF traj.links=NIL AND closed AND fitting=curve THEN shapeObj.trajectory ←
CZone.NEW[Trajectory[cyclic] ←[spline,cyclic[cps]]]
ELSE BEGIN
--assume linked from here on down
link: REF Link;
IF closed THEN BEGIN
IF traj.links=NIL THEN AddToken[ObjToScr[cps[0]],CP]
ELSE AddToken[ObjToScr[traj.links.knots[0]],CP];
cps ← ReadCPs[];
shapeObj.closed ← TRUE;
END;
link ← MakeLink[fitting=lines,cps];
AddLink[shapeObj,link];
WriteLink[shapeObj,link];
END;
ENDCASE;
object.cluster ← 0;
RefreshDefs.PlotAndMark[object];
[] ← ObjectDefs.SelectObject[object];
RefreshDefs.RestoreScreen[];
RefreshDefs.EraseAndSaveAllCPs[];
DeleteAllCPs[];
RefreshDefs.RestoreScreen[];
newObj ← NIL;
END;
editMenu: PUBLIC MenuDefs.MenuHandle←NIL;
styleMenu: PUBLIC MenuDefs.MenuHandle←NIL;
shapeMenu: PUBLIC MenuDefs.MenuHandle←NIL;
splineMenu: PUBLIC MenuDefs.MenuHandle←NIL;
default: MenuDefs.MenuItemHandle←NIL;
showstyle: MenuDefs.MenuItemHandle←NIL;
newLink: MenuDefs.MenuItemHandle←NIL;
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,"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.