opbevel.cpp

Go to the documentation of this file.
00001 // $Id: opbevel.cpp 1752 2006-09-15 09:13:05Z luke $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 // Implementation of the Bevel tool operations
00099 
00100 /*
00101 */
00102 
00103 
00104 #include "camtypes.h"
00105 #include "opbevel.h"    
00106 //#include "nbevcont.h"
00107 #include "nodebmp.h"
00108 
00109 #ifdef BUILDSHADOWS
00110 
00111 // Code headers
00112 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00114 //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00115 #include "attrbev.h"
00116 #include "nodebev.h"
00117 #include "progress.h"
00118 #include "objchge.h"
00119 //#include "becomea.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00120 //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00121 //#include "nodeattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00122 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00123 //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00124 //#include "list.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00125 #include "nodetxts.h"
00126 #include "nodetxtl.h"
00127 #include "nodeblnd.h"
00128 #include "nodebldr.h"
00129 #include "nodemold.h"
00130 #include "mkshapes.h"
00131 #include "groupops.h"
00132 //#include "range.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00133 #include "lineattr.h"
00134 #include "bevtool.h"
00135 //#include "view.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00136 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00137 #include "nodecont.h"
00138 #include "nodeshad.h"
00139 #include "opshadow.h"
00140 #include "textops.h"
00141 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00142 #include "csrstack.h"
00143 #include "nodetxts.h"
00144 #include "nodeblnd.h"
00145 #include "ncntrcnt.h" // ContourNodePathProcessor
00146 #include "ndmldpth.h"
00147 #include "slicehelper.h"
00148 #include "opliveeffects.h"
00149 #include "nodeliveeffect.h"
00150 #include "ophist.h"
00151 #include "nbevcont.h"
00152 #include "nodetext.h"
00153 
00154 // Resource headers
00155 //#include "bevres.h"
00156 
00157 
00158 DECLARE_SOURCE( "$Revision: 1752 $" );
00159 
00160 CC_IMPLEMENT_DYNCREATE(OpCreateBevel, SelOperation)
00161 CC_IMPLEMENT_DYNCREATE(OpRemoveBevel, SelOperation)
00162 CC_IMPLEMENT_DYNCREATE(OpChangeBevelLightAngle, SelOperation)
00163 CC_IMPLEMENT_DYNCREATE(OpSelectBevel, Operation)
00164 CC_IMPLEMENT_DYNCREATE(BevelInfo, OpParam)
00165 CC_IMPLEMENT_DYNCREATE(RegenerateBevelAction, Action)
00166 CC_IMPLEMENT_DYNCREATE(RegenerateBevelBitmapAction, Action)
00167 CC_IMPLEMENT_DYNCREATE(ChangeLightAnglesAction, Action)
00168 CC_IMPLEMENT_DYNCREATE(RemoveBevelAttributesAction, Action)
00169 
00170 #define new CAM_DEBUG_NEW
00171 
00174 // Bevel tools implementation
00175 
00176 /********************************************************************************************
00177 
00178 >   BOOL BevelTools::BuildListOfSelectedNodes(List *pList,
00179                                 const CCRuntimeClass * pClass)
00180 
00181     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00182     Created:    15/3/99
00183     Inputs:     
00184     Purpose:    Builds a list of all given attribute nodes in the selection
00185 ********************************************************************************************/
00186 
00187 BOOL BevelTools::BuildListOfSelectedNodes(List *pList, const CCRuntimeClass * pClass,
00188                                           BOOL bPromoteToParents)
00189 {
00190     if (!pList || GetApplication()->FindSelection() == NULL)
00191         return FALSE;
00192     
00193     // run through the selection adding all nodes to the list
00194     Range Sel(*(GetApplication()->FindSelection()));
00195     RangeControl rg = Sel.GetRangeControlFlags();
00196     rg.PromoteToParent = bPromoteToParents;
00197     Sel.Range::SetRangeControl(rg);
00198 
00199     if (GetApplication()->FindSelection()->IsEmpty())
00200         return FALSE;
00201 
00202     Node * pNode = Sel.FindFirst(FALSE);
00203 
00204 //  NodeListItem * pItem = NULL;
00205 
00206     while (pNode)
00207     {
00208         GetAllNodesUnderNode(pNode, pList, pClass);
00209 
00210         pNode = Sel.FindNext(pNode, FALSE);
00211     }
00212 
00213     if (pList->IsEmpty())
00214         return FALSE;
00215 
00216     return TRUE;
00217 }
00218 
00219 
00220 
00221     
00222 /********************************************************************************************
00223 
00224 >   BOOL BevelTools::GetAllNodesUnderNode(const Node * pNode, List * pList,
00225                         const CCRuntimeClass * pClass, INT32 depth = 0)
00226 
00227     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00228     Created:    15/3/99
00229     Inputs:     The node to recurse down from, and the list to add found attributes to
00230     Purpose:    Recurses down the tree building a list of all light attribute nodes
00231 ********************************************************************************************/
00232 
00233 BOOL BevelTools::GetAllNodesUnderNode(const Node * pNode, List * pList,
00234                                                const CCRuntimeClass * pClass, INT32 depth)
00235 {
00236     if (!pNode || !pList)
00237         return FALSE;
00238 
00239     // NOTHING exists under a locked (destructive) effect!
00240     if (pNode->IsBitmapEffect() && ((NodeBitmapEffect*)pNode)->IsLockedEffect())
00241         return TRUE;
00242 
00243     const Node * pStartNode = pNode;
00244 
00245     Node * pCurNode = pNode->FindFirstChild();
00246 
00247 //  Node * pChild = NULL;
00248     NodeListItem * pItem = NULL;
00249 
00250     if (!pCurNode)
00251     {
00252         // starting conditions
00253         if (pStartNode->IsKindOf(pClass) && depth == 0 && !IsNodeInList(pList, pStartNode))
00254         {
00255             pItem = new NodeListItem;
00256 
00257             if (pItem)
00258             {
00259                 pItem->pNode = (Node *)pStartNode;
00260                 pList->AddTail(pItem);
00261 
00262                 return TRUE;
00263             }
00264         }
00265 
00266         return FALSE;
00267     }
00268     
00269     // step through the node's siblings
00270     while (pCurNode)
00271     {   
00272         // check sub-tree first
00273         GetAllNodesUnderNode(pCurNode, pList, pClass, depth + 1);
00274         
00275         // check this node is of the correct class, and it also has a parent
00276         if (pCurNode->IsKindOf(pClass) && pCurNode->FindParent() &&
00277             !pCurNode->IsNodeHidden() && !IsNodeInList(pList, pCurNode))
00278         {
00279             pItem = new NodeListItem;
00280 
00281             if (!pItem)
00282             {
00283                 ERROR3("Can't create NodeListItem");
00284                 return FALSE;
00285             }
00286 
00287             pItem->pNode = pCurNode;
00288             pList->AddTail(pItem);
00289         }
00290 
00291         // move onto next sibling
00292         pCurNode = pCurNode->FindNext();
00293     }
00294 
00295     // check original node
00296     if (pStartNode->IsKindOf(pClass) && pStartNode->FindParent() &&
00297             !pStartNode->IsNodeHidden() && !IsNodeInList(pList, pStartNode))
00298     {
00299         pItem = new NodeListItem;
00300 
00301         if (!pItem)
00302         {
00303             ERROR3("Can't create NodeListItem");
00304             return FALSE;
00305         }
00306 
00307         pItem->pNode = (Node *)pStartNode;
00308         pList->AddTail(pItem);
00309     }
00310 
00311     return TRUE;
00312 }
00313 
00314 /********************************************************************************************
00315 
00316 >   BOOL BevelTools::IsNodeInList(List * pList, Node * pNode)
00317 
00318     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00319     Created:    29/3/99
00320     Inputs:     A list of NodeListItems and the node to search for
00321     Purpose:    Returns TRUE if the node is in the list
00322 ********************************************************************************************/
00323 BOOL BevelTools::IsNodeInList(List * pList, const Node * pNode)
00324 {
00325     NodeListItem * pItem = (NodeListItem * )pList->GetHead();
00326 
00327     while (pItem)
00328     {
00329         if (pItem->pNode == pNode)
00330             return TRUE;
00331 
00332         pItem = (NodeListItem * )pList->GetNext(pItem);
00333     }
00334 
00335     return FALSE;
00336 }
00337 
00338 /********************************************************************************************
00339 
00340 >   BOOL BevelTools::HasSelectedChild(NodeRenderableInk * pNode)
00341 
00342     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00343     Created:    15/3/99
00344     Inputs:     
00345     Purpose:    returns TRUE if any of the children of this node are selected
00346 ********************************************************************************************/
00347 BOOL BevelTools::HasSelectedChild(NodeRenderableInk * pNode)
00348 {
00349     NodeRenderableInk * pStepNode = (NodeRenderableInk *)pNode->FindFirstDepthFirst();
00350 
00351     while (pStepNode)
00352     {
00353         if (pStepNode->IsSelected() && pStepNode != pNode)
00354         {
00355             return TRUE;
00356         }
00357 
00358         pStepNode = (NodeRenderableInk *)pStepNode->FindNextDepthFirst(pNode);
00359     }
00360 
00361     return FALSE;
00362 }
00363     
00364 
00365 
00366 
00367 
00368 
00371 // Bevel ops implementation
00372 
00373 /********************************************************************************************
00374 >   OpCreateBevel::OpCreateBevel()
00375 
00376     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> & Olivier
00377     Created:    21/11/96
00378     Purpose:    Constructor.
00379 ********************************************************************************************/
00380 
00381 OpCreateBevel::OpCreateBevel()
00382 {
00383     //TRACEUSER( "MarkH", _T("Just Made a OpCreateBevel Class!\n"));
00384     m_NameID = 0;
00385 }
00386 
00387 /********************************************************************************************
00388 >   void OpCreateBevel::GetOpName(String_256 * pString)
00389 
00390     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> & Olivier
00391     Created:    21/11/96
00392     Purpose:    Gets the name of this operation - dependent on what it did !
00393 ********************************************************************************************/
00394 
00395 void OpCreateBevel::GetOpName(String_256 * pString)
00396 {
00397     if (pString && m_NameID != 0)
00398         pString->Load(m_NameID);
00399 }
00400 
00401 /********************************************************************************************
00402 >   OpCreateBevel::~OpCreateBevel()
00403 
00404     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> & Olivier
00405     Created:    21/11/96
00406     Purpose:    Destructor.
00407 ********************************************************************************************/
00408 
00409 OpCreateBevel::~OpCreateBevel()
00410 {
00411     //TRACEUSER( "MarkH", _T("Just Killed OpCreateBevel Class!!!\n"));
00412 }
00413 
00414 /********************************************************************************************
00415 >   virtual void OpCreateBevel::Do(OpDescriptor *pOpDesc)
00416 
00417     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> & Olivier
00418     Created:    21/11/96
00419     Inputs:     pOpDesc - OpDescriptor - unused
00420     Outputs:    -
00421     Returns:    -
00422     Purpose:    The do function.  Applys a Bevel to the selection in the current document
00423 ********************************************************************************************/
00424 
00425 void OpCreateBevel::Do(OpDescriptor *pOpDesc)
00426 {
00427 }
00428 
00429 /********************************************************************************************
00430 >   void OpCreateBevel::DoWithParam(OpDescriptor* pOp, OpParam* pParam)
00431 
00432     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
00433     Created:    13/01/97
00434     Inputs:     
00435     Outputs:    -
00436     Returns:    -
00437     Purpose:    Applys a Bevel to the selected node after a mouse click
00438 ********************************************************************************************/
00439 
00440 void OpCreateBevel::DoWithParam(OpDescriptor* pOp, OpParam* pParam)
00441 {
00442     if (!pParam || !pOp)
00443         return; // can't happen really
00444 
00445     // check for bevel already existing in the selection
00446     BevelInfo *pBevelInfo = (BevelInfo *)pParam;
00447 
00448     if (pBevelInfo->m_Indent <= 0)
00449     {
00450         // can't do anything !
00451         return ;
00452     }
00453 
00454     if (GetApplication()->FindSelection() == NULL)
00455         return;
00456 
00457 //  NodeBevel* pBevel = NULL; 
00458     Node * pNextNode  = NULL;
00459     NodeBevelController * pBevelControl = NULL; 
00460 //  NodeBevelController * pNewBevelControl = NULL; 
00461 //  NodeBevelBegin * pBevelBegin = NULL;
00462     NodeHidden * pNodeHidden =  NULL;
00463     Node * pCurrentNode = NULL;
00464     
00465 //  BOOL bOuterToInner = FALSE;
00466     DocRect LastRect;
00467 
00468 //  Spread * pSpread = Document::GetSelectedSpread();
00469 
00470 //  Node * xpNode = NULL;
00471 //  Node * xpNode2 = NULL;
00472 
00473 //  Node * pAttribNode = NULL;
00474 
00475     Range * pSel = GetApplication()->FindSelection();
00476 
00477     if (pSel->IsEmpty())
00478         return;
00479 
00480     // Start a slow job
00481     BeginSlowJob();
00482     DoStartSelOp(TRUE, TRUE);
00483 
00484     List BevelNodeList;
00485 
00486     // do all the existing bevel nodes in the selection first
00487     BevelTools::BuildListOfSelectedNodes(&BevelNodeList, CC_RUNTIME_CLASS(NodeBevelController));
00488 
00489     NodeListItem *pNodeListItem = (NodeListItem *)BevelNodeList.GetHead();
00490 
00491     AttrBevelIndent*    pAttrIndent = NULL;
00492     AttrBevelType*      pAttrType     = NULL;
00493     AttrBevelContrast*  pAttrContrast = NULL;
00494     AttrBevelLightAngle* pAttrLightAngle = NULL;
00495     AttrBevelLightTilt* pAttrLightTilt = NULL;
00496     AttrJoinType*       pAttrJointType = NULL;
00497 
00498     HideNodeAction *pAction = NULL;
00499 
00500     m_NameID = 0;
00501 
00502     while (pNodeListItem)
00503     {       
00504         // change the bevel
00505         pBevelControl = (NodeBevelController *)pNodeListItem->pNode;
00506 
00507         // no bevel control ? errr - error !
00508         if (!pBevelControl)
00509         {
00510             ERROR3("Can't find bevel control");
00511             BevelNodeList.DeleteAll();
00512             FailAndExecute();
00513             End();
00514             return;
00515         }
00516 
00517         // invalidate the region before
00518         pBevelControl->ReleaseCached();
00519         if (!DoInvalidateRegion(pBevelControl->FindParentSpread(), 
00520             pBevelControl->GetBoundingRect(TRUE, FALSE)))
00521         {
00522             FailAndExecute();
00523             End();
00524             BevelNodeList.DeleteAll();
00525             return;
00526         }
00527 
00528         // insert nodes if they are defaults exist !
00529         // JointType is not handled here, since it has a very different meaning for non-bevels
00530         if (pBevelInfo->m_bBevelIndentChanged || pBevelInfo->m_bBevelDirectionChanged)
00531         {
00532             if (pBevelControl->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBevelIndent), 
00533                 (NodeAttribute **)&pAttrIndent))
00534             {
00535                 if (pAttrIndent)
00536                 {
00537                     if (pAttrIndent->IsADefaultAttr())
00538                     {
00539                         ALLOC_WITH_FAIL(pAttrIndent, 
00540                             new AttrBevelIndent(pBevelControl, FIRSTCHILD), this);
00541                         pAttrIndent->Value.m_Indent = pBevelControl->m_Indent;
00542                         
00543                         if (pBevelControl->m_bOuter)
00544                         {
00545                             pAttrIndent->Value.m_Indent = -pBevelControl->m_Indent;
00546                         }
00547                         
00548                         if (HideNodeAction::Init(this, GetUndoActionList(), (Node *)pAttrIndent,
00549                             FALSE, (Action **)&pAction, FALSE) != AC_OK)
00550                         {
00551                             FailAndExecute();
00552                             End();
00553                             BevelNodeList.DeleteAll();
00554                             return;             
00555                         }
00556                     }
00557                 }
00558             }
00559         }
00560 
00561         if (pBevelInfo->m_bBevelTypeChanged)
00562         {
00563             if (pBevelControl->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBevelType), 
00564                 (NodeAttribute **)&pAttrType))
00565             {
00566                 if (pAttrType)
00567                 {
00568                     if (pAttrType->IsADefaultAttr())
00569                     {
00570                         ALLOC_WITH_FAIL(pAttrType, 
00571                             new AttrBevelType(pBevelControl, FIRSTCHILD), this);
00572                         pAttrType->Value.m_Type = pBevelControl->m_BevelType;
00573                         
00574                         if (HideNodeAction::Init(this, GetUndoActionList(), (Node *)pAttrType,
00575                             FALSE, (Action **)&pAction, FALSE) != AC_OK)
00576                         {
00577                             FailAndExecute();
00578                             End();
00579                             BevelNodeList.DeleteAll();
00580                             return;             
00581                         }           
00582                     }
00583                 }
00584             }                   
00585         }
00586 
00587         if (pBevelInfo->m_bBevelLightAngleChanged)
00588         {
00589             if (pBevelControl->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBevelLightAngle), 
00590                 (NodeAttribute **)&pAttrLightAngle))
00591             {
00592                 if (pAttrLightAngle)
00593                 {
00594                     if (pAttrLightAngle->IsADefaultAttr())
00595                     {
00596                         ALLOC_WITH_FAIL(pAttrLightAngle, 
00597                             new AttrBevelLightAngle(pBevelControl, FIRSTCHILD), this);
00598                         pAttrLightAngle->Value.m_LightAngle = (INT32)pBevelControl->m_LightAngle;
00599                         
00600                         if (HideNodeAction::Init(this, GetUndoActionList(), (Node *)pAttrLightAngle,
00601                             FALSE, (Action **)&pAction, FALSE) != AC_OK)
00602                         {
00603                             FailAndExecute();
00604                             End();
00605                             BevelNodeList.DeleteAll();
00606                             return;             
00607                         }           
00608                     }
00609                 }
00610             }
00611         }
00612 
00613         if (pBevelInfo->m_bBevelLightTiltChanged)
00614         {
00615             if (pBevelControl->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBevelLightTilt), 
00616                 (NodeAttribute **)&pAttrLightTilt))
00617             {
00618                 if (pAttrLightTilt)
00619                 {
00620                     if (pAttrLightTilt->IsADefaultAttr())
00621                     {
00622                         ALLOC_WITH_FAIL(pAttrLightTilt, 
00623                             new AttrBevelLightTilt(pBevelControl, FIRSTCHILD), this);
00624                         pAttrLightTilt->Value.m_LightTilt = (INT32)pBevelControl->m_Tilt;
00625                         
00626                         if (HideNodeAction::Init(this, GetUndoActionList(), (Node *)pAttrLightTilt,
00627                             FALSE, (Action **)&pAction, FALSE) != AC_OK)
00628                         {
00629                             FailAndExecute();
00630                             End();
00631                             BevelNodeList.DeleteAll();
00632                             return;             
00633                         }           
00634                     }
00635                 }
00636             }
00637         }
00638 
00639 
00640         if (pBevelInfo->m_bBevelContrastChanged)
00641         {
00642             if (pBevelControl->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBevelContrast), 
00643                 (NodeAttribute **)&pAttrContrast))
00644             {
00645                 if (pAttrContrast)
00646                 {
00647                     if (pAttrContrast->IsADefaultAttr())
00648                     {
00649                         ALLOC_WITH_FAIL(pAttrContrast, 
00650                             new AttrBevelContrast(pBevelControl, FIRSTCHILD), this);
00651                         pAttrContrast->Value.m_Contrast = pBevelControl->m_Contrast;
00652                         
00653                         if (HideNodeAction::Init(this, GetUndoActionList(), (Node *)pAttrContrast,
00654                             FALSE, (Action **)&pAction, FALSE) != AC_OK)
00655                         {
00656                             FailAndExecute();
00657                             End();
00658                             BevelNodeList.DeleteAll();
00659                             return;             
00660                         }           
00661                     }
00662                 }
00663             }
00664         }
00665 
00666         
00667         // localise out all the attributes
00668         if (!DoLocaliseCommonAttributes(pBevelControl, TRUE, TRUE))
00669         {
00670             FailAndExecute();
00671             End();
00672             BevelNodeList.DeleteAll();
00673             return;
00674         }
00675 
00676         BOOL bGenerateNode = FALSE;
00677 
00678         pCurrentNode = pBevelControl->FindFirstDepthFirst();
00679 
00680         while (pCurrentNode)
00681         {
00682             pNextNode = pCurrentNode->FindNextDepthFirst(pBevelControl);
00683             
00684             // hide the original attribute, and replace it with the new one,
00685             // for undo purposes
00686             if (pCurrentNode->IS_KIND_OF(AttrBevelIndent) && pBevelInfo->m_bBevelIndentChanged)
00687             {
00688                 bGenerateNode = TRUE;
00689                 ALLOC_WITH_FAIL(pAttrIndent, (new AttrBevelIndent()), this);
00690 
00691                 // get the new width out of the parameter
00692                 MILLIPOINT Width = abs(pBevelInfo->m_Indent);
00693 
00694                 if (pBevelInfo->m_bBevelDirectionChanged)
00695                 {
00696                     // direction changed ! no need to check the direction of the original
00697                     // attribute
00698                     if (pBevelInfo->m_bOuter)
00699                     {
00700                         Width = -Width;
00701                     }
00702                 }
00703                 else
00704                 {
00705                     // if the original attribute is an outer bevel, make the width negative
00706                     if (((AttrBevelIndent *)pCurrentNode)->Value.m_Indent < 0)
00707                     {
00708                         Width = -Width;
00709                     }
00710                 }
00711 
00712                 if (Width > 0)
00713                 {
00714                     // check maximum indent of outer bevels
00715                     MILLIPOINT MaxValue = 
00716                         ContourNodePathProcessor::GetMaxInnerContourWidth(pBevelControl);
00717 
00718                     if (Width > MaxValue)
00719                         Width = MaxValue;
00720                 }
00721 
00722                 // set the attribute value
00723                 ((AttrBevelIndent *)pAttrIndent)->Value.m_Indent = Width;
00724                 
00725                 // hide the original node
00726                 if (!DoHideNode(pCurrentNode, TRUE, &pNodeHidden))
00727                 {
00728                     FailAndExecute();
00729                     End();
00730                     BevelNodeList.DeleteAll();
00731                     return;
00732                 }
00733 
00734                 // attach the new node
00735                 pAttrIndent->AttachNode(pNodeHidden, NEXT);
00736 
00737                 // add an hide node action so that undo works ok
00738                 if (HideNodeAction::Init(this, GetUndoActionList(), (Node *)pAttrIndent,
00739                                 FALSE, (Action **)&pAction, FALSE) != AC_OK)
00740                 {
00741                     FailAndExecute();
00742                     End();
00743                     BevelNodeList.DeleteAll();
00744                     return;             
00745                 }
00746 
00747                 m_NameID = _R(IDS_CHANGEBEVELINDENTOPNAME);
00748             } 
00749             else if (pCurrentNode->IS_KIND_OF(AttrBevelType) && pBevelInfo->m_bBevelTypeChanged)
00750             {
00751                 ALLOC_WITH_FAIL(pAttrType, (new AttrBevelType()), this);
00752                 
00753                 ((AttrBevelType *)pAttrType)->Value.m_Type = pBevelInfo->m_BevelType;
00754 
00755                 // hide the original node
00756                 if (!DoHideNode(pCurrentNode, TRUE, &pNodeHidden))
00757                 {
00758                     FailAndExecute();
00759                     End();
00760                     BevelNodeList.DeleteAll();
00761                     return;
00762                 }
00763 
00764                 // attach the new node
00765                 pAttrType->AttachNode(pNodeHidden, NEXT);
00766 
00767                 // add an hide node action so that undo works ok
00768                 if (HideNodeAction::Init(this, GetUndoActionList(), (Node *)pAttrType,
00769                                 FALSE, (Action **)&pAction, FALSE) != AC_OK)
00770                 {
00771                     FailAndExecute();
00772                     End();
00773                     BevelNodeList.DeleteAll();
00774                     return;
00775                 }
00776 
00777                 m_NameID = _R(IDS_CHANGEBEVELTYPEOPNAME);
00778             }
00779             else if (pCurrentNode->IS_KIND_OF(AttrBevelIndent) && pBevelInfo->m_bBevelDirectionChanged)
00780             {
00781                 bGenerateNode = TRUE;
00782                 ALLOC_WITH_FAIL(pAttrIndent, (new AttrBevelIndent()), this);
00783                 
00784                 if (pBevelInfo->m_bOuter)
00785                 {
00786                     ((AttrBevelIndent *)pAttrIndent)->Value.m_Indent = 
00787                         -abs(((AttrBevelIndent *)pCurrentNode)->Value.m_Indent);
00788                 }
00789                 else
00790                 {
00791                     ((AttrBevelIndent *)pAttrIndent)->Value.m_Indent = 
00792                         abs(((AttrBevelIndent *)pCurrentNode)->Value.m_Indent);
00793 
00794                     // check the maximum inner contour width
00795                     MILLIPOINT MaxValue = 
00796                         ContourNodePathProcessor::GetMaxInnerContourWidth(pBevelControl);
00797 
00798                     if (((AttrBevelIndent *)pAttrIndent)->Value.m_Indent > MaxValue)
00799                         ((AttrBevelIndent *)pAttrIndent)->Value.m_Indent = MaxValue;
00800                 }
00801                 
00802                 // hide the original node
00803                 if (!DoHideNode(pCurrentNode, TRUE, &pNodeHidden))
00804                 {
00805                     FailAndExecute();
00806                     End();
00807                     BevelNodeList.DeleteAll();
00808                     return;
00809                 }
00810 
00811                 // attach the new node
00812                 pAttrIndent->AttachNode(pNodeHidden, NEXT);
00813 
00814                 // add an hide node action so that undo works ok
00815                 if (HideNodeAction::Init(this, GetUndoActionList(), (Node *)pAttrIndent,
00816                                 FALSE, (Action **)&pAction, FALSE) != AC_OK)
00817                 {
00818                     FailAndExecute();
00819                     End();
00820                     BevelNodeList.DeleteAll();
00821                     return;
00822                 }
00823 
00824                 if (pBevelInfo->m_bOuter)
00825                 {
00826                     m_NameID = _R(IDS_CHANGEBEVELTOOUTEROPNAME);
00827                 }
00828                 else
00829                 {
00830                     m_NameID = _R(IDS_CHANGEBEVELTOINNEROPNAME);
00831                 }
00832             }           
00833             else if (pCurrentNode->IS_KIND_OF(AttrBevelContrast) && pBevelInfo->m_bBevelContrastChanged)
00834             {
00835                 ALLOC_WITH_FAIL(pAttrContrast, (new AttrBevelContrast()), this);
00836                 
00837                 pAttrContrast->Value.m_Contrast = pBevelInfo->m_Contrast;
00838 
00839                 // hide the original node
00840                 if (!DoHideNode(pCurrentNode, TRUE, &pNodeHidden))
00841                 {
00842                     FailAndExecute();
00843                     End();
00844                     BevelNodeList.DeleteAll();
00845                     return;
00846                 }
00847 
00848                 // attach the new node
00849                 pAttrContrast->AttachNode(pNodeHidden, NEXT);
00850 
00851                 // add an hide node action so that undo works ok
00852                 if (HideNodeAction::Init(this, GetUndoActionList(), (Node *)pAttrContrast,
00853                                 FALSE, (Action **)&pAction, FALSE) != AC_OK)
00854                 {
00855                     FailAndExecute();
00856                     End();
00857                     BevelNodeList.DeleteAll();
00858                     return;
00859                 }
00860 
00861                 m_NameID = _R(IDS_CHANGEBEVELCONTRASTOPNAME);
00862             }
00863             else if (pCurrentNode->IS_KIND_OF(AttrBevelLightAngle) && pBevelInfo->m_bBevelLightAngleChanged)
00864             {
00865                 ALLOC_WITH_FAIL(pAttrLightAngle, (new AttrBevelLightAngle()), this);
00866                 
00867                 pAttrLightAngle->Value.m_LightAngle = (INT32)pBevelInfo->m_LightAngle;
00868 
00869                 // hide the original node
00870                 if (!DoHideNode(pCurrentNode, TRUE, &pNodeHidden))
00871                 {
00872                     FailAndExecute();
00873                     End();
00874                     BevelNodeList.DeleteAll();
00875                     return;
00876                 }
00877 
00878                 // insert the new attribute node
00879                 pAttrLightAngle->AttachNode(pNodeHidden, NEXT);
00880 
00881                 // add an hide node action so that undo works ok
00882                 if (HideNodeAction::Init(this, GetUndoActionList(), (Node *)pAttrLightAngle,
00883                                 FALSE, (Action **)&pAction, FALSE) != AC_OK)
00884                 {
00885                     FailAndExecute();
00886                     End();
00887                     BevelNodeList.DeleteAll();
00888                     return;
00889                 }
00890 
00891                 m_NameID = _R(IDS_CHANGEBEVELLIGHTANGLEOPNAME);
00892             }
00893             else if (pCurrentNode->IS_KIND_OF(AttrBevelLightTilt) && pBevelInfo->m_bBevelLightTiltChanged)
00894             {
00895                 ALLOC_WITH_FAIL(pAttrLightTilt, (new AttrBevelLightTilt()), this);
00896                 
00897                 pAttrLightTilt->Value.m_LightTilt = (INT32)pBevelInfo->m_Tilt;
00898 
00899                 // hide the original node
00900                 if (!DoHideNode(pCurrentNode, TRUE, &pNodeHidden))
00901                 {
00902                     FailAndExecute();
00903                     End();
00904                     BevelNodeList.DeleteAll();
00905                     return;
00906                 }
00907 
00908                 // insert the new attribute node
00909                 pAttrLightTilt->AttachNode(pNodeHidden, NEXT);
00910                 pBevelControl->m_Tilt = pBevelInfo->m_Tilt;
00911 
00912                 // add an hide node action so that undo works ok
00913                 if (HideNodeAction::Init(this, GetUndoActionList(), (Node *)pAttrLightTilt,
00914                                 FALSE, (Action **)&pAction, FALSE) != AC_OK)
00915                 {
00916                     FailAndExecute();
00917                     End();
00918                     BevelNodeList.DeleteAll();
00919                     return;
00920                 }
00921 
00922                 m_NameID = _R(IDS_CHANGEBEVELLIGHTTILTOPNAME);
00923             }
00924             else
00925             if (pCurrentNode->IS_KIND_OF(AttrJoinType) && pBevelInfo->m_bJointTypeChanged)
00926             {
00927                 bGenerateNode = TRUE;
00928                 ALLOC_WITH_FAIL(pAttrJointType, (new AttrJoinType()), this);
00929 
00930                 pAttrJointType->Value.JoinType = pBevelInfo->m_JointType;
00931 
00932                 // hide the original node
00933                 if (!DoHideNode(pCurrentNode, TRUE, &pNodeHidden))
00934                 {
00935                     FailAndExecute();
00936                     End();
00937                     BevelNodeList.DeleteAll();
00938                     return;
00939                 }
00940 
00941                 // insert the new attribute node
00942                 pAttrJointType->AttachNode(pNodeHidden, NEXT);
00943 
00944                 // add an hide node action so that undo works ok
00945                 if (HideNodeAction::Init(this, GetUndoActionList(), (Node *)pAttrJointType,
00946                                 FALSE, (Action **)&pAction, FALSE) != AC_OK)
00947                 {
00948                     FailAndExecute();
00949                     End();
00950                     BevelNodeList.DeleteAll();
00951                     return;
00952                 }
00953 
00954                 m_NameID = _R(IDS_CHANGEJOINTYPEOPNAME);
00955             }
00956 
00957 
00958 //          else if (pCurrentNode->IS_KIND_OF(NodeBevel))
00959 //          {
00960 //              ((NodeBevel*)pCurrentNode)->InvalidateBoundingRect();
00961 //          }
00962 
00963 
00964             pCurrentNode = pNextNode;
00965         }
00966 
00967         if (!DoFactorOutCommonChildAttributes(pBevelControl))
00968         {
00969             FailAndExecute();
00970             End();
00971             
00972             BevelNodeList.DeleteAll();
00973             return;
00974         }
00975         
00976         // regenerate the node - if necessary !
00977         if (bGenerateNode)
00978         {
00979             pBevelControl->RegenerateNode(this, FALSE, TRUE);
00980 
00981             // Ilan 31/5/00
00982             // Inform geom linked attrs of the change. Nb outside the normal AllowOp mechanism
00983             NodeAttribute* pNA = pBevelControl->FindFirstGeometryLinkedAttr();
00984             while(pNA)
00985             {
00986                 pNA->LinkedNodeGeometryHasChanged(this);
00987                 pNA = pNA->FindNextGeometryLinkedAttr();
00988             }
00989         }
00990         else
00991         {
00992             // doesn't regen path so GLA's aren't affected
00993             pBevelControl->RegenerateBevelBitmap(this, TRUE);
00994         }
00995 
00996         pBevelControl->InvalidateBoundingRect(TRUE);
00997         pBevelControl->ReleaseCached();
00998         
00999         // invalidate the region after
01000         if (!DoInvalidateRegion(pBevelControl->FindParentSpread(), 
01001             pBevelControl->GetBoundingRect(TRUE, FALSE)))
01002         {
01003             FailAndExecute();
01004             End();
01005             BevelNodeList.DeleteAll();
01006             return;
01007         }
01008     
01009         pNodeListItem= (NodeListItem *)BevelNodeList.GetNext(pNodeListItem);
01010     }
01011 
01012     // kick the sel range first
01013     GetApplication()->UpdateSelection();
01014 
01015     // if there are any bevel nodes present, then exit - the above will have taken
01016     // care of it
01017     if (!BevelNodeList.IsEmpty() && !pBevelInfo->m_bCreateNewBevels && !pBevelInfo->m_bBevelDirectionChanged)
01018     {
01019         ObjChangeFlags flgs(FALSE, FALSE, FALSE, FALSE);
01020         ObjChangeParam OP(OBJCHANGE_FINISHED, flgs, NULL, this, OBJCHANGE_CALLEDBYOP);
01021 
01022         pBevelControl->AllowOp(&OP);
01023         BevelNodeList.DeleteAll();
01024         End();
01025         return;
01026     }
01027 
01028     EffectsStack* pStack = GetApplication()->FindSelection()->GetEffectsStack();
01029     ENSURE(pStack, "Argh!");
01030     Range* pSelList = pStack->GetBaseLevelRange();
01031     ENSURE(pSelList, "Argh!");
01032 
01033     TextStory *pThisParentStory = NULL;
01034 
01035     // for the allow op mechanism
01036     ObjChangeFlags flgs(FALSE, FALSE, FALSE, FALSE);
01037     ObjChangeParam OP(OBJCHANGE_STARTING, flgs, NULL, this, OBJCHANGE_CALLEDBYOP);
01038 
01039     // call allow op on the selection as we need to make sure it was called on something
01040     // it will just make the extending stuff be called correctly at the end and return quickly here
01041     pSel->AllowOp(&OP);
01042 
01043     BOOL bHasABevel = FALSE;
01044 
01045     // apply bevel to all renderable nodes which don't have a bevel on them
01046     Node* pNode = pSelList->FindFirst();
01047     while (pNode)
01048     {
01049         // are there any bevel nodes under this node ?
01050         BevelTools::GetAllNodesUnderNode(pNode, &BevelNodeList, CC_RUNTIME_CLASS(NodeBevel));
01051 
01052         bHasABevel = !BevelNodeList.IsEmpty();
01053 
01054         if (pNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)) &&
01055             !pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevelController)) &&
01056             pNode->FindParent(CC_RUNTIME_CLASS(NodeBevelController)) == NULL &&
01057             pNode->AllowOp(&OP, FALSE) &&
01058             !bHasABevel)
01059         {
01060             // we don't have a bevel controller node so apply a bevel to it
01061             
01062             // now, is this node a text node but not a text story node ? Oh dear ! Not a text story node,
01063             // which means that the text is selected, so we need to select the text story node and
01064             // bevel this !
01065             if (pNode->IsKindOf(CC_RUNTIME_CLASS(TextLine)) ||
01066                 pNode->IsKindOf(CC_RUNTIME_CLASS(TextChar)))
01067             {
01068                 pThisParentStory = (TextStory *)pNode->FindParent(CC_RUNTIME_CLASS(TextStory));
01069 
01070                 if (pThisParentStory)
01071                 {
01072                     // does the parent story already have a bevel ?
01073                     if (!(pThisParentStory->FindParent(CC_RUNTIME_CLASS(NodeBevelController))) &&
01074                         !pThisParentStory->IsNodeHidden())
01075                     {
01076                         DoSelectNode(pThisParentStory);
01077                         ApplyBevelToNode(pThisParentStory, pBevelInfo);
01078 
01079                         m_NameID = _R(IDS_CREATEBEVELOPNAME);
01080                     }
01081                 }   
01082                 else
01083                 {
01084                     ERROR3("No parent story found for text line/characters");
01085                 }
01086             }
01087             else
01088             {               
01089                 if (pNode->AllowOp(&OP))
01090                 {
01091                     ApplyBevelToNode(pNode, pBevelInfo);
01092 
01093                     m_NameID = _R(IDS_CREATEBEVELOPNAME);
01094                 }
01095             }
01096         }
01097         else if(bHasABevel)
01098         {
01099             // Ok if we have a controller node here and it already has a bevel then we need to move it
01100             // to it correct possition in the tree!
01101             NodeListItem* pItem = (NodeListItem *)BevelNodeList.GetHead();
01102             NodeBevelController* pControl = NULL;
01103             NodeBevel* pBevel = NULL;
01104 
01105             while(pItem)
01106             {
01107                 pControl = (NodeBevelController*)pItem->pNode;
01108                 pBevel = pControl->GetBevelNode();
01109 
01110                 if(pControl && pBevel)
01111                 {
01112                     if(pBevelInfo->m_bOuter)
01113                     {
01114                         Node* pBeginBevel = pControl->FindFirstChild(CC_RUNTIME_CLASS(NodeBevelBegin));
01115                         
01116                         if(pBeginBevel)
01117                         {
01118                             DoMoveNode(pBevel,pBeginBevel,NEXT);
01119                         }
01120                         else
01121                         {
01122                             DoMoveNode(pBevel,pControl,FIRSTCHILD);
01123                         }
01124                     }
01125                     else
01126                     {
01127                         DoMoveNode(pBevel,pControl,LASTCHILD);
01128                     }
01129                 }
01130 
01131                 pItem = (NodeListItem *)BevelNodeList.GetNext(pItem);
01132             }
01133         }
01134         BevelNodeList.DeleteAll();
01135 
01136         pNode = pSelList->FindNext(pNode);
01137     }
01138 
01139     // rid ourselves of the selection list
01140     delete pSelList;
01141 
01142     GetApplication()->UpdateSelection();
01143 
01144     End();
01145 }
01146 
01147 /********************************************************************************************
01148 
01149 >   void OpCreateBevel::ApplyBevelToNode(Node * pNode, OpParam* pParam)
01150 
01151     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
01152     Created:    18/12/98                                                            
01153     Returns:    -
01154     Purpose:    Creates/adjusts a bevel on the given node
01155 
01156 ********************************************************************************************/
01157 
01158 void OpCreateBevel::ApplyBevelToNode(Node * pNode, BevelInfo* pBevelInfo)
01159 {
01160     if (!pNode || !pBevelInfo)
01161         return;
01162 
01163     // can't double-bevel things !
01164     // or bevel things which require their parent
01165     if (pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevelController)) ||
01166         pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevel)) ||
01167         pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevelBegin)) ||
01168         pNode->NeedsParent(pNode->FindParent()))
01169     {
01170         return;
01171     }
01172 
01173     // deselect the node first
01174     if (pNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)))
01175         DoDeselectNode((NodeRenderableInk *)pNode);
01176 
01177     // Create a new NodeBevelController and insert it into the tree
01178     BOOL ok = TRUE;
01179 
01180     NodeBevelController * pBevelControl = NULL; 
01181 //  NodeBevelController * pNewBevelControl = NULL; 
01182     NodeBevelBegin * pBevelBegin = NULL;
01183     NodeBevel      * pBevel      = NULL;
01184     Node * pThisNode = NULL;
01185     Node * pNextNode = NULL;
01186 
01187     ALLOC_WITH_FAIL(pBevelControl, (new NodeBevelController()), this);
01188     ok = (pBevelControl != NULL);
01189 
01190     // Create a new NodeBevel, apply default attributes and insert it into the tree
01191     if (ok)
01192     {
01193         ALLOC_WITH_FAIL(pBevel, (new NodeBevel()), this);
01194         ok = (pBevel != NULL);
01195     }
01196 
01197     if (ok)
01198     {
01199         ALLOC_WITH_FAIL(pBevelBegin, (new NodeBevelBegin()), this);
01200         ok = (pBevelBegin != NULL);
01201     }
01202 
01203     if(ok)
01204     {
01205         pBevel->m_Indent = pBevelInfo->m_Indent;
01206         pBevel->m_LightAngle = pBevelInfo->m_LightAngle;
01207         pBevel->m_BevelType = pBevelInfo->m_BevelType;
01208         pBevel->m_bOuter = pBevelInfo->m_bOuter;
01209         
01210         pBevelControl->m_Indent = pBevelInfo->m_Indent;
01211         pBevelControl->m_LightAngle = pBevelInfo->m_LightAngle;
01212         pBevelControl->m_BevelType = pBevelInfo->m_BevelType;
01213         pBevelControl->m_bOuter = pBevelInfo->m_bOuter;
01214     }
01215 
01216     // check for a shadow controller node
01217     if (!pNode->IsKindOf(CC_RUNTIME_CLASS(NodeShadowController)))
01218     {
01219         if (ok) ok = DoInsertNewNode(pBevelControl, pNode, NEXT, TRUE, FALSE, FALSE, TRUE);
01220 
01221         if (ok) ok = DoMoveNode(pNode, pBevelControl, FIRSTCHILD);
01222 
01223         if (ok) ok = DoSelectNode((NodeRenderableInk *)pNode);
01224     }
01225     else
01226     {
01227         if (ok)
01228         {
01229             ok = DoInsertNewNode(pBevelControl, pNode, LASTCHILD, TRUE, FALSE, FALSE, TRUE);
01230         
01231             // now, move all the children of the shadow controller to be children of the bevel
01232             pThisNode = pNode->FindFirstChild();
01233 
01234             while (pThisNode)
01235             {
01236                 pNextNode = pThisNode->FindNext();
01237 
01238                 if (!pThisNode->IsKindOf(CC_RUNTIME_CLASS(NodeShadow)) && !pThisNode->IsNodeHidden() &&
01239                     !pThisNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevelController)))
01240                 {
01241                     if (!pThisNode->IsKindOf(CC_RUNTIME_CLASS(NodeAttribute)))
01242                     {
01243                         if (ok) ok = DoMoveNode(pThisNode, pBevelControl, FIRSTCHILD);
01244                         if (ok) ok = DoSelectNode((NodeRenderableInk *)pThisNode);
01245                     }
01246                 }
01247 
01248                 pThisNode = pNextNode;
01249             }
01250         }
01251     }
01252 
01253     // insert the bevel begin node
01254     if (ok)
01255         ok = DoInsertNewNode(pBevelBegin, pBevelControl, FIRSTCHILD, TRUE, FALSE, FALSE, TRUE);
01256 
01257     // insert the node, and optimise attributes
01258     if (ok)
01259     {
01260 //      if(pBevelInfo->m_bOuter)
01261             ok = DoInsertNewNode(pBevel, pBevelBegin, NEXT, TRUE, FALSE, FALSE, TRUE);
01262 //      else
01263 //          ok = DoInsertNewNode(pBevel, pBevelControl, LASTCHILD, TRUE, FALSE, FALSE, TRUE);
01264     }
01265     
01266     NodeAttribute * pFillAttr = NULL;
01267     NodeAttribute * pTranspFillAttr = NULL;
01268     NodeAttribute * pFillMapping = NULL;
01269     NodeAttribute * pFillEffect = NULL;
01270     NodeAttribute * pTranspFillMapping = NULL;
01271     NodeAttribute * pJoinType  = NULL;
01272 
01273     if(ok)
01274     {
01275         // get the first renderable node under the bevel controller node
01276         Node * pStepNode = pBevelControl->FindFirstDepthFirst();
01277 
01278         while (pStepNode && pStepNode != (Node *)pBevelControl)
01279         {
01280             if (pStepNode->IsAnObject() && !pStepNode->IsCompound() && !pStepNode->NeedsParent(NULL))
01281             {
01282                 if (!pStepNode->IS_KIND_OF(NodeMouldPath))
01283                 {
01284                     if (pStepNode->IsNodePath())
01285                     {
01286                         // check for path being in a text story
01287                         if (pStepNode->FindParent())
01288                         {
01289                             if (!pStepNode->FindParent()->IS_KIND_OF(TextStory))
01290                             {
01291                                 break;
01292                             }
01293                         }
01294                     }
01295                     else if(pStepNode->IsABitmap())
01296                     {
01297                         // Ok we need to convert this bitmap into a NodePath and replace it in the tree!
01298                         BecomeA BecomeAReplace(BECOMEA_REPLACE, CC_RUNTIME_CLASS(NodePath), this, FALSE);
01299                         pStepNode->DoBecomeA(&BecomeAReplace);
01300 
01301                         // Now reset the search so that it can find the new Converted bitmap path node!
01302                         pStepNode = pBevelControl->FindFirstChildInk();
01303                     }
01304                     else
01305                     {               
01306                         break;
01307                     }
01308                 }
01309             }
01310 
01311             pStepNode = pStepNode->FindNextDepthFirst(pBevelControl);
01312         }
01313 
01314         if (pStepNode && pStepNode != (Node *)pBevelControl)
01315         {
01316             ((NodeRenderableInk *)pStepNode)->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillGeometry),&pFillAttr);
01317             ((NodeRenderableInk *)pStepNode)->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTranspFillGeometry),&pTranspFillAttr);
01318             ((NodeRenderableInk *)pStepNode)->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillMapping),&pFillMapping);
01319             ((NodeRenderableInk *)pStepNode)->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillEffect),&pFillEffect);
01320             ((NodeRenderableInk *)pStepNode)->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTranspFillMapping),&pTranspFillMapping);
01321             ((NodeRenderableInk *)pStepNode)->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrJoinType),&pJoinType);
01322         }
01323 
01324         if (pFillAttr)
01325             pFillAttr->CopyNode(pBevel, FIRSTCHILD);
01326 
01327         if (pTranspFillAttr)
01328             pTranspFillAttr->CopyNode(pBevel, FIRSTCHILD);
01329 
01330         if (pFillMapping)
01331             pFillMapping->CopyNode(pBevel, FIRSTCHILD);
01332 
01333         if (pFillEffect)
01334             pFillEffect->CopyNode(pBevel, FIRSTCHILD);
01335 
01336         if (pTranspFillMapping)
01337             pTranspFillMapping->CopyNode(pBevel, FIRSTCHILD);
01338 
01339         if (pJoinType)
01340             pJoinType->CopyNode(pBevel, FIRSTCHILD);
01341     }
01342     
01343     if(ok && !pBevelInfo->m_bOuter)
01344         pBevel->MoveNode(pBevelControl,LASTCHILD);
01345 
01346     // factor out the child attributes
01347     if (ok) ok = DoFactorOutCommonChildAttributes(pBevelControl);
01348 
01349     if (!ok) FailAndExecute();
01350 
01351     // invalidate the region
01352     DocRect InvalidBevelRect = pBevelControl->GetBoundingRect(TRUE, FALSE);
01353     pBevelControl->ReleaseCached(TRUE, FALSE, TRUE, TRUE);
01354     
01355     if (pBevelInfo->m_bOuter)
01356     {
01357         InvalidBevelRect.lo.x -= pBevelInfo->m_Indent;
01358         InvalidBevelRect.lo.y -= pBevelInfo->m_Indent;
01359         InvalidBevelRect.hi.x += pBevelInfo->m_Indent;
01360         InvalidBevelRect.hi.y += pBevelInfo->m_Indent;
01361     }
01362     
01363     Spread * pSpread = Document::GetSelectedSpread();
01364 
01365     if (pSpread)
01366         DoInvalidateRegion(pSpread, InvalidBevelRect);  
01367 
01368     // sort out the attributes
01369     Document * pDoc = Document::GetCurrent();
01370 
01371     if (pDoc)
01372     {
01373         // apply the current bevel attributes
01374         AttrBevelType * pType = NULL;
01375         AttrBevelLightAngle * pLightAngle = NULL;
01376         AttrBevelContrast * pContrast = NULL;
01377         AttrBevelIndent * pIndent = NULL;
01378         AttrBevelLightTilt * pTilt = NULL;
01379 
01380         ALLOC_WITH_FAIL(pType, new AttrBevelType(pBevelControl, FIRSTCHILD), this);
01381         ALLOC_WITH_FAIL(pLightAngle, new AttrBevelLightAngle(pBevelControl, FIRSTCHILD), this);
01382         ALLOC_WITH_FAIL(pContrast, new AttrBevelContrast(pBevelControl, FIRSTCHILD), this);
01383         ALLOC_WITH_FAIL(pIndent, new AttrBevelIndent(pBevelControl, FIRSTCHILD), this);
01384         ALLOC_WITH_FAIL(pTilt, new AttrBevelLightTilt(pBevelControl, FIRSTCHILD), this);
01385 
01386         if (pType)
01387             pType->Value.m_Type = pBevelInfo->m_BevelType;
01388 
01389         if (pLightAngle)
01390             pLightAngle->Value.m_LightAngle = (INT32)pBevelInfo->m_LightAngle;
01391 
01392         if (pContrast)
01393             pContrast->Value.m_Contrast = pBevelInfo->m_Contrast;
01394 
01395         if (pIndent)
01396             pIndent->Value.m_Indent = pBevelInfo->m_Indent;
01397 
01398         if (pTilt)
01399             pTilt->Value.m_LightTilt = (INT32)pBevelInfo->m_Tilt;
01400 
01401         if (pBevelInfo->m_bOuter)
01402         {
01403             pIndent->Value.m_Indent = -pBevelInfo->m_Indent;
01404         }
01405         else
01406         {
01407             // check the width against the maximum allowed on inner bevels
01408             MILLIPOINT MaxWidth = ContourNodePathProcessor::GetMaxInnerContourWidth(pBevelControl);
01409 
01410             if (pBevelInfo->m_Indent < MaxWidth)
01411                 pIndent->Value.m_Indent = pBevelInfo->m_Indent;
01412             else
01413                 pIndent->Value.m_Indent = MaxWidth;
01414         }
01415     }
01416 
01417     // tell the shadow node to regen
01418     NodeShadow * pShadow = NULL;
01419     NodeShadowController * pShadowCont = NULL;
01420 
01421     // generate the bevel
01422     pBevelControl->CreateBevel();   
01423 
01424     SliceHelper::AddNamesToController(this,pBevelControl);
01425 
01426     pBevelControl->SetSelected(TRUE);
01427     GetApplication()->UpdateSelection();
01428 
01429     pBevel->InvalidateBoundingRect();
01430 
01431     // tell all nodes above the bevel controller node of the change
01432     ObjChangeFlags flgs(FALSE, FALSE, FALSE, FALSE);
01433     flgs.RegenerateNode = TRUE;
01434     ObjChangeParam OP(OBJCHANGE_FINISHED, flgs, pNode, this, OBJCHANGE_CALLEDBYOP);
01435                 
01436 //  Node * pNodeParent = pNode->FindParent();
01437 
01438     // also check for blends needing to be re-initialised
01439     NodeBlender * pBlender = NULL;
01440     NodeBlend * pBlend = NULL;
01441     NodeShadowController* pShadController = NULL;
01442 
01443     if (!IS_A (pBevelControl->FindParent (), NodeShadowController))
01444     {
01445         pBlender = (NodeBlender *)pBevelControl->FindNext(CC_RUNTIME_CLASS(NodeBlender));
01446     }
01447     else
01448     {
01449         pShadController = (NodeShadowController*) pBevelControl->FindParent ();
01450         pBlender = (NodeBlender *)pBevelControl->FindParent ()->FindNext(CC_RUNTIME_CLASS(NodeBlender));
01451     }
01452 
01453     if (pBlender)
01454     {
01455         pBlend = (NodeBlend *)pBlender->FindParent();
01456 
01457         if (InitBlendAction::InitOnBlender(this, GetUndoActionList(), pBlender, TRUE, TRUE) != AC_OK)
01458             ERROR2RAW("Couldn't Initialise blend action");
01459 
01460         // re-insert this action at the head of the list
01461         if (!pShadController)
01462             pBlender->Reinit(pBevelControl, pBlender->GetNodeEnd(), FALSE);
01463         else
01464             pBlender->Reinit(pShadController, pBlender->GetNodeEnd(), FALSE);
01465     }
01466     else 
01467     {
01468         // can't have both ends changed !
01469         pBlender = (NodeBlender *)pBevelControl->FindPrevious(CC_RUNTIME_CLASS(NodeBlender));
01470 
01471         if (pBlender)
01472         {
01473             pBlend = (NodeBlend *)pBlender->FindParent();
01474 
01475             if (InitBlendAction::InitOnBlender(this, GetUndoActionList(), pBlender, TRUE, TRUE) != AC_OK)
01476                 ERROR2RAW("Couldn't Initialise blend action");
01477         
01478             if (!pShadController)
01479                 pBlender->Reinit(pBlender->GetNodeStart(), pBevelControl, FALSE);
01480             else
01481                 pBlender->Reinit(pBlender->GetNodeStart(), pShadController, FALSE);
01482         }
01483     }
01484 
01485     if (pBlender)
01486     {
01487         NodeBlend* ptrBlend = (NodeBlend*) pBlender->FindParent ();
01488 
01489         ERROR3IF (!IS_A (ptrBlend, NodeBlend), "NodeBlend is not a NodeBlend!");
01490 
01491         BOOL done = FALSE;
01492         NodeBlender* ptrNode = ptrBlend->FindFirstBlender ();
01493 
01494         while (!done)
01495         {
01496             if (ptrNode != pBlender)
01497             {
01498                 if (ptrNode->GetNodeStart () == pNode)
01499                 {
01500                     if (InitBlendAction::InitOnBlender(this, GetUndoActionList(), ptrNode, TRUE, TRUE) != AC_OK)
01501                         ERROR2RAW("Couldn't Initialise blend action");
01502 
01503                     if (pBevelControl)
01504                     {
01505                         if (!pShadController)
01506                             ptrNode->Reinit(pBevelControl, NULL, FALSE);
01507                         else
01508                             ptrNode->Reinit(pShadController, NULL, FALSE);
01509                     }
01510                 }
01511                 if (ptrNode->GetNodeEnd () == pNode)
01512                 {
01513                     if (InitBlendAction::InitOnBlender(this, GetUndoActionList(),  ptrNode, TRUE, TRUE) != AC_OK)
01514                         ERROR2RAW("Couldn't Initialise blend action");
01515 
01516                     if (pBevelControl)
01517                     {
01518                         if (!pShadController)
01519                             ptrNode->Reinit(NULL, pBevelControl, FALSE);
01520                         else
01521                             ptrNode->Reinit(NULL, pShadController, FALSE);
01522                     }
01523                 }
01524             }
01525 
01526             ptrNode = ptrBlend->FindNextBlender (ptrNode);
01527 
01528             if (!ptrNode)
01529                 done = TRUE;
01530         }
01531     }
01532 
01533     if (pNode->IsKindOf(CC_RUNTIME_CLASS(NodeShadowController)))
01534     {
01535         pShadowCont = (NodeShadowController *)pNode;
01536 
01537         pShadow = pShadowCont->GetShadow();
01538 
01539         pShadow->InvalidateBoundingRect();
01540         pShadow->GetParentController()->InvalidateBoundingRect();
01541         DoInvalidateNodeRegion(pShadow, TRUE);
01542         DoInvalidateNodeRegion(pShadow->GetParentController(), TRUE);
01543 
01544         ChangePenumbraSizeAction * pAction = NULL;
01545 
01546         ChangePenumbraSizeAction::Init(this, 
01547                                          GetUndoActionList(),
01548                                          pShadowCont,
01549                                          pShadowCont->GetPenumbraWidth(),
01550                                          &pAction);                                     
01551     }
01552 }
01553 
01554 /********************************************************************************************
01555 
01556 >   NodeAttribute * OpCreateBevel::DoDepthSearchForFill(Node * pNode)
01557 
01558     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> Mc
01559     Created:    18/12/98                                                                        
01560     Returns:    The fill attribute found, NULL if non
01561     Purpose:    Searches the subtree of pNode for the first fill attribute
01562 
01563 ********************************************************************************************/
01564 
01565 NodeAttribute * OpCreateBevel::DoDepthSearchForFill(Node * pNode)
01566 {
01567     if (!pNode)
01568         return NULL;
01569 
01570     while (pNode)
01571     {
01572         if (pNode->IsKindOf(CC_RUNTIME_CLASS(AttrFillGeometry)) &&
01573             !pNode->IsKindOf(CC_RUNTIME_CLASS(AttrStrokeColour)) &&
01574             !pNode->IsKindOf(CC_RUNTIME_CLASS(AttrStrokeTransp)) &&
01575             !pNode->IsKindOf(CC_RUNTIME_CLASS(AttrTranspFillGeometry)) &&
01576             !pNode->IsKindOf(CC_RUNTIME_CLASS(AttrValueChange)) &&
01577             !pNode->IsNodeHidden())
01578         {
01579             return (NodeAttribute *)pNode;  
01580         }
01581     
01582         // do the child of this node first
01583         Node * pChild = pNode->FindFirstChild();
01584 
01585         NodeAttribute * pAttr = DoDepthSearchForFill(pChild);
01586 
01587         if (pAttr)
01588             return pAttr;
01589 
01590         pNode = pNode->FindNext();
01591     }
01592 
01593     return NULL;
01594 }
01595 
01596 /********************************************************************************************
01597 
01598 >   void OpCreateBevel::ConvertToPaths(Node * pNode)
01599 
01600     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> Mc
01601     Created:    18/12/98                                                                        
01602     Returns:    
01603     Purpose:    Converts all quick shape nodes (recursively) to paths
01604 
01605 ********************************************************************************************/
01606 
01607 void OpCreateBevel::ConvertToPaths(Node * pNode)
01608 {
01609     /*
01610     BecomeA BAGroup(BECOMEA_REPLACE, CC_RUNTIME_CLASS(NodeGroup), this, TRUE);
01611 
01612     Node * pChildNode = NULL;
01613     Node * pNextNode  = NULL;
01614 
01615     // convert all nodes under the main node into being regular shapes
01616     while (pNode)
01617     {
01618         pChildNode = pNode->FindFirstChild();
01619 
01620         if (pChildNode)
01621         {
01622             ConvertToPaths(pChildNode);
01623         }
01624 
01625         pNextNode = pNode->FindNext();
01626 
01627         if (pNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)))
01628         {
01629             pNode->DoBecomeA(&BAPath);
01630             TRACEUSER( "DavidM", _T("Found regular shape !\n"));
01631         }
01632     
01633         pNode = pNextNode;
01634     }
01635     */
01636 }
01637 
01638 /********************************************************************************************
01639 
01640 >   BOOL OpCreateBevel::Declare()
01641 
01642     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01643     Created:    16/11/94                                                                        
01644     Returns:    TRUE if all went OK, False otherwise
01645     Purpose:    Adds the operation to the list of all known operations
01646 
01647 ********************************************************************************************/
01648 
01649 BOOL OpCreateBevel::Declare()
01650 {
01651     return (RegisterOpDescriptor(
01652                                 0, 
01653                                 _R(IDS_CREATEBEVELOP),
01654                                 CC_RUNTIME_CLASS(OpCreateBevel), 
01655                                 OPTOKEN_CREATEBEVEL,
01656                                 OpCreateBevel::GetState));
01657 
01658 }
01659 
01660 
01661 
01662 /********************************************************************************************
01663 
01664 >   OpState OpCreateBevel::GetState(String_256* Description, OpDescriptor*)
01665 
01666     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01667     Created:    16/11/94
01668     Outputs:    -
01669     Returns:    Ungreyed, Unticked
01670     Purpose:    Find out the state of the new regular shape at the specific time
01671 
01672 ********************************************************************************************/
01673 
01674 OpState OpCreateBevel::GetState(String_256* Description, OpDescriptor*)
01675 {
01676     OpState Blobby;
01677 
01678     // not ALLOCed with fail otherwise this'll fall over all the time !
01679     OpCreateBevel * pBevelOp = new OpCreateBevel;
01680 
01681     if (!pBevelOp)
01682     {
01683         ERROR3("Cannot create shadow op");
01684         Blobby.Greyed = TRUE;
01685         return Blobby;
01686     }
01687 
01688     ObjChangeFlags flgs(FALSE, FALSE, FALSE, FALSE);
01689     ObjChangeParam OP(OBJCHANGE_STARTING, flgs, NULL, pBevelOp, OBJCHANGE_CALLEDBYOP);
01690 
01691     if (GetApplication()->FindSelection()->AllowOp(&OP, FALSE))
01692     {               
01693         Blobby.Greyed = FALSE;
01694     }
01695     else
01696     {
01697         Blobby.Greyed = TRUE;
01698         delete pBevelOp;
01699         return Blobby;
01700     }
01701 
01702     delete pBevelOp;
01703 
01704     return Blobby;
01705 }
01706 
01707 
01712 
01713 /********************************************************************************************
01714 >   OpRemoveBevel::OpRemoveBevel()
01715 
01716     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
01717     Created:    21/11/96
01718     Purpose:    Constructor.
01719 ********************************************************************************************/
01720 
01721 OpRemoveBevel::OpRemoveBevel()
01722 {
01723 }
01724 
01725 
01726 
01727 /********************************************************************************************
01728 >   OpRemoveBevel::~OpRemoveBevel()
01729 
01730     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
01731     Created:    21/11/96
01732     Purpose:    Destructor.
01733 ********************************************************************************************/
01734 
01735 OpRemoveBevel::~OpRemoveBevel()
01736 {
01737 }
01738 
01739 /********************************************************************************************
01740 >   void OpRemoveBevel::GetOpName(String_256 * pString)
01741 
01742     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> & Olivier
01743     Created:    21/11/96
01744     Purpose:    Gets the name of this operation - dependent on what it did !
01745 ********************************************************************************************/
01746 
01747 void OpRemoveBevel::GetOpName(String_256 * pString)
01748 {
01749     if (pString)
01750         pString->Load(_R(IDS_REMOVEBEVELOPNAME));
01751 }
01752 
01753 
01754 
01755 
01756 /********************************************************************************************
01757 >   virtual void OpRemoveBevel::Do(OpDescriptor *pOpDesc)
01758     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
01759     Created:    21/11/96
01760     Inputs:     pOpDesc - OpDescriptor - unused
01761     Outputs:    -
01762     Returns:    -
01763     Purpose:    The do function.  Applys a Bevel to the selection in the current document
01764 ********************************************************************************************/
01765 
01766 void OpRemoveBevel::Do(OpDescriptor *pOpDesc)
01767 {
01768     // have we a bevel controller node in the selection ?
01769     if (!NodeBevelController::SelectionHasBevelNode())
01770         return;
01771     
01772     // Prepare an ObjChangeParam so we can mark which nodes will allow this op to happen to them
01773     ObjChangeFlags cFlags;
01774     ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
01775 
01776     // Get the selection 
01777     Range Sel(*(GetApplication()->FindSelection()));
01778     RangeControl rg = Sel.GetRangeControlFlags();
01779     rg.PromoteToParent = TRUE;
01780     Sel.SetRangeControl(rg);
01781 
01782     BOOL ok = TRUE;
01783 
01784     // Start the SelectionOp
01785     DoStartSelOp(TRUE, TRUE, TRUE, TRUE);
01786 
01787     // invalidate the whole range
01788     ok = DoInvalidateNodesRegions(Sel,
01789                              TRUE);
01790 
01791     Node * pNode = NULL;
01792     Node * pNextNode = NULL;
01793 //  Node * pAttribNode = NULL;
01794 
01795     NodeHidden * pNodeHidden = NULL;
01796 
01797     List AttribList;
01798     NodeListItem * pItem = NULL;
01799     NodeListItem * pNext = NULL;
01800 
01801     DocRect dr;
01802 
01803     Spread * pSpread = Document::GetSelectedSpread();
01804 
01805 //  INT32 count = 0;
01806 
01807     List BevelControllerList;
01808 
01809     // build a list of the selected bevel nodes
01810     BevelTools::BuildListOfSelectedNodes(&BevelControllerList, 
01811         CC_RUNTIME_CLASS(NodeBevelController));
01812 
01813     // go through this list, hiding them
01814     pItem = (NodeListItem *)BevelControllerList.GetHead();
01815 
01816     NodeShadowController * pShadControl = NULL;
01817 
01818     NodeBlend * pBlend = NULL;
01819     NodeBlender * pBlender = NULL;
01820 
01821     BOOL bBlendBefore = FALSE;
01822     BOOL bBlendAfter  = FALSE;
01823 
01824     // for blends
01825     NodeRenderableInk *pRenderableNode = NULL;
01826 
01827     while (pItem)
01828     {
01829         pNext = (NodeListItem *)BevelControllerList.GetNext(pItem);
01830 
01831         NodeBevelController* pControl = (NodeBevelController*) pItem->pNode;
01832 
01833         if (pControl)
01834         {
01835             SliceHelper::RemoveNamesFromController(this,pControl);
01836 
01837             // are we part of a blend ? if so, make a record of the blender object
01838             // and whether we're before or after it
01839             pBlender = (NodeBlender *)pItem->pNode->FindNext(CC_RUNTIME_CLASS(NodeBlender));
01840 
01841             bBlendBefore = FALSE;
01842             bBlendAfter = FALSE;
01843 
01844             if (pBlender)
01845             {
01846                 // we're before it !
01847                 bBlendBefore = TRUE;
01848 
01849                 pBlend = (NodeBlend *)pBlender->FindParent();
01850             }
01851             else
01852             {
01853                 // try the blend after
01854                 pBlender = (NodeBlender *)pItem->pNode->FindPrevious(CC_RUNTIME_CLASS(NodeBlender));
01855 
01856                 if (pBlender)
01857                 {
01858                     bBlendAfter = TRUE;
01859                     pBlend = (NodeBlend *)pBlender->FindParent();
01860                 }
01861             }
01862             
01863             // remove the attributes from the node
01864             if (ok) ok = DoRemoveAttrTypeFromSubtree(pItem->pNode, CC_RUNTIME_CLASS(AttrBevelIndent));
01865             if (ok) ok = DoRemoveAttrTypeFromSubtree(pItem->pNode, CC_RUNTIME_CLASS(AttrBevelLightAngle));
01866             if (ok) ok = DoRemoveAttrTypeFromSubtree(pItem->pNode, CC_RUNTIME_CLASS(AttrBevelType));
01867             if (ok) ok = DoRemoveAttrTypeFromSubtree(pItem->pNode, CC_RUNTIME_CLASS(AttrBevelContrast));
01868             
01869             // invalidate the rect
01870             Node * pParent = pItem->pNode->FindParent();
01871     
01872             if (!pItem->pNode->IsNodeHidden() && pParent)
01873             {
01874                 if (ok) ok = DoInvalidateNodeRegion((NodeRenderableInk *)pItem->pNode, TRUE);           
01875                 
01876                 // localise the attributes
01877                 if (!DoLocaliseCommonAttributes((NodeRenderableInk *)pItem->pNode, TRUE))
01878                 {
01879                     FailAndExecute();
01880                     End();
01881                     BevelControllerList.DeleteAll();
01882                     
01883                     return;
01884                 }
01885                 
01886                 // now, move non-bevel nodes to top level
01887                 // go from back to front to maintain the rendering order
01888                 pNode = pItem->pNode->FindLastChild();
01889                 
01890                 while (pNode)
01891                 {
01892                     pNextNode = pNode->FindPrevious();
01893                     
01894                     if (!pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevel)) &&
01895                         !pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevelBegin)) &&
01896                         !pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevelController)) &&
01897                         !pNode->IsNodeHidden())
01898                     {
01899                         if (pNode->IsAnObject() && !pNode->IsAnAttribute())
01900                         {
01901                             if (ok)
01902                                 ok = DoMoveNode(pNode, pItem->pNode, NEXT);
01903                             
01904                             if (ok)
01905                                 ok = DoSelectNode((NodeRenderableInk *)pNode);
01906                         }
01907                         else if (pNode->IsAnAttribute())
01908                         {
01909                             // hide attributes
01910                             // DoHideNode(pNode, FALSE, &pNodeHidden);
01911 
01912                             if (pNode->IsAnObjectName())
01913                                 DoHideNode(pNode, FALSE);
01914                         }
01915                     }
01916                     
01917                     pNode = pNextNode;
01918                 }
01919                 
01920                 // finally, deselect & hide the bevel controller node
01921                 if (ok)
01922                     ok = DoDeselectNode((NodeRenderableInk *)pItem->pNode);
01923                 
01924                 // need to tell any shadows to regen
01925                 pShadControl = 
01926                     (NodeShadowController *)pItem->pNode->FindParent(CC_RUNTIME_CLASS(NodeShadowController));
01927 
01928                 if (ok) 
01929                 {
01930                     pItem->pNode->AllowOp(&ObjChange);
01931                     ok = DoHideNode((NodeBevelController *)pItem->pNode, TRUE, &pNodeHidden);
01932                 }
01933 
01934                 if (pParent)
01935                 {
01936                     if (pParent->IsAnObject())
01937                     {
01938                         if (ok) 
01939                             ok = DoFactorOutCommonChildAttributes((NodeRenderableInk *)pParent, TRUE);
01940                     }
01941                 }
01942 
01943                 // do the blend inform - i.e. inform them that their objects have changed
01944                 if (bBlendBefore)
01945                 {
01946                     if (InitBlendAction::InitOnBlender(this, GetUndoActionList(), pBlender, TRUE, TRUE) != AC_OK)
01947                     {
01948                         ERROR2RAW("Couldn't Initialise blend action");
01949                     }
01950 
01951                     // reinit the node
01952                     pRenderableNode = (NodeRenderableInk *)pBlender->FindPrevious(CC_RUNTIME_CLASS(NodeRenderableInk)); 
01953                     
01954                     if (pRenderableNode)
01955                     {
01956                         pBlender->Reinit(pRenderableNode,   pBlender->GetNodeEnd(), FALSE);
01957                     }
01958                 }
01959                 else if (bBlendAfter)
01960                 {
01961                     if (InitBlendAction::InitOnBlender(this, GetUndoActionList(), pBlender, TRUE, TRUE) != AC_OK)
01962                     {
01963                         ERROR2RAW("Couldn't Initialise blend action");
01964                     }
01965 
01966                     // reinit the node
01967                     pRenderableNode = (NodeRenderableInk *)pBlender->FindNext(CC_RUNTIME_CLASS(NodeRenderableInk)); 
01968                     
01969                     if (pRenderableNode)
01970                     {
01971                         pBlender->Reinit(pBlender->GetNodeStart(), pRenderableNode, FALSE);
01972                     }
01973                 }
01974 
01975                 if (pBlender)
01976                 {
01977                     NodeBlend* ptrBlend = (NodeBlend*) pBlender->FindParent ();
01978 
01979                     ERROR3IF (!IS_A (ptrBlend, NodeBlend), "NodeBlend is not a NodeBlend!");
01980 
01981                     BOOL done = FALSE;
01982                     NodeBlender* ptrNode = ptrBlend->FindFirstBlender ();
01983 
01984                     while (!done)
01985                     {
01986                         if (ptrNode != pBlender)
01987                         {
01988                             if (ptrNode->GetNodeStart () == pControl)
01989                             {
01990                                 if (InitBlendAction::InitOnBlender(this, GetUndoActionList(), ptrNode, TRUE, TRUE) != AC_OK)
01991                                 {
01992                                     ERROR2RAW("Couldn't Initialise blend action");
01993                                 }
01994                                 
01995                                 if (pRenderableNode)
01996                                 {
01997                                     ptrNode->Reinit(pRenderableNode, NULL, FALSE);
01998                                 }
01999                             }
02000                             if (ptrNode->GetNodeEnd () == pControl)
02001                             {
02002                                 if (InitBlendAction::InitOnBlender(this, GetUndoActionList(), ptrNode, TRUE, TRUE) != AC_OK)
02003                                 {
02004                                     ERROR2RAW("Couldn't Initialise blend action");
02005                                 }
02006 
02007                                 if (pRenderableNode)
02008                                 {
02009                                     ptrNode->Reinit(NULL, pRenderableNode, FALSE);
02010                                 }
02011                             }
02012                         }
02013 
02014                         ptrNode = ptrBlend->FindNextBlender (ptrNode);
02015 
02016                         if (!ptrNode)
02017                         {
02018                             done = TRUE;
02019                         }
02020                     }
02021                 }
02022 /*              
02023                 // inform all parents of the change
02024                 while (pParent)
02025                 {
02026                     // set up the object change parameters
02027                     ObjChangeFlags flgs(FALSE, FALSE, FALSE, TRUE);
02028                     flgs.RegenerateNode = TRUE;
02029                     ObjChangeParam OP(OBJCHANGE_FINISHED, flgs, NULL, this, OBJCHANGE_CALLEDBYOP);
02030 
02031                     pParent->OnChildChange(&OP);
02032 
02033                     pParent = pParent->FindParent();
02034                 }   
02035 */          }
02036         }
02037 
02038         // move onto the next one
02039         pItem = pNext;
02040     }
02041 
02042     BevelControllerList.DeleteAll();
02043 
02044     if (!ok)
02045     {
02046         FailAndExecute();
02047     }
02048 
02049     ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this);
02050     UpdateChangedNodes(&ObjChange, pSpread);
02051 
02052     GetApplication()->UpdateSelection();
02053     End();  
02054 }
02055 
02056 
02057 /********************************************************************************************
02058 
02059 >   BOOL OpRemoveBevel::Declare()
02060 
02061     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
02062     Created:    21/11/96
02063     Returns:    TRUE if all went OK, False otherwise
02064     Purpose:    Adds the operation to the list of all known operations
02065 
02066 ********************************************************************************************/
02067 
02068 BOOL OpRemoveBevel::Declare()
02069 {
02070     return (RegisterOpDescriptor(
02071                                 0, 
02072                                 _R(IDS_REMOVEBEVELOP),
02073                                 CC_RUNTIME_CLASS(OpRemoveBevel), 
02074                                 OPTOKEN_REMOVEBEVEL,
02075                                 OpRemoveBevel::GetState));
02076 
02077 }
02078 
02079 
02080 /********************************************************************************************
02081 
02082 >   OpState OpRemoveBevel::GetState(String_256* Description, OpDescriptor*)
02083 
02084     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
02085     Created:    21/11/96
02086     Outputs:    -
02087     Returns:    Ungreyed, Unticked
02088     Purpose:    Find out the state of the new regular shape at the specific time
02089 
02090 ********************************************************************************************/
02091 
02092 OpState OpRemoveBevel::GetState(String_256* Description, OpDescriptor*)
02093 {
02094     OpState Blobby;
02095     
02096     return Blobby;
02097 }
02098 
02099 
02101 // RegenerateBevelAction class implementation
02102 /********************************************************************************************
02103 
02104 >   RegenerateBevelAction::RegenerateBevelAction()
02105 
02106     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
02107     Created:    07/01/97
02108     Inputs:     -
02109     Outputs:    -
02110     Returns:    -
02111     Purpose:    Constructor for the action
02112     Errors:     -
02113     SeeAlso:    -
02114 
02115 ********************************************************************************************/
02116 
02117 RegenerateBevelAction::RegenerateBevelAction()
02118 {
02119     m_pNodes = NULL;
02120     m_bCache = FALSE;
02121 }
02122 
02123 
02124 /********************************************************************************************
02125 
02126 >   ActionCode RegenerateBevelAction::Init(     Operation*  pOp,
02127                                                 ActionList* pActionList,
02128                                                 List * pNodes
02129                                                 ChangePositionShadowXAction**   ppNewAction);
02130 
02131     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
02132     Created:    17/3/99
02133     Inputs:     pOp             = ptr to the operation to which this action belongs
02134                 pActionList     =  ptr to action list to which this action should be added
02135                 pNodes          = ptr to node list containing the NodeBevel nodes to be 
02136                                   regenerated   
02137     Outputs:    ppNewAction     = ptr to a ptr to an action, allowing the function to return
02138                                   a pointer to the created action
02139     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
02140     Purpose:    This is the function which creates an instance of this action. If there is no room 
02141                 in the undo buffer (which is determined by the base class Init function called within)
02142                 the function will either return AC_NO_RECORD which means the operation can continue, 
02143                 but no undo information needs to be stored, or AC_OK which means the operation should
02144                 continue AND record undo information. If the function returns AC_FAIL, there was not 
02145                 enough memory to record the undo information, and the user has decided not to continue
02146                 with the operation.
02147     Errors:     -
02148     SeeAlso:    Action::Init()
02149 
02150 ********************************************************************************************/
02151 
02152 ActionCode RegenerateBevelAction::Init(Operation* pOp,
02153                                         ActionList* pActionList,
02154                                         List * pNodes,
02155                                         RegenerateBevelAction** ppNewAction,
02156                                         BOOL bCache)
02157 {
02158 
02159     UINT32 ActSize = sizeof(RegenerateBevelAction);
02160 
02161     ERROR2IF(!pOp->IS_KIND_OF(UndoableOperation), AC_FAIL, "Operation isn't undoable");
02162     
02163     ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(RegenerateBevelAction),(Action**)ppNewAction);
02164 
02165     // make a copy of the node list
02166     List * pCopyList = NULL;
02167     ALLOC_WITH_FAIL(pCopyList, new List, pOp);
02168     NodeListItem * pItem = (NodeListItem *)pNodes->GetHead();
02169     NodeListItem * pCopyItem = NULL;
02170 
02171     while (pItem)
02172     {
02173         ALLOC_WITH_FAIL(pCopyItem, new NodeListItem, pOp);
02174         pCopyItem->pNode = pItem->pNode;
02175         
02176         pCopyList->AddTail(pCopyItem);
02177 
02178         pItem = (NodeListItem *)pNodes->GetNext(pItem);
02179     }
02180 
02181     (*ppNewAction)->m_pNodes = pCopyList;
02182     (*ppNewAction)->m_bCache = bCache;
02183 
02184     pItem = (NodeListItem *)pNodes->GetHead();
02185 
02186     DocView * pView = DocView::GetCurrent();
02187 
02188     if (Ac != AC_FAIL)
02189     {
02190         while (pItem)
02191         {
02192             if (pItem->pNode)
02193             {
02194                 if (pItem->pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevel)))
02195                 {
02196                     NodeBevel* pBevel = (NodeBevel*)pItem->pNode;
02197                     if (pView && bCache)
02198                     {
02199                         ASSERT(pBevel->FindParent());
02200                         GetApplication()->AddNodeToRegenList(pBevel->FindParent());
02201                         if (pBevel->FindParent()->IsBounded())
02202                             ((NodeRenderableBounded*)pBevel->FindParent())->InvalidateBoundingRect(TRUE);
02203                     }
02204                     else
02205                     {
02206                         if (pBevel->FindParent(CC_RUNTIME_CLASS(Spread)))
02207                         {
02208                             ((NodeBevelController*)pBevel->GetParentController())->RegenerateNode(NULL, FALSE);
02209                         }
02210                     }
02211                 }
02212             }
02213 
02214             pItem = (NodeListItem *)pNodes->GetNext(pItem);
02215         }
02216     }
02217 
02218     // move my action to the head of the list
02219     pActionList->RemoveItem(*ppNewAction);
02220     pActionList->AddHead(*ppNewAction);
02221 
02222     return Ac;
02223 }
02224 
02225 /********************************************************************************************
02226 
02227 >   ActionCode RegenerateBevelAction::Execute();
02228 
02229     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
02230     Created:    17/3/99
02231     Inputs:     -
02232     Outputs:    -
02233     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
02234     Purpose:    Executes the action.  Causes a regen of all bevels nodes in the action's list
02235     Errors:     -
02236     SeeAlso:    Action::Init()
02237 
02238 ********************************************************************************************/
02239 
02240 ActionCode RegenerateBevelAction::Execute()
02241 {
02242     ActionCode Act;
02243     RegenerateBevelAction* pAction;
02244 
02245     Act = RegenerateBevelAction::Init(  pOperation, 
02246                                         pOppositeActLst,
02247                                         m_pNodes,
02248                                         &pAction,
02249                                         m_bCache);
02250 
02251     if (Act != AC_FAIL)
02252     {
02253     }
02254 
02255     return Act;
02256 }
02257 
02258 RegenerateBevelAction::~RegenerateBevelAction()
02259 {
02260     if (m_pNodes)
02261     {
02262         m_pNodes->DeleteAll();
02263         delete m_pNodes;
02264     }
02265 }
02266 
02268 // RegenerateBevelBitmapAction class implementation
02269 /********************************************************************************************
02270 
02271 >   RegenerateBevelBitmapAction::RegenerateBevelBitmapAction()
02272 
02273     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
02274     Created:    07/01/97
02275     Inputs:     -
02276     Outputs:    -
02277     Returns:    -
02278     Purpose:    Constructor for the action
02279     Errors:     -
02280     SeeAlso:    -
02281 
02282 ********************************************************************************************/
02283 
02284 RegenerateBevelBitmapAction::RegenerateBevelBitmapAction()
02285 {
02286     m_pNodes = NULL;
02287 }
02288 
02289 
02290 /********************************************************************************************
02291 
02292 >   ActionCode RegenerateBevelBitmapAction::Init(   Operation*  pOp,
02293                                                 ActionList* pActionList,
02294                                                 List * pNodes
02295                                                 ChangePositionShadowXAction**   ppNewAction);
02296 
02297     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
02298     Created:    17/3/99
02299     Inputs:     pOp             = ptr to the operation to which this action belongs
02300                 pActionList     =  ptr to action list to which this action should be added
02301                 pNodes          = ptr to node list containing the NodeBevel nodes to be 
02302                                   regenerated   
02303     Outputs:    ppNewAction     = ptr to a ptr to an action, allowing the function to return
02304                                   a pointer to the created action
02305     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
02306     Purpose:    This is the function which creates an instance of this action. If there is no room 
02307                 in the undo buffer (which is determined by the base class Init function called within)
02308                 the function will either return AC_NO_RECORD which means the operation can continue, 
02309                 but no undo information needs to be stored, or AC_OK which means the operation should
02310                 continue AND record undo information. If the function returns AC_FAIL, there was not 
02311                 enough memory to record the undo information, and the user has decided not to continue
02312                 with the operation.
02313     Errors:     -
02314     SeeAlso:    Action::Init()
02315 
02316 ********************************************************************************************/
02317 
02318 
02319 
02320 ActionCode RegenerateBevelBitmapAction::Init(Operation* pOp,
02321                                         ActionList* pActionList,
02322                                         List * pNodes,
02323                                         RegenerateBevelBitmapAction** ppNewAction)
02324 {
02325     UINT32 ActSize = sizeof(RegenerateBevelBitmapAction);
02326     
02327     ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(RegenerateBevelBitmapAction),
02328         (Action**)ppNewAction);
02329 
02330     // make a copy of the node list
02331     List * pCopyList = NULL;
02332     ALLOC_WITH_FAIL(pCopyList, new List, pOp);
02333     NodeListItem * pItem = (NodeListItem *)pNodes->GetHead();
02334     NodeListItem * pCopyItem = NULL;
02335 
02336     while (pItem)
02337     {
02338         ALLOC_WITH_FAIL(pCopyItem, new NodeListItem, pOp);
02339         pCopyItem->pNode = pItem->pNode;
02340         
02341         pCopyList->AddTail(pCopyItem);
02342 
02343         pItem = (NodeListItem *)pNodes->GetNext(pItem);
02344     }
02345 
02346     (*ppNewAction)->m_pNodes = pCopyList;
02347 
02348     pItem = (NodeListItem *)pNodes->GetHead();
02349 
02350 //  DocView * pView = DocView::GetCurrent();
02351 
02352     if (Ac != AC_FAIL)
02353     {
02354         while (pItem)
02355         {
02356             if (pItem->pNode)
02357             {
02358                 if (pItem->pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevel)))
02359                 {
02360                     NodeBevel* pBevel = (NodeBevel*)pItem->pNode;
02361                     NodeBevelController* pControl = (NodeBevelController*)pBevel->GetParentController();
02362     
02363                     if (pControl)
02364                     {
02365                         pControl->RegenerateBevelBitmap(NULL, TRUE);
02366                     }
02367                 }
02368             }
02369 
02370             pItem = (NodeListItem *)pNodes->GetNext(pItem);
02371         }
02372     }
02373 
02374     // move my action to the head of the list
02375     pActionList->RemoveItem(*ppNewAction);
02376     pActionList->AddHead(*ppNewAction);
02377 
02378     return Ac;
02379 }
02380 
02381 /********************************************************************************************
02382 
02383 >   ActionCode RegenerateBevelBitmapAction::Execute();
02384 
02385     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
02386     Created:    17/3/99
02387     Inputs:     -
02388     Outputs:    -
02389     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
02390     Purpose:    Executes the action.  Causes a regen of all bevels nodes in the action's list
02391     Errors:     -
02392     SeeAlso:    Action::Init()
02393 
02394 ********************************************************************************************/
02395 
02396 ActionCode RegenerateBevelBitmapAction::Execute()
02397 {
02398     ActionCode Act;
02399     RegenerateBevelBitmapAction* pAction;
02400 
02401     Act = RegenerateBevelBitmapAction::Init(    pOperation, 
02402                                         pOppositeActLst,
02403                                         m_pNodes,
02404                                         &pAction);
02405 
02406     if (Act != AC_FAIL)
02407     {
02408     }
02409 
02410     return Act;
02411 }
02412 
02413 RegenerateBevelBitmapAction::~RegenerateBevelBitmapAction()
02414 {
02415     if (m_pNodes)
02416     {
02417         m_pNodes->DeleteAll();
02418         delete m_pNodes;
02419     }
02420 }
02421 
02422 
02424 // ChangeLightAnglesAction class implementation
02425 /********************************************************************************************
02426 
02427 >   ChangeLightAnglesAction::ChangeLightAnglesAction()
02428 
02429     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
02430     Created:    07/01/97
02431     Inputs:     -
02432     Outputs:    -
02433     Returns:    -
02434     Purpose:    Constructor for the action
02435     Errors:     -
02436     SeeAlso:    -
02437 
02438 ********************************************************************************************/
02439 
02440 ChangeLightAnglesAction::ChangeLightAnglesAction()
02441 {
02442 }
02443 
02444 
02445 /********************************************************************************************
02446 
02447 >   ActionCode ChangeLightAnglesAction::( Operation* pOp,
02448                                           ActionList* pActionList,
02449                                           List * pNodes,
02450                                           INT32 Angle,
02451                                           INT32 OldAngle,
02452                                           ChangeLightAnglesAction** NewAction);
02453 
02454     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
02455     Created:    17/3/99
02456     Inputs:     pOp             = ptr to the operation to which this action belongs
02457                 pActionList     =  ptr to action list to which this action should be added
02458                 pNodes          = ptr to node list containing the bevel controller nodes to be 
02459                                   addressed
02460                 Angle           = the new light angle
02461                 OldAngle        = the old light angle
02462     Outputs:    ppNewAction     = ptr to a ptr to an action, allowing the function to return
02463                                   a pointer to the created action
02464     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
02465     Purpose:    This is the function which creates an instance of this action. If there is no room 
02466                 in the undo buffer (which is determined by the base class Init function called within)
02467                 the function will either return AC_NO_RECORD which means the operation can continue, 
02468                 but no undo information needs to be stored, or AC_OK which means the operation should
02469                 continue AND record undo information. If the function returns AC_FAIL, there was not 
02470                 enough memory to record the undo information, and the user has decided not to continue
02471                 with the operation.
02472     Errors:     -
02473     SeeAlso:    Action::Init()
02474 
02475 ********************************************************************************************/
02476 
02477 
02478 
02479 ActionCode ChangeLightAnglesAction::Init( Operation* pOp,
02480                                           ActionList* pActionList,
02481                                           List * pNodes,
02482                                           INT32 NewAngle, 
02483                                           INT32 OldAngle,
02484                                           ChangeLightAnglesAction** NewAction)
02485 {
02486     if (!pOp)
02487         return AC_FAIL;
02488 
02489     if (!pOp->IsKindOf(CC_RUNTIME_CLASS(UndoableOperation)))
02490         return AC_FAIL; 
02491     
02492     UINT32 ActSize = sizeof(ChangeLightAnglesAction);
02493     
02494     ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(ChangeLightAnglesAction),(Action**)NewAction);
02495 
02496     if (Ac != AC_OK)
02497         return Ac;
02498 
02499 //  UndoableOperation * pUndoOp = (UndoableOperation *)pOp;
02500 
02501     // run through the node list, making copies of all the affected nodes
02502     NodeListItem * pItem = NULL;
02503     NodeListItem * pNewItem = NULL;
02504 
02505     pItem = (NodeListItem *)pNodes->GetHead();
02506 
02507     AttrBevelLightAngle *pAttr = NULL;
02508     
02509     // store the old angle setting
02510     (*NewAction)->m_OldAngle = (INT32)OldAngle;
02511     (*NewAction)->m_NewAngle = (INT32)NewAngle;
02512 
02513     List AttrList;
02514 
02515 //  NodeListItem * pAttrItem = NULL;
02516 
02517 //  Node * pLastNode = NULL;
02518     NodeBevelController * pBevelNode = NULL;
02519     AttrBevelLightAngle * pAttrNode = NULL;
02520 
02521     DocView * pView = DocView::GetCurrent();
02522     
02523     while (pItem)
02524     {
02525         if (pItem->pNode)
02526         {
02527             if (pItem->pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevelController)))
02528             {
02529                 // first, add this to the action's list of nodes
02530                 pBevelNode = (NodeBevelController *)pItem->pNode;
02531 
02532                 ALLOC_WITH_FAIL(pNewItem, new NodeListItem, pOp);
02533                 pNewItem->pNode = pItem->pNode;
02534                 (*NewAction)->m_NodeList.AddTail(pNewItem);
02535 
02536                 // find out if a light angle attribute exists under this controller
02537                 // node
02538                 if (pBevelNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBevelLightAngle),
02539                     (NodeAttribute **)(&pAttrNode)))
02540                 {
02541                     if (!pAttrNode->IsADefaultAttr())
02542                     {
02543                         // if it exists then
02544                         // just set its value
02545                         pAttrNode->Value.m_LightAngle = NewAngle;
02546                     }
02547                     else
02548                     {
02549                         // well, we have a non-factored out one so add one in based on the 
02550                         // node's settings
02551                         ALLOC_WITH_FAIL(pAttr, new AttrBevelLightAngle(pBevelNode, FIRSTCHILD), pOp);
02552                         pAttr->Value.m_LightAngle = NewAngle;
02553                     }
02554                 }
02555                 
02556                 // change the bevel node's angle
02557                 pBevelNode->m_LightAngle = NewAngle;
02558 
02559                 // and invalidate the bevel node
02560                 if (pBevelNode->GetBevelNode())
02561                 {
02562                     if (pView)
02563                     {
02564                         GetApplication()->AddNodeToRegenList(pBevelNode);
02565                     }
02566                     else
02567                     {
02568                         pBevelNode->GetBevelNode()->InvalidateMe();
02569                     }
02570                 }
02571                             
02572                 // and now factor out
02573                 // ((NodeRenderableInk *)pLastNode)->FactorOutCommonChildAttributes();
02574             }
02575         }
02576 
02577         pItem = (NodeListItem *)pNodes->GetNext(pItem);
02578     }
02579     
02580     return Ac;
02581 }
02582 
02583 /********************************************************************************************
02584 
02585 >   ActionCode ChangeLightAnglesAction::Execute();
02586 
02587     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
02588     Created:    17/3/99
02589     Inputs:     -
02590     Outputs:    -
02591     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
02592     Purpose:    Executes the action.  Causes a regen of all bevels nodes in the action's list
02593     Errors:     -
02594     SeeAlso:    Action::Init()
02595 
02596 ********************************************************************************************/
02597 
02598 ActionCode ChangeLightAnglesAction::Execute()
02599 {
02600     ActionCode Act = AC_OK;
02601     ChangeLightAnglesAction* pAction;
02602 
02603     Act = ChangeLightAnglesAction::Init(pOperation, 
02604                                         pOppositeActLst,
02605                                         &m_NodeList,
02606                                         m_OldAngle,
02607                                         m_NewAngle,
02608                                         &pAction);
02609 
02610     if (Act != AC_FAIL)
02611     {
02612         INT32 angle = m_NewAngle;
02613         m_NewAngle = m_OldAngle;
02614         m_OldAngle = angle;
02615     }
02616 
02617     return Act;
02618 }
02619 
02620 ChangeLightAnglesAction::~ChangeLightAnglesAction()
02621 {
02622     m_NodeList.DeleteAll();
02623 }
02624 
02626 // RemoveBevelAttributesAction class implementation
02627 /********************************************************************************************
02628 
02629 >   RemoveBevelAttributesAction::RemoveBevelAttributesAction()
02630 
02631     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
02632     Created:    07/01/97
02633     Inputs:     -
02634     Outputs:    -
02635     Returns:    -
02636     Purpose:    Constructor for the action
02637     Errors:     -
02638     SeeAlso:    -
02639 
02640 ********************************************************************************************/
02641 
02642 RemoveBevelAttributesAction::RemoveBevelAttributesAction()
02643 {
02644     m_bShouldDo = FALSE;
02645 }
02646 
02647 
02648 /********************************************************************************************
02649 
02650 >   ActionCode RemoveBevelAttributesAction::Init( Operation* pOp,
02651                                           ActionList* pActionList,
02652                                           NodeRenderableInk * pNode, 
02653                                           BOOL m_bShouldDo,
02654                                           RemoveBevelAttributesAction** NewAction);
02655 
02656     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
02657     Created:    17/3/99
02658     Inputs:     pOp             = ptr to the operation to which this action belongs
02659                 pActionList     =  ptr to action list to which this action should be added
02660                 pNode           =   ptr to the node to use
02661                 m_bShouldDo     = whether to perform the action now, or wait until the undo
02662     Outputs:    ppNewAction     = ptr to a ptr to an action, allowing the function to return
02663                                   a pointer to the created action
02664     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
02665     Purpose:    This is the function which creates an instance of this action. If there is no room 
02666                 in the undo buffer (which is determined by the base class Init function called within)
02667                 the function will either return AC_NO_RECORD which means the operation can continue, 
02668                 but no undo information needs to be stored, or AC_OK which means the operation should
02669                 continue AND record undo information. If the function returns AC_FAIL, there was not 
02670                 enough memory to record the undo information, and the user has decided not to continue
02671                 with the operation.
02672     Errors:     -
02673     SeeAlso:    Action::Init()
02674 
02675 ********************************************************************************************/
02676 
02677 
02678 
02679 ActionCode RemoveBevelAttributesAction::Init( Operation* pOp,
02680                                           ActionList* pActionList,
02681                                           NodeRenderableInk * pNode, 
02682                                           BOOL bShouldDo,
02683                                           RemoveBevelAttributesAction** NewAction)
02684 {
02685     if (!pOp)
02686         return AC_FAIL;
02687 
02688     if (!pOp->IsKindOf(CC_RUNTIME_CLASS(UndoableOperation)))
02689         return AC_FAIL; 
02690     
02691     UINT32 ActSize = sizeof(RemoveBevelAttributesAction);
02692     
02693     ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(RemoveBevelAttributesAction),(Action**)NewAction);
02694 
02695     if (Ac != AC_OK)
02696         return Ac;
02697 
02698 //  UndoableOperation * pUndoOp = (UndoableOperation *)pOp;
02699 
02700     (*NewAction)->m_bShouldDo = bShouldDo;
02701     (*NewAction)->m_pNode     = pNode;
02702 
02703 //  HideNodeAction * pHideAction = NULL;
02704 
02705 //  BOOL ok = TRUE;
02706 
02707 //  NodeListItem * pItem = NULL;
02708 
02709     // put this at the head of the list
02710     pActionList->RemoveItem(*NewAction);
02711     pActionList->AddHead(*NewAction);
02712 
02713     return Ac;
02714 }
02715 
02716 /********************************************************************************************
02717 
02718 >   ActionCode ChangeLightAnglesAction::Execute();
02719 
02720     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
02721     Created:    17/3/99
02722     Inputs:     -
02723     Outputs:    -
02724     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
02725     Purpose:    Executes the action.  Causes a regen of all bevels nodes in the action's list
02726     Errors:     -
02727     SeeAlso:    Action::Init()
02728 
02729 ********************************************************************************************/
02730 
02731 ActionCode RemoveBevelAttributesAction::Execute()
02732 {
02733     ActionCode Act = AC_OK;
02734     RemoveBevelAttributesAction* pAction;
02735 
02736     if (m_bShouldDo)
02737     {
02738         Act = RemoveBevelAttributesAction::Init(pOperation, 
02739                                         pOppositeActLst,
02740                                         m_pNode,
02741                                         FALSE,
02742                                         &pAction);
02743     }
02744     else
02745     {
02746         Act = RemoveBevelAttributesAction::Init(pOperation, 
02747                                         pOppositeActLst,
02748                                         m_pNode,
02749                                         TRUE,
02750                                         &pAction);
02751     }
02752 
02753     NodeListItem * pItem = NULL;
02754 
02755     // the business end
02756     if (!m_bShouldDo && Act == AC_OK)
02757     {
02758         // get rid of the existing list
02759         pAction->m_AttrList.DeleteAll();
02760         
02761         // remove all bevel attributes from the node's tree
02762         Node * pChild = pAction->m_pNode->FindFirstDepthFirst();
02763         Node * pNext = NULL;
02764 
02765         while (pChild && pChild != pAction->m_pNode)
02766         {
02767             pNext = pChild->FindNextDepthFirst(pAction->m_pNode);
02768 
02769             if (pChild->IsAnAttribute())
02770             {
02771                 if (pChild->IS_KIND_OF(AttrBevel))
02772                 {
02773                     // delete the node
02774 //                  pChild->UnlinkNodeFromTree();
02775 
02776                     pItem = new NodeListItem(pChild);
02777 
02778                     pAction->m_AttrList.AddTail(pItem);                 
02779                 }
02780             }
02781 
02782             pChild = pNext;
02783         }
02784     }
02785     else
02786     {
02787         pItem = (NodeListItem *)m_AttrList.GetHead();
02788 
02789         while (pItem)
02790         {
02791             pItem->pNode->AttachNode(m_pNode, FIRSTCHILD);
02792 
02793             pItem = (NodeListItem *)m_AttrList.GetNext(pItem);
02794         }
02795 
02796         m_AttrList.DeleteAll();
02797 
02798         NodeBevelController * pController = 
02799             (NodeBevelController *)m_pNode->FindParent(CC_RUNTIME_CLASS(NodeBevelController));
02800 
02801         if (pController)
02802             pController->OptimiseAttributes();
02803 
02804         // m_pNode->NormaliseAttributes();
02805     }
02806 
02807     return Act;
02808 }
02809 
02810 RemoveBevelAttributesAction::~RemoveBevelAttributesAction()
02811 {
02812     m_AttrList.DeleteAll(); 
02813 }
02814 
02815 
02816 
02817 /********************************************************************************************
02818 >   OpChangeBevelLightAngle::OpChangeBevelLightAngle()
02819 
02820     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> & Olivier
02821     Created:    21/11/96
02822     Purpose:    Constructor.
02823 ********************************************************************************************/
02824 
02825 
02826 OpChangeBevelLightAngle::OpChangeBevelLightAngle()
02827 {
02828     //TRACEUSER( "MarkH", _T("Just Made a OpCreateBevel Class!\n"));
02829 }
02830 
02831 
02832 
02833 /********************************************************************************************
02834 >   OpCreateBevel::~OpCreateBevel()
02835 
02836     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> & Olivier
02837     Created:    21/11/96
02838     Purpose:    Destructor.
02839 ********************************************************************************************/
02840 
02841 OpChangeBevelLightAngle::~OpChangeBevelLightAngle()
02842 {
02843     //TRACEUSER( "MarkH", _T("Just Killed OpCreateBevel Class!!!\n"));
02844 }
02845 
02846 /********************************************************************************************
02847 
02848 >   BOOL OpChangeBevelLightAngle::Declare()
02849 
02850     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
02851     Created:    23/3/99
02852     Returns:    TRUE if all went OK, False otherwise
02853     Purpose:    Adds the operation to the list of all known operations
02854 
02855 ********************************************************************************************/
02856 
02857 BOOL OpChangeBevelLightAngle::Declare()
02858 {
02859     BOOL retn = (RegisterOpDescriptor(
02860                                 0, 
02861                                 _R(IDS_CHANGEATTRIBUTE),
02862                                 CC_RUNTIME_CLASS(OpChangeBevelLightAngle), 
02863                                 OPTOKEN_CHANGEATTRIBUTE,
02864                                 OpChangeBevelLightAngle::GetState));
02865     return retn;
02866 
02867 }
02868 
02869 /********************************************************************************************
02870 >   void OpChangeBevelLightAngle::DoWithParam(OpDescriptor* pOp, OpParam* pParam)
02871 
02872     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
02873     Created:    13/01/97
02874     Inputs:     
02875     Outputs:    -
02876     Returns:    -
02877     Purpose:    Changes all the bevel light angles in the list to the given angle
02878 ********************************************************************************************/
02879 
02880 void OpChangeBevelLightAngle::DoWithParam(OpDescriptor* pOp, OpParam* pParam)
02881 {
02882     if (!pOp || !pParam)
02883     {
02884         End();
02885         return;
02886     }
02887 
02888     OpChangeLightAnglesParam * pAttrParam = (OpChangeLightAnglesParam *)pParam;
02889 
02890     if (!pAttrParam->pNodes)
02891     {
02892         End();
02893         return;
02894     }
02895 
02896     if (pAttrParam->pNodes->IsEmpty())
02897     {
02898         End();
02899         return;
02900     }
02901 
02902     // Start a slow job
02903     BeginSlowJob(-1, TRUE);
02904 
02905     DoStartSelOp(TRUE);
02906 
02907     BOOL ok = TRUE;
02908 
02909     // first, localise all the attributes
02910     List * pNodes = pAttrParam->pNodes;
02911     NodeListItem * pItem = (NodeListItem *)pNodes->GetHead();
02912 
02913     AttrBevelLightAngle * pLightAttr = NULL;
02914     AttrBevelLightAngle * pNewLightAttr = NULL;
02915 //  Node * pParent = NULL;
02916     NodeBevelController * pControl = NULL;
02917     NodeHidden      * pHidden = NULL;
02918     Node * pThisNode = NULL;
02919     Node * pNextNode = NULL;
02920     HideNodeAction *pAction = NULL;                         
02921     List AttrList;
02922 
02923     // invalidate all the nodes first and localise attributes
02924     while (pItem)
02925     {
02926         if (pItem->pNode)
02927         {
02928             if (pItem->pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevelController)))
02929             {
02930                 // find the applied attribute
02931                 pControl = (NodeBevelController *)pItem->pNode;
02932 
02933                 if (ok)
02934                     ok = DoLocaliseForAttrChange(pControl, CC_RUNTIME_CLASS(AttrBevelLightAngle),
02935                     NULL);
02936 
02937                 BevelTools::GetAllNodesUnderNode(pControl, &AttrList, CC_RUNTIME_CLASS(AttrBevelLightAngle));
02938 
02939                 if (AttrList.IsEmpty())
02940                 {
02941                     ALLOC_WITH_FAIL(pLightAttr, new AttrBevelLightAngle(pControl, FIRSTCHILD), this);
02942                     pLightAttr->Value.m_LightAngle = (INT32)pControl->m_LightAngle;
02943                     
02944                     if (HideNodeAction::Init(this, GetUndoActionList(), (Node *)pLightAttr,
02945                         FALSE, (Action **)&pAction, FALSE) != AC_OK)
02946                     {
02947                         FailAndExecute();
02948                         End();
02949                         return;             
02950                     }
02951                 }
02952 
02953                 AttrList.DeleteAll();
02954 
02955                 pThisNode = pControl->FindFirstDepthFirst();
02956 
02957                 while (pThisNode && ok)
02958                 {
02959                     pNextNode = pThisNode->FindNextDepthFirst(pControl);
02960                     
02961                     if (pThisNode->IsAnAttribute())
02962                     {
02963                         if (pThisNode->IS_KIND_OF(AttrBevelLightAngle))
02964                         {
02965                             // make a new attribute node to replace this one
02966                             ALLOC_WITH_FAIL(pNewLightAttr, new AttrBevelLightAngle, this);
02967                             pNewLightAttr->Value.m_LightAngle = pAttrParam->NewLightAngle;
02968 
02969                             // hide the original node
02970                             if (ok)
02971                                 ok = DoHideNode(pThisNode, FALSE, &pHidden);
02972 
02973                             // insert the new node
02974                             pNewLightAttr->AttachNode(pHidden, NEXT);
02975 
02976                             if (HideNodeAction::Init(this, GetUndoActionList(), (Node *)pNewLightAttr,
02977                                 FALSE, (Action **)&pAction, FALSE) != AC_OK)
02978                             {
02979                                 ok = FALSE;
02980                             }
02981                         }
02982                     }
02983 
02984                     pThisNode = pNextNode;
02985                 }
02986 
02987                 if (ok)
02988                     ok = DoFactorOutAfterAttrChange(pControl, CC_RUNTIME_CLASS(AttrBevelLightAngle));
02989 
02990                 pControl->RegenerateBevelBitmap(this, TRUE);
02991             }
02992         }
02993 
02994         pItem = (NodeListItem *)pNodes->GetNext(pItem);
02995     }                   
02996 
02997     if (!ok)
02998     {
02999         FailAndExecute();
03000         End();
03001         return;
03002     }
03003                 
03004     End();
03005 }
03006 
03007 
03008 
03009 
03010 /********************************************************************************************
03011 
03012 >   OpState OpChangeBevelLightAngle::GetState(String_256* Description, OpDescriptor*)
03013 
03014     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03015     Created:    16/11/94
03016     Outputs:    -
03017     Returns:    Ungreyed, Unticked
03018     Purpose:    Find out the state of the new regular shape at the specific time
03019 
03020 ********************************************************************************************/
03021 
03022 OpState OpChangeBevelLightAngle::GetState(String_256* Description, OpDescriptor*)
03023 {
03024     OpState Blobby;
03025     
03026     return Blobby;
03027 }
03028 
03029 /********************************************************************************************
03030 
03031 >   void OpChangeBevelLightAngle::GetOpName(String_256 * pString)
03032 
03033     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03034     Created:    16/11/94
03035     Outputs:    -
03036     Returns:    
03037     Purpose:    Gets the name of the op
03038 
03039 ********************************************************************************************/
03040 
03041 void OpChangeBevelLightAngle::GetOpName(String_256 * pString)
03042 {
03043     if (pString)
03044         pString->Load(_R(IDS_CHANGEBEVELLIGHTANGLEOPNAME));
03045 }
03046 
03047 /********************************************************************************************
03048 >   OpSelectBevel::OpSelectBevel()
03049 
03050     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> & Olivier
03051     Created:    21/11/96
03052     Purpose:    Constructor.
03053 ********************************************************************************************/
03054 OpSelectBevel::OpSelectBevel()
03055 {
03056     //TRACEUSER( "MarkH", _T("Just Made a OpCreateBevel Class!\n"));
03057 }
03058 
03059 
03060 
03061 /********************************************************************************************
03062 >   OpCreateBevel::~OpCreateBevel()
03063 
03064     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> & Olivier
03065     Created:    21/11/96
03066     Purpose:    Destructor.
03067 ********************************************************************************************/
03068 OpSelectBevel::~OpSelectBevel()
03069 {
03070     //TRACEUSER( "MarkH", _T("Just Killed OpCreateBevel Class!!!\n"));
03071 }
03072 
03073 /********************************************************************************************
03074 
03075 >   BOOL OpSelectBevel::Declare()
03076 
03077     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03078     Created:    23/3/99
03079     Returns:    TRUE if all went OK, False otherwise
03080     Purpose:    Adds the operation to the list of all known operations
03081 
03082 ********************************************************************************************/
03083 BOOL OpSelectBevel::Declare()
03084 {
03085     BOOL retn = (RegisterOpDescriptor(
03086                                 0, 
03087                                 _R(IDS_SELECTBEVEL),
03088                                 CC_RUNTIME_CLASS(OpSelectBevel), 
03089                                 OPTOKEN_SELECTBEVEL,
03090                                 OpSelectBevel::GetState));
03091     return retn;
03092 
03093 }
03094 
03095 /********************************************************************************************
03096 >   void OpSelectBevel::Do(OpDescriptor* pOp)
03097 
03098     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
03099     Created:    13/01/97
03100     Inputs:     
03101     Outputs:    -
03102     Returns:    -
03103     Purpose:    Changes all the bevel light angles in the list to the given angle
03104 ********************************************************************************************/
03105 
03106 void OpSelectBevel::Do(OpDescriptor* pOp)
03107 {
03108 
03109     if (!pOp)
03110     {
03111         End();
03112         return;
03113     }
03114 
03115     BeginSlowJob(-1, TRUE);
03116 
03117     List ControllerList;
03118 
03119     // build the list of all selected bevel controller nodes
03120     BevelTools::BuildListOfSelectedNodes(&ControllerList, CC_RUNTIME_CLASS(NodeBevelController), TRUE);
03121 
03122     if (ControllerList.IsEmpty())
03123     {
03124         End();
03125         return;
03126     }
03127 
03128     // deselect everything
03129     NodeRenderableInk::DeselectAll();
03130 
03131     // now, run through the list selecting all bevel inking nodes
03132     NodeListItem * pItem  = (NodeListItem *)ControllerList.GetHead();
03133     NodeBevel    * pBevel = NULL;
03134     
03135     while (pItem)
03136     {
03137         if (pItem->pNode)
03138         {
03139             pBevel = ((NodeBevelController *)pItem->pNode)->GetBevelNode();
03140 
03141             if (pBevel)
03142             {
03143                 pBevel->SetSelected(TRUE);
03144             }
03145         }
03146 
03147         pItem = (NodeListItem *)ControllerList.GetNext(pItem);
03148     }
03149 
03150     // clean up
03151     ControllerList.DeleteAll();
03152 
03153     GetApplication()->UpdateSelection();
03154 
03155     End();
03156 
03157     // get the current tool (if it's the bevel tool) and get it
03158     // to regen its blobs
03159     if (Tool::GetCurrentID() == TOOLID_BEVELTOOL)
03160     {
03161         BevelTool * pTool = (BevelTool *)Tool::GetCurrent();
03162         pTool->InvalidateToolBlobs();
03163     }
03164 }
03165 
03166 
03167 
03168 
03169 /********************************************************************************************
03170 
03171 >   OpState OpSelectBevel::GetState(String_256* Description, OpDescriptor*)
03172 
03173     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
03174     Created:    16/11/94
03175     Outputs:    -
03176     Returns:    Ungreyed, Unticked
03177     Purpose:    Find out the state of the new regular shape at the specific time
03178 
03179 ********************************************************************************************/
03180 OpState OpSelectBevel::GetState(String_256* Description, OpDescriptor*)
03181 {
03182     OpState Blobby;
03183     
03184     return Blobby;
03185 }
03186 
03187 
03188 
03189 
03190 #endif
03191 
03192 
03193 

Generated on Sat Nov 10 03:47:42 2007 for Camelot by  doxygen 1.4.4