BOOL OpRetroFit::BuildUndo(NodePath* pPreviousNode, NodePath* pNewNode) { // A few quick error checks ENSURE(pPreviousNode!=NULL, "Previous Node was NULL in RetroFit::BuildUndo()"); ENSURE(pPreviousNode->IsKindOf(CC_RUNTIME_CLASS(NodePath)), "Previous Node not a path"); ENSURE(pNewNode!=NULL, "New Node was NULL in RetroFit::BuildUndo()"); ENSURE(pNewNode->IsKindOf(CC_RUNTIME_CLASS(NodePath)), "New Node not a path"); // Falg to see if it has worked BOOL IsOperationOk = TRUE; // Start the undo of the selected item IsOperationOk = DoStartSelOp(FALSE); // Will the node allow this op to take place? ObjChangeFlags cFlags; cFlags.ReplaceNode = TRUE; ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,pPreviousNode,this); if (IsOperationOk) IsOperationOk = pPreviousNode->AllowOp(&ObjChange); // insert our new object if (IsOperationOk) { // Insert the new node into the tree IsOperationOk = DoInsertNewNode(pNewNode, pPreviousNode, NEXT, TRUE); } // Invalidate the region covered by the old node if (IsOperationOk) IsOperationOk = DoInvalidateNodeRegion(pPreviousNode, TRUE); // Make sure everything has worked if (IsOperationOk) { // Remove the old node IsOperationOk = DoHideNode(pPreviousNode, TRUE); } ObjChange.Define(OBJCHANGE_FINISHED,cFlags,pPreviousNode,this); IsOperationOk = UpdateChangedNodes(&ObjChange); // If something went wrong then fail if (!IsOperationOk) FailAndExecute(); // End the operation properly End(); // return a value back to the caller return IsOperationOk; }
void OpBreakAtPoints::Do(OpDescriptor*) { // Obtain the current selections SelRange* Selected = GetApplication()->FindSelection(); NodePath* pSplitNode; // Now, because we're going to be doing mad things to the selection, we have to make a list // of all the selected nodes, so that adding nodes into the tree won't confuse us List* NodeList = Selected->MakeListOfNodes(); NodeListItem* CurItem = (NodeListItem*)(NodeList->GetHead()); if (!CurItem) goto FailAndDeleteList; if (!DoStartSelOp(TRUE,TRUE)) goto FailAndDeleteList; while (CurItem) { // get a pointer to the NodePath NodePath* pThisNode = (NodePath*)(CurItem->pNode); // Only interested in NodePaths that have a sub selection, and that will allow the op to happen if ((IS_A(pThisNode,NodePath) || IS_A(pThisNode,NodeBlendPath)) && pThisNode->InkPath.IsSubSelection()) { // Find out how many nodes this op will reproduce INT32 NumSplinters = pThisNode->InkPath.NumSplinters(); BOOL DoThisNode = FALSE; if (NumSplinters > 0) { // We need to ask the effected nodes if they (and their parents) can handle this node being replaced ObjChangeFlags cFlags; if (NumSplinters > 1) cFlags.MultiReplaceNode = TRUE; // Node will be replaced with more than one node. else cFlags.ReplaceNode = TRUE; // Node will be replaced with one node only. ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this); DoThisNode = pThisNode->AllowOp(&ObjChange); } if (DoThisNode) { BOOL ok; Node* pnode; // Copy the nodepath and all its children, without placing the copy in the tree CALL_WITH_FAIL(pThisNode->NodeCopy(&pnode), this, ok); if (!ok) goto DeleteList; pSplitNode = (NodePath*)pnode; // remove the fill from this path as we're about to open it pSplitNode->InkPath.IsFilled = FALSE; // Now stick the new path into the tree CALL_WITH_FAIL ( DoInsertNewNode(pSplitNode, pThisNode, NEXT, TRUE, FALSE), this,ok ); if (!ok) goto DeleteListAndPath; // Now breakup this copy of the path where necessary Path* pChildPath; INT32 split; do { // Create a new path, ready for split ALLOC_WITH_FAIL(pChildPath, new Path, this); if (!pChildPath) goto DeleteList; // Now split the path, possibly into two pieces. split = pSplitNode->InkPath.BreakInTwo(pChildPath); if (split==-1) { InformError(_R(IDS_OUT_OF_MEMORY), _R(IDS_OK)); delete pChildPath; goto FailAndDeleteList; } /* Karim 05/12/2000 No longer required - see code addition at the bottom of this loop. if (split==1) { delete pChildPath; continue; } */ if (split>1) { // update the split paths bounding rectangle pSplitNode->InvalidateBoundingRect(); // Create a new nodepath. NodePath* pChildNode; ALLOC_WITH_FAIL(pChildNode, new NodePath(), this); if (!pChildNode) { delete pChildPath; goto DeleteList; } // make room for the new path in the node path. CALL_WITH_FAIL ( pChildNode->SetUpPath(pChildPath->GetNumCoords(),12), this,ok ); if (!ok) { delete pChildNode; delete pChildPath; goto DeleteList; } // now copy the path data in there. pChildNode->InkPath.CopyPathDataFrom(pChildPath); delete pChildPath; // Clear the selection flag from the first element in both the split // and child paths. All others apart from the last will be unselected // by definition. Also select the last element in the child (pSplitNode->InkPath.GetFlagArray())[0].IsSelected = FALSE; (pChildNode->InkPath.GetFlagArray())[0].IsSelected = FALSE; (pChildNode->InkPath.GetFlagArray())[(pChildNode->InkPath.GetNumCoords()-1)].IsSelected = TRUE; pChildNode->InkPath.IsFilled = FALSE; // now, copy all attributes from the parent split to the child split Node* pAttr = pSplitNode->FindFirstChild(); while (pAttr != NULL) { if (pAttr->IsKindOf(CC_RUNTIME_CLASS(NodeAttribute))) { Node* pAttrCopy; CALL_WITH_FAIL(pAttr->NodeCopy(&pAttrCopy), this,ok); if (!ok) { pChildNode->CascadeDelete(); delete pChildNode; goto DeleteList; } pAttrCopy->AttachNode(pChildNode, FIRSTCHILD); } pAttr = pAttr->FindNext(); } for (INT32 loop = 0; loop < pChildNode->InkPath.GetNumCoords(); loop ++) { pChildNode->InkPath.GetVerbArray()[loop] = pChildNode->InkPath.GetVerbArray()[loop] & ~PT_CLOSEFIGURE; } // Now stick the new path into the tree CALL_WITH_FAIL ( DoInsertNewNode(pChildNode, pSplitNode, NEXT, TRUE, FALSE), this,ok ); if (!ok) { pChildNode->CascadeDelete(); delete pChildNode; goto DeleteList; } pSplitNode = pChildNode; } // Karim 05/12/2000 // Fix for memory leak. else { delete pChildPath; } } while (split); // Clear out any remaining closefigures on the last bit of the path for (INT32 loop = 0; loop < pSplitNode->InkPath.GetNumCoords(); loop ++) { pSplitNode->InkPath.GetVerbArray()[loop] = pSplitNode->InkPath.GetVerbArray()[loop] & ~PT_CLOSEFIGURE; } // Now we've broken up this path, let's hide it CALL_WITH_FAIL(DoHideNode(pThisNode,TRUE), this, ok) if (!ok) goto DeleteList; } } CurItem = (NodeListItem*)(NodeList->GetNext(CurItem)); }