// $Id: opcntr.cpp 1282 2006-06-09 09:46:49Z alex $ /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE ================================XARAHEADERSTART=========================== Xara LX, a vector drawing and manipulation program. Copyright (C) 1993-2006 Xara Group Ltd. Copyright on certain contributions may be held in joint with their respective authors. See AUTHORS file for details. LICENSE TO USE AND MODIFY SOFTWARE ---------------------------------- This file is part of Xara LX. Xara LX is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. Xara LX and its component source files are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Xara LX (see the file GPL in the root directory of the distribution); if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ADDITIONAL RIGHTS ----------------- Conditional upon your continuing compliance with the GNU General Public License described above, Xara Group Ltd grants to you certain additional rights. The additional rights are to use, modify, and distribute the software together with the wxWidgets library, the wxXtra library, and the "CDraw" library and any other such library that any version of Xara LX relased by Xara Group Ltd requires in order to compile and execute, including the static linking of that library to XaraLX. In the case of the "CDraw" library, you may satisfy obligation under the GNU General Public License to provide source code by providing a binary copy of the library concerned and a copy of the license accompanying it. Nothing in this section restricts any of the rights you have under the GNU General Public License. SCOPE OF LICENSE ---------------- This license applies to this program (XaraLX) and its constituent source files only, and does not necessarily apply to other Xara products which may in part share the same code base, and are subject to their own licensing terms. This license does not apply to files in the wxXtra directory, which are built into a separate library, and are subject to the wxWindows license contained within that directory in the file "WXXTRA-LICENSE". This license does not apply to the binary libraries (if any) within the "libs" directory, which are subject to a separate license contained within that directory in the file "LIBS-LICENSE". ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS ---------------------------------------------- Subject to the terms of the GNU Public License (see above), you are free to do whatever you like with your modifications. However, you may (at your option) wish contribute them to Xara's source tree. You can find details of how to do this at: http://www.xaraxtreme.org/developers/ Prior to contributing your modifications, you will need to complete our contributor agreement. This can be found at: http://www.xaraxtreme.org/developers/contribute/ Please note that Xara will not accept modifications which modify any of the text between the start and end of this header (marked XARAHEADERSTART and XARAHEADEREND). MARKS ----- Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara designs are registered or unregistered trademarks, design-marks, and/or service marks of Xara Group Ltd. All rights in these marks are reserved. Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. http://www.xara.com/ =================================XARAHEADEREND============================ */ // Implementation of the Contour operations #include "camtypes.h" //#include "selop.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "opcntr.h" //#include "cntres.h" //#include "node.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "ink.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "nodecomp.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "group.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "nodecntr.h" #include "ncntrcnt.h" #include "progress.h" //#include "view.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "lineattr.h" //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "attrval.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "nodepath.h" #include "attrmap.h" #include "gclips.h" //#include "trans2d.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "opbevel.h" #include "nodecont.h" #include "objchge.h" #include "blndtool.h" //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "nodebldr.h" #include "ppbevel.h" // for bevel helpers #include "fitcurve.h" #include "rsmooth.h" #include "nodeblnd.h" #include "brshattr.h" #include "strkattr.h" #include "pbecomea.h" #include "slicehelper.h" //#include "simon.h" // for "no objects selected" Description string #include "ppstroke.h" #include "brshbeca.h" #include "ophist.h" CC_IMPLEMENT_DYNCREATE(CreateContourParam, OpParam) CC_IMPLEMENT_DYNCREATE(OpCreateContour, SelOperation) CC_IMPLEMENT_DYNCREATE(OpChangeContourWidth, UndoableOperation) CC_IMPLEMENT_DYNCREATE(OpRemoveContour, SelOperation) CC_IMPLEMENT_DYNCREATE(RegenerateContourAction, Action) CC_IMPLEMENT_DYNCREATE(ChangeContourWidthAction, Action) CC_IMPLEMENT_DYNCREATE(ChangeContourToOuterAction, Action) CC_IMPLEMENT_DYNCREATE(ChangeContourToInnerAction, Action) CC_IMPLEMENT_DYNCREATE(OpChangeContourToInner, SelOperation) CC_IMPLEMENT_DYNCREATE(OpChangeContourToOuter, SelOperation) CC_IMPLEMENT_DYNCREATE(OpChangeContourSteps, SelOperation) CC_IMPLEMENT_DYNCREATE(ChangeContourStepsAction, Action) CC_IMPLEMENT_DYNCREATE(OpChangeContourColourType, SelOperation) CC_IMPLEMENT_DYNCREATE(ChangeContourColourTypeAction, Action) CC_IMPLEMENT_DYNCREATE(OpChangeContourAttributeProfile, SelOperation) CC_IMPLEMENT_DYNCREATE(ChangeContourAttributeProfileAction, Action) CC_IMPLEMENT_DYNCREATE(OpChangeContourObjectProfile, SelOperation) CC_IMPLEMENT_DYNCREATE(ChangeContourObjectProfileAction, Action) CC_IMPLEMENT_DYNCREATE(OpChangeContourStepDistance, SelOperation) CC_IMPLEMENT_DYNCREATE(OpConvertPathToShapes, SelOperation) CC_IMPLEMENT_DYNCREATE(OpToggleContourInsetPath, SelOperation) CC_IMPLEMENT_DYNCREATE(ToggleInsetPathAction, Action) DECLARE_SOURCE( "$Revision: 1282 $" ); #define new CAM_DEBUG_NEW ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // Contour ops implementation /******************************************************************************************** > OpCreateContour::OpCreateContour() Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Purpose: Constructor. ********************************************************************************************/ OpCreateContour::OpCreateContour() { //TRACEUSER( "MarkH", _T("Just Made a OpCreateContour Class!\n")); } /******************************************************************************************** > OpCreateContour::~OpCreateContour() Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Purpose: Destructor. ********************************************************************************************/ OpCreateContour::~OpCreateContour() { //TRACEUSER( "MarkH", _T("Just Killed OpCreateContour Class!!!\n")); } /******************************************************************************************** > virtual void OpCreateContour::Do(OpDescriptor *pOpDesc) Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Inputs: pOpDesc - OpDescriptor - unused Outputs: - Returns: - Purpose: The do function. Applys a Bevel to the selection in the current document ********************************************************************************************/ void OpCreateContour::Do(OpDescriptor *pOpDesc) { End(); } /******************************************************************************************** > void OpCreateContour::DoWithParam(OpDescriptor* pOp, OpParam* pParam) Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Inputs: Outputs: - Returns: - Purpose: Applys a Bevel to the selected node after a mouse click ********************************************************************************************/ void OpCreateContour::DoWithParam(OpDescriptor* pOp, OpParam* pParam) { DoStartSelOp(TRUE, TRUE); ObjChangeFlags cFlags; cFlags.RegenerateNode = TRUE; ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this); String_64 StatusString; StatusString.Load(_R(IDS_CONTOUR_CREATE_STATUS_STRING)); BeginSlowJob(-1, TRUE, &StatusString); String_256 s(StatusString); GetApplication()->UpdateStatusBarText(&s, FALSE); CreateContourParam * pCCP = (CreateContourParam *)pParam; List * pNodeList = pCCP->m_pNodeList; // first, remove all contours from the list List ContourList; NodeListItem * pItem = (NodeListItem *)pNodeList->GetHead(); NodeListItem * pContourItem = NULL; BOOL ok = TRUE; NodeHidden * pHidden = NULL; while (pItem) { BevelTools::GetAllNodesUnderNode(pItem->pNode, &ContourList, CC_RUNTIME_CLASS(NodeContourController)); if (!ContourList.IsEmpty()) { TRACEUSER( "DavidM", _T("Found non-empty contour list\n")); pContourItem = (NodeListItem *)ContourList.GetHead(); while (pContourItem) { // remove the contour node, and promote all children // invalidate the node if (ok) ok = DoInvalidateNodeRegion((NodeRenderableInk *)pContourItem->pNode, TRUE); // factor out the child attributes if (ok) ok = DoLocaliseCommonAttributes((NodeRenderableInk *)pContourItem->pNode, TRUE); // now, move all child nodes upwards (except for the 'needs parent' nodes) Node * pChild = pContourItem->pNode->FindFirstChild(); Node * pNextChild = NULL; while (pChild) { pNextChild = pChild->FindNext(); if (ok && !pChild->NeedsParent(pContourItem->pNode) && !pChild->IsAnAttribute()) ok = DoMoveNode(pChild, pContourItem->pNode, PREV); pChild = pNextChild; } // hide the original node if (ok) ok = DoHideNode(pContourItem->pNode, TRUE, &pHidden, FALSE); // move on pContourItem = (NodeListItem *)ContourList.GetNext(pContourItem); } ContourList.DeleteAll(); if (ok) ok = DoFactorOutCommonChildAttributes((NodeRenderableInk *)pItem->pNode); } pItem = (NodeListItem *)pNodeList->GetNext(pItem); } pItem = (NodeListItem *)pNodeList->GetHead(); // CCAttrMap * pAttrMap = NULL; AttrLineWidth * pLineWidthAttr = NULL; AttrStrokeColour * pStrokeColourAttr = NULL; // AttrStartArrow * pAttrStartArrow = NULL; // AttrEndArrow * pAttrEndArrow = NULL; // FlatFillAttribute * pFillAttr = NULL; // StrokeColourAttribute * pStrokeAttr = NULL; // NodeAttribute * pAttr = NULL; DocColour StrokeColour; MILLIPOINT LineWidth = 0; // INT32 Red = 0; // INT32 Blue = 0; // INT32 Green = 0; Path ArrowPath; ArrowPath.Initialise(); while (pItem && ok) { if (pItem->pNode->IsNodePath() && pItem->pNode->AllowOp(&ObjChange)) { // for all closed paths in the selection, copy their stroke attribute // colour as a fill attribute NodePath * pPathNode = (NodePath *)pItem->pNode; // find out if the path is closed if (!pPathNode->InkPath.IsSubPathClosed(0)) { // first, localise all the common attributes if (ok) ok = DoLocaliseForAttrChange(pPathNode, (AttrTypeSet *)NULL, (ObjectSet *)NULL); // get the line width & the stroke colour out of the node pLineWidthAttr = (AttrLineWidth *)pPathNode->FindFirstChild(CC_RUNTIME_CLASS(AttrLineWidth)); pStrokeColourAttr = (AttrStrokeColour *)pPathNode->FindFirstChild(CC_RUNTIME_CLASS(AttrStrokeColour)); if (pLineWidthAttr) LineWidth = pLineWidthAttr->Value.LineWidth; if (pStrokeColourAttr) StrokeColour = pStrokeColourAttr->Value.Colour; // eliminate all fills from this node if (ok) ok = DoRemoveAttrTypeFromSubtree(pPathNode, CC_RUNTIME_CLASS(AttrFillGeometry)); // create a new flat fill attribute & apply it to this node AttrFlatColourFill * pFlatFill = NULL; ALLOC_WITH_FAIL(pFlatFill, new AttrFlatColourFill, this); pFlatFill->SetStartColour(&StrokeColour); if (ok) { // [Phil, 17-09-2005] // NO! // Geez, DMc, you can't cast an AttrFlatColourFill* to a NodeRenderableBounded*! // That means that you can't call DoInsertNewNode, so we have to do the same thing // in essence directly... // ok = DoInsertNewNode((NodeRenderableBounded *)pFlatFill, pPathNode, // FIRSTCHILD, FALSE, FALSE, FALSE, FALSE); pFlatFill->AttachNode(pPathNode, FIRSTCHILD); HideNodeAction* UndoHideNodeAction; if (HideNodeAction::Init(this, this->GetUndoActions(), pFlatFill, TRUE, (Action**)(&UndoHideNodeAction)) == AC_FAIL) { pFlatFill->CascadeDelete(); delete pFlatFill; pFlatFill = FALSE; FailAndExecute(); End(); return; } } // factor out all the attributes if (ok) ok = DoFactorOutAfterAttrChange(pPathNode, (AttrTypeSet *)NULL); } } pItem = (NodeListItem *)pNodeList->GetNext(pItem); } if (!ok) { FailAndExecute(); End(); return; } // have we any shadow nodes present ? // if so, build a new list pItem = (NodeListItem *)pNodeList->GetHead(); NodeListItem * pNewItem = NULL; Node * pNode = NULL; Node * pShadowNode = NULL; List ListToContour; while (pItem) { // find out if any parents are shadow controllers pNode = pItem->pNode; pShadowNode = NULL; while (pNode) { if (pNode->IS_KIND_OF(NodeShadowController)) pShadowNode = pNode; // we've found a shadow controller node pNode = pNode->FindParent(); } // do we have a shadow node ? if so, make all non-needs parent children // be contoured if (pShadowNode) { // first, localise all attributes DoLocaliseCommonAttributes((NodeShadowController *)pShadowNode, TRUE); // add children to the contour list pNode = pShadowNode->FindFirstChild(); while (pNode) { if (!pNode->NeedsParent(pShadowNode)) { if (pNode->IsAnObject()) { ALLOC_WITH_FAIL(pNewItem, new NodeListItem(pNode), this); ListToContour.AddTail(pNewItem); } } pNode = pNode->FindNext(); } } else { ALLOC_WITH_FAIL(pNewItem, new NodeListItem(pItem->pNode), this); ListToContour.AddTail(pNewItem); } pItem = (NodeListItem *)pNodeList->GetNext(pItem); } // create the tree factory ContourNodeTreeFactory * pFactory = NULL; ALLOC_WITH_FAIL(pFactory, new ContourNodeTreeFactory, this); pFactory->SetNumberOfSteps(pCCP->m_Steps); pFactory->SetWidth(pCCP->m_Width); pFactory->SetInsetPathFlag(pCCP->m_bInsetPath); List SingleNodeList; // handle each node individually pItem = (NodeListItem *)ListToContour.GetHead(); NodeBlender * pBlender = NULL; while (pItem) { ALLOC_WITH_FAIL(pNewItem, new NodeListItem(pItem->pNode), this); SingleNodeList.AddTail(pNewItem); NodeContourController * pContourNode = (NodeContourController *)pFactory->CreateNode(&SingleNodeList, this); SingleNodeList.DeleteAll(); // do we have a parent shadow node ? if so, regenerate if (!pContourNode) { FailAndExecute(); End(); ListToContour.DeleteAll(); return; } // check for a blend needing to be re-initialised pBlender = (NodeBlender *)pContourNode->FindNext(CC_RUNTIME_CLASS(NodeBlender)); if (pBlender) { if (InitBlendAction::InitOnBlender(this, GetUndoActionList(), pBlender, TRUE, TRUE) != AC_OK) ERROR2RAW("Couldn't Initialise blend action"); pBlender->Reinit(pContourNode, pBlender->GetNodeEnd(), FALSE); } else { pBlender = (NodeBlender *)pContourNode->FindPrevious(CC_RUNTIME_CLASS(NodeBlender)); if (pBlender) { if (InitBlendAction::InitOnBlender(this, GetUndoActionList(), pBlender, TRUE, TRUE) != AC_OK) ERROR2RAW("Couldn't Initialise blend action"); pBlender->Reinit(pBlender->GetNodeStart(), pContourNode, FALSE); } } if (pBlender) { NodeBlend* ptrBlend = (NodeBlend*) pBlender->FindParent (); ERROR3IF (!IS_A (ptrBlend, NodeBlend), "NodeBlend is not a NodeBlend!"); BOOL done = FALSE; NodeBlender* ptrNode = ptrBlend->FindFirstBlender (); while (!done) { if (ptrNode != pBlender) { if (ptrNode->GetNodeStart () == pItem->pNode) { if (InitBlendAction::InitOnBlender(this, GetUndoActionList(), ptrNode, TRUE, TRUE) != AC_OK) ERROR2RAW("Couldn't Initialise blend action"); if (pContourNode) ptrNode->Reinit(pContourNode, NULL, FALSE); } if (ptrNode->GetNodeEnd () == pItem->pNode) { if (InitBlendAction::InitOnBlender(this, GetUndoActionList(), ptrNode, TRUE, TRUE) != AC_OK) ERROR2RAW("Couldn't Initialise blend action"); if (pContourNode) ptrNode->Reinit(NULL, pContourNode, FALSE); } } ptrNode = ptrBlend->FindNextBlender (ptrNode); if (!ptrNode) done = TRUE; } } pNode = pContourNode->FindParent(); while (pNode) { pNode->AllowOp(&ObjChange); pNode = pNode->FindParent(); } // deselect all nodes under the contour node, and select all original nodes if (!pCCP->m_bInsetPath) { pNode = pContourNode->FindFirstChild(); pContourNode->SetSelected(FALSE); while (pNode) { if (pNode->IsAnObject() && !pNode->NeedsParent(NULL)) pNode->SetSelected(TRUE); pNode = pNode->FindNext(); } } else { NodeContour* pContour = pContourNode->GetContourNode(); ERROR3IF(!pContour,"Failed to get the contour node from the controller node!"); ////////// NodeRenderableInk* pChild = pContourNode->FindFirstChildInk(); CCAttrMap AttrMap; if(pChild) ((NodeRenderableInk *)pChild)->FindAppliedAttributes(&AttrMap); // Create and initialize a new NodePath to hold the inset path! NodePath* pNewPath; ALLOC_WITH_FAIL(pNewPath, new NodePath, this); pNewPath->InkPath.Initialise(); DoInvalidateNodeRegion(pContourNode,FALSE); // Create the DoBecomeA Function and call it on the controller BecomeA BecomeAReplace(BECOMEA_REPLACE, CC_RUNTIME_CLASS(NodePath), this, FALSE); pContour->DoBecomeA(&BecomeAReplace); // Now get the relavent path from the group of path nodes NodePath* pPathToCopy = NULL; if(pContourNode->IsContourAnOuterContour()) pPathToCopy = (NodePath*)pContourNode->FindFirstChild(CC_RUNTIME_CLASS(NodePath)); else pPathToCopy = (NodePath*)pContourNode->FindLastChild(CC_RUNTIME_CLASS(NodePath)); pNewPath->InkPath.CloneFrom(pPathToCopy->InkPath); // now Initialize the flag array with the new Path and insert it after the group node! pNewPath->InkPath.InitialiseFlags(0, pNewPath->InkPath.GetNumCoords()); DoInsertNewNode(pNewPath, pContourNode, NEXT, TRUE, FALSE, TRUE, TRUE); pNewPath->InkPath.IsFilled = TRUE; // Make sure we have the correct attributes applied to our new path and make it selected! AttrMap.ApplyAttributesToNode(pNewPath); pNewPath->NormaliseAttributes(); pNewPath->SetSelected(TRUE); DoHideNode(pContourNode, TRUE, &pHidden, TRUE); ////////// /* pContourNode->SetSelected(FALSE); pContour->SetSelected(TRUE); // do a do become a for the contour node BecomeA BecomeAReplace(BECOMEA_REPLACE, CC_RUNTIME_CLASS(NodePath), this, FALSE); pContourNode->DoBecomeA(&BecomeAReplace); */ } SliceHelper::AddNamesToController(this,pContourNode); pItem = (NodeListItem *)ListToContour.GetNext(pItem); } ListToContour.DeleteAll(); delete pFactory; pFactory = NULL; ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this); UpdateChangedNodes(&ObjChange, Document::GetSelectedSpread()); GetApplication()->UpdateSelection(); End(); } /******************************************************************************************** > BOOL OpCreateContour::Declare() Author: Peter_Arnold (Xara Group Ltd) Created: 16/11/94 Returns: TRUE if all went OK, False otherwise Purpose: Adds the operation to the list of all known operations ********************************************************************************************/ BOOL OpCreateContour::Declare() { return (RegisterOpDescriptor( 0, _R(IDS_CREATECONTOUROP), CC_RUNTIME_CLASS(OpCreateContour), OPTOKEN_CREATECONTOUR, OpCreateContour::GetState)); } /******************************************************************************************** > OpState OpCreateContour::GetState(String_256* Description, OpDescriptor*) Author: Peter_Arnold (Xara Group Ltd) Created: 16/11/94 Outputs: - Returns: Ungreyed, Unticked Purpose: Find out the state of the new regular shape at the specific time ********************************************************************************************/ OpState OpCreateContour::GetState(String_256* Description, OpDescriptor*) { OpState Blobby; if (Description) Description->Load(_R(IDS_CONTOUR_CREATE_STATUS_STRING)); return Blobby; } ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// ////////// OpRemoveContour class ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // Bevel ops implementation /******************************************************************************************** > OpRemoveContour::OpRemoveContour() Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Purpose: Constructor. ********************************************************************************************/ OpRemoveContour::OpRemoveContour() { //TRACEUSER( "MarkH", _T("Just Made a OpRemoveContour Class!\n")); } /******************************************************************************************** > OpRemoveContour::~OpRemoveContour() Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Purpose: Destructor. ********************************************************************************************/ OpRemoveContour::~OpRemoveContour() { //TRACEUSER( "MarkH", _T("Just Killed OpRemoveContour Class!!!\n")); } /******************************************************************************************** > virtual void OpRemoveContour::Do(OpDescriptor *pOpDesc) Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Inputs: pOpDesc - OpDescriptor - unused Outputs: - Returns: - Purpose: The do function. Applys a Bevel to the selection in the current document ********************************************************************************************/ void OpRemoveContour::Do(OpDescriptor *pOpDesc) { // CGS: (13/7/2000) I have ammended this function to take into account multiple NodeBlends // since the contour may be part of more than one blend! // get all the contour nodes DoStartSelOp(TRUE, TRUE); ObjChangeFlags cFlags; ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this); String_64 s(_T("Removing contour - please wait")); BeginSlowJob(-1, TRUE, &s); List NodeList; BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeContourController), TRUE); //List BlendList; //BevelTools::BuildListOfSelectedNodes(&BlendList, CC_RUNTIME_CLASS(NodeBlender), TRUE); // run through these nodes, eliminating them NodeListItem * pItem = (NodeListItem *)NodeList.GetHead(); Node * pChildNode = NULL; Node * pNextNode = NULL; NodeHidden * pHidden = NULL; Node * pParent = NULL; BOOL ok = TRUE; NodeContourController * pControl = NULL; NodeBlender * pBlender = NULL; BOOL bBlendBefore = FALSE; BOOL bBlendAfter = FALSE; // for blends NodeRenderableInk *pRenderableNode = NULL; while (pItem) { pControl = (NodeContourController *)pItem->pNode; // try to find a blender node, as if there's one present we // need to reinitialise it pBlender = (NodeBlender *)pControl->FindNext(CC_RUNTIME_CLASS(NodeBlender)); bBlendBefore = FALSE; bBlendAfter = FALSE; if (pBlender) { bBlendBefore = TRUE; } else { pBlender = (NodeBlender *)pControl->FindPrevious(CC_RUNTIME_CLASS(NodeBlender)); if (pBlender) { bBlendAfter = TRUE; } } // get the parent for child change messaging pParent = pControl->FindParent(); // invalidate the region if (ok) ok = DoInvalidateNodeRegion(pControl, TRUE); // factor out the common child attributes if (ok) ok = DoLocaliseCommonAttributes(pControl, TRUE); if (ok) SliceHelper::RemoveNamesFromController(this,pControl); pChildNode = pControl->FindFirstChild(); // move all nodes to being siblings of the controller node, except for the // contour node itself while (pChildNode) { pNextNode = pChildNode->FindNext(); if (pChildNode->IsAnObject() && !pChildNode->IS_KIND_OF(NodeContour)) { if (ok) { ok = DoMoveNode(pChildNode, pControl, PREV); } if (ok) ok = DoSelectNode((NodeRenderableInk *)pChildNode); if (ok) ok = DoFactorOutAfterAttrChange((NodeRenderableInk *)pChildNode, (AttrTypeSet *)NULL); } pChildNode = pNextNode; } pParent = pControl->FindParent(); // agh why do i have to mess with a list just to add this action into the undo list? List ContList; NodeListItem * pActionItem = NULL; RegenerateContourAction* pRegenAction = NULL; ALLOC_WITH_FAIL(pActionItem, new NodeListItem, this); pActionItem->pNode = pControl; ContList.AddTail(pActionItem); RegenerateContourAction::Init(this, GetUndoActionList(),&ContList,&pRegenAction, TRUE); ContList.DeleteAll(); // now, hide the controller node if (ok) ok = DoHideNode(pControl, TRUE, &pHidden, FALSE); // reinit the blends (if necessary) if (ok) { if (bBlendBefore) { if (InitBlendAction::InitOnBlender(this, GetUndoActionList(), pBlender, TRUE, TRUE) != AC_OK) { ERROR2RAW("Couldn't Initialise blend action"); } // reinit the node pRenderableNode = (NodeRenderableInk *)pBlender->FindPrevious(CC_RUNTIME_CLASS(NodeRenderableInk)); if (pRenderableNode) { pBlender->Reinit(pRenderableNode, pBlender->GetNodeEnd(), FALSE); } } else if (bBlendAfter) { if (InitBlendAction::InitOnBlender(this, GetUndoActionList(), pBlender, TRUE, TRUE) != AC_OK) { ERROR2RAW("Couldn't Initialise blend action"); } // reinit the node pRenderableNode = (NodeRenderableInk *)pBlender->FindNext(CC_RUNTIME_CLASS(NodeRenderableInk)); if (pRenderableNode) { pBlender->Reinit(pBlender->GetNodeStart(), pRenderableNode, FALSE); } } if (pBlender) { NodeBlend* ptrBlend = (NodeBlend*) pBlender->FindParent (); ERROR3IF (!IS_A (ptrBlend, NodeBlend), "NodeBlend is not a NodeBlend!"); BOOL done = FALSE; NodeBlender* ptrNode = ptrBlend->FindFirstBlender (); while (!done) { if (ptrNode != pBlender) { if (ptrNode->GetNodeStart () == pControl) { if (InitBlendAction::InitOnBlender(this, GetUndoActionList(), ptrNode, TRUE, TRUE) != AC_OK) { ERROR2RAW("Couldn't Initialise blend action"); } if (pRenderableNode) { ptrNode->Reinit(pRenderableNode, NULL, FALSE); } } if (ptrNode->GetNodeEnd () == pControl) { if (InitBlendAction::InitOnBlender(this, GetUndoActionList(), ptrNode, TRUE, TRUE) != AC_OK) { ERROR2RAW("Couldn't Initialise blend action"); } if (pRenderableNode) { ptrNode->Reinit(NULL, pRenderableNode, FALSE); } } } ptrNode = ptrBlend->FindNextBlender (ptrNode); if (!ptrNode) { done = TRUE; } } } } // Karim 19/07/2000 // the parent's bounds will have changed, so tell them so. if (pParent->IsBounded()) // paranoia code - this is always true. ((NodeRenderableBounded*)pParent)->InvalidateBoundingRect(); // update all the changed nodes on the parent of the contour // ObjChangeFlags flgs(FALSE, FALSE, FALSE, TRUE); // flgs.RegenerateNode = TRUE; // ObjChangeParam OP(OBJCHANGE_FINISHED, flgs, NULL, this, OBJCHANGE_CALLEDBYOP); while (pParent) { pParent->AllowOp(&ObjChange); // pParent->OnChildChange(&OP); pParent = pParent->FindParent(); } // go onto the next item pItem = (NodeListItem *)NodeList.GetNext(pItem); } NodeList.DeleteAll(); if (!ok) { FailAndExecute(); } ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this); UpdateChangedNodes(&ObjChange, Document::GetSelectedSpread()); GetApplication()->UpdateSelection(); End(); } /******************************************************************************************** > void OpRemoveContour::DoWithParam(OpDescriptor* pOp, OpParam* pParam) Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Inputs: Outputs: - Returns: - Purpose: Applys a Bevel to the selected node after a mouse click ********************************************************************************************/ void OpRemoveContour::DoWithParam(OpDescriptor* pOp, OpParam* pParam) { End(); } /******************************************************************************************** > BOOL OpRemoveContour::Declare() Author: Peter_Arnold (Xara Group Ltd) Created: 16/11/94 Returns: TRUE if all went OK, False otherwise Purpose: Adds the operation to the list of all known operations ********************************************************************************************/ BOOL OpRemoveContour::Declare() { return (RegisterOpDescriptor( 0, _R(IDS_REMOVECONTOUROP), CC_RUNTIME_CLASS(OpRemoveContour), OPTOKEN_REMOVECONTOUR, OpRemoveContour::GetState, 0, _R(IDBBL_REMOVECONTOUR), 0)); } /******************************************************************************************** > OpState OpRemoveContour::GetState(String_256* Description, OpDescriptor*) Author: Peter_Arnold (Xara Group Ltd) Created: 16/11/94 Outputs: - Returns: Ungreyed, Unticked Purpose: Find out the state of the new regular shape at the specific time ********************************************************************************************/ OpState OpRemoveContour::GetState(String_256* Description, OpDescriptor*) { OpState State(FALSE,TRUE); // It's not ticked, but it is greyed by default // Get an ObjChangeParam ready so we can tell the selected blend's parents what we hope to do // to the blend (i.e. replace it with other nodes). ObjChangeFlags cFlags; cFlags.MultiReplaceNode = TRUE; ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,NULL); // BOOL Denied = FALSE; List NodeList; BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeContourController), TRUE); if (NodeList.IsEmpty()) { State.Greyed = TRUE; } else { State.Greyed = FALSE; } NodeList.DeleteAll(); UINT32 IDS = 0; if (IDS == 0) IDS = _R(IDS_REMOVECONTOUR); *Description = String_256(IDS); return State; } //////////////////////////////////////////////////////////////////// // RegenerateContourAction class implementation /******************************************************************************************** > RegenerateContourAction::RegenerateContourAction() Author: Olivier_Gascoin (Xara Group Ltd) Created: 07/01/97 Inputs: - Outputs: - Returns: - Purpose: Constructor for the action Errors: - SeeAlso: - ********************************************************************************************/ RegenerateContourAction::RegenerateContourAction() { m_pNodes = NULL; m_bCache = FALSE; } /******************************************************************************************** > ActionCode RegenerateContourAction::Init( Operation* pOp, ActionList* pActionList, List * pNodes ChangePositionShadowXAction** ppNewAction); Author: David_McClarnon (Xara Group Ltd) Created: 17/3/99 Inputs: pOp = ptr to the operation to which this action belongs pActionList = ptr to action list to which this action should be added pNodes = ptr to node list containing the NodeBevel nodes to be regenerated Outputs: ppNewAction = ptr to a ptr to an action, allowing the function to return a pointer to the created action Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: This is the function which creates an instance of this action. If there is no room in the undo buffer (which is determined by the base class Init function called within) the function will either return AC_NO_RECORD which means the operation can continue, but no undo information needs to be stored, or AC_OK which means the operation should continue AND record undo information. If the function returns AC_FAIL, there was not enough memory to record the undo information, and the user has decided not to continue with the operation. Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode RegenerateContourAction::Init(Operation* pOp, ActionList* pActionList, List * pNodes, RegenerateContourAction** ppNewAction, BOOL bCache) { UINT32 ActSize = sizeof(RegenerateContourAction); ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(RegenerateContourAction),(Action**)ppNewAction); // make a copy of the node list List * pCopyList = NULL; ALLOC_WITH_FAIL(pCopyList, new List, pOp); NodeListItem * pItem = (NodeListItem *)pNodes->GetHead(); NodeListItem * pCopyItem = NULL; while (pItem) { ALLOC_WITH_FAIL(pCopyItem, new NodeListItem, pOp); pCopyItem->pNode = pItem->pNode; pCopyList->AddTail(pCopyItem); pItem = (NodeListItem *)pNodes->GetNext(pItem); } (*ppNewAction)->m_pNodes = pCopyList; (*ppNewAction)->m_bCache = bCache; pItem = (NodeListItem *)pNodes->GetHead(); DocView * pView = DocView::GetCurrent(); Document * pDoc = Document::GetCurrent(); DocRect dr; if (Ac != AC_FAIL) { while (pItem) { if (pItem->pNode && !pItem->pNode->IsNodeHidden() && pItem->pNode->FindParent()!=NULL) { dr = dr.Union(((NodeRenderableBounded *)pItem->pNode)->GetBoundingRect()); if (pView && bCache) { GetApplication()->AddNodeToRegenList(pItem->pNode); } else { ((NodeContourController *)(pItem->pNode))->RegenerateNode(NULL, FALSE); } dr = dr.Union(((NodeRenderableBounded *)pItem->pNode)->GetBoundingRect()); } ((NodeRenderableInk*)pItem->pNode)->ReleaseCached(); pItem = (NodeListItem *)pNodes->GetNext(pItem); } if (pDoc) { if (Document::GetSelectedSpread()) { pDoc->ForceRedraw(Document::GetSelectedSpread(), dr); } } } (*ppNewAction)->m_OldRect = dr; // move my action to the head of the list // I have a problem, for certain ops we need to do the following, BUT for others // we don't (otherwise access violations occur). um? pActionList->RemoveItem(*ppNewAction); pActionList->AddHead(*ppNewAction); return Ac; } /******************************************************************************************** > ActionCode RegenerateContourAction::Execute(); Author: David_McClarnon (Xara Group Ltd) Created: 17/3/99 Inputs: - Outputs: - Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: Executes the action. Causes a regen of all bevels nodes in the action's list Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode RegenerateContourAction::Execute() { ActionCode Act; RegenerateContourAction* pAction; Act = RegenerateContourAction::Init(pOperation, pOppositeActLst, m_pNodes, &pAction, m_bCache); if (Act != AC_FAIL) { } return Act; } RegenerateContourAction::~RegenerateContourAction() { if (m_pNodes) { m_pNodes->DeleteAll(); delete m_pNodes; } } ///////////////////////////////////////////////////////////////////////////// // Contour ops implementation /******************************************************************************************** > OpChangeContourWidth::OpChangeContourWidth() Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Purpose: Constructor. ********************************************************************************************/ OpChangeContourWidth::OpChangeContourWidth() { //TRACEUSER( "MarkH", _T("Just Made a OpChangeContourWidth Class!\n")); } /******************************************************************************************** > OpChangeContourWidth::~OpChangeContourWidth() Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Purpose: Destructor. ********************************************************************************************/ OpChangeContourWidth::~OpChangeContourWidth() { //TRACEUSER( "MarkH", _T("Just Killed OpChangeContourWidth Class!!!\n")); } /******************************************************************************************** > virtual void OpChangeContourWidth::Do(OpDescriptor *pOpDesc) Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Inputs: pOpDesc - OpDescriptor - unused Outputs: - Returns: - Purpose: The do function. Applys a Bevel to the selection in the current document ********************************************************************************************/ void OpChangeContourWidth::Do(OpDescriptor *pOpDesc) { End(); } /******************************************************************************************** > void OpChangeContourWidth::DoWithParam(OpDescriptor* pOp, OpParam* pParam) Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Inputs: Outputs: - Returns: - Purpose: Applys a Bevel to the selected node after a mouse click ********************************************************************************************/ void OpChangeContourWidth::DoWithParam(OpDescriptor* pOp, OpParam* pParam) { // first, begin the operation ObjChangeFlags cFlags; ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this); String_64 StatusString; StatusString.Load(_R(IDS_CONTOUR_CREATE_STATUS_STRING)); BeginSlowJob(-1, TRUE, &StatusString); ChangeContourWidthParam * pCCW = (ChangeContourWidthParam *)pParam; // fire off an action ChangeContourWidthAction * pAction = NULL; if (ChangeContourWidthAction::Init(this, this->GetUndoActionList(), pCCW->m_pNodes, pCCW->m_Width, pCCW->m_bKeepDirection, &pAction) != AC_OK) { FailAndExecute(); return; } // do the child change messages NodeListItem * pItem = (NodeListItem *)pCCW->m_pNodes->GetHead(); Node * pNode = NULL; ObjChangeFlags flgs(FALSE, FALSE, FALSE, TRUE); Node * pContourNode = NULL; Node * pInsertNode = NULL; BOOL ok = TRUE; while (pItem) { // move all contour nodes in the list appropriately if (!pCCW->m_bKeepDirection) { pContourNode = pItem->pNode->FindFirstChild(CC_RUNTIME_CLASS(NodeContour)); if (pContourNode) pContourNode->AllowOp(&ObjChange); if (pCCW->m_Width < 0) { // outer contour nodes come before the nodes they are contouring pInsertNode = pItem->pNode->FindFirstChild(CC_RUNTIME_CLASS(NodeRenderableInk)); if (pInsertNode != pContourNode) { if (ok) ok = DoMoveNode(pContourNode, pInsertNode, PREV); } } else { // inner contour nodes come after the nodes they are contouring pInsertNode = pItem->pNode->FindLastChild(CC_RUNTIME_CLASS(NodeRenderableInk)); if (pInsertNode != pContourNode) { if (ok) ok = DoMoveNode(pContourNode, pInsertNode, NEXT); } } } pNode = pItem->pNode->FindParent(); // Ilan 7/5/00 // Inform geom linked attrs of the change. Nb outside the normal AllowOp mechanism NodeAttribute* pNA = pItem->pNode->FindFirstGeometryLinkedAttr(); while(pNA) { pNA->LinkedNodeGeometryHasChanged(this); pNA = pNA->FindNextGeometryLinkedAttr(); } while (pNode) { //ObjChangeParam OP(OBJCHANGE_FINISHED, flgs, pNode, this, OBJCHANGE_CALLEDBYOP); if (pNode->IsAnObject()) { //pNode->OnChildChange(&OP); pNode->AllowOp(&ObjChange); } pNode = pNode->FindParent(); } pItem = (NodeListItem *)pCCW->m_pNodes->GetNext(pItem); } ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this); UpdateChangedNodes(&ObjChange, Document::GetSelectedSpread()); End(); } /******************************************************************************************** > BOOL OpChangeContourWidth::Declare() Author: Peter_Arnold (Xara Group Ltd) Created: 16/11/94 Returns: TRUE if all went OK, False otherwise Purpose: Adds the operation to the list of all known operations ********************************************************************************************/ BOOL OpChangeContourWidth::Declare() { return (RegisterOpDescriptor( 0, _R(IDS_CHANGECONTOURWIDTHOP), CC_RUNTIME_CLASS(OpChangeContourWidth), OPTOKEN_CHANGECONTOURWIDTH, OpChangeContourWidth::GetState)); } /******************************************************************************************** > OpState OpChangeContourWidth::GetState(String_256* Description, OpDescriptor*) Author: Peter_Arnold (Xara Group Ltd) Created: 16/11/94 Outputs: - Returns: Ungreyed, Unticked Purpose: Find out the state of the new regular shape at the specific time ********************************************************************************************/ OpState OpChangeContourWidth::GetState(String_256* Description, OpDescriptor*) { OpState Blobby; return Blobby; } /******************************************************************************************** > void OpChangeContourWidth::GetOpName(String_256 *pName) Author: David_McClarnon (Xara Group Ltd) Created: 25/11/99 Outputs: - Returns: The name of the op Purpose: Returns the name of this op ********************************************************************************************/ void OpChangeContourWidth::GetOpName(String_256 *pName) { if (pName) pName->Load(_R(IDS_CHANGECONTOURWIDTHOPNAME)); } //////////////////////////////////////////////////////////////////// // ChangeContourWidthAction class implementation /******************************************************************************************** > ChangeContourWidthAction::ChangeContourWidthAction() Author: Olivier_Gascoin (Xara Group Ltd) Created: 07/01/97 Inputs: - Outputs: - Returns: - Purpose: Constructor for the action Errors: - SeeAlso: - ********************************************************************************************/ ChangeContourWidthAction::ChangeContourWidthAction() { } /******************************************************************************************** > ActionCode ChangeContourWidthAction::Init( Operation* pOp, ActionList* pActionList, List * pNodes ChangePositionShadowXAction** ppNewAction); Author: David_McClarnon (Xara Group Ltd) Created: 17/3/99 Inputs: pOp = ptr to the operation to which this action belongs pActionList = ptr to action list to which this action should be added pNodes = ptr to node list containing the NodeBevel nodes to be addressed NewWidth = the new width to set all nodes in the list to bKeepDirection = Whether to keep the direction (either inner or outer) when setting the widths, or just to take the width as passed in Outputs: ppNewAction = ptr to a ptr to an action, allowing the function to return a pointer to the created action Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: This is the function which creates an instance of this action. If there is no room in the undo buffer (which is determined by the base class Init function called within) the function will either return AC_NO_RECORD which means the operation can continue, but no undo information needs to be stored, or AC_OK which means the operation should continue AND record undo information. If the function returns AC_FAIL, there was not enough memory to record the undo information, and the user has decided not to continue with the operation. Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode ChangeContourWidthAction::Init(Operation* pOp, ActionList* pActionList, List * pNodes, MILLIPOINT NewWidth, BOOL bKeepDirection, ChangeContourWidthAction** ppNewAction) { if (bKeepDirection && NewWidth < 0) { ERROR3("Can't keep the direction when the width is < 0"); return AC_FAIL; } UINT32 ActSize = sizeof(ChangeContourWidthAction); ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(ChangeContourWidthAction),(Action**)ppNewAction); NodeListItem * pItem = NULL; NodeListItem * pNewItem = NULL; ContourWidthListItem * pNewWidthItem = NULL; Document * pDoc = Document::GetCurrent(); NodeContourController * pContour = NULL; MILLIPOINT MaxWidth = 0; if (Ac == AC_OK) { // make a copy of the node list pItem = (NodeListItem *)pNodes->GetHead(); while (pItem) { // store the node, and its old width value pContour = (NodeContourController *)pItem->pNode; ALLOC_WITH_FAIL(pNewItem, new NodeListItem(pContour), pOp); ALLOC_WITH_FAIL(pNewWidthItem, new ContourWidthListItem(pContour->GetWidth()), pOp); // invalidate the old rect if (pDoc) { pDoc->ForceRedraw(pContour->FindParentSpread(), pContour->GetBoundingRect(FALSE, FALSE), FALSE, pContour); } // regenerate the node if (NewWidth != 0) { // set the contour controller's new width if (!bKeepDirection) { if (NewWidth > 0) { MaxWidth = ContourNodePathProcessor::GetMaxInnerContourWidth(pContour); if (NewWidth > MaxWidth) { pContour->SetWidth(MaxWidth); } else { pContour->SetWidth(NewWidth); } } else { pContour->SetWidth(NewWidth); } } else { if (pContour->GetWidth() < 0) { pContour->SetWidth(-NewWidth); } else { MaxWidth = ContourNodePathProcessor::GetMaxInnerContourWidth(pContour); if (NewWidth > MaxWidth) { pContour->SetWidth(MaxWidth); } else { pContour->SetWidth(NewWidth); } } } pContour->RegenerateNode(NULL, FALSE); } // invalidate the new rect if (pDoc) { pDoc->ForceRedraw(pContour->FindParentSpread(), pContour->GetBoundingRect(FALSE, FALSE), FALSE, pContour); } // add the items to the lists (*ppNewAction)->m_Nodes.AddTail(pNewItem); (*ppNewAction)->m_WidthList.AddTail(pNewWidthItem); pItem = (NodeListItem *)pNodes->GetNext(pItem); } } return Ac; } /******************************************************************************************** > ActionCode ChangeContourWidthAction::Execute(); Author: David_McClarnon (Xara Group Ltd) Created: 17/3/99 Inputs: - Outputs: - Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: Executes the action. Causes a regen of all bevels nodes in the action's list Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode ChangeContourWidthAction::Execute() { ChangeContourWidthAction * pNewAction = NULL; // first, initialise an action to restore all the current widths in my list ActionCode Ac = ChangeContourWidthAction::Init(pOperation, pOppositeActLst, &m_Nodes, 0, // tell the action not to regen - I'm FALSE, // going to do that &pNewAction); NodeListItem * pItem = NULL; NodeContourController * pContour = NULL; ContourWidthListItem * pWidthItem = NULL; Document * pDoc = Document::GetCurrent(); if (Ac == AC_OK) { // run through my lists resetting the original widths back to what they were pItem = (NodeListItem *)m_Nodes.GetHead(); pWidthItem = (ContourWidthListItem *)m_WidthList.GetHead(); while (pItem && pWidthItem) { pContour = (NodeContourController *)pItem->pNode; // invalidate the old rect if (pDoc) { pDoc->ForceRedraw(pContour->FindParentSpread(), pContour->GetBoundingRect(FALSE, FALSE), FALSE, pContour); } // restore the width of the node, and regenerate pContour->SetWidth(pWidthItem->m_Width); pContour->RegenerateNode(NULL, FALSE); // invalidate the new rect if (pDoc) { pDoc->ForceRedraw(pContour->FindParentSpread(), pContour->GetBoundingRect(FALSE, FALSE), FALSE, pContour); } pItem = (NodeListItem *)m_Nodes.GetNext(pItem); pWidthItem = (ContourWidthListItem *)m_WidthList.GetNext(pWidthItem); } } return Ac; } ChangeContourWidthAction::~ChangeContourWidthAction() { m_Nodes.DeleteAll(); m_WidthList.DeleteAll(); } //////////////////////////////////////////////////////////////////// // ChangeContourToOuterAction class implementation /******************************************************************************************** > ChangeContourToOuterAction::ChangeContourToOuterAction() Author: Olivier_Gascoin (Xara Group Ltd) Created: 07/01/97 Inputs: - Outputs: - Returns: - Purpose: Constructor for the action Errors: - SeeAlso: - ********************************************************************************************/ ChangeContourToOuterAction::ChangeContourToOuterAction() { m_LastWidth = 0; } /******************************************************************************************** > ActionCode ChangeContourToOuterAction::Init( Operation* pOp, ActionList* pActionList, List * pNodes ChangePositionShadowXAction** ppNewAction); Author: David_McClarnon (Xara Group Ltd) Created: 17/3/99 Inputs: pOp = ptr to the operation to which this action belongs pActionList = ptr to action list to which this action should be added pNodes = ptr to node list containing the NodeBevel nodes to be regenerated Outputs: ppNewAction = ptr to a ptr to an action, allowing the function to return a pointer to the created action Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: This is the function which creates an instance of this action. If there is no room in the undo buffer (which is determined by the base class Init function called within) the function will either return AC_NO_RECORD which means the operation can continue, but no undo information needs to be stored, or AC_OK which means the operation should continue AND record undo information. If the function returns AC_FAIL, there was not enough memory to record the undo information, and the user has decided not to continue with the operation. Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode ChangeContourToOuterAction::Init(Operation* pOp, ActionList* pActionList, NodeContourController * pController, ChangeContourToOuterAction** ppNewAction) { UINT32 ActSize = sizeof(ChangeContourToOuterAction); ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(ChangeContourToOuterAction),(Action**)ppNewAction); if (Ac == AC_OK) { (*ppNewAction)->m_pContour = pController; (*ppNewAction)->m_LastWidth = pController->GetWidth(); } return Ac; } /******************************************************************************************** > ActionCode ChangeContourToOuterAction::Execute(); Author: David_McClarnon (Xara Group Ltd) Created: 17/3/99 Inputs: - Outputs: - Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: Executes the action. Causes a regen of all bevels nodes in the action's list Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode ChangeContourToOuterAction::Execute() { ChangeContourToOuterAction * pNewAction = NULL; // first, initialise an action to restore all the current widths in my list ActionCode Ac = ChangeContourToOuterAction::Init(pOperation, pOppositeActLst, m_pContour, &pNewAction); Document * pDoc = Document::GetCurrent(); if (Ac == AC_OK) { if (pDoc) pDoc->ForceRedraw(m_pContour->FindParentSpread(), m_pContour->GetBoundingRect(), FALSE, m_pContour); m_pContour->SetWidth(m_LastWidth); m_pContour->RegenerateNode(NULL, FALSE); if (pDoc) pDoc->ForceRedraw(m_pContour->FindParentSpread(), m_pContour->GetBoundingRect(), FALSE, m_pContour); } return Ac; } ChangeContourToOuterAction::~ChangeContourToOuterAction() { } //////////////////////////////////////////////////////////////////// // ChangeContourToInnerAction class implementation /******************************************************************************************** > ChangeContourToInnerAction::ChangeContourToInnerAction() Author: Olivier_Gascoin (Xara Group Ltd) Created: 07/01/97 Inputs: - Outputs: - Returns: - Purpose: Constructor for the action Errors: - SeeAlso: - ********************************************************************************************/ ChangeContourToInnerAction::ChangeContourToInnerAction() { m_LastWidth = 0; } /******************************************************************************************** > ActionCode ChangeContourToInnerAction::Init( Operation* pOp, ActionList* pActionList, List * pNodes ChangePositionShadowXAction** ppNewAction); Author: David_McClarnon (Xara Group Ltd) Created: 17/3/99 Inputs: pOp = ptr to the operation to which this action belongs pActionList = ptr to action list to which this action should be added pNodes = ptr to node list containing the NodeBevel nodes to be regenerated Outputs: ppNewAction = ptr to a ptr to an action, allowing the function to return a pointer to the created action Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: This is the function which creates an instance of this action. If there is no room in the undo buffer (which is determined by the base class Init function called within) the function will either return AC_NO_RECORD which means the operation can continue, but no undo information needs to be stored, or AC_OK which means the operation should continue AND record undo information. If the function returns AC_FAIL, there was not enough memory to record the undo information, and the user has decided not to continue with the operation. Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode ChangeContourToInnerAction::Init(Operation* pOp, ActionList* pActionList, NodeContourController * pController, ChangeContourToInnerAction** ppNewAction) { UINT32 ActSize = sizeof(ChangeContourToInnerAction); ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(ChangeContourToInnerAction),(Action**)ppNewAction); if (Ac == AC_OK) { (*ppNewAction)->m_pContour = pController; (*ppNewAction)->m_LastWidth = pController->GetWidth(); } return Ac; } /******************************************************************************************** > ActionCode ChangeContourToInnerAction::Execute(); Author: David_McClarnon (Xara Group Ltd) Created: 17/3/99 Inputs: - Outputs: - Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: Executes the action. Causes a regen of all bevels nodes in the action's list Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode ChangeContourToInnerAction::Execute() { ChangeContourToInnerAction * pNewAction = NULL; // first, initialise an action to restore all the current widths in my list ActionCode Ac = ChangeContourToInnerAction::Init(pOperation, pOppositeActLst, m_pContour, &pNewAction); Document * pDoc = Document::GetCurrent(); if (Ac == AC_OK) { if (pDoc) pDoc->ForceRedraw(m_pContour->FindParentSpread(), m_pContour->GetBoundingRect(), FALSE, m_pContour); m_pContour->SetWidth(m_LastWidth); m_pContour->RegenerateNode(NULL, FALSE); if (pDoc) pDoc->ForceRedraw(m_pContour->FindParentSpread(), m_pContour->GetBoundingRect(), FALSE, m_pContour); } return Ac; } ChangeContourToInnerAction::~ChangeContourToInnerAction() { } ///////////////////////////////////////////////////////////////////////////// // OpChangeContourToInner class /******************************************************************************************** > OpChangeContourWidth::OpChangeContourWidth() Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Purpose: Constructor. ********************************************************************************************/ OpChangeContourToInner::OpChangeContourToInner() { //TRACEUSER( "MarkH", _T("Just Made a OpChangeContourWidth Class!\n")); } /******************************************************************************************** > OpChangeContourToInner::~OpChangeContourToInner() Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Purpose: Destructor. ********************************************************************************************/ OpChangeContourToInner::~OpChangeContourToInner() { //TRACEUSER( "MarkH", _T("Just Killed OpChangeContourToInner Class!!!\n")); } /******************************************************************************************** > virtual void OpChangeContourToInner::Do(OpDescriptor *pOpDesc) Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Inputs: pOpDesc - OpDescriptor - unused Outputs: - Returns: - Purpose: The do function. Applys a Bevel to the selection in the current document ********************************************************************************************/ void OpChangeContourToInner::Do(OpDescriptor *pOpDesc) { TRACEUSER( "DavidM", _T("OpChangeContourToInner - Do !\n")); BeginSlowJob(-1, TRUE); DoStartSelOp(TRUE, TRUE); // get all the contour nodes in the selection List ContourList; BevelTools::BuildListOfSelectedNodes(&ContourList, CC_RUNTIME_CLASS(NodeContourController), TRUE); NodeListItem * pItem = (NodeListItem *)ContourList.GetHead(); ChangeContourToInnerAction * pAction = NULL; NodeContourController * pControl = NULL; BOOL ok = TRUE; Document * pDoc = Document::GetCurrent(); // set up the object changed param ObjChangeFlags flgs(FALSE, FALSE, FALSE, TRUE); flgs.RegenerateNode = TRUE; ObjChangeParam MyObjChangeParam(OBJCHANGE_FINISHED, flgs, NULL, this, OBJCHANGE_CALLEDBYOP); Node * pParent = NULL; // run through the list, changing all widths to be positive while (pItem && ok) { if (pItem->pNode) { pControl = (NodeContourController *)pItem->pNode; if (pControl->GetWidth() < 0) { // redraw the node if (pDoc) pDoc->ForceRedraw(pControl->FindParentSpread(), pControl->GetBoundingRect(), FALSE, pControl); // and invalidate all parents' rectangles pParent = pControl->FindParent(); pControl->ReleaseCached(); // Associated with DoInvalidateRegion, does parents itself while (pParent) { if (pParent->IsAnObject()) { DoInvalidateRegion(pParent->FindParentSpread(), ((NodeRenderableInk *)pParent)->GetBoundingRect()); } pParent = pParent->FindParent(); } // check for maximum width MILLIPOINT MaxWidth = ContourNodePathProcessor::GetMaxInnerContourWidth(pControl); if (ChangeContourToInnerAction::Init(this, this->GetUndoActionList(), pControl, &pAction) != AC_OK) { ok = FALSE; } // set the width to positive pControl->SetWidth(-pControl->GetWidth()); if (pControl->GetWidth() > MaxWidth) pControl->SetWidth(MaxWidth); // move the node if (ok) { Node * pContourNode = pControl->FindFirstChild(CC_RUNTIME_CLASS(NodeContour)); if (pContourNode) { Node * pInsertNode = pControl->FindLastChild(CC_RUNTIME_CLASS(NodeRenderableInk)); if (pInsertNode != pContourNode) ok = DoMoveNode(pContourNode, pInsertNode, NEXT); } } // regenerate the node pControl->RegenerateNode(NULL, FALSE); // Ilan 7/5/00 // Inform geom linked attrs of the change. Nb outside the normal AllowOp mechanism NodeAttribute* pNA = pControl->FindFirstGeometryLinkedAttr(); while(pNA) { pNA->LinkedNodeGeometryHasChanged(this); pNA = pNA->FindNextGeometryLinkedAttr(); } // redraw the node if (pDoc) pDoc->ForceRedraw(pControl->FindParentSpread(), pControl->GetBoundingRect(), FALSE, pControl); } } pItem = (NodeListItem *)ContourList.GetNext(pItem); } ContourList.DeleteAll(); if (!ok) { FailAndExecute(); End(); return; } End(); } /******************************************************************************************** > void OpChangeContourToInner::DoWithParam(OpDescriptor* pOp, OpParam* pParam) Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Inputs: Outputs: - Returns: - Purpose: Changes all contours in the selection to inner contours ********************************************************************************************/ void OpChangeContourToInner::DoWithParam(OpDescriptor* pOp, OpParam* pParam) { // first, begin the operation BeginSlowJob(-1, TRUE); DoStartSelOp(TRUE, TRUE); End(); } /******************************************************************************************** > BOOL OpChangeContourToInner::Declare() Author: Peter_Arnold (Xara Group Ltd) Created: 16/11/94 Returns: TRUE if all went OK, False otherwise Purpose: Adds the operation to the list of all known operations ********************************************************************************************/ BOOL OpChangeContourToInner::Declare() { return (RegisterOpDescriptor( 0, _R(IDS_OP_CONTOURINNER), CC_RUNTIME_CLASS(OpChangeContourToInner), OPTOKEN_CHANGECONTOUR_INNER, OpChangeContourToInner::GetState, 0, _R(IDBBL_CONTOURINNER) )); } /******************************************************************************************** > OpState OpChangeContourToInner::GetState(String_256* Description, OpDescriptor*) Author: Peter_Arnold (Xara Group Ltd) Created: 16/11/94 Outputs: - Returns: Ungreyed, Unticked Purpose: Find out the state of the new regular shape at the specific time ********************************************************************************************/ OpState OpChangeContourToInner::GetState(String_256* Description, OpDescriptor*) { OpState Blobby; TRACEUSER( "DavidM", _T("OpChangeContourToInner - get state !\n")); if (Description) { Description->Load(_R(IDS_CONTOURINNEROPNAME)); } return Blobby; } ///////////////////////////////////////////////////////////////////////////// // OpChangeContourToOuter class /******************************************************************************************** > OpChangeContourWidth::OpChangeContourWidth() Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Purpose: Constructor. ********************************************************************************************/ OpChangeContourToOuter::OpChangeContourToOuter() { //TRACEUSER( "MarkH", _T("Just Made a OpChangeContourWidth Class!\n")); } /******************************************************************************************** > OpChangeContourToOuter::~OpChangeContourToOuter() Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Purpose: Destructor. ********************************************************************************************/ OpChangeContourToOuter::~OpChangeContourToOuter() { //TRACEUSER( "MarkH", _T("Just Killed OpChangeContourToOuter Class!!!\n")); } /******************************************************************************************** > virtual void OpChangeContourToOuter::Do(OpDescriptor *pOpDesc) Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Inputs: pOpDesc - OpDescriptor - unused Outputs: - Returns: - Purpose: Changes all contours in the selection to outer contours ********************************************************************************************/ void OpChangeContourToOuter::Do(OpDescriptor *pOpDesc) { TRACEUSER( "DavidM", _T("OpChangeContourToOuter - Do !\n")); BeginSlowJob(-1, TRUE); DoStartSelOp(TRUE, TRUE); // get all the contour nodes in the selection List ContourList; BevelTools::BuildListOfSelectedNodes(&ContourList, CC_RUNTIME_CLASS(NodeContourController), TRUE); NodeListItem * pItem = (NodeListItem *)ContourList.GetHead(); ChangeContourToOuterAction * pAction = NULL; NodeContourController * pControl = NULL; BOOL ok = TRUE; // set up the object changed param ObjChangeFlags flgs(FALSE, FALSE, FALSE, TRUE); flgs.RegenerateNode = TRUE; ObjChangeParam MyObjChangeParam(OBJCHANGE_FINISHED, flgs, NULL, this, OBJCHANGE_CALLEDBYOP); Node * pParent = NULL; Document * pDoc = Document::GetCurrent(); // run through the list, changing all widths to be positive while (pItem && ok) { if (pItem->pNode) { pControl = (NodeContourController *)pItem->pNode; if (pControl->GetWidth() > 0) { // redraw the node if (pDoc) pDoc->ForceRedraw(pControl->FindParentSpread(), pControl->GetBoundingRect(), FALSE, pControl); // invalidate the parents pParent = pControl->FindParent(); pControl->ReleaseCached(); // Associated with DoInvalidateRegion, does parents itself while (pParent) { if (pParent->IsAnObject()) { DoInvalidateRegion(pParent->FindParentSpread(), ((NodeRenderableInk *)pParent)->GetBoundingRect()); } pParent = pParent->FindParent(); } if (ChangeContourToOuterAction::Init(this, this->GetUndoActionList(), pControl, &pAction) != AC_OK) { ok = FALSE; } // set the width to negative pControl->SetWidth(-pControl->GetWidth()); // move the node if (ok) { Node * pContourNode = pControl->FindFirstChild(CC_RUNTIME_CLASS(NodeContour)); if (pContourNode) { Node * pInsertNode = pControl->FindFirstChild(CC_RUNTIME_CLASS(NodeRenderableInk)); if (pInsertNode != pContourNode) ok = DoMoveNode(pContourNode, pInsertNode, PREV); } } // regenerate the node pControl->RegenerateNode(NULL, FALSE); // Ilan 7/5/00 // Inform geom linked attrs of the change. Nb outside the normal AllowOp mechanism NodeAttribute* pNA = pControl->FindFirstGeometryLinkedAttr(); while(pNA) { pNA->LinkedNodeGeometryHasChanged(this); pNA = pNA->FindNextGeometryLinkedAttr(); } // redraw the node if (pDoc) pDoc->ForceRedraw(pControl->FindParentSpread(), pControl->GetBoundingRect(), FALSE, pControl); } } pItem = (NodeListItem *)ContourList.GetNext(pItem); } ContourList.DeleteAll(); if (!ok) { FailAndExecute(); End(); return; } End(); } /******************************************************************************************** > void OpChangeContourToOuter::DoWithParam(OpDescriptor* pOp, OpParam* pParam) Author: David_McClarnon (Xara Group Ltd) Created: 12/8/99 Inputs: Outputs: - Returns: - Purpose: Applys a Bevel to the selected node after a mouse click ********************************************************************************************/ void OpChangeContourToOuter::DoWithParam(OpDescriptor* pOp, OpParam* pParam) { // first, begin the operation BeginSlowJob(-1, TRUE); End(); } /******************************************************************************************** > BOOL OpChangeContourToOuter::Declare() Author: Peter_Arnold (Xara Group Ltd) Created: 16/11/94 Returns: TRUE if all went OK, False otherwise Purpose: Adds the operation to the list of all known operations ********************************************************************************************/ BOOL OpChangeContourToOuter::Declare() { return (RegisterOpDescriptor( 0, _R(IDS_OP_CONTOUROUTER), CC_RUNTIME_CLASS(OpChangeContourToOuter), OPTOKEN_CHANGECONTOUR_OUTER, OpChangeContourToOuter::GetState, 0, _R(IDBBL_CONTOUROUTER) )); } /******************************************************************************************** > OpState OpChangeContourToOuter::GetState(String_256* Description, OpDescriptor*) Author: Peter_Arnold (Xara Group Ltd) Created: 16/11/94 Outputs: - Returns: Ungreyed, Unticked Purpose: Find out the state of the new regular shape at the specific time ********************************************************************************************/ OpState OpChangeContourToOuter::GetState(String_256* Description, OpDescriptor*) { OpState Blobby; if (Description) { Description->Load(_R(IDS_CONTOUROUTEROPNAME)); } return Blobby; } /////////////////////////////////////////////////////////////////////////////////////////// // OpChangeContourSteps // // Changes the number of steps of all the selected blends /******************************************************************************************** > void OpChangeContourSteps::DoWithParam(OpDescriptor*,OpParam* pOpParam) Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Returns: - Purpose: This changes all the selected blend objects to have pOpParam->Param1 number of steps ********************************************************************************************/ void OpChangeContourSteps::DoWithParam(OpDescriptor*,OpParam* pOpParam) { ERROR3IF(pOpParam == NULL,"NULL OpParam ptr"); if (pOpParam == NULL) return; List NodeList; BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeRenderableInk)); NodeListItem *pItem = NULL; BOOL ok = !NodeList.IsEmpty(); if (ok) ok = DoStartSelOp(FALSE,FALSE); if (ok) { // The new number of steps is in pOpParam->Param1 of the UINT32 NewNumSteps = UINT32(pOpParam->Param1); pItem = (NodeListItem *)NodeList.GetHead(); Node* pSelNode = NULL; if (pItem) { pSelNode = pItem->pNode; } while (pSelNode != NULL && ok) { Node* pNode = pSelNode; pItem = (NodeListItem *)NodeList.GetNext(pItem); if (pItem) { pSelNode = pItem->pNode; } else { pSelNode = NULL; } if (pNode->IS_KIND_OF(NodeContourController)) { // We now have a selected blend node so: // Invalidate the node's region // Store the current number of blend steps in an undo actiom // Change the number of steps to NewNumSteps NodeRenderableInk * pInk = (NodeRenderableInk *)pNode; UINT32 NumSteps = 0; double DistanceEntered = 0.0; NumSteps = ((NodeContourController *)pNode)->GetNumberOfSteps(); DistanceEntered = 0.0; ChangeContourStepsAction* pAction; // Ask the node if it's ok to do the op ObjChangeFlags cFlags; ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this); ok = pInk->AllowOp(&ObjChange); if (ok) ok = DoInvalidateNodeRegion(pInk,TRUE,FALSE); if (ok) ok = (InvalidateBoundsAction::Init(this,&UndoActions,pInk,TRUE) != AC_FAIL); if (ok) ok = ChangeContourStepsAction::Init(this,&UndoActions,pInk,NumSteps, DistanceEntered, &pAction) != AC_FAIL; if (ok) { ((NodeContourController *)pNode)->SetNumberOfSteps(NewNumSteps); pNode->RegenerateNode(NULL, FALSE); } if (ok) ok = DoInvalidateNodeRegion(pInk,TRUE,FALSE); if (ok) ok = (InvalidateBoundsAction::Init(this,&UndoActions,pInk,TRUE) != AC_FAIL); } } } NodeList.DeleteAll(); if (ok) { } else FailAndExecute(); End(); } /******************************************************************************************** > BOOL OpChangeContourSteps::Declare() Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Returns: TRUE if all went OK, FALSE otherwise Purpose: Adds the operation to the list of all known operations ********************************************************************************************/ BOOL OpChangeContourSteps::Declare() { return (RegisterOpDescriptor( 0, 0, CC_RUNTIME_CLASS(OpChangeContourSteps), OPTOKEN_CHANGECONTOURSTEPS, OpChangeContourSteps::GetState, 0, /* help ID */ 0, /* bubble ID */ 0 /* bitmap ID */ )); } /******************************************************************************************** > static OpState OpChangeContourSteps::GetState(String_256* Description, OpDescriptor*) Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Outputs: Description - GetState fills this string with an approriate description of the current state of the operation Returns: The state of the operation, so that menu items (ticks and greying) can be done properly Purpose: Find out the state of the operation at the specific time ********************************************************************************************/ OpState OpChangeContourSteps::GetState(String_256* Description, OpDescriptor*) { OpState State(FALSE,TRUE); // It's not ticked, but it is greyed by default // DMc - to test for bevels & contours // are there any contour nodes in the selection List NodeList; BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeContourController)); if (!NodeList.IsEmpty()) { State.Greyed = FALSE; } NodeList.DeleteAll(); if (State.Greyed) *Description = String_256(_R(IDS_CONTOURSTEPS)); else *Description = String_256(_R(IDS_CONTOURSTEPS)); return State; } /******************************************************************************************** > virtual void OpChangeContourSteps::GetOpName(String_256* OpName) Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: - Outputs: The undo string for the operation Returns: Purpose: The GetOpName fn is overridden so that we return back a description appropriate to the type of attribute that the operation applies. Errors: - SeeAlso: - ********************************************************************************************/ void OpChangeContourSteps::GetOpName(String_256* OpName) { *OpName = String_256(_R(IDS_CONTOURSTEPS_UNDO)); } //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ // The ChangeContourStepsAction class /******************************************************************************************** > ChangeContourStepsAction::ChangeContourStepsAction() Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: - Outputs: - Returns: - Purpose: Constructor for the action Errors: - SeeAlso: - ********************************************************************************************/ ChangeContourStepsAction::ChangeContourStepsAction() { pNodeBlend = NULL; OldNumSteps = 0; } /******************************************************************************************** > ActionCode ChangeContourStepsAction::Init( Operation* pOp, ActionList* pActionList, NodeBlend* pThisNodeBlend, UINT32 NumSteps, ChangeContourStepsAction** ppNewAction); Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: pOp = ptr to the operation to which this action belongs pActionList = ptr to action list to which this action should be added pThisNodeBlend = ptr to NodeBlend to change NumSteps = Num steps to applied to pThisNodeBlend Outputs: ppNewAction = ptr to a ptr to an action, allowing the function to return a pointer to the created action Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: This is the function which creates an instance of this action. If there is no room in the undo buffer (which is determined by the base class Init function called within) the function will either return AC_NO_RECORD which means the operation can continue, but no undo information needs to be stored, or AC_OK which means the operation should continue AND record undo information. If the function returns AC_FAIL, there was not enough memory to record the undo information, and the user has decided not to continue with the operation. Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode ChangeContourStepsAction::Init(Operation* pOp, ActionList* pActionList, Node* pThisNodeBlend, UINT32 NumSteps, double DistanceEntered, ChangeContourStepsAction** ppNewAction) { UINT32 ActSize = sizeof(ChangeContourStepsAction); ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(ChangeContourStepsAction),(Action**)ppNewAction); if (Ac != AC_FAIL) { (*ppNewAction)->pNodeBlend = pThisNodeBlend; (*ppNewAction)->OldNumSteps = NumSteps; (*ppNewAction)->OldDistanceEntered = DistanceEntered; } return Ac; } /******************************************************************************************** > ActionCode ChangeContourStepsAction::Execute(); Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: - Outputs: - Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: Executes the action. This will reset the num blend steps in pThisNodeBlend to OldNumSteps, after creating another action to record the current num steps of pThisNodeBlend Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode ChangeContourStepsAction::Execute() { ActionCode Act; ChangeContourStepsAction* pAction; UINT32 NumSteps = 0; double DistanceEntered = 0.0; NumSteps = ((NodeContourController *)pNodeBlend)->GetNumberOfSteps(); Act = ChangeContourStepsAction::Init( pOperation, pOppositeActLst, pNodeBlend, NumSteps, DistanceEntered, &pAction); if (Act != AC_FAIL) { ((NodeContourController *)pNodeBlend)->SetNumberOfSteps(OldNumSteps); pNodeBlend->RegenerateNode(NULL, FALSE); } return Act; } ChangeContourStepsAction::~ChangeContourStepsAction() { } /////////////////////////////////////////////////////////////////////////////////////////// // OpChangeContourColourType // // Changes the number of steps of all the selected blends /******************************************************************************************** > void OpChangeContourColourType::DoWithParam(OpDescriptor*,OpParam* pOpParam) Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Returns: - Purpose: This changes all the selected blend objects to have pOpParam->Param1 number of steps ********************************************************************************************/ void OpChangeContourColourType::DoWithParam(OpDescriptor*,OpParam* pOpParam) { ERROR3IF(pOpParam == NULL,"NULL OpParam ptr"); if (pOpParam == NULL) return; DoStartSelOp(TRUE, TRUE); BeginSlowJob(-1, TRUE); List NodeList; BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeContourController)); NodeListItem * pItem = (NodeListItem *)NodeList.GetHead(); NodeContourController * pController = NULL; BOOL ok = TRUE; Node * pParent = NULL; while (pItem && ok) { pController = (NodeContourController *)pItem->pNode; ChangeContourColourTypeAction *pAction = NULL; if (ChangeContourColourTypeAction::Init(this, GetUndoActionList(), pController, (ColourBlendType)(INT32)(pOpParam->Param1), &pAction) != AC_OK) { FailAndExecute(); End(); return; } if (ok) ok = DoInvalidateNodeRegion(pController, TRUE); if (ok) { pParent = pController->FindParent(); while (pParent) { ObjChangeFlags flgs; ObjChangeParam OP(OBJCHANGE_FINISHED, flgs, NULL, this, OBJCHANGE_CALLEDBYOP); pParent->OnChildChange(&OP); pParent = pParent->FindParent(); } } pItem = (NodeListItem *)NodeList.GetNext(pItem); } NodeList.DeleteAll(); // Inform the effected parents of the change if (ok) { End(); } else { FailAndExecute(); End(); } } /******************************************************************************************** > BOOL OpChangeContourColourType::Declare() Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Returns: TRUE if all went OK, FALSE otherwise Purpose: Adds the operation to the list of all known operations ********************************************************************************************/ BOOL OpChangeContourColourType::Declare() { return (RegisterOpDescriptor( 0, 0, CC_RUNTIME_CLASS(OpChangeContourColourType), OPTOKEN_CHANGECONTOURCOLOURTYPE, OpChangeContourColourType::GetState, 0, /* help ID */ 0, /* bubble ID */ 0 /* bitmap ID */ )); } /******************************************************************************************** > static OpState OpChangeContourColourType::GetState(String_256* Description, OpDescriptor*) Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Outputs: Description - GetState fills this string with an approriate description of the current state of the operation Returns: The state of the operation, so that menu items (ticks and greying) can be done properly Purpose: Find out the state of the operation at the specific time ********************************************************************************************/ OpState OpChangeContourColourType::GetState(String_256* Description, OpDescriptor*) { OpState State(FALSE,TRUE); // It's not ticked, but it is greyed by default // DMc - to test for bevels & contours // are there any contour nodes in the selection List NodeList; BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeContourController)); if (!NodeList.IsEmpty()) { State.Greyed = FALSE; } NodeList.DeleteAll(); if (State.Greyed) *Description = String_256(_R(IDS_CONTOURCOLOURTYPE)); else *Description = String_256(_R(IDS_CONTOURCOLOURTYPE)); return State; } /******************************************************************************************** > virtual void OpChangeContourColourType::GetOpName(String_256* OpName) Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: - Outputs: The undo string for the operation Returns: Purpose: The GetOpName fn is overridden so that we return back a description appropriate to the type of attribute that the operation applies. Errors: - SeeAlso: - ********************************************************************************************/ void OpChangeContourColourType::GetOpName(String_256* OpName) { *OpName = String_256(_R(IDS_CONTOURCOLOURTYPE)); } //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ // The ChangeContourColourTypeAction class /******************************************************************************************** > ChangeContourColourTypeAction::ChangeContourColourTypeAction() Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: - Outputs: - Returns: - Purpose: Constructor for the action Errors: - SeeAlso: - ********************************************************************************************/ ChangeContourColourTypeAction::ChangeContourColourTypeAction() { m_pNode = NULL; } /******************************************************************************************** > ActionCode ChangeContourColourTypeAction::Init( Operation* pOp, ActionList* pActionList, NodeBlend* pThisNodeBlend, UINT32 NumSteps, ChangeContourColourTypeAction** ppNewAction); Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: pOp = ptr to the operation to which this action belongs pActionList = ptr to action list to which this action should be added pThisNodeBlend = ptr to NodeBlend to change NumSteps = Num steps to applied to pThisNodeBlend Outputs: ppNewAction = ptr to a ptr to an action, allowing the function to return a pointer to the created action Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: This is the function which creates an instance of this action. If there is no room in the undo buffer (which is determined by the base class Init function called within) the function will either return AC_NO_RECORD which means the operation can continue, but no undo information needs to be stored, or AC_OK which means the operation should continue AND record undo information. If the function returns AC_FAIL, there was not enough memory to record the undo information, and the user has decided not to continue with the operation. Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode ChangeContourColourTypeAction::Init( Operation* pOp, ActionList* pActionList, NodeContourController* pThisNodeContour, ColourBlendType type, ChangeContourColourTypeAction** NewAction) { UINT32 ActSize = sizeof(ChangeContourColourTypeAction); ActionCode Ac = Action::Init(pOp,pActionList,ActSize, CC_RUNTIME_CLASS(ChangeContourColourTypeAction),(Action**)NewAction); Document * pDoc = Document::GetCurrent(); if (Ac != AC_FAIL) { (*NewAction)->m_pNode = pThisNodeContour; (*NewAction)->m_OldType = pThisNodeContour->GetColourBlendType(); pThisNodeContour->SetColourBlendType(type); // redraw the contour if (pDoc) { pDoc->ForceRedraw(pThisNodeContour->FindParentSpread(), pThisNodeContour->GetBoundingRect(), FALSE, pThisNodeContour); } } return Ac; } /******************************************************************************************** > ActionCode ChangeContourColourTypeAction::Execute(); Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: - Outputs: - Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: Executes the action. This will reset the num blend steps in pThisNodeBlend to OldNumSteps, after creating another action to record the current num steps of pThisNodeBlend Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode ChangeContourColourTypeAction::Execute() { ChangeContourColourTypeAction * pAction = NULL; ActionCode Act = ChangeContourColourTypeAction::Init( pOperation, pOppositeActLst, m_pNode, m_OldType, &pAction); if (Act != AC_FAIL) { } return Act; } ChangeContourColourTypeAction::~ChangeContourColourTypeAction() { } //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ // The ChangeContourAttributeProfileAction class /******************************************************************************************** > ChangeContourAttributeProfileAction::ChangeContourAttributeProfileAction() Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: - Outputs: - Returns: - Purpose: Constructor for the action Errors: - SeeAlso: - ********************************************************************************************/ ChangeContourAttributeProfileAction::ChangeContourAttributeProfileAction() { m_pNode = NULL; } /******************************************************************************************** > ActionCode ChangeContourAttributeProfileAction::Init( Operation* pOp, ActionList* pActionList, NodeBlend* pThisNodeBlend, UINT32 NumSteps, ChangeContourAttributeProfileAction** ppNewAction); Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: pOp = ptr to the operation to which this action belongs pActionList = ptr to action list to which this action should be added pThisNodeBlend = ptr to NodeBlend to change NumSteps = Num steps to applied to pThisNodeBlend Outputs: ppNewAction = ptr to a ptr to an action, allowing the function to return a pointer to the created action Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: This is the function which creates an instance of this action. If there is no room in the undo buffer (which is determined by the base class Init function called within) the function will either return AC_NO_RECORD which means the operation can continue, but no undo information needs to be stored, or AC_OK which means the operation should continue AND record undo information. If the function returns AC_FAIL, there was not enough memory to record the undo information, and the user has decided not to continue with the operation. Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode ChangeContourAttributeProfileAction::Init( Operation* pOp, ActionList* pActionList, NodeContourController* pThisNodeContour, CProfileBiasGain Profile, ChangeContourAttributeProfileAction** NewAction) { UINT32 ActSize = sizeof(ChangeContourAttributeProfileAction); ActionCode Ac = Action::Init(pOp,pActionList,ActSize, CC_RUNTIME_CLASS(ChangeContourAttributeProfileAction),(Action**)NewAction); Document * pDoc = Document::GetCurrent(); if (Ac != AC_FAIL) { (*NewAction)->m_pNode = pThisNodeContour; (*NewAction)->m_Profile = pThisNodeContour->GetAttrProfile(); // change the profile & regen pThisNodeContour->SetAttrProfile(Profile); pThisNodeContour->RegenerateNode(NULL, FALSE); // redraw the contour if (pDoc) { pDoc->ForceRedraw(pThisNodeContour->FindParentSpread(), pThisNodeContour->GetBoundingRect(), FALSE, pThisNodeContour); } } return Ac; } /******************************************************************************************** > void ChangeContourAttributeProfileAction::ChangeAttributeProfileWithNoUndo (CProfileBiasGain &Profile) Author: Chris_Snook (Xara Group Ltd) Created: 24/2/2000 Inputs: Profile - the profile that is to be applied directly (i.e. applied with no undo) Purpose: When applying contour (attribute) profiles, we only want to generate one bit of undo information. This function allows us to meet this requirement (the one bit of undo information is generated via OpChangeContourAttributeProfile::DoWithParam ()). This function is ONLY called from within ContourInfoBarOp::ChangeProfile () - after OpChangeContourAttributeProfile::DoWithParam () has been called. Errors: - SeeAlso: SoftShadowInfoBarOp::ChangeProfile (), OpChangeContourAttributeProfile::DoWithParam (). ********************************************************************************************/ void ChangeContourAttributeProfileAction::ChangeAttributeProfileWithNoUndo (CProfileBiasGain &Profile) { BeginSlowJob(-1, TRUE); List NodeList; BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeContourController)); NodeListItem * pItem = (NodeListItem *)NodeList.GetHead(); NodeContourController * pController = NULL; // Node * pParent = NULL; // ChangeContourObjectProfileAction * pAction= NULL; Document * pDoc = Document::GetCurrent(); while (pItem) { pController = (NodeContourController *)pItem->pNode; // change the profile & regen pController->SetAttrProfile(Profile); pController->RegenerateNode(NULL, FALSE); // redraw the contour if (pDoc) { pDoc->ForceRedraw(pController->FindParentSpread(), pController->GetBoundingRect(), FALSE, pController); } pItem = (NodeListItem *)NodeList.GetNext(pItem); } NodeList.DeleteAll(); EndSlowJob (); if (pDoc->GetOpHistory ().CanRedo ()) { // then we need to clear out the redo information - since we are now 'before' it .... pDoc->GetOpHistory ().DeleteRedoableOps (); // and update the state of things .... DialogBarOp::SetSystemStateChanged(); DialogBarOp::UpdateStateOfAllBars(); } } /******************************************************************************************** > ActionCode ChangeContourAttributeProfileAction::Execute(); Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: - Outputs: - Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: Executes the action. This will reset the num blend steps in pThisNodeBlend to OldNumSteps, after creating another action to record the current num steps of pThisNodeBlend Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode ChangeContourAttributeProfileAction::Execute() { ChangeContourAttributeProfileAction * pAction = NULL; ActionCode Act = ChangeContourAttributeProfileAction::Init( pOperation, pOppositeActLst, m_pNode, m_Profile, &pAction); if (Act != AC_FAIL) { } return Act; } ChangeContourAttributeProfileAction::~ChangeContourAttributeProfileAction() { } /////////////////////////////////////////////////////////////////////////////////////////// // OpChangeContourColourType // // Changes the number of steps of all the selected blends /******************************************************************************************** > void OpChangeContourAttributeProfile::DoWithParam(OpDescriptor*,OpParam* pOpParam) Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Returns: - Purpose: This changes all the selected blend objects to have pOpParam->Param1 number of steps ********************************************************************************************/ void OpChangeContourAttributeProfile::DoWithParam(OpDescriptor*,OpParam* pOpParam) { ERROR3IF(pOpParam == NULL,"NULL OpParam ptr"); if (pOpParam == NULL) return; BOOL ok = TRUE; ChangeContourProfileParam * pCParam = (ChangeContourProfileParam *)pOpParam; DoStartSelOp(TRUE, TRUE); BeginSlowJob(-1, TRUE); List NodeList; BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeContourController)); NodeListItem * pItem = (NodeListItem *)NodeList.GetHead(); NodeContourController * pController = NULL; // Node * pParent = NULL; ChangeContourAttributeProfileAction * pAction= NULL; while (pItem && ok) { pController = (NodeContourController *)pItem->pNode; ChangeContourAttributeProfileAction::Init(this, this->GetUndoActionList(), pController, pCParam->m_Profile, &pAction); pItem = (NodeListItem *)NodeList.GetNext(pItem); } NodeList.DeleteAll(); // Inform the effected parents of the change if (ok) { End(); } else { FailAndExecute(); End(); } } /******************************************************************************************** > BOOL OpChangeContourAttributeProfile::Declare() Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Returns: TRUE if all went OK, FALSE otherwise Purpose: Adds the operation to the list of all known operations ********************************************************************************************/ BOOL OpChangeContourAttributeProfile::Declare() { return (RegisterOpDescriptor( 0, _R(IDS_CHANGECONTOURATTRIBUTEPROFILE), CC_RUNTIME_CLASS(OpChangeContourAttributeProfile), OPTOKEN_CHANGECONTOURATTRPROFILE, OpChangeContourAttributeProfile::GetState, 0, /* help ID */ 0, /* bubble ID */ 0 /* bitmap ID */ )); } /******************************************************************************************** > static OpState OpChangeContourAttributeProfile::GetState(String_256* Description, OpDescriptor*) Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Outputs: Description - GetState fills this string with an approriate description of the current state of the operation Returns: The state of the operation, so that menu items (ticks and greying) can be done properly Purpose: Find out the state of the operation at the specific time ********************************************************************************************/ OpState OpChangeContourAttributeProfile::GetState(String_256* Description, OpDescriptor*) { OpState State(FALSE,TRUE); // It's not ticked, but it is greyed by default // DMc - to test for bevels & contours // are there any contour nodes in the selection List NodeList; BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeContourController)); if (!NodeList.IsEmpty()) { State.Greyed = FALSE; } NodeList.DeleteAll(); return State; } /******************************************************************************************** > virtual void OpChangeContourAttributeProfile::GetOpName(String_256* OpName) Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: - Outputs: The undo string for the operation Returns: Purpose: The GetOpName fn is overridden so that we return back a description appropriate to the type of attribute that the operation applies. Errors: - SeeAlso: - ********************************************************************************************/ void OpChangeContourAttributeProfile::GetOpName(String_256* OpName) { *OpName = String_256(_R(IDS_CONTOURCOLOURTYPE)); } //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ // The ChangeContourObjectProfileAction class /******************************************************************************************** > ChangeContourObjectProfileAction::ChangeContourObjectProfileAction() Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: - Outputs: - Returns: - Purpose: Constructor for the action Errors: - SeeAlso: - ********************************************************************************************/ ChangeContourObjectProfileAction::ChangeContourObjectProfileAction() { m_pNode = NULL; } /******************************************************************************************** > ActionCode ChangeContourObjectProfileAction::Init( Operation* pOp, ActionList* pActionList, NodeBlend* pThisNodeBlend, UINT32 NumSteps, ChangeContourObjectProfileAction** ppNewAction); Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: pOp = ptr to the operation to which this action belongs pActionList = ptr to action list to which this action should be added pThisNodeBlend = ptr to NodeBlend to change NumSteps = Num steps to applied to pThisNodeBlend Outputs: ppNewAction = ptr to a ptr to an action, allowing the function to return a pointer to the created action Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: This is the function which creates an instance of this action. If there is no room in the undo buffer (which is determined by the base class Init function called within) the function will either return AC_NO_RECORD which means the operation can continue, but no undo information needs to be stored, or AC_OK which means the operation should continue AND record undo information. If the function returns AC_FAIL, there was not enough memory to record the undo information, and the user has decided not to continue with the operation. Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode ChangeContourObjectProfileAction::Init( Operation* pOp, ActionList* pActionList, NodeContourController* pThisNodeContour, CProfileBiasGain Profile, ChangeContourObjectProfileAction** NewAction) { UINT32 ActSize = sizeof(ChangeContourObjectProfileAction); ActionCode Ac = Action::Init(pOp,pActionList,ActSize, CC_RUNTIME_CLASS(ChangeContourObjectProfileAction),(Action**)NewAction); Document * pDoc = Document::GetCurrent(); if (Ac != AC_FAIL) { (*NewAction)->m_pNode = pThisNodeContour; (*NewAction)->m_Profile = pThisNodeContour->GetObjectProfile(); // change the profile & regen pThisNodeContour->SetObjectProfile(Profile); pThisNodeContour->RegenerateNode(NULL, FALSE); // redraw the contour if (pDoc) { pDoc->ForceRedraw(pThisNodeContour->FindParentSpread(), pThisNodeContour->GetBoundingRect(), FALSE, pThisNodeContour); } } return Ac; } /******************************************************************************************** > void ChangeContourObjectProfileAction::ChangeObjectProfileWithNoUndo (CProfileBiasGain &Profile) Author: Chris_Snook (Xara Group Ltd) Created: 24/2/2000 Inputs: Profile - the profile that is to be applied directly (i.e. applied with no undo) Purpose: When applying contour (object) profiles, we only want to generate one bit of undo information. This function allows us to meet this requirement (the one bit of undo information is generated via OpChangeContourObjectProfile::DoWithParam ()). This function is ONLY called from within ContourInfoBarOp::ChangeProfile () - after OpChangeContourObjectProfile::DoWithParam () has been called. Errors: - SeeAlso: SoftShadowInfoBarOp::ChangeProfile (), OpChangeContourObjectProfile::DoWithParam (). ********************************************************************************************/ void ChangeContourObjectProfileAction::ChangeObjectProfileWithNoUndo (CProfileBiasGain &Profile) { BeginSlowJob(-1, TRUE); List NodeList; BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeContourController)); NodeListItem * pItem = (NodeListItem *)NodeList.GetHead(); NodeContourController * pController = NULL; // Node * pParent = NULL; // ChangeContourObjectProfileAction * pAction= NULL; Document * pDoc = Document::GetCurrent(); while (pItem) { pController = (NodeContourController *)pItem->pNode; // change the profile & regen pController->SetObjectProfile(Profile); pController->RegenerateNode(NULL, FALSE); // redraw the contour if (pDoc) { pDoc->ForceRedraw(pController->FindParentSpread(), pController->GetBoundingRect(), FALSE, pController); } pItem = (NodeListItem *)NodeList.GetNext(pItem); } NodeList.DeleteAll(); EndSlowJob (); if (pDoc->GetOpHistory ().CanRedo ()) { // then we need to clear out the redo information - since we are now 'before' it .... pDoc->GetOpHistory ().DeleteRedoableOps (); // and update the state of things .... DialogBarOp::SetSystemStateChanged(); DialogBarOp::UpdateStateOfAllBars(); } } /******************************************************************************************** > ActionCode ChangeContourObjectProfileAction::Execute(); Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: - Outputs: - Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: Executes the action. This will reset the num blend steps in pThisNodeBlend to OldNumSteps, after creating another action to record the current num steps of pThisNodeBlend Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode ChangeContourObjectProfileAction::Execute() { ChangeContourObjectProfileAction * pAction = NULL; ActionCode Act = ChangeContourObjectProfileAction::Init( pOperation, pOppositeActLst, m_pNode, m_Profile, &pAction); if (Act != AC_FAIL) { } return Act; } ChangeContourObjectProfileAction::~ChangeContourObjectProfileAction() { } /******************************************************************************************** > void OpChangeContourObjectProfile::DoWithParam(OpDescriptor*,OpParam* pOpParam) Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Returns: - Purpose: This changes all the selected blend objects to have pOpParam->Param1 number of steps ********************************************************************************************/ void OpChangeContourObjectProfile::DoWithParam(OpDescriptor*,OpParam* pOpParam) { ERROR3IF(pOpParam == NULL,"NULL OpParam ptr"); if (pOpParam == NULL) return; BOOL ok = TRUE; ChangeContourProfileParam * pCParam = (ChangeContourProfileParam *)pOpParam; DoStartSelOp(TRUE, TRUE); BeginSlowJob(-1, TRUE); List NodeList; BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeContourController)); NodeListItem * pItem = (NodeListItem *)NodeList.GetHead(); NodeContourController * pController = NULL; // Node * pParent = NULL; ChangeContourObjectProfileAction * pAction= NULL; while (pItem && ok) { pController = (NodeContourController *)pItem->pNode; ChangeContourObjectProfileAction::Init(this, this->GetUndoActionList(), pController, pCParam->m_Profile, &pAction); pItem = (NodeListItem *)NodeList.GetNext(pItem); } NodeList.DeleteAll(); // Inform the effected parents of the change if (ok) { End(); } else { FailAndExecute(); End(); } } /******************************************************************************************** > BOOL OpChangeContourObjectProfile::Declare() Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Returns: TRUE if all went OK, FALSE otherwise Purpose: Adds the operation to the list of all known operations ********************************************************************************************/ BOOL OpChangeContourObjectProfile::Declare() { return (RegisterOpDescriptor( 0, _R(IDS_CHANGECONTOUROBJECTPROFILE), CC_RUNTIME_CLASS(OpChangeContourObjectProfile), OPTOKEN_CHANGECONTOUROBJPROFILE, OpChangeContourObjectProfile::GetState, 0, /* help ID */ 0, /* bubble ID */ 0 /* bitmap ID */ )); } /******************************************************************************************** > static OpState OpChangeContourObjectProfile::GetState(String_256* Description, OpDescriptor*) Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Outputs: Description - GetState fills this string with an approriate description of the current state of the operation Returns: The state of the operation, so that menu items (ticks and greying) can be done properly Purpose: Find out the state of the operation at the specific time ********************************************************************************************/ OpState OpChangeContourObjectProfile::GetState(String_256* Description, OpDescriptor*) { OpState State(FALSE,TRUE); // It's not ticked, but it is greyed by default // DMc - to test for bevels & contours // are there any contour nodes in the selection List NodeList; BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeContourController)); if (!NodeList.IsEmpty()) { State.Greyed = FALSE; } NodeList.DeleteAll(); return State; } /******************************************************************************************** > virtual void OpChangeContourObjectProfile::GetOpName(String_256* OpName) Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: - Outputs: The undo string for the operation Returns: Purpose: The GetOpName fn is overridden so that we return back a description appropriate to the type of attribute that the operation applies. Errors: - SeeAlso: - ********************************************************************************************/ void OpChangeContourObjectProfile::GetOpName(String_256* OpName) { *OpName = String_256(_R(IDS_CONTOURCOLOURTYPE)); } /////////////////////////////////////////////////////////////////////////////////////////// // OpChangeContourStepDistance // // Changes the number of steps of all the selected blends /******************************************************************************************** > void OpChangeContourStepDistance::DoWithParam(OpDescriptor*,OpParam* pOpParam) Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Returns: - Purpose: This changes all the selected blend objects to have pOpParam->Param1 number of steps ********************************************************************************************/ void OpChangeContourStepDistance::DoWithParam(OpDescriptor*,OpParam* pOpParam) { ERROR3IF(pOpParam == NULL,"NULL OpParam ptr"); if (pOpParam == NULL) return; List NodeList; BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeRenderableInk)); NodeListItem *pItem = NULL; BOOL ok = !NodeList.IsEmpty(); if (ok) ok = DoStartSelOp(FALSE,FALSE); if (ok) { // The new number of steps is in pOpParam->Param1 of the INT32 NewStepDistance = INT32(pOpParam->Param1); pItem = (NodeListItem *)NodeList.GetHead(); Node* pSelNode = NULL; if (pItem) { pSelNode = pItem->pNode; } while (pSelNode != NULL && ok) { Node* pNode = pSelNode; pItem = (NodeListItem *)NodeList.GetNext(pItem); if (pItem) { pSelNode = pItem->pNode; } else { pSelNode = NULL; } if (pNode->IS_KIND_OF(NodeContourController)) { // We now have a selected blend node so: // Invalidate the node's region // Store the current number of blend steps in an undo actiom // Change the number of steps to NewNumSteps NodeRenderableInk * pInk = (NodeRenderableInk *)pNode; UINT32 NumSteps = 0; double DistanceEntered = 0.0; NumSteps = ((NodeContourController *)pNode)->GetNumberOfSteps(); DistanceEntered = 0.0; ChangeContourStepsAction* pAction; // Ask the node if it's ok to do the op ObjChangeFlags cFlags; ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this); ok = pInk->AllowOp(&ObjChange); if (ok) ok = DoInvalidateNodeRegion(pInk,TRUE,FALSE); if (ok) ok = (InvalidateBoundsAction::Init(this,&UndoActions,pInk,TRUE) != AC_FAIL); if (ok) ok = ChangeContourStepsAction::Init(this,&UndoActions,pInk,NumSteps, DistanceEntered, &pAction) != AC_FAIL; if (ok) { if (abs(((NodeContourController *)pNode)->GetWidth()) < NewStepDistance * 2) { ((NodeContourController *)pNode)->SetNumberOfSteps(0); } else { ((NodeContourController *)pNode)->SetNumberOfSteps( (abs(((NodeContourController *)pNode)->GetWidth()) / NewStepDistance) - 1); } pNode->RegenerateNode(NULL, FALSE); } if (ok) ok = DoInvalidateNodeRegion(pInk,TRUE,FALSE); if (ok) ok = (InvalidateBoundsAction::Init(this,&UndoActions,pInk,TRUE) != AC_FAIL); } } } NodeList.DeleteAll(); if (ok) { // Inform the effected parents of the change ObjChangeFlags cFlags; ObjChangeParam ObjChange(OBJCHANGE_FINISHED,cFlags,NULL,this); UpdateChangedNodes(&ObjChange); } else FailAndExecute(); End(); } /******************************************************************************************** > BOOL OpChangeContourStepDistance::Declare() Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Returns: TRUE if all went OK, FALSE otherwise Purpose: Adds the operation to the list of all known operations ********************************************************************************************/ BOOL OpChangeContourStepDistance::Declare() { return (RegisterOpDescriptor( 0, 0, CC_RUNTIME_CLASS(OpChangeContourStepDistance), OPTOKEN_CHANGECONTOURSTEPDISTANCE, OpChangeContourStepDistance::GetState, 0, /* help ID */ 0, /* bubble ID */ 0 /* bitmap ID */ )); } /******************************************************************************************** > static OpState OpChangeContourStepDistance::GetState(String_256* Description, OpDescriptor*) Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Outputs: Description - GetState fills this string with an approriate description of the current state of the operation Returns: The state of the operation, so that menu items (ticks and greying) can be done properly Purpose: Find out the state of the operation at the specific time ********************************************************************************************/ OpState OpChangeContourStepDistance::GetState(String_256* Description, OpDescriptor*) { OpState State(FALSE,TRUE); // It's not ticked, but it is greyed by default // DMc - to test for bevels & contours // are there any contour nodes in the selection List NodeList; BevelTools::BuildListOfSelectedNodes(&NodeList, CC_RUNTIME_CLASS(NodeContourController)); if (!NodeList.IsEmpty()) { State.Greyed = FALSE; } NodeList.DeleteAll(); if (State.Greyed) *Description = String_256(_R(IDS_CONTOURSTEPS)); else *Description = String_256(_R(IDS_CONTOURSTEPS)); return State; } /******************************************************************************************** > virtual void OpChangeContourStepDistance::GetOpName(String_256* OpName) Author: Mark_Neves (Xara Group Ltd) Created: 7/11/94 Inputs: - Outputs: The undo string for the operation Returns: Purpose: The GetOpName fn is overridden so that we return back a description appropriate to the type of attribute that the operation applies. Errors: - SeeAlso: - ********************************************************************************************/ void OpChangeContourStepDistance::GetOpName(String_256* OpName) { *OpName = String_256(_R(IDS_CONTOURSTEPS_UNDO)); } ///////////////////////////////////////////////////////////////// // OpConvertPathToShapes class /******************************************************************************************** > BOOL OpConvertPathToShapes::Declare() Author: David_McClarnon (Xara Group Ltd) Created: 10/2/2000 Returns: TRUE if all went OK, False otherwise Purpose: Adds the operation to the list of all known operations ********************************************************************************************/ BOOL OpConvertPathToShapes::Declare() { return (RegisterOpDescriptor( 0, _R(IDS_CONVERTPATHTOSHAPES), CC_RUNTIME_CLASS(OpConvertPathToShapes), OPTOKEN_CONVERTPATHTOSHAPES, OpConvertPathToShapes::GetState)); } /******************************************************************************************** > OpState OpConvertPathToShapes::GetState(String_256* Description, OpDescriptor*); Author: David_McClarnon (Xara Group Ltd) Created: 10/2/2000 Returns: TRUE if all went OK, False otherwise Purpose: Gets the state of the operation ********************************************************************************************/ OpState OpConvertPathToShapes::GetState(String_256* Description, OpDescriptor*) { OpState Blobby; // do greyed for no selection Range * pSel = GetApplication()->FindSelection(); Blobby.Greyed = FALSE; if (!pSel) { Blobby.Greyed = TRUE; return Blobby; } // If there is nothing selected, grey the item and give a reason. if (pSel->IsEmpty()) { Blobby.Greyed = TRUE; *Description = String_256 (_R(IDS_NO_OBJECTS_SELECTED)); return Blobby; } // run through the range finding out if any nodes have promote hit test on // children to me set in their parents, or are needs parent nodes Node * pNode = pSel->FindFirst(); Node * pSubNode = NULL; Node * pParent = NULL; while (pNode && Blobby.Greyed == FALSE) { if (pNode->NeedsParent(NULL)) { Blobby.Greyed = TRUE; break; } pParent = pNode->FindParent(); while (pParent) { if (pParent->ShouldITransformWithChildren()) { Blobby.Greyed = TRUE; break; } pParent = pParent->FindParent(); } // check all nodes under this node too pSubNode = pNode->FindFirstDepthFirst(); while (pSubNode && pSubNode != pNode) { if (pSubNode->NeedsParent(NULL) || pSubNode->ShouldITransformWithChildren()) { Blobby.Greyed = TRUE; break; } pSubNode = pSubNode->FindNextDepthFirst(pNode); } pNode = pSel->FindNext(pNode); } return Blobby; } /******************************************************************************************** > void OpConvertPathToShapes::Do(OpDescriptor * pDesc) Author: David_McClarnon (Xara Group Ltd) Created: 10/2/2000 Returns: Purpose: Does the operation ********************************************************************************************/ void OpConvertPathToShapes::Do(OpDescriptor * pDesc) { // run through the sel range, dealing with every node DoStartSelOp(TRUE, TRUE, TRUE, TRUE); Range * pSel = GetApplication()->FindSelection(); if (!pSel) { FailAndExecute(); End(); return; } Node * pNode = pSel->FindFirst(); Node * pNextNode = NULL; while (pNode) { // must get the next node first since the geometry will change pNextNode = pSel->FindNext(pNode); if (pNode->IsAnObject()) { if (!ConvertPathToShapes(this, (NodeRenderableInk *)pNode)) { FailAndExecute(); End(); return; } } pNode = pNextNode; } End(); } /******************************************************************************************** > void OpConvertPathToShapes::GetOpName(String_256* OpName) Author: David_McClarnon (Xara Group Ltd) Created: 10/2/2000 Returns: Purpose: Gets the op's name ********************************************************************************************/ void OpConvertPathToShapes::GetOpName(String_256* OpName) { if (OpName) { OpName->Load(_R(IDS_CONVERTPATHTOSHAPES)); } } /******************************************************************************************** > static BOOL OpConvertPathToShapes::ConvertPathToShapes(OpConvertPathToShapes* pOp, NodeRenderableInk* pInk) Author: David_McClarnon (Xara Group Ltd) Created: 10/2/2000 Inputs: pOp - pointer to the op doing this (can be NULL for external use) pInk - the node to convert Returns: TRUE for success, FALSE for failure Purpose: Does the convert DY 28/11/2000 Some serious changes have taken place now, in order to deal with groups of objects containing brushes or strokes. Basically the following can occur: - pInk is a single ink object with a brush or stroke attribute, in which case it is dealt with indiviually in ConvertBrush/Stroke. - pInk is an ink object with no brush or stroke attribute - basically the old case, here we simply sum the paths of pInk and make a new shape out of them. - pInk is a group containing any combination of normal shapes, brushed or stroked shapes. This is the difficult case, basically the ConvertPathToShapesBecomeA passback function will store converted brushes and strokes under a group context node (though there is one exception to this, where there are no brushes), and stores the summed paths of any normal shapes. We then extract these and put them all under one new group. ********************************************************************************************/ BOOL OpConvertPathToShapes::ConvertPathToShapes(OpConvertPathToShapes* pOp, NodeRenderableInk* pInk) { // UINT32 NumObjs = 0; // first, find out whether we have a non-transparent line attribute // if we do, then lets not do anything. // BUT, if we do; then lets get on a do some funky stuff .... // i.e. make the line colour into the fill colour for this node AttrStrokeColour * pColour = NULL; pInk->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeColour), (NodeAttribute **)(&pColour)); ConvertPathToShapesBecomeA MyBecomeA(BECOMEA_PASSBACK, CC_RUNTIME_CLASS(NodePath), pOp, FALSE); if (pColour) { StrokeColourAttribute * pAttrVal = (StrokeColourAttribute *)pColour->GetAttributeValue(); if (pAttrVal->Colour.IsTransparent ()) { return TRUE; } if (!pInk->CanBecomeA(&MyBecomeA)) { ERROR3("Ink node cannot become nodepath in OpConvertPathToShapes::ConvertPathToShapes"); return TRUE; } } /* find out if we have an applied brush node, if so then do our own thing Note that this block must always be before the Stroke attribute block because the stroke attribute, when used in conjunction with the brush attribute, acts as a pressure provider to the brush */ // NodeAttribute* pAttr = NULL; AttrBrushType* pBrush = NULL; pInk->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBrushType), (NodeAttribute**)&pBrush); // note that this only deals with a single ink node case, it cannot deal with groups if (pBrush != NULL && pBrush->GetBrushHandle() != BrushHandle_NoBrush && !pInk->IsCompound()) { if (ConvertBrush(pOp, pBrush, pInk)) return TRUE; } // We have another special case if there is a stroke attribute applied AttrStrokeType* pStroke = NULL; pInk->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeType), (NodeAttribute**)&pStroke); AttrVariableWidth* pVarWidth = NULL; pInk->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrVariableWidth), (NodeAttribute**)&pVarWidth); /* This next block exists as the simplest stroke case, and allows us to avoid making any groups, however we can only enter the next block if we are a single ink node with an an acitve stroke applied the entry conditions to this block: - Do you have an active PathProcessorStroke? - Do you have an active VariableWidthFunction? - Are you not compound? */ if (pStroke != NULL && pStroke->HasPathProcessor() && pVarWidth != NULL && pVarWidth->HasActiveValueFunction() &&!pInk->IsCompound()) { BOOL Success = ConvertStroke(pOp, pStroke, pInk); if (Success) { // invalidate the node so we get rid of any fill there might have been DocRect BRect = pInk->GetBoundingRect(); pInk->ReleaseCached(); Spread* pSpread = Document::GetSelectedSpread(); if (pOp != NULL && pSpread != NULL) pOp->DoInvalidateRegion(pSpread, BRect); pInk->SetSelected(FALSE); NodeHidden * pHidden = NULL; if (pOp) return pOp->DoHideNode(pInk, TRUE, &pHidden, FALSE); else { pInk->CascadeDelete(); delete pInk; return(TRUE); } } } /* If we have reached this point then we are one of the following: - A group, potentially containing various combinations of brushes or strokes - A single normal ink node, with no brush or stroke applied */ // create the new path node NodePath * pNewNode = NULL; ALLOC_WITH_FAIL(pNewNode, new NodePath, pOp); pNewNode->InkPath.Initialise(); if (pOp) pOp->DoLocaliseForAttrChange(pInk, (AttrTypeSet *)NULL, (ObjectSet *)NULL); else { Node* pParent = pInk->FindParent(); ERROR3IF(!pParent, "UndoableOperation::DoLocaliseForAttrChange called on an object which has no parent"); if (pParent->IsCompound()) { ((NodeRenderableInk*)pParent)->LocaliseCommonAttributes(FALSE, TRUE, NULL); } } // we need a group to store any groups of strokes we might have NodeRenderableInk* pGroup = NULL; // Do the conversion pInk->DoBecomeA(&MyBecomeA); // the summed path consists of the outlines of all the normal (i.e. non-brush or stroke) objects MyBecomeA.GetSummedPath(&(pNewNode->InkPath)); // the context node is a group under which all strokes and brushes are placed pGroup = MyBecomeA.GetContextNode(); // Right, some changes here to do with the case where we have strokes and brushes in a group // basically the BecomeA mechanism will have dealt with them separately, and generated a nodegroup // out of any brushes we may have had, and summed the paths of all other nodes. // first deal with any summed paths we may have generated if (pNewNode->InkPath.GetNumCoords() > 0) { AdjustStrokeAndFillAttrs(pOp, pNewNode, pInk); } else { delete pNewNode; pNewNode = NULL; } BOOL ok = TRUE; // ok, if we have a) a group and a nodepath or b) a group with a sibling, // then we'll make an extra nodegroup to store them under if ((pNewNode && pGroup) || (pGroup && pGroup->FindNext())) { NodeGroup* pNewGroup = NULL; ALLOC_WITH_FAIL(pNewGroup, new NodeGroup, pOp); if (pNewGroup) { pGroup->InsertChainSimple(pNewGroup, LASTCHILD); if (pNewNode) pNewNode->AttachNode(pNewGroup, LASTCHILD); } if (pOp) { ok = pOp->DoInsertNewNode(pNewGroup, pInk, NEXT, TRUE, FALSE, TRUE, TRUE); if (ok) ok = pOp->DoFactorOutAfterAttrChange(pNewGroup, (AttrTypeSet *)NULL); } else { pNewGroup->AttachNode(pInk, NEXT); Node* pParent; pParent = pNewGroup->FindParent(); ERROR3IF(!pParent, "Trying to FactorOutCommonChildAttributes on an object which has no parent"); if (pParent->IsCompound()) { ((NodeRenderableInk*)pParent)->FactorOutCommonChildAttributes(TRUE, (AttrTypeSet *)NULL); } } } else if (pNewNode != NULL) { // otherwise we've only got one new node, made from non-strokes and brushes if (pOp) { ok = pOp->DoInsertNewNode(pNewNode, pInk, NEXT, TRUE, FALSE, TRUE, TRUE); // if (ok) ok = DoFactorOutAfterAttrChange(pNewNode, (AttrTypeSet *)NULL); } else { pNewNode->AttachNode(pInk, NEXT); } } else if (pGroup != NULL) { if (pOp) { ok = pOp->DoInsertNewNode(pGroup, pInk, NEXT, TRUE, FALSE, TRUE, TRUE); if (ok) ok = pOp->DoFactorOutAfterAttrChange(pGroup, (AttrTypeSet *)NULL); } else { pGroup->AttachNode(pInk, NEXT); Node* pParent; pParent = pGroup->FindParent(); ERROR3IF(!pParent, "Trying to FactorOutCommonChildAttributes on an object which has no parent"); if (pParent->IsCompound()) { ((NodeRenderableInk*)pParent)->FactorOutCommonChildAttributes(TRUE, (AttrTypeSet *)NULL); } } } if (pOp) { pOp->DoFactorOutAfterAttrChange(pInk, (AttrTypeSet *)NULL); } else { Node* pParent; pParent = pInk->FindParent(); ERROR3IF(!pParent, "Trying to FactorOutCommonChildAttributes on an object which has no parent"); if (pParent->IsCompound()) { ((NodeRenderableInk*)pParent)->FactorOutCommonChildAttributes(TRUE, (AttrTypeSet *)NULL); } } pInk->SetSelected(FALSE); // Hide the original ink node if (pOp) { NodeHidden * pHidden = NULL; if (ok) ok = pOp->DoHideNode(pInk, TRUE, &pHidden, FALSE); } else { pInk->CascadeDelete(); delete pInk; } return ok; } /******************************************************************************************** > static BOOL OpConvertPathToShapes::ConvertBrush(OpConvertPathToShapes* pOp, AttrBrushType* pAttrBrush, NodeRenderableInk* pInk) Author: Diccon_Yamanaka (Xara Group Ltd) Created: 28/11/2000 Inputs: pAttrBrush - the brush attribute that is applied to the node we wish to convert pInk - the node we wish to convert Returns: TRUE for success, FALSE for failure Purpose: To convert nodes with a brush attribute applied to them. Note that this ONLY works for single nodes, compound nodes are dealt with in the main Convert function as there are many different possible permutations. ********************************************************************************************/ BOOL OpConvertPathToShapes::ConvertBrush(OpConvertPathToShapes* pOp, AttrBrushType* pAttrBrush, NodeRenderableInk* pInk) { ERROR2IF(pAttrBrush == NULL || pInk == NULL, FALSE, "Inputs are NULL to OpConvertPathToShapes::ConvertBrush"); if (pInk->IsCompound()) { ERROR3("Attempting to convert brush on a compound node when we really shouldn't be"); return FALSE; } PathProcessorBrush* pPPB = pAttrBrush->GetPathProcessor(); if (pPPB == NULL) { ERROR3("Brush has no path processor in OpConvertPathToShapes::ConvertBrush"); return FALSE; } // Fairly simple, as we let the attributes becomea function do the work pInk->ReleaseCached(); // This call is associated with the DoInvalidateRegion call below // but must be called before pInk is removed from the tree pInk->SetSelected(FALSE); BecomeA BecomeAPath(BECOMEA_REPLACE,CC_RUNTIME_CLASS(NodePath), pOp, FALSE); BOOL Retval = pAttrBrush->DoBecomeA(&BecomeAPath, pInk); // If DoBecomeA worked, pInk is no longer in the tree... // invalidate the node so we get rid of any fill there might have been if (pOp) { DocRect BRect = pAttrBrush->GetAttrBoundingRect(pInk); Spread* pSpread = Document::GetSelectedSpread(); if (pSpread != NULL) pOp->DoInvalidateRegion(pSpread, BRect); } return Retval; } /******************************************************************************************** > static BOOL OpConvertPathToShapes::ConvertStroke(OpConvertPathToShapes* pOp, AttrStrokeType* pStroke, NodeRenderableInk* pInk) Author: Diccon_Yamanaka (Xara Group Ltd) Created: 28/11/2000 Inputs: pStroke - the stroke attribute that is applied to the node we wish to convert pInk - the node we wish to convert Returns: TRUE for success, FALSE for failure Purpose: To convert nodes with a stroke attribute applied to them. Note that this ONLY works for single nodes, compound nodes are dealt with in the main Convert function as there are many different possible permutations. Note that this function assumes that there is also an AttrVariableWidth applied to pInk, if there is not then your stroke attr just won't do anything. ********************************************************************************************/ BOOL OpConvertPathToShapes::ConvertStroke(OpConvertPathToShapes* pOp, AttrStrokeType* pStroke, NodeRenderableInk* pInk) { ERROR2IF(pStroke == NULL || pInk == NULL, FALSE, "Inputs are NULL to OpConvertPathToShapes::ConvertBrush"); if (pInk->IsCompound()) { ERROR3("Attempting to convert brush on a compound node when we really shouldn't be"); return FALSE; } // we need the path processor to do the work PathProcessorStroke* pPPS = pStroke->GetPathProcessor(); if (pPPS == NULL) { ERROR3("Can't get PathProcessorStroke in OpConvertPathToShapes::ConvertStroke"); return FALSE; } // Use a SimpleBecomeA to get the path from the parent object SimpleBecomeA BecomeA(BECOMEA_PASSBACK, CC_RUNTIME_CLASS(NodePath), NULL); BOOL Retval = FALSE; if (pInk->DoBecomeA(&BecomeA)) { NodePath* pNodePath = BecomeA.GetNodePath(); if (pNodePath) { NodePath* pStrokePath = pPPS->GetSmoothProcessedPath(&(pNodePath->InkPath), pInk); if (pStrokePath) { // Karim 05/12/2000 // process the returned stroke, to change its working // winding rule from non-zero to even-odd. Path* pInkStrokePath = &(pStrokePath->InkPath); double Flatness = pInkStrokePath->CalculateFlatnessValueFromPath(750.0, 2.0, 375.0); pInkStrokePath->ClipPathToPath(*pInkStrokePath, pInkStrokePath, 3 | 0x10, 20, Flatness, Flatness); // We've got the path we wish to use if (AdjustStrokeAndFillAttrs(pOp, pStrokePath, pInk)) { if (pOp) Retval = pOp->DoInsertNewNode(pStrokePath, pInk, NEXT, TRUE, FALSE, TRUE, TRUE); else { pStrokePath->AttachNode(pInk, NEXT); Retval = TRUE; } } else { delete pStrokePath; } } delete pNodePath; pNodePath = NULL; } else { ERROR3("Failed to get nodepath from ink object in OpConvertPathToShapes::ConvertStroke"); } } return Retval; } /******************************************************************************************** > static BOOL OpConvertPathToShapes::AdjustStrokeAndFillAttrs(OpConvertPathToShapes* pOp, NodePath* pNewNode, NodeRenderableInk* pCreatedByNode = NULL, CCAttrMap* pAttrMap = NULL) Author: Diccon_Yamanaka (Xara Group Ltd) Created: 28/11/2000 Inputs: pNewNode - the newpath node that we have inserted into the tree pCreatedByNode - the original node that created pNewNode, can be null pAttrMap - if pCreatedByNode is not supplied then an attrmap of the creator node must be supplied Returns: TRUE for success, FALSE for failure Purpose: This is only of use for ink nodes that had a variable width stroke attribute applied to them. In this case we wish to take the old stroke colour and make it into a new fill colour for pNewNode. We also wish to apply a transparent stroke colour. ********************************************************************************************/ BOOL OpConvertPathToShapes::AdjustStrokeAndFillAttrs(OpConvertPathToShapes* pOp, NodePath* pNewNode, NodeRenderableInk* pCreatedByNode, CCAttrMap* pAttrMap) { ERROR2IF(pNewNode == NULL, FALSE, "New node is NULL in OpConvertPathToShapes::AdjustStrokeAndFillAttrs"); ERROR2IF(pCreatedByNode == NULL && pAttrMap == NULL, FALSE, "Both parent node and attrmap are NULL in OpConvertPathToShapes::AdjustStrokeAndFillAttrs"); pNewNode->InkPath.IsFilled = TRUE; pNewNode->InkPath.IsStroked = TRUE; pNewNode->InkPath.InitialiseFlags(); // we need to get the stroke colour of our original object AttrStrokeColour * pColour = NULL; // look up this attribute if (pCreatedByNode) { pCreatedByNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeColour), (NodeAttribute **)(&pColour)); } else { pAttrMap->Lookup(CC_RUNTIME_CLASS(AttrStrokeColour), (void*&)pColour); } // make a new flat fill attribute and apply this to the node if (pColour) { StrokeColourAttribute * pAttrVal = (StrokeColourAttribute *)pColour->GetAttributeValue(); if (pAttrVal) { AttrFlatColourFill *pFill = NULL; ALLOC_WITH_FAIL(pFill, new AttrFlatColourFill(pNewNode, FIRSTCHILD), pOp); if (pFill) pFill->SetStartColour(&(pAttrVal->Colour)); } } else ERROR3("Unable to find stroke colour in OpConvertPathToShapes::AdjustStrokeAndFillAttrs"); // If we've got a current fill transparency then leave it alone AttrFillGeometry* pTranspFill = NULL; if (pCreatedByNode) { pCreatedByNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTranspFillGeometry), (NodeAttribute**)&pTranspFill); } else { pAttrMap->Lookup(CC_RUNTIME_CLASS(AttrTranspFillGeometry), (void*&)pTranspFill); } if (pTranspFill && !pTranspFill->IsAFlatFill()) { Node* pNewTranspFill = NULL; ALLOC_WITH_FAIL(pNewTranspFill, pTranspFill->PublicCopy(), pOp); if (pNewTranspFill) { pNewTranspFill->AttachNode(pNewNode, FIRSTCHILD); } } else { // if we've got a current stroke transparency then lets convert this to a fill transparency AttrStrokeTransp* pTransp = NULL; if (pCreatedByNode) { pCreatedByNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeTransp), (NodeAttribute**)&pTransp); } else { pAttrMap->Lookup(CC_RUNTIME_CLASS(AttrStrokeTransp), (void*&)pTransp); } if (pTransp) { // make a flatfill transp and apply it AttrFlatTranspFill* pTranspFill = NULL; ALLOC_WITH_FAIL(pTranspFill, new AttrFlatTranspFill(pNewNode, FIRSTCHILD), pOp); if (pTranspFill) { pTranspFill->SetStartTransp(&pTransp->Value.Transp); pTranspFill->SetTranspType(pTransp->Value.TranspType); } } } // apply a transparent line colour AttrStrokeColour * pTranspAttr = NULL; ALLOC_WITH_FAIL(pTranspAttr, new AttrStrokeColour(pNewNode, FIRSTCHILD), pOp); if (pTranspAttr) { StrokeColourAttribute * pTranspVal = (StrokeColourAttribute *)pTranspAttr->GetAttributeValue(); pTranspVal->Colour = DocColour(COLOUR_NONE); } // apply a line width AttrLineWidth* pLineWidth = NULL; ALLOC_WITH_FAIL(pLineWidth, new AttrLineWidth(pNewNode, FIRSTCHILD), pOp); if (pLineWidth) pLineWidth->Value.LineWidth = 500; AttrWindingRule * pWindingRule = NULL; ALLOC_WITH_FAIL(pWindingRule, new AttrWindingRule(pNewNode, LASTCHILD), pOp); if (pWindingRule) pWindingRule->Value.WindingRule = NegativeWinding; return TRUE; } /////////////////////////////////////////////////////////////// // The becomeA structure for the above /******************************************************************************************** > ConvertPathToShapesBecomeA::ConvertPathToShapesBecomeA( BecomeAReason Reason, CCRuntimeClass* pClass, UndoableOperation* pOp, BOOL Sel) : BecomeA(Reason, pClass, pOp, Sel) Author: David_McClarnon (Xara Group Ltd) Created: 10/2/2000 Inputs: See base class Purpose: Constructor (initialises the path) ********************************************************************************************/ ConvertPathToShapesBecomeA::ConvertPathToShapesBecomeA( BecomeAReason Reason, CCRuntimeClass* pClass, UndoableOperation* pOp, BOOL Sel) : BecomeA(Reason, pClass, pOp, Sel) { m_SummedPath.Initialise(); m_pContextNode = NULL; } /******************************************************************************************** > BOOL ConvertPathToShapesBecomeA::PassBack(NodeRenderableInk* pNewNode, NodeRenderableInk* pCreatedByNode, CCAttrMap* pAttrMap=NULL) Author: David_McClarnon (Xara Group Ltd) Inputs: See base class Outputs: TRUE for success, FALSE for failure Created: 10/2/2000 Purpose: The passback function for the convert path to shapes operation Just stores the path passed in so that the operation can use it DY 28/11/2000 This has been changed to deal with what gets passed back by brush and stroke attributes. So basically there are three cases: 1) No brush or stroke attributes applied: Easy, we just add the paths to the summed path that we are storing. 2) Stroke attribute applied: We ask the stroke for its stroked path and store it as a sibling to our context node. 3) Brush applied: Somewhat more complex - the BrushBecomeAGroup does pretty much what its name suggests, and we store the returned group under the context node. Recall that if both a brush and a stroke are applied then the stroke acts as a pressure provider to the brush. ********************************************************************************************/ BOOL ConvertPathToShapesBecomeA::PassBack(NodeRenderableInk* pNewNode, NodeRenderableInk* pCreatedByNode, CCAttrMap* pAttrMap) { // continuity checks if (!pNewNode || !pCreatedByNode) { ERROR3("The new node or the created by node is NULL"); return FALSE; } if (!pNewNode->IsNodePath()) { ERROR3("New node isn't a node path"); return FALSE; } // if (!GetUndoOp()) // { // ERROR3("No operation defined"); // return FALSE; // } // first, if we've not been given an attribute map, then create one if (!pAttrMap) { CCAttrMap * pXMap = CCAttrMap::MakeAppliedAttrMap(pCreatedByNode); pAttrMap = pXMap->Copy(); delete pXMap; // exit if we don't have an attribute map if (!pAttrMap) { pNewNode->DeleteChildren(pNewNode->FindFirstChild()); delete pNewNode; ERROR3("Couldn't create attribute map"); return FALSE; } } NodePath * pPathNode = NULL; // Pre release bodge - DY 15/11 Brush attributes should really be catered for in MakeNodePathFromAttributes // but that has too many potential knock-on effects for me to test now AttrBrushType* pAttrBrush = NULL; pAttrMap->Lookup(CC_RUNTIME_CLASS(AttrBrushType), (void*&)pAttrBrush); if (pAttrBrush && pAttrBrush->GetBrushHandle() != BrushHandle_NoBrush) { //Turn the brush into a group with lots of nodepaths BrushBecomeAGroup BecomeA(BECOMEA_PASSBACK, CC_RUNTIME_CLASS(NodePath), GetUndoOp()); pAttrBrush->DoBecomeA(&BecomeA, pCreatedByNode); // the brush will create a group out of itself and we want to retrieve that NodeGroup* pBrushGroup = BecomeA.GetNodeGroup(); if (pBrushGroup != NULL) { if (m_pContextNode == NULL) { m_pContextNode = pBrushGroup; } else { // insert as the last sibling Node* pNode = m_pContextNode; Node* pNext = NULL; while (pNode) { pNext = pNode->FindNext(); if (pNext == NULL) pBrushGroup->AttachNode(pNode, NEXT); pNode = pNext; } } } else ERROR3("Failed to create node group!"); pAttrMap->DeleteAttributes(); delete pAttrMap; delete pNewNode; return TRUE; } // likewise if we have an active stroke attribute AttrStrokeType* pStroke = NULL; pAttrMap->Lookup(CC_RUNTIME_CLASS(AttrStrokeType), (void*&)pStroke); AttrVariableWidth* pVarWidth = NULL; pAttrMap->Lookup(CC_RUNTIME_CLASS(AttrVariableWidth), (void*&)pVarWidth); if (pStroke && pStroke->HasPathProcessor() && pVarWidth && pVarWidth->HasActiveValueFunction()) { PathProcessorStroke* pPPS = pStroke->GetPathProcessor(); Path* pPath = &((NodePath*)pNewNode)->InkPath; NodePath* pStrokedPath = pPPS->GetSmoothProcessedPath(pPath, pCreatedByNode); if (pStrokedPath) { // if we don't have a context node then make one if (m_pContextNode == NULL) { ALLOC_WITH_FAIL(m_pContextNode, new NodeGroup, GetUndoOp()); if (m_pContextNode == NULL) { delete pStrokedPath; return FALSE; } } // Karim 05/12/2000 // process the returned stroke, to change its working // winding rule from non-zero to even-odd. Path* pInkStrokePath = &(pStrokedPath->InkPath); double Flatness = pInkStrokePath->CalculateFlatnessValueFromPath(750.0, 2.0, 375.0); pInkStrokePath->ClipPathToPath(*pInkStrokePath, pInkStrokePath, 3 | 0x10, 20, Flatness, Flatness); // bit of a hack here, but it avoids some code duplication. Basically OpConvertPathToShapes // has a really handy function doing all the things you need to do when converting a stroked shape // to a path, so we're going to assume that our undo op is definitely an OpConvertPathToShapes. UndoableOperation* pOp = GetUndoOp(); if (pOp == NULL || pOp->IsKindOf(CC_RUNTIME_CLASS(OpConvertPathToShapes))) { OpConvertPathToShapes* pConvert = (OpConvertPathToShapes*)pOp; OpConvertPathToShapes::AdjustStrokeAndFillAttrs(pConvert, pStrokedPath, NULL, pAttrMap); } // insert as the last sibling Node* pNode = m_pContextNode; Node* pNext = NULL; while (pNode) { pNext = pNode->FindNext(); if (pNext == NULL) pStrokedPath->AttachNode(pNode, NEXT); pNode = pNext; } pAttrMap->DeleteAttributes(); delete pAttrMap; delete pNewNode; return TRUE; } } // This deals with the case if we have neither a brush or stroke attribute, // simply sum the paths. double Flatness = ((NodePath *)pNewNode)->InkPath.CalculateFlatnessValueFromPath(750.0, 1.0, 375.0); pPathNode = ((NodePath *)pNewNode)->MakeNodePathFromAttributes(Flatness, pAttrMap, TRUE); // ensure that the path is correct by clipping it Path BlankPath; BlankPath.Initialise(); Path ClipPath; ClipPath.Initialise(); // delete the new node pNewNode->DeleteChildren(pNewNode->FindFirstChild()); delete pNewNode; pAttrMap->DeleteAttributes(); delete pAttrMap; if (!pPathNode) { return FALSE; } /* // smooth the new node's path double Error = SMOOTH_MIN + (SMOOTH_MAX - SMOOTH_MIN)*pow((35/100), 3.0); FitCurveNoChangeGeometry::SmoothPath(&(pPathNode->InkPath), Error); */ DocRect dr1(0,0,0,0); DocRect dr2(0,0,0,0); m_SummedPath.GetTrueBoundingRect(&dr1); pPathNode->InkPath.GetTrueBoundingRect(&dr2); // now, let's add this node to the become A path // if (m_SummedPath.GetBoundingRect().IsIntersectedWith(pPathNode->InkPath.GetBoundingRect())) MRH 19/5/00 if (dr1.IsIntersectedWith(dr2)) { Path OrigPath; OrigPath.Initialise(); OrigPath.CloneFrom(m_SummedPath); m_SummedPath.ClearPath(); OrigPath.ClipPathToPath(pPathNode->InkPath, &m_SummedPath, 7 | CLIPPING_CLIP_WINDING, 50, 50, 50); } else { m_SummedPath.MergeTwoPaths(pPathNode->InkPath); } delete pPathNode; return TRUE; } /******************************************************************************************** > NodeRenderableInk* ConvertPathToShapesBecomeA::GetContextNode() Author: Diccon_Yamanaka (Xara Group Ltd) Inputs: - Outputs: The context node that was generated to hold brushes or strokes converted to shapes, or NULL if there isn't one Created: 10/2/2000 Purpose: Having potentially converted brushes or strokes to shapes we need to retrieve them. This can take a couple of forms, depending on what was converted: 1 brush will return one group containing nodepaths of the brush objects >1 brush will return a group, with group children containing the brushes 1 or more brushes + 1 or more strokes will return a group Strokes ONLY - will return a nodepath, which will contain any other strokes as its siblings. ********************************************************************************************/ NodeRenderableInk* ConvertPathToShapesBecomeA::GetContextNode() { if (m_pContextNode == NULL) return NULL; NodeRenderableInk* pRetNode = m_pContextNode; // if the context node has no children then we have no brushes, only strokes, so return the first sibling if (pRetNode->FindFirstChild() == NULL) { // we will have inserted any strokes as siblings to the context node pRetNode = static_cast(pRetNode->FindNext()); if (pRetNode == NULL) { ERROR3("Urk, we don't seem to have anything to return in ConvertPathToShapesBecomeA::GetContextNode"); } // unhook the context node and delete it m_pContextNode->CascadeDelete(); delete m_pContextNode; } m_pContextNode = NULL; return pRetNode; } ///////////////////////////////////////////////////////////////////// // OpToggleContourInsetPath class /******************************************************************************************** > BOOL OpToggleContourInsetPath::Declare() Author: David_McClarnon (Xara Group Ltd) Created: 10/2/2000 Returns: TRUE if all went OK, False otherwise Purpose: Adds the operation to the list of all known operations ********************************************************************************************/ BOOL OpToggleContourInsetPath::Declare() { return (RegisterOpDescriptor( 0, _R(IDS_INSETPATHOP), CC_RUNTIME_CLASS(OpToggleContourInsetPath), OPTOKEN_TOGGLEINSETPATH, OpToggleContourInsetPath::GetState)); } /******************************************************************************************** > OpState OpToggleContourInsetPath::GetState(String_256* Description, OpDescriptor*); Author: David_McClarnon (Xara Group Ltd) Created: 10/2/2000 Returns: TRUE if all went OK, False otherwise Purpose: Gets the state of the operation ********************************************************************************************/ OpState OpToggleContourInsetPath::GetState(String_256* Description, OpDescriptor*) { OpState Blobby; // are there any contours in the selection ? List ContourList; BevelTools::BuildListOfSelectedNodes(&ContourList, CC_RUNTIME_CLASS(NodeContour)); if (ContourList.IsEmpty()) { Blobby.Greyed = TRUE; } else { ContourList.DeleteAll(); } return Blobby; } /******************************************************************************************** > void OpToggleContourInsetPath::Do(OpDescriptor * pDesc, OpParam * pParam) Author: David_McClarnon (Xara Group Ltd) Created: 10/2/2000 Returns: Purpose: Does the operation ********************************************************************************************/ void OpToggleContourInsetPath::DoWithParam(OpDescriptor * pDesc, OpParam * pParam) { DoStartSelOp(TRUE, TRUE); if (!GetApplication()->FindSelection()) { End(); return; } BOOL bFlag = FALSE; if (pParam->Param1) bFlag = TRUE; // BOOL ok = TRUE; if (bFlag) m_OpName = _R(IDS_INSETPATH_OP_UNDO_NAME); else m_OpName = _R(IDS_INSETPATH_OP_REDO_NAME); List ContourList; BevelTools::BuildListOfSelectedNodes(&ContourList, CC_RUNTIME_CLASS(NodeContourController)); NodeListItem * pItem = (NodeListItem *)ContourList.GetHead(); // ToggleInsetPathAction * pAction = NULL; NodeContour * pContour = NULL; NodeContourController * pController = NULL; NodeHidden * pHidden = NULL; Node * pChild = NULL; // Node * pNext = NULL; // Node * pNodeGroup = NULL; CCAttrMap AttrMap; // NodeContour * pContourCopy = NULL; BOOL IsAnOuter = TRUE; while (pItem) { pController = (NodeContourController *)pItem->pNode; pContour = (NodeContour *)pController->FindFirstChild(CC_RUNTIME_CLASS(NodeContour)); if (!pController || !pContour) goto FailExit; IsAnOuter = pController->IsContourAnOuterContour(); if (bFlag) { // only swap attributes when you're going from a contour to an inset path node // now, try to find the first appropriate node to take an attribute map from to // copy over to the contour node pChild = pController->FindFirstDepthFirst(); while (pChild) { if (pChild->IsAnObject() && !pChild->IS_KIND_OF(NodeContour) && !pChild->IsCompound()) { if (((NodeRenderableInk *)pChild)->FindAppliedAttributes(&AttrMap)) { /* // create a copy of the contour node, and apply this attribute map to it pContourCopy = (NodeContour *)pContour->PublicCopy(); AttrMap.ApplyAttributesToNode(pContourCopy); // insert this node into the tree after the contour node if (!DoInsertNewNode(pContourCopy, pContour, NEXT, TRUE, FALSE, FALSE, TRUE)) { goto FailExit; } if (!DoHideNode(pContour, TRUE, &pHidden, TRUE)) goto FailExit; */ // Create and initialize a new NodePath to hold the inset path! NodePath* pNewPath; ALLOC_WITH_FAIL(pNewPath, new NodePath, this); pNewPath->InkPath.Initialise(); DoInvalidateNodeRegion(pController,FALSE); // Create the DoBecomeA Function and call it on the controller BecomeA BecomeAReplace(BECOMEA_REPLACE, CC_RUNTIME_CLASS(NodePath), this, FALSE); pContour->DoBecomeA(&BecomeAReplace); // Now get the relavent path from the group of path nodes NodePath* pPathToCopy = NULL; if(IsAnOuter) pPathToCopy = (NodePath*)pController->FindFirstChild(CC_RUNTIME_CLASS(NodePath)); else pPathToCopy = (NodePath*)pController->FindLastChild(CC_RUNTIME_CLASS(NodePath)); pNewPath->InkPath.CloneFrom(pPathToCopy->InkPath); // now Initialize the flag array with the new Path and insert it after the group node! pNewPath->InkPath.InitialiseFlags(0, pNewPath->InkPath.GetNumCoords()); DoInsertNewNode(pNewPath, pController, NEXT, TRUE, FALSE, TRUE, TRUE); pNewPath->InkPath.IsFilled = TRUE; // Make sure we have the correct attributes applied to our new path and make it selected! AttrMap.ApplyAttributesToNode(pNewPath); pNewPath->NormaliseAttributes(); pNewPath->SetSelected(TRUE); DoHideNode(pController, TRUE, &pHidden, TRUE); // ok we're out break; } } pChild = pChild->FindNextDepthFirst(pController); } } /* if (ToggleInsetPathAction::Init(this, GetUndoActionList(), pController, bFlag, &pAction) != AC_OK) { goto FailExit; } // make sure that the controller node is deselected and the contour node is pController->SetSelected(FALSE); if (pContourCopy) pContourCopy->SetSelected(TRUE); // do a do become a on the controller BecomeA BecomeAReplace(BECOMEA_REPLACE, CC_RUNTIME_CLASS(NodePath), this, FALSE); pController->DoBecomeA(&BecomeAReplace); */ pItem = (NodeListItem *)ContourList.GetNext(pItem); } ContourList.DeleteAll(); if (GetApplication()->FindSelection()) { GetApplication()->FindSelection()->Update(TRUE); } End(); return; FailExit: FailAndExecute(); End(); } /******************************************************************************************** > void OpToggleContourInsetPath::GetOpName(String_256* OpName) Author: David_McClarnon (Xara Group Ltd) Created: 10/2/2000 Returns: Purpose: Gets the op's name ********************************************************************************************/ void OpToggleContourInsetPath::GetOpName(String_256* OpName) { if (OpName) { OpName->Load(m_OpName); } } ////////////////////////////////////////////////////////////////// // The ToggleInsetPathAction class /******************************************************************************************** > ToggleInsetPathAction::ToggleInsetPathAction() Author: Olivier_Gascoin (Xara Group Ltd) Created: 07/01/97 Inputs: - Outputs: - Returns: - Purpose: Constructor for the action Errors: - SeeAlso: - ********************************************************************************************/ ToggleInsetPathAction::ToggleInsetPathAction() { m_pNode = NULL; } /******************************************************************************************** > ActionCode ToggleInsetPathAction::Init( Operation* pOp, ActionList* pActionList, NodeContourController * pNode ChangePositionShadowXAction** ppNewAction); Author: David_McClarnon (Xara Group Ltd) Created: 17/3/99 Inputs: pOp = ptr to the operation to which this action belongs pActionList = ptr to action list to which this action should be added pNode = ptr to the node to address Outputs: ppNewAction = ptr to a ptr to an action, allowing the function to return a pointer to the created action Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: This is the function which creates an instance of this action. If there is no room in the undo buffer (which is determined by the base class Init function called within) the function will either return AC_NO_RECORD which means the operation can continue, but no undo information needs to be stored, or AC_OK which means the operation should continue AND record undo information. If the function returns AC_FAIL, there was not enough memory to record the undo information, and the user has decided not to continue with the operation. Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode ToggleInsetPathAction::Init(Operation* pOp, ActionList* pActionList, NodeContourController * pNode, BOOL bFlag, ToggleInsetPathAction** ppNewAction) { UINT32 ActSize = sizeof(ToggleInsetPathAction); ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(ToggleInsetPathAction),(Action**)ppNewAction); if (Ac == AC_OK) { (*ppNewAction)->m_pNode = pNode; (*ppNewAction)->m_OldSetting = pNode->GetInsetPathFlag(); pNode->SetInsetPathFlag(bFlag); pNode->RegenerateNode(NULL, FALSE, TRUE); } return Ac; } /******************************************************************************************** > ActionCode ToggleInsetPathAction::Execute(); Author: David_McClarnon (Xara Group Ltd) Created: 17/3/99 Inputs: - Outputs: - Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL Purpose: Executes the action. Causes a regen of all bevels nodes in the action's list Errors: - SeeAlso: Action::Init() ********************************************************************************************/ ActionCode ToggleInsetPathAction::Execute() { ActionCode Act; ToggleInsetPathAction* pAction; // re-invalidate the old rect Document * pDoc = Document::GetCurrent(); if (pDoc) { pDoc->ForceRedraw(m_pNode->FindParentSpread(), m_pNode->GetBoundingRect(), FALSE, m_pNode); } Act = ToggleInsetPathAction::Init( pOperation, pOppositeActLst, m_pNode, m_OldSetting, &pAction); if (Act != AC_FAIL) { } return Act; } ToggleInsetPathAction::~ToggleInsetPathAction() { }