<> <> <> 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 ]; RefreshProcessState: TYPE = {alive, dying}; CreateRefreshProcess: PUBLIC PROCEDURE [pathViewer: ViewerClasses.Viewer, clientRedrawProc: DrawProc _ NIL] RETURNS [data: RefreshData] = { <> refreshProcessData: RefreshProcessData _ NEW[RefreshProcessDataRec _ [pathViewer: pathViewer, clientRedrawProc: clientRedrawProc]]; TRUSTED {Process.Detach[FORK RefreshProcess[refreshProcessData]]}; RETURN [refreshProcessData]; }; DestroyRefreshProcess: PUBLIC ENTRY PROCEDURE [data: RefreshData] = { <> refreshProcessData: RefreshProcessData _ NARROW[data]; refreshProcessData.state _ dying; NOTIFY refreshProcessData.refreshCondition; }; EnableSegmentRefresh: PUBLIC ENTRY PROCEDURE [segment: Segment] = { <> IF segment # NIL THEN segment.refresh _ TRUE; }; DisableSegmentRefresh: PUBLIC ENTRY PROCEDURE [segment: Segment] = { <> IF segment # NIL THEN segment.refresh _ FALSE; }; EnableTrajectoryRefresh: PUBLIC ENTRY PROCEDURE [trajectory: Trajectory] = { <> IF trajectory # NIL THEN trajectory.refresh _ TRUE; }; DisableTrajectoryRefresh: PUBLIC ENTRY PROCEDURE [trajectory: Trajectory] = { <> IF trajectory # NIL THEN trajectory.refresh _ FALSE; }; NewRefreshData: PUBLIC ENTRY PROCEDURE [data: RefreshData, trajectoryList: TrajectoryList, activeTrajectory: TrajectoryNode] = { <> refreshProcessData: RefreshProcessData _ NARROW[data]; refreshProcessData.trajectoryList _ trajectoryList; refreshProcessData.activeTrajectory _ activeTrajectory; }; RequestRefresh: PUBLIC ENTRY PROCEDURE [data: RefreshData, erase: BOOLEAN _ FALSE] = { <> refreshProcessData: RefreshProcessData _ NARROW[data]; refreshProcessData.eraseFirst _ erase; refreshProcessData.screenNeedsRefreshing _ TRUE; NOTIFY refreshProcessData.refreshCondition; }; RefreshProcess: PRIVATE PROCEDURE [myData: RefreshProcessData] = { <> 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]; }; ForAllSegments[t.first.segments, DoRefreshSegment]; }; 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] = { <> 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] = { <> 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.