PERefreshImpl.mesa
Copyright (C) 1984 by Xerox Corporation. All rights reserved.
Written by Darlene Plebon on August 31, 1983 11:23 am
Refresh process routines. This process redraws the entire image at background priority whenever it is notified that an operation has been performed which may have damaged the displayed image. Active segments and vertices are NOT redrawn. Vertices are only drawn for the active trajectory.
DIRECTORY
Graphics USING [Context, DrawBox, GetBounds, Mark, Restore, Save, SetColor, white],
PEDisplay USING [DrawSegment, DrawSegmentAndVertices],
PERefresh,
PETrajectoryOps USING [ForAllSegments, ForAllTrajectories, SegmentProc, TrajectoryProc],
PETypes USING [Segment, Trajectory, TrajectoryList, TrajectoryNode],
PEViewer USING [DrawInViewer, DrawProc],
Process USING [Detach, priorityBackground, SetPriority],
ViewerClasses USING [Viewer];
PERefreshImpl: CEDAR MONITOR
IMPORTS Graphics, PEDisplay, PETrajectoryOps, PEViewer, Process
EXPORTS PERefresh =
BEGIN OPEN PEDisplay, PERefresh, PETrajectoryOps, PETypes, PEViewer;
RefreshProcessData: TYPE = REF RefreshProcessDataRec;
RefreshProcessDataRec: TYPE = RECORD [
pathViewer: ViewerClasses.Viewer ← NIL,
clientRedrawProc: DrawProc ← NIL,
trajectoryList: TrajectoryList ← NIL,
activeTrajectory: TrajectoryNode ← NIL,
state: RefreshProcessState ← alive,
refreshCondition: CONDITION,
eraseFirst: BOOLEANFALSE,
screenNeedsRefreshing: BOOLEANFALSE
];
RefreshCondition: TYPE = {disabled, enabled, busy};
RefreshProcessState: TYPE = {alive, dying};
IsRefreshing: CONDITION;
CreateRefreshProcess: PUBLIC PROCEDURE [pathViewer: ViewerClasses.Viewer, clientRedrawProc: DrawProc ← NIL] RETURNS [data: RefreshData] = {
This routine creates the refresh process.
refreshProcessData: RefreshProcessData ← NEW[RefreshProcessDataRec ← [pathViewer: pathViewer, clientRedrawProc: clientRedrawProc]];
TRUSTED {Process.Detach[FORK RefreshProcess[refreshProcessData]]};
RETURN [refreshProcessData];
};
DestroyRefreshProcess: PUBLIC ENTRY PROCEDURE [data: RefreshData] = {
This routine causes the refresh process to kill itself.
refreshProcessData: RefreshProcessData ← NARROW[data];
refreshProcessData.state ← dying;
NOTIFY refreshProcessData.refreshCondition;
};
EnableSegmentRefresh: PUBLIC ENTRY PROCEDURE [segment: Segment] = {
This routine allows the specified segment to be refreshed on refresh requests.
IF segment # NIL THEN segment.refresh ← TRUE;
};
DisableSegmentRefresh: PUBLIC ENTRY PROCEDURE [segment: Segment] = {
This routine prevents the specified segment from being refreshed.
IF segment # NIL THEN segment.refresh ← FALSE;
};
EnableTrajectoryRefresh: PUBLIC ENTRY PROCEDURE [trajectory: Trajectory] = {
This routine allows the specified trajectory to be refreshed on refresh requests.
IF trajectory # NIL THEN trajectory.refresh ← enabled;
};
DisableTrajectoryRefresh: PUBLIC ENTRY PROCEDURE [trajectory: Trajectory] = {
This routine prevents the specified trajectory from being refreshed.
WHILE trajectory.refresh = busy DO WAIT IsRefreshing ENDLOOP;
IF trajectory # NIL THEN trajectory.refresh ← disabled;
};
NewRefreshData: PUBLIC ENTRY PROCEDURE [data: RefreshData, trajectoryList: TrajectoryList, activeTrajectory: TrajectoryNode] = {
This procedure provides information about the image to be refreshed. In particular, it provides a list of trajectories to be refreshed and which trajectory is active (i.e. the trajectory whose vertices are to be refreshed). This routine should be called whenever this information changes.
refreshProcessData: RefreshProcessData ← NARROW[data];
refreshProcessData.trajectoryList ← trajectoryList;
refreshProcessData.activeTrajectory ← activeTrajectory;
};
RequestRefresh: PUBLIC ENTRY PROCEDURE [data: RefreshData, erase: BOOLEAN ← FALSE] = {
This routine requests that the image be refreshed. It may optionally request that the screen be erased first.
refreshProcessData: RefreshProcessData ← NARROW[data];
refreshProcessData.eraseFirst ← erase;
refreshProcessData.screenNeedsRefreshing ← TRUE;
NOTIFY refreshProcessData.refreshCondition;
};
RefreshProcess: PRIVATE PROCEDURE [myData: RefreshProcessData] = {
The routine is the refresh process which redraws the entire image at background priority.
DoErase: DrawProc = {
mark: Graphics.Mark ← Graphics.Save[context];
Graphics.SetColor[context, Graphics.white];
Graphics.DrawBox[context, Graphics.GetBounds[context]];
Graphics.Restore[context, mark];
};
DoRefreshTrajectory: TrajectoryProc = {
DoRefreshSegment: SegmentProc = {
RefreshSegment[data: myData, segment: s.first, trajectory: t];
};
Notify: PRIVATE ENTRY PROCEDURE = {NOTIFY IsRefreshing;};
IF t.first # NIL AND t.first.refresh = enabled THEN {
t.first.refresh ← busy;
ForAllSegments[t.first.segments, DoRefreshSegment];
t.first.refresh ← enabled;
Notify;
};
};
TRUSTED {Process.SetPriority[Process.priorityBackground]};
WHILE myData.state = alive DO
WaitForWork[myData];
IF myData.state # alive THEN EXIT;
IF myData.eraseFirst THEN DrawInViewer[myData.pathViewer, DoErase];
IF myData.clientRedrawProc # NIL THEN DrawInViewer[myData.pathViewer, myData.clientRedrawProc];
ForAllTrajectories[myData.trajectoryList, DoRefreshTrajectory];
ENDLOOP;
};
WaitForWork: PRIVATE ENTRY PROCEDURE [data: RefreshProcessData] = {
This routine waits for a refresh request from the path editor.
WHILE ~data.screenNeedsRefreshing AND data.state = alive DO
WAIT data.refreshCondition;
ENDLOOP;
data.screenNeedsRefreshing ← FALSE;
};
RefreshSegment: PRIVATE ENTRY PROCEDURE [data: RefreshProcessData, segment: Segment, trajectory: TrajectoryNode] = {
This routine refreshes a segment.
IF segment # NIL AND segment.refresh THEN {
IF trajectory = data.activeTrajectory THEN DrawSegmentAndVertices[pathViewer: data.pathViewer, segment: segment, background: FALSE]
ELSE DrawSegment[pathViewer: data.pathViewer, segment: segment, background: TRUE];
};
};
END.