<> <> <> <> <> DIRECTORY CD, CDLayers, CDPrivate, CDValue; CDLayersImpl: CEDAR MONITOR IMPORTS CDPrivate, CDValue EXPORTS CDLayers SHARES CDLayers = BEGIN Layer: TYPE = CD.Layer; Number: TYPE = CD.Number; Design: TYPE = CD.Design; DesignNotifyProc: TYPE = CDLayers.DesignNotifyProc; LayerNotifyProc: TYPE = CDLayers.LayerNotifyProc; LayerKind: TYPE = CDLayers.LayerKind; LayerRec: TYPE = RECORD [w: Number, use: Layer]; GetGlobalLayerRec: PROC [layer: Layer] RETURNS [REF LayerRec] = { WITH CDValue.Fetch[boundTo: NIL, key: CDPrivate.layers[layer].globalUniqueKey] SELECT FROM lr: REF LayerRec => RETURN [lr]; ENDCASE => { lr: REF LayerRec _ NEW[LayerRec _ [w: 0, use: layer]]; [] _ CDValue.StoreConditional[NIL, CDPrivate.layers[layer].globalUniqueKey, lr]; RETURN [GetGlobalLayerRec[layer]]; --recursion prevents concurrency problems }; }; GetLayerRec: PROC [design: Design, layer: Layer] RETURNS [REF LayerRec] = { WITH CDValue.Fetch[boundTo: design, key: CDPrivate.layers[layer].globalUniqueKey, propagation: design] SELECT FROM lr: REF LayerRec => RETURN [lr]; ENDCASE => { lr: REF LayerRec _ NEW[LayerRec _ GetGlobalLayerRec[layer]^]; [] _ CDValue.StoreConditional[design, CDPrivate.layers[layer].globalUniqueKey, lr]; RETURN [GetLayerRec[design, layer]]; --recursion prevents concurrency problems }; }; CurrentLayer: PUBLIC PROC [design: Design] RETURNS [Layer] = { RETURN [CDValue.FetchInt[design, $CurrentLayer, technology]] }; LayerWidth: PUBLIC PROC [design: Design, layer: Layer] RETURNS [Number] = { RETURN [GetLayerRec[design, layer].w] }; PlaceholderToAbstract: PUBLIC PROC [design: Design, layer: Layer] RETURNS [Layer] = { IF lKind[layer]=placeholder THEN RETURN [GetLayerRec[design, layer].use]; RETURN [layer]; }; SetCurrentLayer: PUBLIC PROC [design: REF, layer: Layer] = { CDValue.StoreInt[boundTo: design, key: $CurrentLayer, value: layer]; WITH design SELECT FROM d: Design => FOR list: LIST OF DesignNotifyProc _ layerPs, list.rest WHILE list#NIL DO list.first[d]; ENDLOOP; ENDCASE => NULL; }; <<--design can exceptionally be a technology to set default values>> <<--reserve call for CDPanelImpl; otherwise CDPanel gets fooled>> SetLayerWidth: PUBLIC PROC [design: Design, layer: Layer, width: Number] = { IF design=NIL THEN GetGlobalLayerRec[layer].w _ width ELSE { GetLayerRec[design, layer].w _ width; FOR list: LIST OF LayerNotifyProc _ widthPs, list.rest WHILE list#NIL DO list.first[design, layer]; ENDLOOP; }; }; SetPlaceholderToAbstract: PUBLIC PROC [design: Design, placeholder, abstract: Layer] = { IF lKind[placeholder]=placeholder THEN ERROR; IF design=NIL THEN GetGlobalLayerRec[placeholder].use _ abstract ELSE { GetLayerRec[design, placeholder].use _ abstract; FOR list: LIST OF LayerNotifyProc _ placeholderPs, list.rest WHILE list#NIL DO list.first[design, placeholder]; ENDLOOP; }; }; MakeAbstract: PUBLIC PROC [abstract: CD.Layer, represents: CD.Layer] = { <<--only technology implementor should call this procedure>> IF lKind[abstract]#paint THEN ERROR; lKind[abstract] _ abstract; lPaint[abstract] _ represents; }; MakePlaceholder: PUBLIC PROC [layer: CD.Layer, defaultsTo: CD.Layer] = { <<--only technology implementor should call this procedure>> IF lKind[layer]#paint THEN ERROR; lKind[layer] _ placeholder; lPaint[layer] _ CD.errorLayer; GetGlobalLayerRec[layer].use _ defaultsTo; }; MakePaint: PUBLIC PROC [layer: CD.Layer] = { <<--only technology implementor should call this procedure>> IF lKind[layer]#placeholder THEN ERROR; lKind[layer] _ paint; lPaint[layer] _ layer; GetGlobalLayerRec[layer].use _ layer; }; RegisterNotifiers: PUBLIC ENTRY PROC [layer: DesignNotifyProc_NIL, width: LayerNotifyProc_NIL, placeholder: LayerNotifyProc_NIL] = { IF layer#NIL THEN layerPs _ CONS[layer, layerPs]; IF width#NIL THEN widthPs _ CONS[width, widthPs]; IF placeholder#NIL THEN placeholderPs _ CONS[placeholder, placeholderPs]; }; lKind: REF ARRAY Layer OF LayerKind = NEW[ARRAY Layer OF LayerKind]; layerKind: PUBLIC REF READONLY ARRAY Layer OF LayerKind = lKind; lPaint: REF ARRAY Layer OF Layer = NEW[ARRAY Layer OF Layer]; layerPaint: PUBLIC REF READONLY ARRAY Layer OF Layer = lPaint; layerPs: LIST OF DesignNotifyProc _ NIL; widthPs: LIST OF LayerNotifyProc _ NIL; placeholderPs: LIST OF LayerNotifyProc _ NIL; CDValue.RegisterKey[key: $CurrentLayer]; FOR l: Layer IN Layer DO lKind[l] _ placeholder; lPaint[l] _ l; [] _ CDValue.RegisterKey[CDPrivate.layers[l].globalUniqueKey]; ENDLOOP; END.