shapeops.cpp

Go to the documentation of this file.
00001 // $Id: shapeops.cpp 1776 2007-06-27 11:16:49Z 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 
00099 /*
00100 */
00101 
00102 #include "camtypes.h"
00103 #include "shapeops.h"
00104 
00105 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 #include "blobs.h"
00107 #include "csrstack.h"
00108 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 #include "nodepath.h"
00110 #include "nodershp.h"
00111 #include "pathedit.h"
00112 //#include "peter.h"
00113 #include "progress.h"
00114 //#include "resource.h"
00115 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00116 //#include "tool.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00117 //#include "trans2d.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00118 //#include "viewrc.h"
00119 #include "objchge.h"
00120 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00121 
00122 #define PATRACE if(IsUserName("Peter")) TRACE
00123 
00124 // Useful macro, given a pointer to a CCObject (or an object derived
00125 // from it) and a string format, it will output the class name of the object. 
00126 // Example usage PACLASSNAME(CurrentNode,"Node class = %s\n");
00127 // N.B. No checking is node or parameters.  Note semi-colon on end.
00128 #define PACLASSNAME(a,b) CCRuntimeClass* Blob; Blob = a->GetRuntimeClass(); PATRACE(b,Blob->m_lpszClassName)
00129 
00130 
00131 DECLARE_SOURCE( "$Revision: 1776 $" );
00132 
00133 
00134 CC_IMPLEMENT_MEMDUMP(EditRegularShapeParam, OpParam)    
00135 CC_IMPLEMENT_DYNCREATE(OpEditRegularShape, SelOperation)
00136 CC_IMPLEMENT_DYNCREATE(OpDragRegularShape, SelOperation)
00137 CC_IMPLEMENT_DYNCREATE(OpReformShapeEdge, SelOperation)
00138 CC_IMPLEMENT_DYNCREATE(ChangeShapeDataAction, Action)
00139 CC_IMPLEMENT_DYNCREATE(ChangeShapePointAction, Action)
00140 CC_IMPLEMENT_DYNCREATE(ChangeShapePathAction, Action)
00141 CC_IMPLEMENT_DYNAMIC(ShapeEditedMsg, Msg)
00142 CC_IMPLEMENT_DYNCREATE(OpShapeToggleBase, SelOperation)
00143 CC_IMPLEMENT_DYNCREATE(OpShapeToggleElipPoly, OpShapeToggleBase)
00144 CC_IMPLEMENT_DYNCREATE(OpShapeToggleStellation, OpShapeToggleBase)
00145 CC_IMPLEMENT_DYNCREATE(OpShapeToggleCurvature, OpShapeToggleBase)
00146 CC_IMPLEMENT_DYNCREATE(OpShapeMakeRegular, SelOperation)
00147 
00148 CC_IMPLEMENT_DYNCREATE( OpShapeToggleSetNumSides, SelOperation )    
00149 CC_IMPLEMENT_DYNCREATE( OpShapeToggleSetNumSides3, OpShapeToggleSetNumSides )    
00150 CC_IMPLEMENT_DYNCREATE( OpShapeToggleSetNumSides4, OpShapeToggleSetNumSides )    
00151 CC_IMPLEMENT_DYNCREATE( OpShapeToggleSetNumSides5, OpShapeToggleSetNumSides )    
00152 CC_IMPLEMENT_DYNCREATE( OpShapeToggleSetNumSides6, OpShapeToggleSetNumSides )    
00153 CC_IMPLEMENT_DYNCREATE( OpShapeToggleSetNumSides7, OpShapeToggleSetNumSides )    
00154 CC_IMPLEMENT_DYNCREATE( OpShapeToggleSetNumSides8, OpShapeToggleSetNumSides )    
00155 CC_IMPLEMENT_DYNCREATE( OpShapeToggleSetNumSides9, OpShapeToggleSetNumSides )    
00156 CC_IMPLEMENT_DYNCREATE( OpShapeToggleSetNumSides10, OpShapeToggleSetNumSides )    
00157 
00158 
00159 
00160 // Declare smart memory handling in Debug builds
00161 #define new CAM_DEBUG_NEW
00162 
00163 const DocCoord DontCare (0,0);
00164 
00165 /********************************************************************************************
00166 
00167 >   ShapeEditedMsg::ShapeEditedMsg(NodeRegularShape* pChangeShape, Spread* pParentSpread) 
00168 
00169     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00170     Created:    17/1/95
00171     Inputs:     pChangeShape - pointer to the edited shape
00172                 pParentSpread - pointer to the parent spread of the object
00173     Purpose:    initilise a ShapeEditedMsg
00174     SeeAlso:    ShapeEditedMsg
00175 
00176 ********************************************************************************************/
00177 ShapeEditedMsg::ShapeEditedMsg(NodeRegularShape* pChangeShape, Spread* pParentSpread)                           
00178 {                              
00179     pShape = pChangeShape;
00180     pSpread = pParentSpread;
00181 }
00182 
00183 
00185 //                                     EditRegularShapeParam                                //
00187 
00188 
00189 
00190 /********************************************************************************************
00191 
00192 >   EditRegularShapeParam::EditRegularShapeParam(NodeRegularShape* ChangeShapes) 
00193 
00194     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00195     Created:    08/12/94    
00196     Inputs:     ChangeShapes - pointer to the shape to change OR NULL to change all selected shapes                                   
00197     Purpose:    EditRegularShapeParam constructor - sets all member items to unchange.
00198                 After constructing the object, the caller should set those items that it wants
00199                 OpEditRegularShape to change.
00200 
00201 ********************************************************************************************/
00202 EditRegularShapeParam::EditRegularShapeParam(NodeRegularShape* ChangeShapes)                                
00203 {                              
00204     ShapeToChange = ChangeShapes;
00205     ShapesToAffect = AFFECT_ALL;
00206     
00207     NewEdgePath1 = NULL;    
00208     NewEdgePath2 = NULL;    
00209     NewNumSides = 0;        
00210     NewCircular = CHANGE_DONTCARE;
00211     NewStellated = CHANGE_DONTCARE;
00212     NewPrimaryCurvature = CHANGE_DONTCARE;
00213     NewStellationCurvature = CHANGE_DONTCARE;
00214     NewStellRadiusToPrimary = -1.0; 
00215     NewPrimaryCurveToPrimary = -1.0;    
00216     NewStellCurveToStell = -1.0;        
00217     NewStellOffsetRatio = -1000.0;
00218 //  NewCentrePoint = DontCare;      
00219 //  NewMajorAxes = DontCare;        
00220 //  NewMinorAxes = DontCare;        
00221 
00222     TranslateTo = DontCare;     
00223     TranslateBy = DontCare;     
00224     SetRadiusLength = -1;
00225     AddRadiusLength = -1;
00226     RotateTo = -1000.0;         
00227     RotateBy = -1000.0;         
00228     SetStellationLength = -1;   
00229     AddStellationLength = -1;   
00230     SetStellationOffset = -1000.0;
00231     AddStellationOffset = -1000.0;
00232     AddPrimaryCurvature = 0.0;
00233     AddStellationCurvature = 0.0;
00234     SetMajorAxisLength = 0;
00235     AddMajorAxisLength = 0;
00236     SetMinorAxisLength = 0;
00237     AddMinorAxisLength = 0;
00238 }
00239 
00240 
00241 
00243 //                                     OpEditRegularShape                                   //
00245 
00246 /********************************************************************************************
00247 
00248 >   OpEditRegularShape::OpEditRegularShape() 
00249 
00250     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00251     Created:    08/12/94                                          
00252     Purpose:    OpEditRegularShape constructor - does nothing itself
00253 
00254 ********************************************************************************************/
00255 OpEditRegularShape::OpEditRegularShape(): SelOperation()                                
00256 {                              
00257 }
00258 
00259 
00260 
00261  /********************************************************************************************
00262 
00263 >   BOOL OpEditRegularShape::Init()
00264 
00265     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00266     Created:    08/12/94
00267     Returns:    TRUE if the operation could be successfully initialised 
00268                 FALSE if no more memory could be allocated 
00269     Purpose:    OpEditRegularShape initialiser method
00270     Errors:     ERROR will be called if there was insufficient memory to allocate the 
00271                 operation.
00272     SeeAlso:    -
00273 
00274 ********************************************************************************************/
00275 BOOL OpEditRegularShape::Init()
00276 {
00277     BOOL Success = RegisterOpDescriptor(0, 
00278                                         _R(IDS_EDITREGULARSHAPEOP),
00279                                         CC_RUNTIME_CLASS(OpEditRegularShape), 
00280                                         OPTOKEN_EDITREGULARSHAPE,
00281                                         OpEditRegularShape::GetState);
00282 
00283     if (Success)
00284         Success = OpShapeToggleElipPoly::Init();
00285     if (Success)
00286         Success = OpShapeToggleStellation::Init();
00287     if (Success)
00288         Success = OpShapeToggleCurvature::Init();
00289     if (Success)
00290         Success = OpShapeToggleSetNumSides::Init();
00291     if (Success)
00292         Success = OpShapeMakeRegular::Init();
00293 
00294     return Success;
00295 }               
00296     
00297 
00298 
00299 /********************************************************************************************
00300 
00301 >   OpState OpEditRegularShape::GetState(String_256*, OpDescriptor*)
00302 
00303     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00304     Created:    08/12/94
00305     Returns:    The state of the OpEditRegularShape
00306     Purpose:    For finding the OpEditRegularShape's state. 
00307     SeeAlso:    -
00308 
00309 ********************************************************************************************/
00310 OpState OpEditRegularShape::GetState(String_256* UIDescription, OpDescriptor*)
00311 {
00312     OpState OpSt;
00313 
00314     return OpSt;                                 
00315 }
00316 
00317 
00318 
00319 /********************************************************************************************
00320 
00321 >   void OpEditRegularShape::DoWithParam(OpDescriptor* pOpDesc, OpParam* pEntryOpParam)
00322 
00323     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00324     Created:    08/12/94
00325     Inputs:     OpDescriptor (unused)
00326                 pOpParam - pointer to the parameter object.
00327     Purpose:    Performs the edit regular shapes operation. 
00328     Errors:     -
00329     SeeAlso:    EditRegularShapeParam, OpEditRegularShape::CarryOut
00330 
00331 ********************************************************************************************/
00332 void OpEditRegularShape::DoWithParam(OpDescriptor* pOpDesc, OpParam* pEntryOpParam)
00333 {   
00334     EditRegularShapeParam* pOpParam = (EditRegularShapeParam*)pEntryOpParam;
00335     
00336     // Tell the operation system its kickoff time.
00337     if (DoStartSelOp(FALSE))
00338     {
00339         BOOL Complete = TRUE;
00340 
00341         // Data used by AllowOp() to ask the node if it's ok to do the op
00342         ObjChangeFlags cFlags;
00343         ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
00344 
00345         // Either change just one shape or all selected shapes.
00346         if (pOpParam->ShapeToChange != NULL)
00347         {
00348             if (ShouldDoThisShape(pOpParam->ShapeToChange, pOpParam->ShapesToAffect))
00349             {
00350                 if (pOpParam->ShapeToChange->AllowOp(&ObjChange))                   // Will node allow the op?
00351                     Complete = CarryOut(pOpParam->ShapeToChange, pOpParam);
00352             }
00353         }
00354         else
00355         {
00356             // Obtain the current selections and the first node in the selection
00357             SelRange*   Selected = GetApplication()->FindSelection();
00358             Node*       pNode = Selected->FindFirst();
00359 
00360             while ((pNode != NULL) && Complete)
00361             {
00362                 if (IS_A(pNode,NodeRegularShape))
00363                 {
00364                     if (ShouldDoThisShape((NodeRegularShape*)pNode, pOpParam->ShapesToAffect))
00365                     {
00366                         if (pNode->AllowOp(&ObjChange))                             // Will node allow the op?
00367                             Complete = CarryOut((NodeRegularShape*)pNode, pOpParam);
00368                     }
00369                 }
00370                 pNode = Selected->FindNext(pNode);
00371             }
00372         }
00373 
00374         GetApplication()->FindSelection()->Update(FALSE);
00375     
00376         if (Complete)
00377         {
00378             // updated effected parents
00379             ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this);
00380             Complete = UpdateChangedNodes(&ObjChange);
00381         }
00382 
00383         // See if anything failed
00384         if (!Complete)
00385         {
00386             FailAndExecute();
00387         }
00388     }
00389     else
00390     {
00391         FailAndExecute();
00392     }
00393 
00394     End();
00395 }
00396 
00397 
00398 
00399 /********************************************************************************************
00400 
00401 >   BOOL OpEditRegularShape::CarryOut(NodeRegularShape* ShapeToEdit, EditRegularShapeParam* NewShapeData)
00402 
00403     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00404     Created:    08/12/94
00405     Inputs:     ShapeToEdit points to the Shape to change.
00406                 NewShapeData points to the parameter object with the changes data.
00407     Purpose:    Performs the edit regular shapes operation on one particular shape
00408     Errors:     ERROR2 if there is no current DocView
00409     SeeAlso:    EditRegularShapeParam, OpEditRegularShape::DoWithParam
00410 
00411 ********************************************************************************************/
00412 
00413 BOOL OpEditRegularShape::CarryOut(NodeRegularShape* ShapeToEdit, EditRegularShapeParam* NewShapeData)
00414 {
00415     // Create an action to will cause the shape to recalc its bounds
00416     if (RecalcBoundsAction::DoRecalc(this, &UndoActions, ShapeToEdit) == AC_FAIL)
00417     {
00418         return FALSE;
00419     }
00420 
00421     // See if we should change the polygon/circular flag
00422     if (NewShapeData->NewCircular != EditRegularShapeParam::CHANGE_DONTCARE)
00423     {
00424         if (ChangeShapeDataAction::DoToggle(this, &UndoActions, ShapeToEdit, ChangeShapeDataAction::CHANGE_CIRCULAR,
00425                                                 ShapeToEdit->IsCircular() ? 1.0 : 0.0) == AC_FAIL)
00426         {
00427             return FALSE;
00428         }
00429         ShapeToEdit->SetCircular(NewShapeData->NewCircular == EditRegularShapeParam::CHANGE_SETTRUE);
00430     }
00431 
00432     // See if we should change the stellated flag
00433     if (NewShapeData->NewStellated != EditRegularShapeParam::CHANGE_DONTCARE)
00434     {
00435 /*      // If were turning off stellation them we may need to fix the primary curvature ratio
00436         if (NewShapeData->NewStellated == EditRegularShapeParam::CHANGE_SETFALSE)
00437         {
00438             if (ShapeToEdit->GetPrimaryCurveToPrimary() > 0.5)
00439                 NewShapeData->NewPrimaryCurveToPrimary = 0.2;
00440         }
00441         else
00442         {
00443             // If we've turned on stellation them we may need to fix both curvature ratios
00444             if (ShapeToEdit->GetPrimaryCurveToPrimary()+ShapeToEdit->GetStellCurveToStell() > 1.0)
00445             {
00446                 NewShapeData->NewPrimaryCurveToPrimary = 0.2;
00447                 NewShapeData->NewStellCurveToStell = 0.2;
00448             }
00449         }*/
00450 
00451         if (ChangeShapeDataAction::DoToggle(this, &UndoActions, ShapeToEdit, ChangeShapeDataAction::CHANGE_STELLATED,
00452                                                  ShapeToEdit->IsStellated() ? 1.0 : 0.0) == AC_FAIL)
00453         {
00454             return FALSE;
00455         }
00456         ShapeToEdit->SetStellated(NewShapeData->NewStellated == EditRegularShapeParam::CHANGE_SETTRUE);
00457     }
00458 
00459     // See if we should change the primary curvature flag
00460     if (NewShapeData->NewPrimaryCurvature != EditRegularShapeParam::CHANGE_DONTCARE)
00461     {
00462         if (ChangeShapeDataAction::DoToggle(this, &UndoActions, ShapeToEdit, ChangeShapeDataAction::CHANGE_PRIMARYCURVATURE,
00463                                                  ShapeToEdit->IsPrimaryCurvature() ? 1.0 : 0.0) == AC_FAIL)
00464         {
00465             return FALSE;
00466         }
00467         ShapeToEdit->SetPrimaryCurvature(NewShapeData->NewPrimaryCurvature == EditRegularShapeParam::CHANGE_SETTRUE);
00468     }
00469 
00470     // See if we should change the stellation curvature flag
00471     if (NewShapeData->NewStellationCurvature != EditRegularShapeParam::CHANGE_DONTCARE)
00472     {
00473         if (ChangeShapeDataAction::DoToggle(this, &UndoActions, ShapeToEdit, ChangeShapeDataAction::CHANGE_STELLATIONCURVATURE,
00474                                                  ShapeToEdit->IsStellationCurvature() ? 1.0 : 0.0) == AC_FAIL)
00475         {
00476             return FALSE;
00477         }
00478         ShapeToEdit->SetStellationCurvature(NewShapeData->NewStellationCurvature == EditRegularShapeParam::CHANGE_SETTRUE);
00479     }
00480 
00481     // See if we should change the stellation offset
00482     if (NewShapeData->NewStellOffsetRatio != -1000.0)
00483     {
00484         if (ChangeShapeDataAction::DoToggle(this, &UndoActions, ShapeToEdit, 
00485                 ChangeShapeDataAction::CHANGE_STELLATIONOFFSET, ShapeToEdit->GetStellationRatio()) == AC_FAIL)
00486         {
00487             return FALSE;
00488         }
00489         ShapeToEdit->SetStellationRatio(NewShapeData->NewStellOffsetRatio);
00490     }
00491 
00492     // See if we should change the number of sides
00493     if (NewShapeData->NewNumSides != 0)
00494     {
00495         if (ChangeShapeDataAction::DoToggle(this, &UndoActions, ShapeToEdit, 
00496                 ChangeShapeDataAction::CHANGE_NUMSIDES, ShapeToEdit->GetNumSides()) == AC_FAIL)
00497         {
00498             return FALSE;
00499         }
00500         ShapeToEdit->SetNumSides(NewShapeData->NewNumSides);
00501     }
00502 
00503     // See if we should change the stellation radius ratio
00504     if (NewShapeData->NewStellRadiusToPrimary != -1.0)
00505     {
00506         if (ChangeShapeDataAction::DoToggle(this, &UndoActions, ShapeToEdit, 
00507                 ChangeShapeDataAction::CHANGE_STELLRADIUSTOPRIMARY, 
00508                                             ShapeToEdit->GetStellRadiusToPrimary()) == AC_FAIL)
00509         {
00510             return FALSE;
00511         }
00512         ShapeToEdit->SetStellRadiusToPrimary(NewShapeData->NewStellRadiusToPrimary);
00513     }
00514 
00515     // See if we should change the primary curvature ratio
00516     if (NewShapeData->NewPrimaryCurveToPrimary != -1.0)
00517     {
00518         double NewRatio = NewShapeData->NewPrimaryCurveToPrimary;
00519 /*      if (ShapeToEdit->IsStellated())
00520         {
00521             double StellRatio = ShapeToEdit->GetStellCurveToStell();
00522             if (NewShapeData->NewStellCurveToStell != -1.0)
00523                 StellRatio = NewShapeData->NewStellCurveToStell;    
00524 
00525             NewRatio = __min(1.0-StellRatio, NewShapeData->NewPrimaryCurveToPrimary); 
00526         }
00527         else
00528         {
00529             NewRatio = __min(0.5, NewShapeData->NewPrimaryCurveToPrimary); 
00530         }*/
00531         
00532         if (ChangeShapeDataAction::DoToggle(this, &UndoActions, ShapeToEdit, 
00533                 ChangeShapeDataAction::CHANGE_PRIMARYCURVETOPRIMARY, 
00534                                             ShapeToEdit->GetPrimaryCurveToPrimary()) == AC_FAIL)
00535         {
00536             return FALSE;
00537         }
00538         ShapeToEdit->SetPrimaryCurveToPrimary(NewRatio);
00539     }
00540 
00541     // See if we should bump the primary curvature ratio
00542     if (NewShapeData->AddPrimaryCurvature != -0.0)
00543     {
00544         double NewRatio = ShapeToEdit->GetPrimaryCurveToPrimary() + NewShapeData->AddPrimaryCurvature;
00545 /*      if (ShapeToEdit->IsStellated())
00546         {
00547             NewRatio = __min(1.0-ShapeToEdit->GetStellCurveToStell(), NewRatio);
00548         }
00549         else
00550         {
00551             NewRatio = __min(0.5, NewRatio); 
00552         }*/
00553         NewRatio = max( 0.0, NewRatio );
00554         
00555         if (ChangeShapeDataAction::DoToggle(this, &UndoActions, ShapeToEdit, 
00556                 ChangeShapeDataAction::CHANGE_PRIMARYCURVETOPRIMARY, 
00557                                             ShapeToEdit->GetPrimaryCurveToPrimary()) == AC_FAIL)
00558         {
00559             return FALSE;
00560         }
00561         ShapeToEdit->SetPrimaryCurveToPrimary(NewRatio);
00562     }
00563 
00564     // See if we should change the stellation curvature ratio
00565     if (NewShapeData->NewStellCurveToStell != -1.0)
00566     {
00567         double NewRatio = NewShapeData->NewStellCurveToStell;
00568         
00569 //      NewRatio = __min (1.0-ShapeToEdit->GetPrimaryCurveToPrimary(), NewShapeData->NewStellCurveToStell); 
00570 
00571         if (ChangeShapeDataAction::DoToggle(this, &UndoActions, ShapeToEdit, 
00572                 ChangeShapeDataAction::CHANGE_STELLCURVETOSTELL, 
00573                                             ShapeToEdit->GetStellCurveToStell()) == AC_FAIL)
00574         {
00575             return FALSE;
00576         }
00577         ShapeToEdit->SetStellCurveToStell(NewRatio);
00578     }
00579 
00580     // See if we should bump the stellation curvature ratio
00581     if (NewShapeData->AddStellationCurvature != 0.0)
00582     {
00583         double NewRatio = ShapeToEdit->GetStellCurveToStell() + NewShapeData->AddStellationCurvature;
00584 //      NewRatio = __min(1.0-ShapeToEdit->GetPrimaryCurveToPrimary(), NewRatio); 
00585         NewRatio = max( 0.0, NewRatio );
00586         
00587         if (ChangeShapeDataAction::DoToggle(this, &UndoActions, ShapeToEdit, 
00588                 ChangeShapeDataAction::CHANGE_PRIMARYCURVETOPRIMARY, 
00589                                             ShapeToEdit->GetStellCurveToStell()) == AC_FAIL)
00590         {
00591             return FALSE;
00592         }
00593         ShapeToEdit->SetStellCurveToStell(NewRatio);
00594     }
00595 
00596     // See if we should change the minor axes
00597 /*  if (NewShapeData->NewMinorAxes != DontCare)
00598     {
00599         if (ChangeShapePointAction::DoToggle(this, &UndoActions, ShapeToEdit, 
00600                         ChangeShapePointAction::CHANGE_MINOR, ShapeToEdit->GetMinorAxes()) == AC_FAIL)
00601         {
00602             return FALSE;
00603         }
00604         ShapeToEdit->SetMinorAxes(NewShapeData->NewMinorAxes);
00605     }
00606 
00607     // See if we should change the major axes
00608     if (NewShapeData->NewMajorAxes != DontCare)
00609     {
00610         if (ChangeShapePointAction::DoToggle(this, &UndoActions, ShapeToEdit, 
00611                         ChangeShapePointAction::CHANGE_MAJOR, ShapeToEdit->GetMajorAxes()) == AC_FAIL)
00612         {
00613             return FALSE;
00614         }
00615         ShapeToEdit->SetMajorAxes(NewShapeData->NewMajorAxes);
00616     }*/
00617 
00618     // See if we should change the size of the shape to a new length
00619     // OR see if we should change the size of the shape by a specified ammount
00620     if ((NewShapeData->SetRadiusLength != -1) || (NewShapeData->AddRadiusLength != -1) )
00621     {
00622         // Get scaling factor
00623         fixed16 ScaleFactor;
00624         const double CurrentLength = ShapeToEdit->GetCentrePoint().Distance(ShapeToEdit->GetMajorAxes()) ;
00625         if (CurrentLength != 0.0)
00626         {
00627             if (NewShapeData->SetRadiusLength != -1)
00628             {
00629                 double RequiredLength = NewShapeData->SetRadiusLength;
00630                 ScaleFactor = RequiredLength / CurrentLength;
00631             }
00632             else
00633             {
00634                 double RequiredAddition = NewShapeData->AddRadiusLength;
00635                 ScaleFactor = (RequiredAddition + CurrentLength) / CurrentLength;
00636             }       
00637         }
00638         else
00639             ScaleFactor = 1.0;
00640         
00641         // Translate to origin, scale and translate back
00642         Trans2DMatrix* TransOriginMat = new Trans2DMatrix(-ShapeToEdit->GetCentrePoint().x, -ShapeToEdit->GetCentrePoint().y);
00643         Trans2DMatrix* ScaleMat = new Trans2DMatrix(Matrix(ScaleFactor,ScaleFactor));
00644         Trans2DMatrix* TransBackMat = new Trans2DMatrix(ShapeToEdit->GetCentrePoint().x, ShapeToEdit->GetCentrePoint().y);
00645         if (!(DoTransformNode(ShapeToEdit, TransOriginMat) && DoTransformNode(ShapeToEdit, ScaleMat)
00646                                                             && DoTransformNode(ShapeToEdit, TransBackMat) ))
00647         {
00648             return FALSE;
00649         }
00650     }
00651 
00652     // See if we should change the MajorAxis of the shape to a new length
00653     // OR see if we should change the MajorAxis of the shape by a specified ammount
00654     if ((NewShapeData->SetMajorAxisLength != 0) || (NewShapeData->AddMajorAxisLength != 0) )
00655     {
00656         // Get scaling factor
00657         fixed16 ScaleFactor;
00658         const double CurrentLength = ShapeToEdit->GetCentrePoint().Distance(ShapeToEdit->GetMajorAxes()) ;
00659         if (CurrentLength != 0.0)
00660         {
00661             if (NewShapeData->SetMajorAxisLength != 0)
00662             {
00663                 double RequiredLength = NewShapeData->SetMajorAxisLength;
00664                 ScaleFactor = RequiredLength / CurrentLength;
00665             }
00666             else
00667             {
00668                 double RequiredAddition = NewShapeData->AddMajorAxisLength;
00669                 ScaleFactor = (RequiredAddition + CurrentLength) / CurrentLength;
00670             }       
00671         }
00672         else
00673             ScaleFactor = 1.0;
00674 
00675         if (ChangeShapePointAction::DoToggle(this, &UndoActions, ShapeToEdit, 
00676                         ChangeShapePointAction::CHANGE_MAJOR, ShapeToEdit->GetUTMajorAxes()) == AC_FAIL)
00677         {
00678             return FALSE;
00679         }
00680 
00681         // Scale the major axes relative to the centre point
00682         Matrix ScaleMatrix(FIXED16(1.0), ScaleFactor);
00683         DocCoord Offset = ShapeToEdit->GetUTMajorAxes() - ShapeToEdit->GetUTCentrePoint();
00684         ScaleMatrix.transform(&Offset);
00685         ShapeToEdit->SetMajorAxes(ShapeToEdit->GetUTCentrePoint() + Offset);
00686     }
00687 
00688     // See if we should change the MinorAxis of the shape to a new length
00689     // OR see if we should change the MinorAxis of the shape by a specified ammount
00690     if ((NewShapeData->SetMinorAxisLength != 0) || (NewShapeData->AddMinorAxisLength != 0) )
00691     {
00692         // Get scaling factor
00693         fixed16 ScaleFactor;
00694         const double CurrentLength = ShapeToEdit->GetCentrePoint().Distance(ShapeToEdit->GetMinorAxes()) ;
00695         if (CurrentLength != 0.0)
00696         {
00697             if (NewShapeData->SetMinorAxisLength != 0)
00698             {
00699                 double RequiredLength = NewShapeData->SetMinorAxisLength;
00700                 ScaleFactor = RequiredLength / CurrentLength;
00701             }
00702             else
00703             {
00704                 double RequiredAddition = NewShapeData->AddMinorAxisLength;
00705                 ScaleFactor = (RequiredAddition + CurrentLength) / CurrentLength;
00706             }       
00707         }
00708         else
00709             ScaleFactor = 1.0;
00710 
00711         if (ChangeShapePointAction::DoToggle(this, &UndoActions, ShapeToEdit, 
00712                         ChangeShapePointAction::CHANGE_MINOR, ShapeToEdit->GetUTMinorAxes()) == AC_FAIL)
00713         {
00714             return FALSE;
00715         }
00716 
00717         // Scale the minor axes relative to the centre point
00718         Matrix ScaleMatrix(ScaleFactor, FIXED16(1.0));
00719         DocCoord Offset = ShapeToEdit->GetUTMinorAxes() - ShapeToEdit->GetUTCentrePoint();
00720         ScaleMatrix.transform(&Offset);
00721         ShapeToEdit->SetMinorAxes(ShapeToEdit->GetUTCentrePoint() + Offset);
00722     }
00723 
00724     // See if we should change the size of the stellation radius to a new length
00725     // OR see if we should change the size of the stellation radius by a specified ammount
00726     if ((NewShapeData->SetStellationLength != -1) || (NewShapeData->AddStellationLength != -1) )
00727     {
00728         const double CurrentLength = ShapeToEdit->GetCentrePoint().Distance(ShapeToEdit->GetMajorAxes()) ;
00729         double NewRatio;
00730         if (NewShapeData->SetStellationLength != -1)
00731         {
00732             // Get the current length of the shape and get the ratio from that
00733             NewRatio = double( min( fabs( NewShapeData->SetStellationLength / CurrentLength ), 1.0 ) );
00734         }
00735         else
00736         {
00737             double NewLength = fabs(CurrentLength - NewShapeData->AddStellationLength);
00738             NewRatio = double( min( fabs( ( NewLength / CurrentLength ) - 1 + ShapeToEdit->GetStellRadiusToPrimary() ), 1.0 ) );
00739         }
00740 
00741         if (ChangeShapeDataAction::DoToggle(this, &UndoActions, ShapeToEdit, 
00742                 ChangeShapeDataAction::CHANGE_STELLRADIUSTOPRIMARY, 
00743                                             ShapeToEdit->GetStellRadiusToPrimary()) == AC_FAIL)
00744         {
00745             return FALSE;
00746         }
00747         ShapeToEdit->SetStellRadiusToPrimary(NewRatio);
00748     }
00749 
00750     // See if we should rotate the shape to a specific angle
00751     // OR see if we should rotate the shape by a specified ammount
00752     if ((NewShapeData->RotateTo != -1000.0) || (NewShapeData->RotateBy != -1000.0) )
00753     {
00754         // Get rotate matrix
00755         ANGLE RotateBy;
00756         const DocCoord MajorOrigin = ShapeToEdit->GetMajorAxes() - ShapeToEdit->GetCentrePoint();
00757         const double CurrentAngle = atan2((double)MajorOrigin.y, (double)MajorOrigin.x) ;
00758         if (NewShapeData->RotateTo != -1000.0)
00759         {
00760             RotateBy = -(CurrentAngle - NewShapeData->RotateTo) * (180/PI); 
00761         }
00762         else
00763         {                                                                  
00764             RotateBy = NewShapeData->RotateBy * (180/PI); 
00765         }       
00766         
00767         Trans2DMatrix* RotateMat = new Trans2DMatrix(ShapeToEdit->GetCentrePoint(), RotateBy);
00768         if (!DoTransformNode(ShapeToEdit, RotateMat))
00769         {
00770             return FALSE;
00771         }
00772     }
00773 
00774     // See if we should change the stellation offset to a new angle
00775     // OR see if we should change the stellation offset by a specified ammount
00776     if ((NewShapeData->SetStellationOffset != -1000.0) || (NewShapeData->AddStellationOffset != -1000.0) )
00777     {
00778         const UINT32 NumSides = ShapeToEdit->GetNumSides();
00779         const double OppositeRatio = 180.0/(360.0/NumSides);
00780         double NewRatio;
00781         if (NewShapeData->SetStellationOffset != -1000.0)
00782         {
00783             NewRatio = OppositeRatio * (NewShapeData->SetStellationOffset / 180.0);
00784         }
00785         else
00786         {
00787             double NewOffset = (ShapeToEdit->GetStellationRatio()/OppositeRatio)*180.0 + NewShapeData->AddStellationOffset;
00788 
00789             if (NewOffset < -180.0)
00790                 NewOffset = 180.0 + (NewOffset + 180.0);
00791             if (NewOffset > 180.0)
00792                 NewOffset = -180.0 + (NewOffset - 180.0);
00793             NewRatio = OppositeRatio * (NewOffset / 180.0);
00794         }
00795 
00796         if (ChangeShapeDataAction::DoToggle(this, &UndoActions, ShapeToEdit, 
00797                 ChangeShapeDataAction::CHANGE_STELLATIONOFFSET, ShapeToEdit->GetStellationRatio()) == AC_FAIL)
00798         {
00799             return FALSE;
00800         }
00801         ShapeToEdit->SetStellationRatio(NewRatio);
00802     }
00803 
00804     // See if we should change the centre point
00805 /*  if (NewShapeData->NewCentrePoint != DontCare)
00806     {
00807         if (ChangeShapePointAction::DoToggle(this, &UndoActions, ShapeToEdit, 
00808                     ChangeShapePointAction::CHANGE_CENTRE, ShapeToEdit->GetCentrePoint()) == AC_FAIL)
00809         {
00810             return FALSE;
00811         }
00812         ShapeToEdit->SetCentrePoint(NewShapeData->NewCentrePoint);
00813     }*/
00814 
00815     // See if we should translate the shape to an exact location
00816     if (NewShapeData->TranslateTo != DontCare)
00817     {
00818         DocCoord Offset = NewShapeData->TranslateTo - ShapeToEdit->GetCentrePoint() ;
00819 
00820         Trans2DMatrix* TransMat = new Trans2DMatrix(Offset.x, Offset.y);
00821         if (!DoTransformNode(ShapeToEdit, TransMat))
00822             return FALSE;
00823     }
00824 
00825     // See if we should translate the shape by an offset
00826     if (NewShapeData->TranslateBy != DontCare)
00827     {
00828         Trans2DMatrix* TransMat = new Trans2DMatrix(NewShapeData->TranslateBy.x, NewShapeData->TranslateBy.y);
00829         if (!DoTransformNode(ShapeToEdit, TransMat))
00830             return FALSE;
00831     }
00832 
00833     // See if we should change edge path one
00834     if (NewShapeData->NewEdgePath1 != NULL)
00835     {
00836         if (ChangeShapePathAction::DoReshape(this, &UndoActions, ShapeToEdit, 
00837                     ChangeShapePathAction::CHANGE_PATH1, &(ShapeToEdit->EdgePath1)) == AC_FAIL)
00838         {
00839             return FALSE;
00840         }
00841         ShapeToEdit->EdgePath1.ClearPath();
00842         ShapeToEdit->EdgePath1.CopyPathDataFrom(NewShapeData->NewEdgePath1);        
00843     }
00844 
00845     // See if we should change edge path two
00846     if (NewShapeData->NewEdgePath2 != NULL)
00847     {
00848         if (ChangeShapePathAction::DoReshape(this, &UndoActions, ShapeToEdit, 
00849                     ChangeShapePathAction::CHANGE_PATH2, &(ShapeToEdit->EdgePath2)) == AC_FAIL)
00850         {
00851             return FALSE;
00852         }
00853         ShapeToEdit->EdgePath2.ClearPath();
00854         ShapeToEdit->EdgePath2.CopyPathDataFrom(NewShapeData->NewEdgePath2);        
00855     }
00856 
00857     // Invalidate the shapes bounding rect as it's changed
00858     ShapeToEdit->InvalidateBoundingRect();
00859     ShapeToEdit->InvalidateCache();
00860 
00861     // Cause a redraw of the shape with its end bounds
00862     if (RecordBoundsAction::DoRecord(this, &UndoActions, ShapeToEdit) == AC_FAIL)
00863     {
00864         return FALSE;
00865     }
00866 
00867     return TRUE;
00868 }
00869 
00870 
00871 
00872 /********************************************************************************************
00873 
00874 >   BOOL OpEditRegularShape::ShouldDoThisShape(NodeRegularShape* pShape, EditRegularShapeParam::AffectShape Allowance)
00875 
00876     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00877     Created:    26/03/95
00878     Inputs:     pShape - points to a regular shape 
00879                 Allowance - the current shape allowance mode
00880     Outputs:    -
00881     Returns:    TRUE if this shape should be changed in this operation
00882                 FALSE if this shape should not be changed
00883     Purpose:    Do decide wether or not the shape should be edited.  The decision is based upon
00884                 the Allowance mode.
00885     Errors:     -
00886     SeeAlso:    -
00887 
00888 ********************************************************************************************/
00889 BOOL OpEditRegularShape::ShouldDoThisShape(NodeRegularShape* pShape, EditRegularShapeParam::AffectShape Allowance)
00890 {
00891     ERROR2IF(pShape == NULL, FALSE, "Can't edit a NULL shape!");
00892 
00893     switch (Allowance)
00894     {
00895         case EditRegularShapeParam::AFFECT_ALL:
00896             return TRUE;
00897             break;
00898         case EditRegularShapeParam::AFFECT_ELLIPSES:
00899             return pShape->IsCircular();
00900             break;
00901         case EditRegularShapeParam::AFFECT_RECTANGLES:
00902             return (!pShape->IsCircular() && (pShape->GetNumSides() == 4) );
00903             break;
00904         default:
00905             ERROR3("Allowance was not known");
00906             return FALSE;
00907     }
00908 }
00909 
00910 
00911 
00912 
00914 // The ChangeShapeDataAction class                                                           //
00916 
00917 /********************************************************************************************
00918 
00919 >   ChangeShapeDataAction::ChangeShapeDataAction()
00920 
00921     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00922     Created:    10/12/94
00923     Inputs:     -
00924     Outputs:    -
00925     Returns:    -
00926     Purpose:    Constructor for the action to toggle a data item of a regular state.
00927                 Initialises the data members to sensible defaults.
00928     Errors:     -
00929     SeeAlso:    -
00930 
00931 ********************************************************************************************/
00932 ChangeShapeDataAction::ChangeShapeDataAction()
00933 {
00934     pToggleShape = NULL;
00935     ChangeItemID = CHANGE_NUMSIDES;
00936     NewValue = 0.0;
00937 }
00938 
00939 
00940 
00941 /********************************************************************************************
00942 
00943 >   ActionCode ChangeShapeDataAction::Init( Operation* pOp,
00944                                             ActionList* pActionList,
00945                                             NodeRegularShape* pShape,
00946                                             enum ChangeItem NewItem,
00947                                             double NewData,
00948                                             Action** NewAction)
00949 
00950     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00951     Created:    10/12/94
00952     Inputs:     pOp is the pointer to the operation to which this action belongs
00953                 pShape is a pointer to the NodeRegularShape to change
00954                 NewItem identifes the data item that shoudl be changed
00955                 NewData is the value this action should set the data item to
00956                 pActionList is the action list to which this action should be added
00957     Outputs:    NewAction is a pointer to a pointer to an action, allowing the function to
00958                 return a pointer to the created action
00959     Returns:    ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
00960     Purpose:    This is the function which creates an instance of this action. If there is no
00961                 room in the undo buffer (which is determined by the base class Init function
00962                 called within) the function will either return AC_NO_RECORD which means the
00963                 operation can continue, but no undo information needs to be stored, or AC_OK
00964                 which means the operation should continue AND record undo information. If
00965                 the function returns AC_FAIL, there was not enough memory to record the undo
00966                 information, and the user has decided not to continue with the operation.
00967     Errors:     -
00968     SeeAlso:    Action::Init()
00969 
00970 ********************************************************************************************/
00971 ActionCode ChangeShapeDataAction::Init( Operation* pOp,
00972                                         ActionList* pActionList,
00973                                         NodeRegularShape* pShape,
00974                                         enum ChangeItem NewItem,
00975                                         double NewData,
00976                                         Action** NewAction)
00977 {
00978     UINT32 ActSize = sizeof(ChangeShapeDataAction);         
00979 
00980     ActionCode Ac = Action::Init( pOp, pActionList, ActSize, CC_RUNTIME_CLASS(ChangeShapeDataAction), NewAction);
00981     if ((Ac == AC_OK) && (*NewAction != NULL))
00982     {
00983         ((ChangeShapeDataAction*)*NewAction)->pToggleShape = pShape;
00984         ((ChangeShapeDataAction*)*NewAction)->ChangeItemID = NewItem;
00985         ((ChangeShapeDataAction*)*NewAction)->NewValue = NewData;
00986     }
00987     return Ac;
00988 }
00989 
00990 
00991 
00992 /********************************************************************************************
00993 
00994 >   ActionCode ChangeShapeDataAction::DoToggle(Operation* pOp,
00995                                             ActionList* pActionList,
00996                                             NodeRegularShape* pShape,
00997                                             enum ChangeItem NewItem,
00998                                             double NewData)
00999 
01000     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01001     Created:    10/12/94
01002     Inputs:     pOp is the currently running operation.
01003                 pActionList is a pointer ot the action list to which the action should be appended.
01004                 pShape is a pointer to the NodeRegularShape to change.
01005                 NewItem identifes the data item that shoudl be changed
01006                 NewData is the value this action should set the data item to
01007     Outputs:    -
01008     Returns:    Action code which indicates success or failure to create the action
01009     Purpose:    This static function makes it a little easier to use this action. It creates an instance
01010                 of this action and appends it to the action list.
01011     Errors:     -
01012     SeeAlso:    -
01013 
01014 ********************************************************************************************/
01015 
01016 ActionCode ChangeShapeDataAction::DoToggle(Operation* pOp,
01017                                         ActionList* pActionList,
01018                                         NodeRegularShape* pShape,
01019                                         enum ChangeItem NewItem,
01020                                         double NewData)
01021 {
01022     // Get the runtime class info on this object and create a pointer to another object of the same type 
01023     ChangeShapeDataAction* NewAction; 
01024 
01025     // Now call the init function to set everything up
01026     ActionCode Act = ChangeShapeDataAction::Init(pOp, pActionList, pShape, NewItem, NewData, (Action**)&NewAction);
01027     return Act;
01028 }
01029 
01030 
01031 
01032 /********************************************************************************************
01033 
01034 >   ActionCode ChangeShapeDataAction::Execute()
01035 
01036     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01037     Created:    09/12/94
01038     Inputs:     -
01039     Outputs:    -
01040     Returns:    ActionCode, either AC_OK, AC_NORECORD or AC_FAIL
01041     Purpose:    Changes a data item in a Regular shape, createing another
01042                 ChangeShapeDataAction to undo the change.
01043     Errors:     ERROR3 if the internal shape pointer was NULL.  ERROR2 checks on individual
01044                 changes.
01045     SeeAlso:    -
01046 
01047 ********************************************************************************************/
01048 ActionCode ChangeShapeDataAction::Execute()
01049 {
01050     ERROR3IF(pToggleShape == NULL, "Pointer to shape was NULL.  Did you call Init/DoToggle OR handle their failure?");
01051 
01052     // Get the runtime class info on this object and create a pointer to another object of the same type 
01053     ChangeShapeDataAction *ReAction; 
01054     ActionCode Act = AC_FAIL;
01055     double ReData = 0.0;
01056 
01057     switch (ChangeItemID)
01058     {
01059         case CHANGE_NUMSIDES:
01060             ReData = pToggleShape->GetNumSides();
01061             break;
01062         case CHANGE_CIRCULAR:
01063             ReData = pToggleShape->IsCircular() ? 1.0 : 0.0;    
01064             break;
01065         case CHANGE_STELLATED:
01066             ReData = pToggleShape->IsStellated() ? 1.0 : 0.0;   
01067             break;
01068         case CHANGE_STELLRADIUSTOPRIMARY:
01069             ReData = pToggleShape->GetStellRadiusToPrimary();   
01070             break;
01071         case CHANGE_PRIMARYCURVATURE:
01072             ReData = pToggleShape->IsPrimaryCurvature() ? 1.0 : 0.0;    
01073             break;
01074         case CHANGE_STELLATIONCURVATURE:
01075             ReData = pToggleShape->IsStellationCurvature() ? 1.0 : 0.0; 
01076             break;
01077         case CHANGE_PRIMARYCURVETOPRIMARY:
01078             ReData = pToggleShape->GetPrimaryCurveToPrimary();  
01079             break;
01080         case CHANGE_STELLCURVETOSTELL:
01081             ReData = pToggleShape->GetStellCurveToStell();  
01082             break;
01083         case CHANGE_STELLATIONOFFSET:
01084             ReData = pToggleShape->GetStellationRatio();    
01085             break;
01086         default:
01087             ERROR2(Act, "What was that Change ID?!");
01088             break;
01089     }
01090     
01091     // Create a redo action for this action
01092     if (pToggleShape != NULL)
01093     {
01094         Act = ChangeShapeDataAction::Init(pOperation, pOppositeActLst, pToggleShape, ChangeItemID, 
01095                                                                             ReData, (Action**)(&ReAction));
01096 
01097         if (Act == AC_FAIL)
01098             return AC_FAIL;
01099 
01100         // Now do the actual action
01101         switch (ChangeItemID)
01102         {
01103             case CHANGE_NUMSIDES:
01104                 pToggleShape->SetNumSides((UINT32)NewValue);
01105                 break;
01106             case CHANGE_CIRCULAR:
01107                 pToggleShape->SetCircular(NewValue == 1.0 ? TRUE : FALSE);
01108                 break;
01109             case CHANGE_STELLATED:
01110                 pToggleShape->SetStellated(NewValue == 1.0 ? TRUE : FALSE);
01111                 break;
01112             case CHANGE_STELLRADIUSTOPRIMARY:
01113                 pToggleShape->SetStellRadiusToPrimary(NewValue);
01114                 break;
01115             case CHANGE_PRIMARYCURVATURE:
01116                 pToggleShape->SetPrimaryCurvature(NewValue == 1.0 ?