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 OpMakeStroke::Do(OpDescriptor*) Author: Richard_Millican (Xara Group Ltd) <*****@*****.**> Created: 04/03/97 Inputs: OpDescriptor (unused) Outputs: - Returns: - Purpose: Performs the MakeShapes operation. ********************************************************************************************/ void OpMakeStroke::Do(OpDescriptor*) { // Obtain the current selections Range Selection = *GetApplication()->FindSelection(); Node* CurrentNode = Selection.FindFirst(); BOOL Success = TRUE; ERROR3IF(CurrentNode == NULL, "Make shapes called with no nodes selected"); if (CurrentNode != NULL) // No nodes selected so End { // Try to record the selection state, don't render the blobs though if (Success) Success = DoStartSelOp(FALSE,FALSE); // First, Make Shapes on everything so they're all simple paths String_256 Desc("Building new stroke brush..."); Progress::Start(FALSE, &Desc); OpDescriptor *pOp = OpDescriptor::FindOpDescriptor(OPTOKEN_MAKE_SHAPES); if (pOp != NULL) pOp->Invoke(); // Second, Group everything pOp = OpDescriptor::FindOpDescriptor(OPTOKEN_GROUP); if (pOp != NULL) pOp->Invoke(); pOp = OpDescriptor::FindOpDescriptor(OPTOKEN_GROUP); if (pOp != NULL) pOp->Invoke(); // Finally, create a new brush PathStrokerVector::BodgeRipSelection(/*(CommandIndex == 0) ? FALSE :*/ TRUE); Progress::Stop(); } if (!Success) { InformError(); FailAndExecute(); } End(); }
/******************************************************************************************** > virtual void OpRemoveClipView::Do(OpDescriptor* pOpDesc, OpParam* pOpParam) Author: Karim_MacDonald (Xara Group Ltd) <*****@*****.**> Created: 01 February 2000 Inputs: Outputs: Returns: Purpose: Errors: See also: ********************************************************************************************/ void OpRemoveClipView::Do(OpDescriptor* pOpDesc) { // try to record the selection state. if (DoStartSelOp(FALSE, FALSE)) { // obtain the current selection. Range Sel(*(GetApplication()->FindSelection())); RangeControl rc = Sel.GetRangeControlFlags(); rc.PromoteToParent = TRUE; Sel.Range::SetRangeControl(rc); // check that the selection is one lone NodeClipViewController. BOOL ok = FALSE; Node* pFirstNode = Sel.FindFirst(); if (pFirstNode != NULL && pFirstNode->IsANodeClipViewController()) if (Sel.FindNext(pFirstNode) == NULL) ok = TRUE; // remove tool blobs and localise any common attributes. Tool* pTool = NULL; Spread* pSpread = NULL; if (ok) { // render blobs off for tools which don't automatically redraw their blobs. pTool = Tool::GetCurrent(); pSpread = Document::GetSelectedSpread(); if (pSpread != NULL && pTool != NULL && !pTool->AreToolBlobsRenderedOnSelection()) pTool->RenderToolBlobs(pSpread, NULL); // invalidate the region of screen covering the selection. DoInvalidateNodesRegions(*(GetApplication()->FindSelection()), TRUE, FALSE, FALSE); // localise any common attributes. ok = DoLocaliseCommonAttributes((NodeGroup*)pFirstNode); } // deselect and hide the NCVC. NodeHidden* pHiddenNode = NULL; if (ok) { // deselect the NCVC, but don't ask for its blobs to be redrawn. ((NodeRenderable*)pFirstNode)->DeSelect(FALSE); ERROR3IF(pFirstNode->IsSelected(), "Deselect failed to deselect current node"); // hide the NodeClipViewController. ok = DoHideNode(pFirstNode, FALSE, &pHiddenNode, FALSE); ERROR3IF(!ok, "Unable to hide NodeClipViewController!"); } // hide the NCVC's NodeClipView node. if (ok) { NodeHidden* pDummy; NodeClipView* pClipView = ((NodeClipViewController*)pFirstNode)->GetClipView(); ok = DoHideNode(pClipView, FALSE, &pDummy, FALSE); ERROR3IF(!ok, "Unable to hide NodeClipView!"); } // show and select the NCVC's children. // a straight loop-over should do, as it should skip the now-hidden NodeClipView. if (ok) { // get the first child node (the NCVC's keyhole node). Node* pChildNode = pFirstNode->FindFirstChild(); if (pChildNode == NULL) TRACEUSER( "Karim", _T("OpRemoveClipView::Do(); Found an empty NodeClipViewController!\n")); // move and select the child nodes in turn. Node* pAnchorNode = pHiddenNode; Node* pNextChildNode = NULL; while (pChildNode != NULL) { // get the next child-node. pNextChildNode = pChildNode->FindNext(); // if the node is not a NodeHidden then move the node to its new location in // the tree - there is no need to render the node. if (!pChildNode->IsAnAttribute() && !pChildNode->IsNodeHidden()) { // move pChildNode to be the next-sibling of the anchor node. ok = DoMoveNode(pChildNode, pAnchorNode, NEXT); if (!ok) break; pAnchorNode = pChildNode; } // select the child node and invalidate its bounding rect, // but don't bother redrawing its blobs yet. if (pChildNode->IsAnObject()) { ((NodeRenderableInk*)pChildNode)->Select(FALSE); ((NodeRenderableInk*)pChildNode)->InvalidateBoundingRect(); ok = this->DoInvalidateNodeRegion(((NodeRenderableInk*)pChildNode), TRUE); if (!ok) break; } pChildNode = pNextChildNode; } } // render blobs back on for tools which don't automatically redraw their blobs. if (ok) { if (pSpread != NULL && pTool != NULL && !pTool->AreToolBlobsRenderedOnSelection()) pTool->RenderToolBlobs(pSpread, NULL); } // fail gracefully if things went pear-shaped. else FailAndExecute(); } End(); }
/******************************************************************************************** > virtual void OpApplyClipView::Do(OpDescriptor* pOpDesc, OpParam* pOpParam) Author: Karim_MacDonald (Xara Group Ltd) <*****@*****.**> Created: 01 February 2000 Inputs: Outputs: Returns: Purpose: Errors: See also: ********************************************************************************************/ void OpApplyClipView::Do(OpDescriptor* pOpDesc) { // obtain the current selection. Range Sel(*(GetApplication()->FindSelection())); RangeControl rc = Sel.GetRangeControlFlags(); rc.PromoteToParent = TRUE; Sel.Range::SetRangeControl(rc); // check that at least two nodes are selected. Node* pNode = NULL; Node* pFirstNode = Sel.FindFirst(); if (pFirstNode != NULL) pNode = Sel.FindNext(pFirstNode); if (pFirstNode == NULL || pNode == NULL) { ERROR3("OpApplyClipView invoked with less than two selected nodes. This should never occur."); End(); return; } // render blobs off for tools which don't automatically redraw their blobs. Tool* pTool = Tool::GetCurrent(); Spread* pSpread = Document::GetSelectedSpread(); if (pSpread != NULL && pTool != NULL && !pTool->AreToolBlobsRenderedOnSelection()) pTool->RenderToolBlobs(pSpread, NULL); // record the current selection state and if required, render off any selection blobs. if (!DoStartSelOp(FALSE, FALSE)) { End(); return; } // invalidate the region bounding the selection. // the commented code doesn't do the job properly (doesn't tackle undo) // though it should - I get the feeling I'm not using it correctly. // so we'll just have to invalidate the selection node by node. // if (!DoInvalidateNodesRegions(Sel, TRUE, FALSE, FALSE)) // { // End(); // return; // } Node* pSelNode = Sel.FindFirst(); while (pSelNode != NULL) { if (pSelNode->IsAnObject()) { if (!DoInvalidateNodeRegion((NodeRenderableInk*)pSelNode, TRUE)) { End(); return; } } pSelNode = Sel.FindNext(pSelNode); } // we need to insert the controller node at the position of the highest // selected node in the z-order, ie last in the selection, so find it. Node* pLastNode = NULL; while (pNode != NULL) { pLastNode = pNode; pNode = Sel.FindNext(pLastNode); } // loop terminates with pNode == NULL, pLastNode == last-node-in-sel. // create a new NodeClipViewController, which we will shortly insert into the tree; // note that ALLOC_WITH_FAIL automatically calls FailAndExecute() if things go wrong. NodeClipViewController* pClipViewController = NULL; ALLOC_WITH_FAIL(pClipViewController, new NodeClipViewController, this); BOOL ok = (pClipViewController != NULL); // put an action to hide the NodeClipViewController onto the undo action-list, // so that if the user presses undo then it will be hidden. if (ok) { HideNodeAction* pUndoHideNodeAction = NULL; ActionCode ac = HideNodeAction::Init(this, &UndoActions, pClipViewController, FALSE, // don't include subtree size (Action**)&pUndoHideNodeAction, FALSE); // don't tell subtree when undone if (ac == AC_FAIL) { delete pClipViewController; End(); return; } else { // right! we've got our node, we've got our action - lets stick it in the tree // (at a position just next to the last node which will go in the group). pClipViewController->AttachNode(pLastNode, NEXT); } } // move each item from the selection into our ClipView group, // remembering to deselect them as we go. // TODO: // sneaky suspicion I should be putting this in a Do fn in UndoableOperation... if (ok) { pNode = Sel.FindNext(pFirstNode); // the node we're moving now. ok = DoMoveNode(pFirstNode, pClipViewController, FIRSTCHILD); if (ok) ((NodeRenderable*)pFirstNode)->DeSelect(FALSE); } Node* pNextNode = NULL; // the next node to move. Node* pAnchorNode = pFirstNode; // the node we've just moved. while (ok && pNode != NULL) { // get the next node to move. pNextNode = Sel.FindNext(pNode); // now move the current node next to the anchor and deselect it. ok = DoMoveNode(pNode, pAnchorNode, NEXT); if (ok) ((NodeRenderable*)pNode)->DeSelect(FALSE); // get the new anchor node and the next node to move. pAnchorNode = pNode; pNode = pNextNode; } // try and locate a suitable candidate for a keyhole node. Node* pKeyhole = NULL; if (ok) { // now get the keyhole node, which is the first object-node child of the NCVC. pKeyhole = pClipViewController->FindFirstChild(); while (pKeyhole != NULL && !pKeyhole->IsAnObject()) { pKeyhole = pKeyhole->FindNext(); } // doh! can't find _one_ NodeRenderableInk child! I don't know... if (pKeyhole == NULL) { ok = FALSE; ERROR2RAW("ClipViewController has no object children"); } } // now attach a new NodeClipView, as the immediate NEXT-sibling of the keyhole node. NodeClipView* pClipView = NULL; if (ok) { ALLOC_WITH_FAIL(pClipView, new NodeClipView(pKeyhole, NEXT), this); ok = (pClipView != NULL); } // wow - succeeded! now all we need to do is some house-keeping. if (ok) { // tell the new NodeClipViewController that its current keyhole path is now invalid. pClipViewController->MarkKeyholeInvalid(); // invalidate ours and our parent's bounding rects. our bounding rect is almost // certainly already invalid, as we haven't done anything to make it valid yet. // this is why we invalidate *both* rects - just to cover all cases. pClipViewController->InvalidateBoundingRect(); Node* pParent = pClipViewController->FindParent(); if (pParent != NULL && pParent->IsBounded()) ((NodeRenderableBounded*)pParent)->InvalidateBoundingRect(); // select the new NodeClipViewController, but don't draw any blobs yet. pClipViewController->Select(FALSE); // invalidate the region bounding the selection. if (!DoInvalidateNodesRegions(*(GetApplication()->FindSelection()), TRUE, FALSE, FALSE)) { End(); return; } // factor out any common attributes. if (!DoFactorOutCommonChildAttributes(pClipViewController)) { End(); return; } // render blobs back on if the current tool doesn't automatically redraw its blobs. if (pSpread != NULL && pTool != NULL && !pTool->AreToolBlobsRenderedOnSelection()) pTool->RenderToolBlobs(pSpread, NULL); } else { FailAndExecute(); } // end the operation. End(); }
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)); }
/******************************************************************************************** > void OpBaseConvertPathSegment::Do(OpDescriptor*) Author: Peter_Arnold (Xara Group Ltd) <*****@*****.**> Created: 16/8/95 Inputs: OpDescriptor (unused) Purpose: Performs the common SelRange scanning part of converting path segments. Calls the ProcessSegment function in derived classes to do the actual processing Errors: - SeeAlso: - ********************************************************************************************/ void OpBaseConvertPathSegment::Do(OpDescriptor*) { #ifndef STANDALONE // Obtain the current selections and the first node in the selection SelRange* Selected = GetApplication()->FindSelection(); BOOL ok = (Selected != NULL); // Start the op BeginSlowJob(); if (ok) ok = DoStartSelOp(TRUE,TRUE); // Check with the selrange it is ok to run this op ObjChangeFlags cFlags; ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this); if (ok) { if (!Selected->AllowOp(&ObjChange)) { EndSlowJob(); FailAndExecute(); End(); return; } } Node* pNode = Selected->FindFirst(); NodePath* ThisPath = NULL; while (ok && (pNode != NULL)) { // we're only interested in NodePaths which have selected points BOOL DoThisNode = pNode->IsNodePath(); if (DoThisNode) DoThisNode = (((NodePath*)pNode)->InkPath.IsSubSelection()); if (DoThisNode) DoThisNode = (((NodePath*)pNode)->IsPathAllowable()); if ( DoThisNode ) { // for convenience, cast the pointer to a pointer to a NodePath ThisPath = (NodePath*)pNode; // First get pointers to the arrays PathVerb* Verbs = NULL; PathFlags* Flags = NULL; DocCoord* Coords = NULL; ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags); INT32 NumCoords = ThisPath->InkPath.GetNumCoords(); BOOL PrevSelected = FALSE; INT32 PrevPos = 0; // Set the NeedToRender flags INT32 loop; for (loop = 0; loop < NumCoords; loop++) { if (Flags[loop].IsEndPoint && Flags[loop].IsSelected) Flags[loop].NeedToRender = TRUE; else Flags[loop].NeedToRender = FALSE; } // Force a re-draw of the place where the path used to be if (ok) ok = (RecalcBoundsAction::DoRecalc(this, &UndoActions, ThisPath, TRUE) != AC_FAIL); // loop through the points for (loop = 0; loop<NumCoords; loop++) { if (Flags[loop].IsEndPoint) { // its an endpoint if (Flags[loop].IsSelected) { // which is selected if (PrevSelected && ((Verbs[loop] & ~PT_CLOSEFIGURE) == GetProcessPathType()) ) { // and the previous was selected and it's a processable segment if (ok) ok = ProcessSegment(ThisPath, &loop, PrevPos); // Recache array pointers ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags); NumCoords = ThisPath->InkPath.GetNumCoords(); Flags[loop].NeedToRender = TRUE; } PrevSelected = TRUE; PrevPos = loop; } else PrevSelected = FALSE; } } // Having finished processing this path go round and smooth it. DocCoord NewCoord; for (loop = 0; (ok && (loop < NumCoords)); loop++) { if (Verbs[loop] == PT_BEZIERTO && !(Flags[loop].IsEndPoint) && Flags[loop].IsSmooth) { NewCoord = ThisPath->InkPath.SmoothControlPoint(loop); if (ok && (NewCoord != Coords[loop])) { ok = DoAlterPathElement(ThisPath, loop, NewCoord, Flags[loop], Verbs[loop], FALSE); ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags); } } } ThisPath->InvalidateBoundingRect(); // Force a redraw of the place where the path is now. if (ok) ok = (RecordBoundsAction::DoRecord(this, &UndoActions, ThisPath, TRUE) != AC_FAIL); } pNode = Selected->FindNext(pNode); } if (ok) { ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this); if (!UpdateChangedNodes(&ObjChange)) { FailAndExecute(); End(); return; } } EndSlowJob(); if (!ok) { FailAndExecute(); InformError(); } #endif End(); }
void OpReversePath::Do (OpDescriptor*) { // Obtain the current selections and the first node in the selection SelRange* Selected = GetApplication()->FindSelection(); BOOL ok = (Selected != NULL); // Start the op BeginSlowJob(); if (ok) ok = DoStartSelOp(TRUE,TRUE); // Check with the selrange it is ok to run this op ObjChangeFlags cFlags; ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this); if (ok) { if (!Selected->AllowOp(&ObjChange)) { EndSlowJob(); FailAndExecute(); End(); return; } } Node* pNode = Selected->FindFirst(); NodePath* ThisPath = NULL; //Document* pDocument = GetWorkingDoc(); while (ok && (pNode != NULL)) { // we're only interested in NodePaths which have selected points BOOL DoThisNode = pNode->IsNodePath(); //if (DoThisNode) // DoThisNode = (((NodePath*)pNode)->InkPath.IsSubSelection()); if (DoThisNode) DoThisNode = (((NodePath*)pNode)->IsPathAllowable()); if ( DoThisNode ) { // for convenience, cast the pointer to a pointer to a NodePath ThisPath = (NodePath*)pNode; // First get pointers to the arrays PathVerb* Verbs = NULL; PathFlags* Flags = NULL; DocCoord* Coords = NULL; ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags); INT32 NumCoords = ThisPath->InkPath.GetNumCoords(); // BOOL PrevSelected = FALSE; // INT32 PrevPos = 0; ObjChangeFlags cFlags; cFlags.TransformNode = TRUE; ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,ThisPath,this); if (!ThisPath->AllowOp(&ObjChange, TRUE)) { return; } // Set the NeedToRender flags for (INT32 loop = 0; loop < NumCoords; loop++) { if (Flags[loop].IsEndPoint && Flags[loop].IsSelected) Flags[loop].NeedToRender = TRUE; else Flags[loop].NeedToRender = FALSE; } // Force a re-draw of the place where the path used to be if (ok) ok = (RecalcBoundsAction::DoRecalc(this, &UndoActions, ThisPath, TRUE) != AC_FAIL); DoReversePath (ThisPath); // Force a redraw of the place where the path is now. if (ok) ok = (RecordBoundsAction::DoRecord(this, &UndoActions, ThisPath, TRUE) != AC_FAIL); } pNode = Selected->FindNext(pNode); } if (ok) { ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this); if (!UpdateChangedNodes(&ObjChange)) { FailAndExecute(); End(); return; } } EndSlowJob(); if (!ok) { FailAndExecute(); InformError(); } End(); }
/******************************************************************************************** > void OpMoveToLayer::Do(OpDescriptor*) Author: Simon_Knight (Xara Group Ltd) <*****@*****.**> Created: 3/5/00 Purpose: This takes the selection and moves it to the active layer. This is a more powerful operation than the move forward/backward a layer ********************************************************************************************/ void OpMoveToLayer::Do(OpDescriptor*) { if (DoStartSelOp(FALSE,TRUE)) { // get the selection Range Sel(*(GetApplication()->FindSelection())); // set the range flags so it includes shadow and bevel manager nodes RangeControl rg = Sel.GetRangeControlFlags(); rg.PromoteToParent = TRUE; Sel.Range::SetRangeControl(rg); // Prepare an ObjChangeParam so we can mark which nodes will allow this op to happen to them ObjChangeFlags cFlags; cFlags.MoveNode = TRUE; ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this); // add items directly after the layer node as its first child Node * pTail = (Node *) (Document::GetCurrent()->GetInsertionPosition()); AttachNodeDirection TailAttachDirection = PREV; Spread* pSpread = Document::GetSelectedSpread(); if (!pTail) { if (pSpread) { pTail = pSpread->FindActiveLayer(); // AttachNodeDirection TailAttachDirection = LASTCHILD; <--- AMB removed this and inserted the next line 2006-04-10 presuming bug TailAttachDirection = LASTCHILD; } else { FailAndExecute(); End(); return; // nowhere to put the nodes } } // Mark nodes that will allow this to happen, and error if no nodes will let it happen if (!Sel.AllowOp(&ObjChange)) { FailAndExecute(); End(); return; // op not allowed } // get a list from which to move the nodes (fixes job #10781 - the re-selection of // moved nodes caused an infinite loop) List* pNodeList = Sel.MakeListOfNodes(FALSE); NodeListItem* CurItem = (NodeListItem*)(pNodeList->GetHead()); while (CurItem) { Node* pNode = CurItem->pNode; // Make sure the current owner Layer is told about the changes // and given the chance to release any cached info it may be // holding about the selected object // (I know that the original position coincides with the destination position // but this is hte simplest way to get the original parent layer uncached // and to get a record in the undo history so that the layer cacheing will // be dealt with properly during gundo/redo) DoInvalidateNodeRegion((NodeRenderableBounded*) pNode, TRUE, FALSE); // localise attribs for this node DoLocaliseForAttrChange((NodeRenderableInk*) pNode, (AttrTypeSet *)NULL, (ObjectSet*) NULL); DoMoveNode(pNode, pTail, TailAttachDirection); // factor out common attribs if (pNode->IsCompound()) DoFactorOutCommonChildAttributes((NodeRenderableInk*) pNode); else DoFactorOutAfterAttrChange((NodeRenderableInk*) pNode, (AttrTypeSet *)NULL); // make the nodes region be redrawn DoInvalidateNodeRegion((NodeRenderableBounded*) pNode, TRUE, FALSE); CurItem = (NodeListItem*)(pNodeList->GetNext(CurItem)); } // delete the the list objects pNodeList->DeleteAll(); delete pNodeList; // the selection will have changed - after all we just deleted it BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::NONCOLOURATTCHANGED)); GetApplication()->UpdateSelection(); ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this); UpdateChangedNodes(&ObjChange); // end the op End(); // update the bars DialogBarOp::SetSystemStateChanged(); DialogBarOp::UpdateStateOfAllBars(); } else { // give up and go home FailAndExecute(); End(); } }
/******************************************************************************************** > void OpConvertToBitmap::Do(OpDescriptor*) Author: Will_Cowling (Xara Group Ltd) <*****@*****.**> Created: 11/6/96 Inputs: - Purpose: Convert the selection into a bitmap Errors: - SeeAlso: - ********************************************************************************************/ void OpConvertToBitmap::Do(OpDescriptor*) { // We want to include bevel/contour/shadow controller nodes in our bitmap-copy // deliberations, so set PromoteToParent on a copy of the app's SelRange. SelRange Sel(*(GetApplication()->FindSelection())); RangeControl rg = Sel.GetRangeControlFlags(); rg.PromoteToParent = TRUE; Sel.Range::SetRangeControl(rg); // Find the first node which is selected Node* CurrentNode = Sel.FindFirst(); ERROR3IF(CurrentNode == NULL, "Called ConvertToBitmap with no nodes selected"); // In the retail build it is best to do nothing if we find there are no selected nodes if (CurrentNode != NULL) // No nodes selected so End { // We need to invalidate the region if (!DoInvalidateNodesRegions(Sel, TRUE)) goto EndOperation; if (!DoStartSelOp(FALSE,FALSE)) // Try to record the selection state , don't goto EndOperation; // render the blobs though // Create a special Bitmap filter, that creates a bitmap // and puts it in the tree MakeBitmapFilter* pBitmapFilter = new MakeBitmapFilter(); if (pBitmapFilter == NULL) { FailAndExecute(); goto EndOperation; } KernelBitmap* pBitmapToCreate = NULL; if (!pBitmapFilter->DoCreateBitmap(this, Document::GetSelected(), &pBitmapToCreate)) { delete pBitmapFilter; FailAndExecute(); goto EndOperation; } if (!pBitmapFilter->InsertBitmapIntoDocument(this, pBitmapToCreate, Document::GetSelected())) { delete pBitmapToCreate; delete pBitmapFilter; FailAndExecute(); goto EndOperation; } delete pBitmapFilter; if (!DoInvalidateNodesRegions(*(GetApplication()->FindSelection()), TRUE)) { // We need to invalidate the region FailAndExecute(); goto EndOperation; } } EndOperation: SelRange* pRng = GetApplication()->FindSelection(); End(); }
/******************************************************************************************** > void OpMakeShapes::Do(OpDescriptor*) Author: Simon_Maneggio (Xara Group Ltd) <*****@*****.**> Created: 29/04/94 Inputs: OpDescriptor (unused) Outputs: - Returns: - Purpose: Performs the MakeShapes operation. ********************************************************************************************/ void OpMakeShapes::Do(OpDescriptor*) { // Obtain the current selections Range Selection(*GetApplication()->FindSelection()); RangeControl rg = Selection.GetRangeControlFlags(); rg.PromoteToParent = TRUE; Selection.Range::SetRangeControl(rg); // change the selection flags Node* CurrentNode = Selection.FindFirst(); BOOL Success = TRUE; ERROR3IF(CurrentNode == NULL, "Make shapes called with no nodes selected"); if (CurrentNode != NULL) // No nodes selected so End { // We need to invalidate the region if (Success) Success = DoInvalidateNodesRegions(Selection, TRUE, FALSE, FALSE, FALSE); // Don't recache // Try to record the selection state, don't render the blobs though if (Success) Success = DoStartSelOp(FALSE,FALSE); // The DoMakeShapes function does all the work while (Success && CurrentNode!=NULL) { Node* Next = Selection.FindNext(CurrentNode); // BODGE - since the group is selected and won't be replaced by anything else, no need to reselect it // this fixes a bug where make shapes on grouped text stories/molds/blends don't leave the parent group // selected but selects the objects inside! BOOL reselect = !IS_A(CurrentNode,NodeGroup) && !IS_A(CurrentNode,NodeBlend); // BOOL ok = TRUE; ObjChangeFlags cFlags(TRUE); ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,NULL); if (CurrentNode->AllowOp(&ObjChange)) { BecomeA BecomeAPath(BECOMEA_REPLACE,CC_RUNTIME_CLASS(NodePath), this, reselect); BecomeAPath.SetResultsStayInPlace(TRUE); Success = CurrentNode->DoBecomeA(&BecomeAPath); } CurrentNode = Next; } // We need to invalidate the region again for the new positions GetApplication()->FindSelection()->Update(); if (Success) Success = DoInvalidateNodesRegions(*GetApplication()->FindSelection(), TRUE); } if (!Success) { InformError(); FailAndExecute(); } End(); }