<> <> <> <> DIRECTORY CD, CDBasics, CDDrawQueue, CDInstances, CDProperties, CDViewHighlight, CDVPrivate, ViewerClasses USING [Viewer]; CDViewHighlightImpl: CEDAR MONITOR IMPORTS CDBasics, CDDrawQueue, CDInstances, CDProperties, CDVPrivate EXPORTS CDViewHighlight SHARES CDProperties = BEGIN State: TYPE = RECORD [pr: REF CDVPrivate.PainterRec, included: BOOL _ FALSE]; RemoveAll: PUBLIC PROC [v: ViewerClasses.Viewer] = BEGIN keyList: LIST OF REF_NIL; me: CDVPrivate.VRef = NARROW[v.data]; GetThem: PROC [] = { FOR list: CD.PropList _ me.properties^, list.rest WHILE list#NIL DO WITH list.first.val SELECT FROM s: REF State => keyList _ CONS[list.first.key, keyList]; ENDCASE => NULL; ENDLOOP; }; CDProperties.DoWithinLock[GetThem]; FOR list: LIST OF REF _ keyList, list.rest WHILE list#NIL DO ShowInstance[v, NIL, TRUE, list.first]; ENDLOOP; END; GetData: INTERNAL PROC [me: CDVPrivate.VRef, key: REF] RETURNS [state: REF State] = { IF key=NIL THEN key _ defaultKey; WITH CDProperties.GetListProp[me.properties^, key] SELECT FROM s: REF State => state _ s; ENDCASE => { state _ NEW[State]; state.pr _ NEW[CDVPrivate.PainterRec _ [rect: CDBasics.empty, proc: PaintIt, data: NIL]]; CDProperties.PutProp[me.properties, key, state]; }; }; ToInstList: PROC [x: REF] RETURNS [CD.InstanceList] = BEGIN WITH x SELECT FROM l: CD.InstanceList => RETURN [l]; inst: CD.Instance => RETURN [LIST[inst]]; ENDCASE => RETURN [NIL]; END; Paint: PROC [me: CDVPrivate.VRef, rect: CD.Rect, erase: BOOL] = INLINE BEGIN IF CDBasics.NonEmpty[rect] THEN CDDrawQueue.QueueInsertDrawCommand[me.ct, CDDrawQueue.Request[(IF erase THEN $redraw ELSE $draw), rect]]; END; Update: PUBLIC ENTRY PROC [v: ViewerClasses.Viewer, key: REF_NIL] = BEGIN ENABLE UNWIND => NULL; me: CDVPrivate.VRef = NARROW[v.data]; state: REF State = GetData[me, key]; clearRect: CD.Rect _ state.pr.rect; paintRect: CD.Rect _ CDInstances.BoundingRectO[ToInstList[state.pr.data]]; state.pr.rect _ paintRect; Paint[me, paintRect, FALSE]; Paint[me, clearRect, TRUE]; END; ShowInstance: PUBLIC ENTRY PROC[v: ViewerClasses.Viewer, instOrList: REF_NIL, removeOthers: BOOL_TRUE, key: REF_NIL] = BEGIN ENABLE UNWIND => NULL; me: CDVPrivate.VRef = NARROW[v.data]; state: REF State = GetData[me, key]; instL: CD.InstanceList _ ToInstList[instOrList]; clearRect: CD.Rect _ CDBasics.empty; paintRect: CD.Rect _ CDInstances.BoundingRectO[instL]; IF removeOthers THEN { clearRect _ state.pr.rect; state.pr.rect _ CDBasics.empty; state.pr.data _ NIL; }; FOR list: CD.InstanceList _ ToInstList[state.pr.data], list.rest WHILE list#NIL DO instL _ CONS[list.first, instL] ENDLOOP; state.pr.data _ instL; state.pr.rect _ CDBasics.Surround[paintRect, state.pr.rect]; IF state.pr.data#NIL AND ~state.included THEN { state.included _ TRUE; CDVPrivate.IncludeAPainterRec[me, state.pr]; } ELSE IF state.pr.data=NIL THEN { state.included _ FALSE; CDVPrivate.RemoveAPainterRec[me, state.pr]; }; Paint[me, paintRect, FALSE]; Paint[me, clearRect, TRUE]; END; PaintIt: PROC [me: CDVPrivate.VRef, paintRef: REF CDVPrivate.PainterRec, interrestRect: CD.Rect] = { WITH paintRef.data SELECT FROM instL: CD.InstanceList => { FOR l: CD.InstanceList _ instL, l.rest WHILE l#NIL DO IF me.stoprequest^ THEN EXIT; IF CDBasics.Intersect[CDInstances.InstRectO[l.first], interrestRect] THEN l.first.ob.class.quickDrawMe[me.deviceDrawRef, l.first.ob, l.first.trans, l.first.properties] ENDLOOP; }; inst: CD.Instance => { inst.ob.class.quickDrawMe[me.deviceDrawRef, inst.ob, inst.trans, inst.properties] }; ENDCASE => NULL; }; defaultKey: REF _ NEW[INT]; END.