-- Compiler DrawOps/n
--m.stone December 2, 1981 11:24 PM
--Tiberi December 11, 1979 8:42 PM
DIRECTORY
GriffinDefs: FROM "GriffinDefs",
GriffinStartDefs: FROM "GriffinStartDefs",
StringDefs: FROM "StringDefs",
MenuDefs: FROM "MenuDefs",
ObjectDefs: FROM "ObjectDefs",
GriffinFontDefs: FROM "GriffinFontDefs",
ControllerDefs: FROM "ControllerDefs",
RefreshDefs: FROM "RefreshDefs",
StyleDefs: FROM "StyleDefs",
PointDefs: FROM "PointDefs",
GriffinMemoryDefs: FROM "GriffinMemoryDefs",
SplineDefs: FROM "SplineDefs",
ControllerMenuDefs: FROM "ControllerMenuDefs";
DrawOps: PROGRAM
IMPORTS GriffinDefs, MenuDefs, ObjectDefs, ControllerMenuDefs, StringDefs, GriffinMemoryDefs, PointDefs, ControllerDefs,RefreshDefs
EXPORTS GriffinDefs, GriffinStartDefs =
BEGIN OPEN ObjectDefs,PointDefs,GriffinMemoryDefs;
newObj: POINTER TO shape Object ← NIL;
spline: SplineDefs.SplineType ← naturalAL;
Fitting: TYPE = {lines,curve};
fitting: Fitting;
SetStyle: PROCEDURE[style: StyleDefs.StyleHandle] =
BEGIN
fd: GriffinFontDefs.FontDescriptor;
name: STRING ← [128];
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];
StringDefs.AppendString[to: name, from: fd.name];
StringDefs.AppendDecimal[name, fd.points];
SELECT fd.face FROM
3 => StringDefs.AppendString[to: name, from: "BI"];
2 => StringDefs.AppendString[to: name, from: "B"];
1 => StringDefs.AppendString[to: name, from: "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: STRING]=
BEGIN OPEN MenuDefs;
menuItem: MenuItemHandle ← menu.head;
IsThisItem: MenuProc =
BEGIN
IF StringDefs.EquivalentString[MenuString[item], string]
THEN menuItem ← item;
END;
ForAllMenuItems[menu, IsThisItem];
BugItem[menuItem]
END;
ExpandShape: 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: 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: 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: 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
width: REAL ← obj.style.width;
outlined: BOOLEAN ← obj.style.outlined;
filled: BOOLEAN ← obj.style.filled;
obj.style ← ControllerDefs.CurrentStyle[];
IF width > obj.style.width OR (outlined # obj.style.outlined)
OR (filled # obj.style.filled) OR obj.objectType=caption
THEN RefreshDefs.EraseAndSave[obj];
RefreshDefs.PlotAndMark[obj];
END;
ForAllSelectedDo[ChangeObj];
RefreshDefs.RestoreScreen[];
END;
IndicateStyle: 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[STRING]=
BEGIN
RETURN[SELECT color FROM
[0,0,0] => "black",
[7,255,59] => "dk brown",
[7,255,118] => "brown",
[0,131,217] => "tan",
[234,255,79] => "maroon",
[0,255,160] => "dk red",
[0,255,255] => "red",
[10,255,255] => "orange",
[25,255,255] => "dk yellow",
[40,255,255] => "yellow",
[40,190,255] => "lt yellow",
[71,255,59] => "dk green",
[76,255,255] => "green",
[71,193,255] => "lt green",
[150,255,170] => "dk blue",
[150,255,255] => "blue",
[141,150,255] => "lt blue",
[107,255,98] => "dk aqua",
[107,224,255] => "aqua",
[120,255,255] => "cyan",
[178,255,178] => "dk purple",
[170,224,255] => "purple",
[170,131,255] => "violet",
[200,255,255] => "magenta",
[206,170,255] => "pink",
[0,0,40] => "dk grey",
[0,0,120] => "grey",
[0,0,200] => "lt grey",
[0,0,230] => "pale grey",
[0,0,255] => "white",
ENDCASE => "black"];
END;
FittingType: MenuDefs.MenuProc =
BEGIN OPEN StringDefs;
string: STRING ← MenuDefs.MenuString[item];
fitting ← SELECT TRUE FROM
EquivalentStrings[string,"Straight"] => lines,
EquivalentStrings[string,"Curved"] => curve,
ENDCASE => ERROR;
MenuDefs.SelectOnly[item];
END;
ExpandSplines: 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: MenuDefs.MenuProc =
BEGIN OPEN StringDefs;
string: STRING ← MenuDefs.MenuString[item];
IF newObj#NIL THEN GriffinDefs.UserMessage["Only one spline type per object"];
spline ← SELECT TRUE FROM
EquivalentStrings[string,"Natural: Arc Length"] => naturalAL,
EquivalentStrings[string,"Natural: Unit Length"] => naturalUM,
EquivalentStrings[string,"Bezier Curve"] => bezier,
EquivalentStrings[string,"B-Spline"] => bspline,
EquivalentStrings[string,"Catmull-Rom Curve"] => crspline,
ENDCASE => ERROR;
MenuDefs.SelectOnly[item];
END;
SetSplineType: PROCEDURE[splinetype: SplineDefs.SplineType] =
BEGIN OPEN StringDefs;
string: STRING ← 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: MenuDefs.MenuProc =
BEGIN
tempLink: POINTER TO Link ← NIL;
lastPt: PointDefs.ScrPt;
cps: DESCRIPTOR FOR ARRAY OF PointDefs.ObjPt;
IF spline=bspline OR spline=crspline THEN
GriffinDefs.UserMessage["B-Splines and Catmull-Rom Curves cannot be used in linked objects"];
cps ← ReadCPs[];
IF LENGTH[cps] <=1 THEN BEGIN
IF LENGTH[cps]#0 THEN Free[BASE[cps]];
RETURN;
END;
lastPt ← PointDefs.ObjToScr[cps[LENGTH[cps]-1]];
tempLink ← MakeLink[fitting=lines,cps];
IF newObj=NIL THEN BEGIN
newObj ← LOOPHOLE[StartObject[shape]];
newObj.body ← shape[FALSE,[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: DESCRIPTOR FOR ARRAY OF PointDefs.ObjPt]RETURNS[newLink: POINTER TO Link] =
BEGIN
newLink ← Allocate[SIZE[Link]];
newLink↑ ← [NIL, (IF isLines THEN D1 ELSE D3), cps];
END;
BackLink: MenuDefs.MenuProc =
BEGIN
lastLink: POINTER TO 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: DESCRIPTOR FOR ARRAY OF ObjPt, exceptLast: BOOLEAN] =
BEGIN
i: CARDINAL;
lastknot: CARDINAL ← LENGTH[knots]-1;
cps: DESCRIPTOR FOR ARRAY OF PointDefs.ObjPt ← 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 LENGTH[cps]#0 THEN BEGIN
FOR i IN [0..LENGTH[cps]) DO
AddToken[ObjToScr[cps[i]], CP];
ENDLOOP;
Free[BASE[cps]];
END;
END;
GetNewObjectLinks: PROCEDURE RETURNS [link: POINTER TO Link]=
BEGIN
IF newObj=NIL THEN RETURN[NIL];
WITH traj: newObj.trajectory SELECT FROM
linked => link ← traj.links;
ENDCASE => ERROR;
RETURN;
END;
Draw: MenuDefs.MenuProc =
BEGIN
DrawObject[newObj,FALSE];
END;
Close: MenuDefs.MenuProc =
BEGIN
DrawObject[newObj,TRUE];
END;
Box: MenuDefs.MenuProc =
BEGIN
cps: DESCRIPTOR FOR ARRAY OF PointDefs.ObjPt;
pt: ObjPt;
cps ← ReadCPs[];
IF LENGTH[cps] #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];
Free[BASE[cps]];
BugItemByString[shapeMenu,"Straight"];
DrawObject[newObj,TRUE];
END;
Modify: 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: POINTER TO 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: POINTER TO 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: DESCRIPTOR FOR ARRAY OF ObjPt, exceptLast: BOOLEAN] =
BEGIN
i: CARDINAL;
lastknot: CARDINAL ← LENGTH[knots]-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: POINTER TO shape Object ← NIL;
cps: DESCRIPTOR FOR ARRAY OF PointDefs.ObjPt ← ReadCPs[];
IF object=NIL AND LENGTH[cps]<1 THEN BEGIN
IF LENGTH[cps]#0 THEN Free[BASE[cps]]; RETURN; END;
IF object = NIL THEN BEGIN
object ← StartObject[shape];
object.body ← shape[closed,[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 ← [spline,cyclic[cps]];
linked =>
IF traj.links=NIL AND closed AND fitting=curve THEN shapeObj.trajectory ← [spline,cyclic[cps]]
ELSE BEGIN
--assume linked from here on down
link: POINTER TO Link;
IF closed THEN BEGIN
IF traj.links=NIL THEN AddToken[ObjToScr[cps[0]],CP]
ELSE AddToken[ObjToScr[traj.links.knots[0]],CP];
Free[BASE[cps]];
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;
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.