CDVArrowImpl.mesa (part of ChipNDale)
Copyright © 1984, 1987 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, August 30, 1984 10:21:27 am PDT
Last edited by Christian Jacobi, March 6, 1987 2:16:38 pm PST
DIRECTORY
CedarProcess,
CD,
CDBasics,
CDDrawQueue,
CDOps,
CDProperties,
CDSequencer,
CDValue,
CDVArrow,
CDViewerBackdoor,
CDVPrivate,
CDVScale,
Imager,
Process,
TerminalIO,
ViewerEvents;
CDVArrowImpl: CEDAR MONITOR
IMPORTS CDBasics, CDDrawQueue, CDOps, CDProperties, CDSequencer, CDValue, CDVArrow, CDViewerBackdoor, CDVPrivate, CDVScale, CedarProcess, Imager, Process, TerminalIO, ViewerEvents
EXPORTS CDVArrow =
BEGIN
-- implements arrows on ChipNDale viewers
-- we have to distribute the command to the separate viewers because
-- arrows have different sizes in design coordinates, depending on scale
-- of the viewer.
-- we do store the arrow position twice!
-- 1: on a per design basis (using CDValue); this is used to reeinstall arrows
-- when viewers are opened
-- 2: on a per viewer basis (in the PainterRec); this allows erasing the arrows
-- however we need a flag in the PainterRec if it is valid ($on)
ShowArrow: PUBLIC PROC [design: CD.Design, pos: CD.Position] = {
--called from client
IF design#NIL THEN {
CDValue.Store[boundTo: design, key: $arrow, value: NEW[CD.Position←pos]];
CDDrawQueue.InsertDrawCommand[design, CDDrawQueue.Request[$PutArrowXXX, [pos.x, pos.y, 0, 0]]]
}
};
RemoveArrow: PUBLIC PROC[design: CD.Design] = {
--called from client
IF design#NIL THEN {
CDValue.Store[boundTo: design, key: $arrow, value: NIL];
CDDrawQueue.InsertDrawCommand[design, CDDrawQueue.Request[$RemoveArrowXXX, [0, 0, 0, 0]]];
}
};
GetAPainterRec: ENTRY PROC [me: CDVPrivate.VRef] RETURNS [pr: REF CDVPrivate.PainterRec] = {
ENABLE UNWIND => NULL;
x: REF = CDProperties.GetProp[me.properties, $CDxArrowPaintProc];
IF x#NIL THEN pr ← NARROW[x]
ELSE {
pr ← NEW[CDVPrivate.PainterRec←[proc: PaintArrow]];
CDProperties.PutProp[me.properties, $CDxArrowPaintProc, pr]
}
};
PaintArrow: CDVPrivate.PainterProc = {
vp: CD.Position ← CDVScale.DesignToViewerPosition[me.scale, [paintRef.rect.x1, paintRef.rect.y1]];
vp ← CDBasics.AddPoints[vp, [1, 1]];
Imager.SetColor[me.viewContext, Imager.black];
Imager.MaskVector[me.viewContext, [vp.x+10, vp.y], [vp.x, vp.y]];
Imager.MaskVector[me.viewContext, [vp.x, vp.y], [vp.x, vp.y+10]];
Imager.MaskVector[me.viewContext, [vp.x, vp.y], [vp.x+18, vp.y+18]];
};
PaintTheArrow: CDViewerBackdoor.FurtherPaintProc = {
--called through ProtectedRepaint only
--called in viewers paint proc
pr: REF CDVPrivate.PainterRec = GetAPainterRec[me];
comm: REF CDDrawQueue.Request = NARROW[key];
arrowSize: CD.Number = MAX[CDVScale.UngriddedViewerToDesignScalar[me.scale, 20], 1];
aRect: CD.Rect ← [x1: comm.rect.x1, y1: comm.rect.y1,
x2: comm.rect.x1+arrowSize, y2: comm.rect.y1+arrowSize];
IF pr.data = $on THEN {
oldRect: CD.Rect;
IF pr.rect=aRect THEN RETURN;
oldRect ← pr.rect;
pr.rect ← aRect;
CDDrawQueue.QueueInsertDrawCommand[me.ct, CDDrawQueue.Request[$redraw, oldRect]];
}
ELSE {
pr.rect ← aRect;
CDVPrivate.IncludeAPainterRec[me, pr];
pr.data ← $on;
};
CDDrawQueue.QueueInsertDrawCommand[me.ct, CDDrawQueue.Request[$draw, aRect]];
};
RemoveTheArrow: CDViewerBackdoor.FurtherPaintProc = {
--called through ProtectedRepaint only
--called in viewers paint proc
pr: REF CDVPrivate.PainterRec = GetAPainterRec[me];
IF pr.data = $on THEN {
oldRect: CD.Rect ← pr.rect;
pr.rect ← CDBasics.empty;
pr.data ← NIL;
CDDrawQueue.QueueInsertDrawCommand[me.ct, CDDrawQueue.Request[$redraw, oldRect]];
CDVPrivate.RemoveAPainterRec[me, pr];
}
};
CallOnOpenOrCreate: ViewerEvents.EventProc = TRUSTED {
--crazy: we fork, because we want to wait
Process.Detach[FORK ReInstallTheArrow[NARROW[viewer.data]]];
};
ReInstallTheArrow: PROC [me: CDVPrivate.VRef] = {
--crazy: we wait, to increase propability of the commandtable beeing initialized
CedarProcess.SetPriority[CedarProcess.Priority[background]];
Process.PauseMsec[500];
IF me.ct#NIL THEN { -- which now certainly is true
WITH CDValue.Fetch[boundTo: me.actualDesign, key: $arrow, propagation: design] SELECT FROM
pos: REF CD.Position => {
CDDrawQueue.QueueInsertDrawCommand[me.ct, CDDrawQueue.Request[$PutArrowXXX, [pos.x, pos.y, 0, 0]]]
};
ENDCASE => {
CDDrawQueue.QueueInsertDrawCommand[me.ct, CDDrawQueue.Request[$RemoveArrowXXX, [0, 0, 0, 0]]]
};
}
};
Init: PROC [] = {
CDValue.RegisterKey[$arrow];
CDViewerBackdoor.InstallFurtherPaint[keyValue: $PutArrowXXX, proc: PaintTheArrow];
CDViewerBackdoor.InstallFurtherPaint[keyValue: $RemoveArrowXXX, proc: RemoveTheArrow];
[] ← ViewerEvents.RegisterEventProc[proc: CallOnOpenOrCreate, event: open, filter: $ChipNDale, before: FALSE];
[] ← ViewerEvents.RegisterEventProc[proc: CallOnOpenOrCreate, event: create, filter: $ChipNDale, before: FALSE];
};
SetArrowComm: PROC [comm: CDSequencer.Command] = {
WriteInLambda: PROC [n: CD.Number] = {
TerminalIO.PutRope[CDOps.LambdaRope[n, lambda]]
};
lambda: INT ← comm.design.technology.lambda;
TerminalIO.PutRope["set arrow at ("];
WriteInLambda[comm.pos.x];
TerminalIO.PutRope[","];
WriteInLambda[comm.pos.y];
TerminalIO.PutRope[")\024\n"];
CDVArrow.ShowArrow[comm.design, comm.pos];
};
RemoveArrowComm: PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope["remove arrow\n"];
CDVArrow.RemoveArrow[comm.design];
};
Init[];
CDSequencer.ImplementCommand[$SetArrow, SetArrowComm,, doQueue];
CDSequencer.ImplementCommand[$RemoveArrow, RemoveArrowComm,, doQueue];
END.