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: BOOLEAN ← FALSE,
screenNeedsRefreshing: BOOLEAN ← FALSE
];
RefreshCondition: TYPE = {disabled, enabled, busy};
RefreshProcessState: TYPE = {alive, dying};
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.