<<--File: IPTopEditOpsExtraImpl.mesa>> <> <<>> DIRECTORY Rope, CDOrient, IP, IPCTG, IPCoTab, IPTop, IPToolBox, IPTopOpRecs, IPBasicOps, IPEditPrimitives, IPTopOpsPrivate, IPTopOps; IPTopEditOpsExtraImpl: CEDAR PROGRAM IMPORTS CDOrient, IPCTG, IPCoTab, IPBasicOps, IPEditPrimitives, IPToolBox, IPTopOps, IPTopOpsPrivate EXPORTS IPTopOps, IPTopOpsPrivate = BEGIN OPEN TOR: IPTopOpRecs, IPTopOps; SpawnComps: PUBLIC PROC[top: IPTop.Ref, comp: IPCoTab.Component, negChildName, posChildName: Rope.ROPE, negChildShape, posChildShape: IP.ShapeRep, splitDirection: IP.OrientationTypes, chkArgs, keepTrack: BOOL, negChild, posChild: IPCoTab.Component _ NIL] RETURNS [fr: TOR.FRSpawnComps, ir: TOR.RComposite _ NIL]={ <<--Having chkArgs is a change in format of TopOps. >> <<-- In this way we won't need to do the trick as in FlipT>> insertCoHint: [1..2] = 1; chToSplit, negBnd, posBnd: IPCTG.Channel; IF chkArgs AND ~ SpawnCompsChk[top, comp, negChildName, posChildName, negChildShape, posChildShape, splitDirection] THEN ERROR InvalidArgs[$SpawnComps]; --(1) Check Arguments negChild _ IPCoTab.CreateComponent2[top.coTab, negChildName, negChildShape, FALSE, CDOrient.original, [0,0], negChild]; posChild _ IPCoTab.CreateComponent2[top.coTab, posChildName, posChildShape, FALSE, CDOrient.original, [0,0], posChild]; SELECT splitDirection FROM hor => { chToSplit _ IPCoTab.GetPrinCh[comp, north]; negBnd _ IPCoTab.GetPrinCh[comp, west]; posBnd _ IPCoTab.GetPrinCh[comp, east];}; ver => { chToSplit _ IPCoTab.GetPrinCh[comp, east]; negBnd _ IPCoTab.GetPrinCh[comp, south]; posBnd _ IPCoTab.GetPrinCh[comp, north];}; ENDCASE => ERROR; ir _ CONS[NEW[TOR.IRDestroyComp2Rep _ [negChild]], ir]; ir _ CONS[NEW[TOR.IRDestroyComp2Rep _ [posChild]], ir]; ir _ CONS[SwapComponents[top, comp, negChild, FALSE].ir, ir]; ir _ CONS[IPTopOpsPrivate.InsertCo[top, posChild, chToSplit, negBnd, posBnd, neg, insertCoHint, FALSE].ir, ir]; ir _ CONS[NEW[TOR.IRCreateComp2Rep _ [comp]], ir]; fr _ NEW[TOR.FRSpawnCompsRep _ [comp, splitDirection, chkArgs, negChild, posChild]]; IPCoTab.DestroyComponent2[top.coTab, comp]; top.initialized _ FALSE; IF keepTrack THEN PushStacks[top, fr, ir] --(3) Push Stacks?-- }; --SpawnComps SpawnCompsChk: PUBLIC PROC[top: IPTop.Ref, comp: IPCoTab.Component, negChildName, posChildName: Rope.ROPE, negChildShape, posChildShape: IP.ShapeRep, splitDirection: IP.OrientationTypes] RETURNS [BOOL]={ IF ~ IPCoTab.CoActive[comp] THEN RETURN [FALSE]; FOR corner: IPCoTab.CornerTypes IN [sw..nw] DO <<--This restriction may be removed later.>> IF IPCoTab.GetCornerChs[comp, corner] # NIL THEN RETURN [FALSE] ENDLOOP; IF IPCoTab.GetComponent[top.coTab, negChildName, FALSE] # NIL OR IPCoTab.GetComponent[top.coTab, posChildName, FALSE] # NIL THEN RETURN [FALSE]; RETURN [TRUE] }; --SpawnCompsChk SetCompShape: PUBLIC PROC[top: IPTop.Ref, comp: IPCoTab.Component, shape: IP.ShapeRep, chkArgs, keepTrack: BOOL] RETURNS [fr, ir: TOR.RSetCompShape]={ oShape: IP.ShapeRep; IF chkArgs AND ~ SetCompShapeChk[comp, shape] THEN ERROR InvalidArgs[$SetCompShape]; --(1) Check Argument oShape _ comp.shape; IF comp.type = NIL THEN comp.shape _ shape ELSE { coType: REF IP.CoTypeRep _ comp.type; refShape: REF IP.ShapeRep _ NEW[IP.ShapeRep _ shape]; IPToolBox.OrientShape[refShape, CDOrient.InverseOrient[comp.orient]]; coType.shapeInfo.shape _ refShape; FOR l: LIST OF IPCoTab.Component _ coType.instances, l.rest UNTIL l = NIL DO l.first.shape _ IPToolBox.CopyShape[refShape, l.first.orient]^ ENDLOOP;}; ir _ NEW[TOR.RSetCompShapeRep _ [comp, oShape, chkArgs]]; fr _ NEW[TOR.RSetCompShapeRep _ [comp, shape, chkArgs]]; top.initialized _ FALSE; IF keepTrack THEN PushStacks[top, fr, ir] --(3) Push Stacks?-- }; --SetCompShape SetCompShapeChk: PUBLIC PROC[comp: IPCoTab.Component, shape: IP.ShapeRep] RETURNS [BOOL] ={ shapeConflict: PROC[inst: IPCoTab.Component] RETURNS [BOOL] ={ FOR corner: IPCoTab.CornerTypes IN [sw..nw] DO IF IPCoTab.GetCornerChs[inst, corner] # NIL AND IPToolBox.GetCorner[shape, corner] = NIL THEN RETURN [TRUE] ENDLOOP; RETURN [FALSE] }; --shapeConflict <> <> <> <<--The above loop should be used. But since its absence is quite benign, >> <<-- will let it be for the time being.>> IF comp.type # NIL THEN { FOR l: LIST OF IPCoTab.Component _ comp.type.instances, l.rest UNTIL l = NIL DO IF shapeConflict[l.first] THEN RETURN [FALSE] ENDLOOP}; RETURN [NOT shapeConflict[comp]] }; --SetCompShapeChk FlipT: PUBLIC PROC[top: IPTop.Ref, chToBend, attachTo: IPCTG.Channel, whichEnd: IPCTG.Side, keepTrack: BOOL _ FALSE] RETURNS [fr: TOR.FRFlipT, ir: TOR.RComposite] ={ endCh: IPCTG.Channel _ IPCTG.End[chToBend, whichEnd].ch; endChSide: IPCTG.Side _ IPBasicOps.PTNot[whichEnd]; whichDirection: IPCTG.Side _ IF IPCTG.InCount[endCh, attachTo, endChSide] < IPCTG.InCount[endCh, chToBend, endChSide] THEN neg ELSE pos; refComp: IPCoTab.Component _ IPCTG.NthComponent[chToBend, IPBasicOps.PTNot[whichDirection], -IPBasicOps.PTToInt[whichEnd]]; compCorner: IPCoTab.CornerTypes _ IF chToBend.type = hor THEN IPBasicOps.CTFromPTs[hor: endChSide, ver: whichDirection] ELSE IPBasicOps.CTFromPTs[hor: whichDirection, ver: endChSide]; prevCornerSp: IPCoTab.CornerSpace _ GetCoCornerSp[refComp, compCorner]; flipTOk: PROC RETURNS [BOOL] ={ tArmIntrsctn: IPCTG.Intersection _ IPCTG.NthIntersection[chToBend, IPBasicOps.PTNot[whichDirection], - IPBasicOps.PTToInt[whichEnd]]; IF tArmIntrsctn = NIL OR tArmIntrsctn.ch = NIL THEN RETURN [FALSE]; IF IPCoTab.GetCornerChs[refComp, compCorner] # NIL THEN RETURN [FALSE]; IF IPCTG.End[chToBend, whichEnd].type # IPCTG.TEnd THEN RETURN [FALSE]; IF ~ IPCTG.ArmOn[endCh, attachTo, endChSide] THEN RETURN [FALSE]; RETURN [TRUE]; }; --flipTOk <<--The above are taken almost directly from IPTopEditOpsImpl.FlexKnee and LtoT>> IF ~ flipTOk[] THEN ERROR IPTopOps.InvalidArgs[$FlipT]; --(1) Check args {ir _ LIST[SetCoCornerSp[refComp, compCorner, IPBasicOps.NuNatVector[0, 0]]]}; --DIRTY TRICK! <<--The above is to keep a dummy IPCoTab.CornerSpace in that corner of comp>> <<--to fool IPTopOps.FlexKnee in accepting the argument>> fr _ NEW[TOR.FRFlipTRec _ [chToBend, attachTo, whichEnd]]; --(a) Setup fr ir _ CONS[IPTopOps.FlexKnee[top, chToBend, attachTo, whichEnd, FALSE].ir, ir]; --(b1) Setup ir ir_ CONS[IPTopOps.LtoT[top, chToBend, whichEnd, FALSE].ir, ir]; -- (b2) Setup ir {ir _ CONS[SetCoCornerSp[refComp, compCorner, prevCornerSp], ir]}; --DIRTY TRICK! <<--Undo the dirty trick above>> IF keepTrack THEN PushStacks[top, fr, ir] --(3) Push Stacks?-- }; --FlipT FlipTChk: PUBLIC PROC[top: IPTop.Ref, chToBend, attachTo: IPCTG.Channel, whichEnd: IPCTG.Side] RETURNS [BOOL] ={ <<-- Copied from FlipT above>> endCh: IPCTG.Channel _ IPCTG.End[chToBend, whichEnd].ch; endChSide: IPCTG.Side _ IPBasicOps.PTNot[whichEnd]; whichDirection: IPCTG.Side _ IF IPCTG.InCount[endCh, attachTo, endChSide] < IPCTG.InCount[endCh, chToBend, endChSide] THEN neg ELSE pos; refComp: IPCoTab.Component _ IPCTG.NthComponent[chToBend, IPBasicOps.PTNot[whichDirection], -IPBasicOps.PTToInt[whichEnd]]; compCorner: IPCoTab.CornerTypes _ IF chToBend.type = hor THEN IPBasicOps.CTFromPTs[hor: endChSide, ver: whichDirection] ELSE IPBasicOps.CTFromPTs[hor: whichDirection, ver: endChSide]; tArmIntrsctn: IPCTG.Intersection _ IPCTG.NthIntersection[chToBend, IPBasicOps.PTNot[whichDirection], - IPBasicOps.PTToInt[whichEnd]]; IF tArmIntrsctn = NIL OR tArmIntrsctn.ch = NIL THEN RETURN [FALSE]; IF IPCoTab.GetCornerChs[refComp, compCorner] # NIL THEN RETURN [FALSE]; IF IPCTG.End[chToBend, whichEnd].type # IPCTG.TEnd THEN RETURN [FALSE]; IF ~ IPCTG.ArmOn[endCh, attachTo, endChSide] THEN RETURN [FALSE]; RETURN [TRUE]; };--FlipTChk FormZChk: PUBLIC PROC[top: IPTop.Ref, comp1, comp2: IPCoTab.Component, zType: IPCTG.Side] RETURNS [BOOL] ={ <<--Copied from: IPTopEditOpsImpl.FormZ>> et: IPCoTab.EdgeTypes _ south; refCh: IPCTG.Channel _ NIL; negComp, posComp: IPCoTab.Component; THROUGH [0..4) DO IF IPCoTab.GetPrinCh[comp1, et] = IPCoTab.GetPrinCh[comp2, IPBasicOps.ETRotate[et, 2]] THEN {refCh _ IPCoTab.GetPrinCh[comp1, et]; EXIT}; et _ IPBasicOps.ETRotate[et]; ENDLOOP; IF IPBasicOps.ETDirectn[et] = neg THEN {negComp _ comp2; posComp _ comp1} ELSE {negComp _ comp1; posComp _ comp2}; IF refCh = NIL OR NOT IPEditPrimitives.FormZChk[refCh, negComp, posComp, zType] THEN RETURN [FALSE] ELSE RETURN [TRUE]; <<>> }; --FormZChk <<--##Strictly Private procedures ##-->> GetCoCornerSp: PROC[co: IPCoTab.Component, ct: IPCoTab.CornerTypes] RETURNS [IPCoTab.CornerSpace] ={ <<-- This procedure is specially created to do the dirty trick in FlipT>> OPEN coS: co.shape.cornerSpaces; RETURN[SELECT ct FROM sw => coS.sw, se => coS.se, ne => coS.ne, nw => coS.nw, ENDCASE => ERROR]; }; --GetCoCornerSp SetCoCornerSp: PUBLIC PROC[co: IPCoTab.Component, ct: IPCoTab.CornerTypes, sp: IPCoTab.CornerSpace] RETURNS [REF IPTopOpRecs.IRSetCoCornerSpRec] ={ <<-- This procedure is specially created to do the dirty trick in FlipT>> OPEN coS: co.shape.cornerSpaces; oSpace: IPCoTab.CornerSpace; SELECT ct FROM sw => {oSpace _ coS.sw; coS.sw _ sp}; se => {oSpace _ coS.se; coS.se _ sp}; ne => {oSpace _ coS.ne; coS.ne _ sp}; nw => {oSpace _ coS.nw; coS.nw_ sp}; ENDCASE => ERROR; RETURN [NEW[IPTopOpRecs.IRSetCoCornerSpRec _ [co, ct, oSpace]]] }; --SetCoCornerSp END.