CDVArrowImpl.mesa (part of ChipNDale)
Copyright © 1984 by Xerox Corporation. All rights reserved.
by Christian Jacobi, August 30, 1984 10:21:27 am PDT
last edited by Christian Jacobi, November 5, 1984 10:23:57 am PST
DIRECTORY
Atom USING [PutPropOnList],
CD,
CDBasics,
CDDraw,
CDProperties,
CDValue,
CDVArrow,
CDVPrivate,
CDVScale,
CDVFurtherPainters,
Graphics,
Process,
ViewerEvents;
CDVArrowImpl: CEDAR MONITOR
IMPORTS CDDraw, CDBasics, CDProperties, CDValue, CDVPrivate, CDVScale, CDVFurtherPainters, Graphics, Process, 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.DesignPosition] =
--called from client
BEGIN
CDValue.Store[boundTo: design, key: $arrow, value: NEW[CD.DesignPosition←pos]];
CDDraw.InsertCommandAll[design,
CDDraw.Comm[cmd: ref, erase: FALSE, rect: [pos.x, pos.y, 0, 0], ref: $PutArrowXXX]]
END;
RemoveArrow: PUBLIC PROC[design: CD.Design] =
--called from client
BEGIN
CDValue.Store[boundTo: design, key: $arrow, value: NIL];
CDDraw.InsertCommandAll[design,
CDDraw.Comm[cmd: ref, erase: FALSE, rect: [0, 0, 0, 0], ref: $RemoveArrowXXX]]
END;
GetAPainterRec: ENTRY PROC [me: CDVPrivate.MyGraphicRef]
RETURNS [pr: REF CDVPrivate.PainterRec] =
BEGIN ENABLE UNWIND => NULL;
x: REF = CDProperties.GetPropFromList[me.properties, $CDxArrowPaintProc];
IF x#NIL THEN pr ← NARROW[x]
ELSE {
pr ← NEW[CDVPrivate.PainterRec←[proc: PaintArrow]];
me.properties ← Atom.PutPropOnList[me.properties, $CDxArrowPaintProc, pr]
}
END;
PaintArrow: CDVPrivate.PainterProc =
-- PROC [me: MyGraphicRef, paintRef: REF PainterRec, interrestRect: CD.DesignRect];
BEGIN
vp: CD.Position ← CDVScale.DesignToViewerPosition[me.scale, [paintRef.rect.x1, paintRef.rect.y1]];
vp ← CDBasics.AddPoints[vp, [1, 1]];
me.viewContext.SetColor[Graphics.black];
[]← Graphics.SetPaintMode[me.viewContext, opaque];
me.viewContext.SetCP[vp.x+10, vp.y];
me.viewContext.DrawTo[vp.x, vp.y];
me.viewContext.DrawTo[vp.x, vp.y+10];
me.viewContext.SetCP[vp.x, vp.y];
me.viewContext.DrawTo[vp.x+18, vp.y+18];
END;
PaintTheArrow: CDVFurtherPainters.FurtherPaintProc =
--PROC [me: CDVPrivate.MyGraphicRef, key: REF]
--eg. former paints ticks
--called through ProtectedRepaint only
--called in viewers paint proc
BEGIN
pr: REF CDVPrivate.PainterRec = GetAPainterRec[me];
comm: REF CDDraw.Comm = NARROW[key];
arrowSize: CD.DesignNumber = MAX[CDVScale.UngriddedViewerToDesignScalar[me.scale, 20], 1];
aRect: CD.DesignRect ← [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.DesignRect;
IF pr.rect=aRect THEN RETURN;
oldRect ← pr.rect;
pr.rect ← aRect;
CDDraw.InsertCommand[me.ct, CDDraw.Comm[cmd: rect, erase: TRUE, rect: oldRect, ref: NIL]];
}
ELSE {
pr.rect ← aRect;
CDVPrivate.IncludeAPainterRec[me, pr];
pr.data ← $on;
};
CDDraw.InsertCommand[me.ct, CDDraw.Comm[cmd: rect, erase: FALSE, rect: aRect, ref: NIL]];
END;
RemoveTheArrow: CDVFurtherPainters.FurtherPaintProc =
--PROC [me: CDVPrivate.MyGraphicRef, key: REF]
--eg. former paints ticks
--called through ProtectedRepaint only
--called in viewers paint proc
BEGIN
pr: REF CDVPrivate.PainterRec = GetAPainterRec[me];
IF pr.data = $on THEN {
oldRect: CD.DesignRect ← pr.rect;
pr.rect ← CDBasics.empty;
pr.data ← NIL;
CDDraw.InsertCommand[me.ct, CDDraw.Comm[cmd: rect, erase: TRUE, rect: oldRect, ref: NIL]];
CDVPrivate.RemoveAPainterRec[me, pr];
}
END;
CallOnOpenOrCreate: ViewerEvents.EventProc =
-- PROC [viewer: ViewerClasses.Viewer, event: ViewerEvent, before: BOOL] RETURNS[abort: BOOLFALSE]
TRUSTED BEGIN
--crazy: we fork, because we want to wait
Process.Detach[FORK ReInstallTheArrow[NARROW[viewer.data]]];
END;
ReInstallTheArrow: PROC [me: CDVPrivate.MyGraphicRef] =
BEGIN
--crazy: we wait, to increase propability of the commandtable beeing initialized
TRUSTED {Process.SetPriority[Process.priorityBackground]};
Process.Pause[Process.MsecToTicks[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.DesignPosition => {
CDDraw.InsertCommand[me.ct,
CDDraw.Comm[cmd: ref, erase: FALSE, rect: [pos.x, pos.y, 0, 0], ref: $PutArrowXXX]]
};
ENDCASE => {
CDDraw.InsertCommand[me.ct,
CDDraw.Comm[cmd: ref, erase: FALSE, rect: [0, 0, 0, 0], ref: $RemoveArrowXXX]]
};
}
END;
Init: PROC [] =
BEGIN
CDValue.EnregisterKey[$arrow];
CDVFurtherPainters.InstallFurtherPaint[keyValue: $PutArrowXXX, proc: PaintTheArrow];
CDVFurtherPainters.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];
END;
Init[];
END.