nodemldr.cpp

Go to the documentation of this file.
00001 // $Id: nodemldr.cpp 1315 2006-06-14 09:51:34Z alex $
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 // NodeMoulder implementation.
00099 
00100 /*
00101 */
00102 
00103 #include "camtypes.h"
00104 #include "nodemldr.h"
00105 //#include "mike.h"
00106 #include "nodepath.h"
00107 #include "nodebmp.h"
00108 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 #include "moldshap.h"
00110 #include "ndmldink.h"
00111 #include "ndmldgrp.h"
00112 //#include "nodeattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "nativeps.h"       // The old style EPS native filter, used in v1.1
00114 #include "cameleps.h"
00115 #include "aw_eps.h"
00116 //#include "oilprog.h"
00117 
00118 #include "moldpers.h"   // For MouldPerspecive class definition
00119 //#include "fillattr.h"     // For AttrFillGeometry::MakePerspective() - in camtypes.h [AUTOMATICALLY REMOVED]
00120 
00121 #include "extender.h"
00122 #include "ngcore.h"     // NameGallery, for stretching functionality
00123 
00124 #include "strkattr.h"
00125 #include "ophist.h"
00126 
00127 DECLARE_SOURCE("$Revision: 1315 $");
00128 
00129 CC_IMPLEMENT_DYNAMIC(NodeMoulder, NodeGroup )
00130 
00131 // Declare smart memory handling in Debug builds
00132 #define new CAM_DEBUG_NEW
00133 
00134 /***********************************************************************************************
00135 
00136 >   NodeMoulder::NodeMoulder(Node*  ContextNode,
00137                         AttachNodeDirection Direction,
00138                         const DocRect&      BoundingRect,
00139                         BOOL                Locked = FALSE,
00140                         BOOL                Mangled = FALSE,
00141                         BOOL                Marked = FALSE,
00142                         BOOL                Selected = FALSE,
00143                         BOOL                Renderable = FALSE
00144                         )
00145 
00146     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00147     Created:    2/12/94
00148     
00149     Inputs:     ContextNode: Pointer to a node which this node is to be attached to.
00150                 MonoOn Direction: MonoOff
00151                 Specifies the direction in which the node is to be attached to the
00152                 ContextNode. The values this variable can take are as follows:
00153                                   
00154                 PREV      : Attach node as a previous sibling of the context node
00155                 NEXT      : Attach node as a next sibling of the context node
00156                 FIRSTCHILD: Attach node as the first child of the context node
00157                 LASTCHILD : Attach node as a last child of the context node
00158 
00159                 BoundingRect: Bounding rectangle
00160 
00161                 The remaining inputs specify the status of the node:
00162             
00163                 Locked:     Is node locked ?
00164                 Mangled:    Is node mangled ?
00165                 Marked:     Is node marked ?
00166                 Selected:   Is node selected ?
00167 
00168     Purpose:    This constructor initialises the nodes flags and links it to ContextNode in the
00169                 direction specified by Direction. All necessary tree links are updated.
00170 
00171     Note:       Initialise() must be called before the NodeMoulder is in a state in which it can be used.
00172     SeeAlso:    Initialise()   
00173     Errors:     An assertion error will occur if ContextNode is NULL
00174 
00175 ***********************************************************************************************/
00176 
00177 NodeMoulder::NodeMoulder(Node* ContextNode,  
00178                     AttachNodeDirection Direction,  
00179                     BOOL Locked, 
00180                     BOOL Mangled,  
00181                     BOOL Marked, 
00182                     BOOL Selected    
00183               ):NodeGroup(ContextNode, Direction, Locked, Mangled, Marked, Selected )  
00184 {                         
00185     pProviderNode = NULL;
00186 }
00187 
00188 /*********************************************************************************************
00189 
00190 >   NodeMoulder::NodeMoulder() 
00191 
00192     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00193     Created:    2/12/94
00194     Purpose:    This constructor creates a NodeMoulder linked to no other with all status
00195                 flags false and an uninitialized bounding rectangle.           
00196     Note:       Initialise() must be called before the NodeMoulder is in a state in which 
00197                 it can be used.         
00198     SeeAlso:    Initialise()                                                        
00199  
00200 **********************************************************************************************/
00201 /* Technical Notes:   
00202     The default constructor is required so that SimpleCopy will work 
00203 */  
00204 
00205 NodeMoulder::NodeMoulder(): NodeGroup()
00206 {
00207     pProviderNode = NULL;
00208 }
00209 
00210 
00211 /*********************************************************************************************
00212 
00213 >   NodeMoulder::~NodeMoulder() 
00214 
00215     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00216     Created:    2/12/94
00217     Purpose:    Default destructor
00218  
00219 **********************************************************************************************/
00220 
00221 NodeMoulder::~NodeMoulder()
00222 {
00223 }
00224 
00225 
00226 /*********************************************************************************************
00227 
00228 >   BOOL NodeMoulder::Initialise(NodeRenderableInk* pContextNode)
00229 
00230     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00231     Created:    2/12/94
00232     Inputs:     pContextNode = pointer to node which will be moulded
00233     Returns:    TRUE if able to initialise the moulder object
00234                 FALSE if not
00235     Purpose:    Initialise a moulder object with information necessary for it to perform
00236                 a mould
00237  
00238 **********************************************************************************************/
00239 
00240 BOOL NodeMoulder::Initialise(NodeRenderableInk* pContextNode)
00241 {
00242     ERROR2IF(pContextNode == NULL,FALSE,"pContext == NULL in NodeMoulder::Init");
00243     pProviderNode = pContextNode; 
00244     return (TRUE);
00245 }
00246 
00247 
00248 /********************************************************************************************
00249 
00250 >   virtual String NodeMoulder::Describe(BOOL Plural, BOOL Verbose = TRUE)
00251 
00252     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00253     Created:    5/12/94
00254     Inputs:     Plural: Flag indicating if the string description should be plural or
00255                         singular. 
00256     Outputs:    -
00257     Retuns:     Description of the moulder node 
00258     Purpose:    To return a description of the Moulder object in either the singular or the 
00259                 plural. This method is called by the DescribeRange method.
00260                 
00261                 The description will always begin with a lower case letter.   
00262 
00263 ********************************************************************************************/
00264 
00265 String NodeMoulder::Describe(BOOL Plural, BOOL Verbose) 
00266 {     
00267     if (Plural)
00268         return(String(_R(IDS_MOULDER_DESCRP)));  
00269     else
00270         return(String(_R(IDS_MOULDER_DESCRS))); 
00271 }; 
00272 
00273 
00274 /********************************************************************************************
00275 
00276 >   NodePath* NodeMoulder::CreateMouldPath( NodePath* pSourceNodePath,
00277                                             MouldGeometry* pGeometry
00278                                             UndoableOperation* pOp)
00279 
00280     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00281     Created:    19/12/94
00282     Inputs      pSourceNodePath = pointer to a source node path object
00283                 pGeometry       = pointer to a mould shape
00284                 pOp             = pointer to an active operation or NULL if none
00285     Outputs:
00286     Returns:    a pointer to a node path if successfull.
00287                 NULL if failed to create the object
00288     Purpose:    Creates a new Node path object containing a moulded version of the path held
00289                 within the source node path and returns a pointer to it. This can then be
00290                 inserted somewhere in the tree
00291 
00292 ********************************************************************************************/
00293 
00294 NodePath* NodeMoulder::CreateMouldPath( NodePath* pSourceNodePath, 
00295                                         MouldGeometry* pGeometry,
00296                                         UndoableOperation* pOp)
00297 {                           
00298     ERROR2IF(pSourceNodePath==NULL, NULL, "CreateMouldPath called with a null source pointer");
00299     ERROR2IF(pGeometry==NULL, NULL, "CreateMouldPath called with a null geometry pointer");
00300 
00301     BOOL ok;
00302 
00303     // ok we have the source node, so find the original path and mould it
00304     Path* pSourcePath = &(pSourceNodePath->InkPath);
00305 
00306     // create a node path receptor.
00307     NodePath* pDestinNodePath;
00308     ALLOC_WITH_FAIL( pDestinNodePath, new NodePath, pOp);
00309     if (!pDestinNodePath)
00310         return NULL;
00311 
00312     // allocate the node path some space
00313     CALL_WITH_FAIL((pDestinNodePath->SetUpPath(12,12)),pOp,ok);
00314     if (!ok)
00315     {
00316         delete pDestinNodePath;
00317         return NULL;
00318     }
00319 
00320     // create a destination path receptor for the mould
00321     Path* pDestinPath = &(pDestinNodePath->InkPath);
00322     CALL_WITH_FAIL((pGeometry->MouldPathToPath(pSourcePath, pDestinPath)),pOp,ok);
00323     if (!ok)
00324     {
00325         delete pDestinNodePath;
00326         return NULL;
00327     }
00328 
00329     // Set up the fill where necessary
00330     pDestinPath->IsFilled = pSourcePath->IsFilled;
00331 
00332     return pDestinNodePath;
00333 }
00334 
00335 
00336 
00337 /********************************************************************************************
00338 
00339 >   BOOL NodeMoulder::MouldPath(NodePath* pNodePath,
00340                                 MouldGeometry* pGeometry
00341                                 UndoableOperation* pOp)
00342 
00343     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00344     Created:    19/12/94
00345     Inputs      pNodePath   = pointer to a source node path object
00346                 pGeometry   = pointer to a mould shape
00347                 pOp         = pointer to an active operation or NULL if none
00348     Outputs:
00349     Returns:    TRUE if the path has been moulded correctly
00350                 FALSE, then unable to mould the path, the originial is intact
00351     Purpose:    This function moulds the path contained within a NodPath to itself.
00352                 It will use a temp path as a mould destination and copy this back over
00353                 the source when successful.
00354 
00355 ********************************************************************************************/
00356 
00357 BOOL NodeMoulder::MouldPath(NodePath* pNodePath, 
00358                             MouldGeometry* pGeometry,
00359                             UndoableOperation* pOp)
00360 {                           
00361     ERROR2IF(pNodePath==NULL, FALSE, "MouldPath called with a null source pointer");
00362     ERROR2IF(pGeometry==NULL, FALSE, "MouldPath called with a null geometry pointer");
00363 
00364     // ok we have the source node, so find the original path and mould it
00365     Path* pSourcePath = &(pNodePath->InkPath);
00366 
00367     // convert the source path into a destination path
00368     if (!pGeometry->MouldPathToPath(pSourcePath, pSourcePath))
00369         return FALSE;
00370 
00371     pNodePath->InvalidateBoundingRect();
00372     return TRUE;
00373 }
00374 
00375 
00376 
00377 /********************************************************************************************
00378 
00379 >   NodeMouldBitmap* NodeMoulder::CreateMouldBitmap(NodeBitmap* pSourceNodeBlit, 
00380                                                     MouldGeometry* pGeometry,
00381                                                     UndoableOperation* pOp)
00382 
00383     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00384     Created:    19/12/94
00385     Inputs:     pSourceNodeBlit = pointer to a node bitmap
00386                 pGeometry       = pointer to a mould shape to use for moulding
00387                 pOp             = pointer to an active operation or NULL if none
00388     Purpose:    Creates a NodeMouldBitmap object which is used during rendering to
00389                 render normal bitmaps through the mould.
00390     SeeAlso:    -
00391     Notes:
00392 
00393         We've found a source bitmap so we need to do something about moulding it.
00394         We either mould to a destination bitmap or create a NodeMouldBitmap node,
00395         which uses the bitmap and renders through the current mould. Eek
00396 
00397             Algorithm
00398             (1) Create NodeMouldBitmap node
00399             (2) Add the source node type to it
00400             (3) Add the source node object pointer to it
00401             (4) return ok;
00402     
00403         The idea here is hopefully simple. Currently bitmaps get rendered in
00404         Camelot as fill attributes. That means what really gets rendered is 
00405         a rectangular path, with a fill attribute set to the bitmap. We should
00406         attempt to simulate this but use one of our manifold paths instead. So
00407         when asked to render a NodeMouldBitmap object that we create here, the
00408         render function will simply take the original rectangle, mould it and
00409         render the result with a bitmap fill. I hope.
00410         Hmm, actually this may not be the best way. We need a MouldInk object
00411         but we cannot use a pointer to NodeBitmap due to the fact that we are
00412         in trouble if we copy the whole structure to another document.
00413 
00414 ********************************************************************************************/
00415 
00416 NodeMouldBitmap* NodeMoulder::CreateMouldBitmap(NodeBitmap* pSourceNodeBlit, 
00417                                                 MouldGeometry* pGeometry, 
00418                                                 UndoableOperation* pOp)
00419 {                           
00420     ERROR2IF(pSourceNodeBlit==NULL, NULL, "CreateMouldBitmap() called with a null source pointer");
00421     ERROR2IF(pGeometry==NULL, NULL, "CreateMouldBitmap() called with a null geometry pointer");
00422 
00423     // ok we have the source node, so lets create a mould render object
00424     NodeMouldBitmap* pNodeMouldBitmap;
00425     ALLOC_WITH_FAIL( pNodeMouldBitmap, new NodeMouldBitmap, pOp);
00426     if (!pNodeMouldBitmap) 
00427         return NULL;
00428 
00429     return pNodeMouldBitmap;
00430 }
00431 
00432 
00433 /********************************************************************************************
00434 
00435 >   BOOL NodeMoulder::DestroyMouldedObjects()
00436 
00437     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00438     Created:    19/12/94
00439     Inputs:     -
00440     Outputs:    -
00441     Returns:    TRUE if the moulder children were all destroyed successfully
00442                 FALSE, if failed.
00443     Purpose:
00444 
00445 ********************************************************************************************/
00446 
00447 BOOL NodeMoulder::DestroyMouldedObjects()
00448 {
00449     // first need to add a record to the undo to rebuild the
00450     // moulded objects on a fail!
00451     Node* pChild = FindFirstChild();
00452     if (pChild!=NULL)
00453         DeleteChildren(pChild);
00454 
00455     return TRUE;
00456 }
00457 
00458 
00459 
00460 /********************************************************************************************
00461 
00462 >   BOOL NodeMoulder::CreateMouldedObjects( NodeMouldGroup* pGroup,
00463                                             MouldGeometry* pGeometry, 
00464                                             UndoableOperation* pOp) 
00465 
00466     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00467     Created:    19/12/94
00468     Inputs:     pGroup      = pointer to a node mould group object
00469                 pGeometry   = pointer to a node path shape to use for moulding
00470                 pOp         = pointer to an active operation or NULL if none
00471     Outputs:
00472     Returns:    TRUE if all moulded objects have been created
00473                 FALSE if unable to create some moulded objects
00474     Purpose:    Given a pointer to a moulder object, create all the moulded children
00475                 using the source objects under the nodemouldgroup object
00476 
00477 ********************************************************************************************/
00478 
00479 BOOL NodeMoulder::CreateMouldedObjects(NodeMouldGroup* pGroup, MouldGeometry* pGeometry, UndoableOperation* pOp)
00480 {
00481     BOOL Success;
00482 
00483     if (pOp!=NULL)
00484         Success=CreateMouldObjsWithUndo(pGroup, pGeometry, pOp);
00485     else
00486         Success=CreateMouldObjsWithoutUndo(pGroup, pGeometry);
00487 
00488     return Success;
00489 }
00490 
00491 
00492 /********************************************************************************************
00493 
00494 >   BOOL NodeMoulder::CreateMouldObjsWithUndo(  NodeMouldGroup* pGroup,
00495                                                 MouldGeometry* pGeometry, 
00496                                                 UndoableOperation* pOp) 
00497 
00498     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00499     Created:    19/12/94
00500     Inputs:     pGroup      = pointer to a node mould group object
00501                 pGeometry   = pointer to a node path shape to use for moulding
00502                 pOp         = pointer to an active operation
00503     Outputs:
00504     Returns:    TRUE if all moulded objects have been created
00505                 FALSE if unable to create some moulded objects
00506     Purpose:    Given a pointer to a moulder object, create all the moulded children
00507                 using the source objects under the nodemouldgroup object
00508 
00509 ********************************************************************************************/
00510 
00511 BOOL NodeMoulder::CreateMouldObjsWithUndo(NodeMouldGroup* pGroup, MouldGeometry* pGeometry, UndoableOperation* pOp)
00512 {
00513     ERROR2IF(pGroup==NULL, FALSE, "CreateMouldedObjects() called with a null group pointer");
00514     ERROR2IF(pGeometry==NULL, FALSE, "CreateMouldedObjects() called with a null geometry pointer");
00515 
00516     Node *pNode, *qNode;
00517 
00518     // Stage 1
00519     // Copy all objects from the mould group to this new moulder object
00520     pNode = pGroup->FindFirstChild();
00521     while (pNode)
00522     {
00523         if (!IS_A(pNode,NodeHidden))
00524         {
00525             if (!pNode->CopyNode(this,LASTCHILD))
00526             {
00527                 CascadeDelete();
00528                 return FALSE;
00529             }
00530         }
00531         pNode=pNode->FindNext();
00532     }
00533 
00534     // Localise the current attributes. I do this because, although
00535     // most DoBecomeA() functions do their own localisation, bitmaps
00536     // see to apply AttrStrokeColour attributes to Pathified bitmaps
00537     // without localisation. This causes things like ConvertToShapes
00538     // produce MakeAttributeComplete found duplicate attr errors.
00539     if (!pOp->DoLocaliseCommonAttributes(this))
00540         return FALSE;
00541 
00542     // Stage 2
00543     // Get all objects to become paths or nodemouldbitmaps
00544     // Set up a BecomeA derived object, so that we can get everyone to become paths
00545     BecomeA ParamBecomeA(BECOMEA_REPLACE, CC_RUNTIME_CLASS(NodePath), pOp, FALSE);
00546     
00547     AttrStrokeType* pStroke = NULL;
00548     
00549     pNode = FindFirstChild();
00550     while (pNode)
00551     {
00552         qNode = pNode->FindNext();
00553         
00554         // bodge to deal with variable width strokes
00555         if (pNode->IsAnObject())
00556         {
00557             ((NodeRenderableInk*)pNode)->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeType), (NodeAttribute**)&pStroke);
00558             if (pStroke && pStroke->HasPathProcessor())
00559             {
00560                 if (!pStroke->DoBecomeA(&ParamBecomeA, (NodeRenderableInk*)pNode))
00561                     return FALSE;
00562             }
00563             else
00564                 if (!pNode->DoBecomeA(&ParamBecomeA))
00565                     return FALSE;
00566 
00567         }
00568         pStroke = NULL;
00569         pNode=qNode;
00570     }
00571 
00572     // As we've localised lets factor up. Make sure we do the factoring NONE globally.
00573     // We don't want to confuse any attributes.
00574     if (!pOp->DoFactorOutCommonChildAttributes(this))
00575         return FALSE;
00576 
00577     // Stage3
00578     // Process all objects, moulding each object as we go
00579     pNode = FindFirstChild();
00580     MouldTransform Transformer(pGeometry);
00581     if (!MouldAllChildren(pNode, pGeometry, Transformer, pOp))
00582         return FALSE;
00583 
00584     // Stage4
00585     // Deselect all the naughty selected objects inside ourselves
00586     pNode = FindFirstChild();
00587     while (pNode)
00588     {
00589         pNode->SetSelected(FALSE);
00590         pNode=pNode->FindNext();
00591     }
00592 
00593     // Stage5, make sure we know our bounds will be updated.
00594     InvalidateBoundingRect();
00595     return TRUE;
00596 }
00597 
00598 
00599 
00600 /********************************************************************************************
00601 
00602 >   BOOL NodeMoulder::CreateMouldObjsWithoutUndo(   NodeMouldGroup* pGroup,
00603                                                     MouldGeometry* pGeometry) 
00604 
00605     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00606     Created:    19/12/94
00607     Inputs:     pGroup      = pointer to a node mould group object
00608                 pGeometry   = pointer to a node path shape to use for moulding
00609     Outputs:
00610     Returns:    TRUE if all moulded objects have been created
00611                 FALSE if unable to create some moulded objects
00612     Purpose:    Given a pointer to a moulder object, create all the moulded children
00613                 using the source objects under the nodemouldgroup object
00614 
00615 ********************************************************************************************/
00616 
00617 BOOL NodeMoulder::CreateMouldObjsWithoutUndo(NodeMouldGroup* pGroup, MouldGeometry* pGeometry)
00618 {
00619     ERROR2IF(pGroup==NULL, FALSE, "CreateMouldedObjects() called with a null group pointer");
00620     ERROR2IF(pGeometry==NULL, FALSE, "CreateMouldedObjects() called with a null geometry pointer");
00621 
00622     Node *pNode;
00623 
00624     // Stage1
00625     // Copy the tree as shapes
00626     if (!pGroup->CopyChildrenAsShapes(this))
00627         return FALSE;
00628 
00629     // Stage2
00630     // Process all objects, moulding each object as we go
00631     pNode = FindFirstChild();
00632     MouldTransform Transformer(pGeometry);
00633     if (!MouldAllChildren(pNode, pGeometry, Transformer, NULL))
00634         return FALSE;
00635 
00636     // Stage 3
00637     // Factor out those attributes!
00638     if (!FactorOutCommonChildAttributes(FALSE,NULL))
00639         return FALSE;
00640 
00641     // Stage3
00642     // Deselect all the naughty selected objects inside ourselves
00643     pNode = FindFirstChild();
00644     while (pNode)
00645     {
00646         pNode->SetSelected(FALSE);
00647         pNode=pNode->FindNext();
00648     }
00649 
00650     // Stage4, make sure we know our bounds will be updated.
00651     InvalidateBoundingRect();
00652     return TRUE;
00653 }
00654 
00655 
00656 
00657 /********************************************************************************************
00658 
00659 >   BOOL NodeMoulder::MouldAllChildren( Node* pNode,
00660                                         MouldGeometry* pGeometry,
00661                                         TransformBase& Trans, 
00662                                         UndoableOperation* pOp) 
00663 
00664     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00665     Created:    22/01/95
00666     Inputs:     pNode       = pointer to a node to start moulding from
00667                 pGeometry   = pointer to a node path shape to use for moulding
00668                 Trans       = reference to a mould transform object
00669                 pOp         = pointer to an active operation or NULL if none
00670     Outputs:
00671     Returns:    TRUE if all objects have been moulded
00672                 FALSE if unable to mould some objects
00673     Purpose:    Given a pointer to a node, begin moulding it, all its children and all
00674                 its forward siblings and their children
00675 
00676 ********************************************************************************************/
00677 
00678 BOOL NodeMoulder::MouldAllChildren(Node* pNode,
00679                                    MouldGeometry* pGeometry,
00680                                    TransformBase& Trans,
00681                                    UndoableOperation* pOp)
00682 {
00683     Node* qNode;
00684 
00685     while (pNode)
00686     {
00687         if (pNode->IsKindOf(CC_RUNTIME_CLASS(NodePath)))
00688         {
00689             // Ok, alter the path
00690             NodePath* pNodePath = (NodePath*)pNode;
00691             if (!MouldPath(pNodePath,pGeometry,pOp))
00692                 return FALSE;
00693         }
00694         else
00695         {
00696             if (pNode->IsAnAttribute())
00697             {
00698                 NodeAttribute* pAttr = (NodeAttribute*)pNode;
00699 
00700                 if ( pAttr->IsAFillAttr() && IS_A(pGeometry,MouldPerspective) )
00701                 {
00702                     // Tell the fill attr to render perspectivised
00703                     ((AttrFillGeometry*)pAttr)->MakePerspective();
00704                 }
00705 
00706                 pAttr->Transform(Trans);
00707             }
00708         }
00709 
00710         qNode=pNode->FindFirstChild();
00711         pNode=pNode->FindNext();
00712         if (qNode)
00713         {   
00714             if (!MouldAllChildren(qNode, pGeometry, Trans, pOp))
00715                 return FALSE;
00716         }
00717     }
00718     return TRUE;
00719 }
00720 
00721 
00722 
00723 /*
00724     if (pList !=NULL)
00725     {
00726         // we have a moulder list so now we can start creating moulded objects
00727         BOOL ok;
00728 
00729         MouldListObj* pMouldItem = pList->GetFirstMouldObj();
00730         NodeRenderableInk* pDestinNode;
00731 
00732         while (pMouldItem!=NULL)
00733         {
00734             switch (pMouldItem->GetMouldedType())
00735             {
00736                 case MOULD_PATH:
00737                 {
00738                     // source object is a path, so we mould to a path
00739                     NodePath* pSourceNodePath = (NodePath*)(pMouldItem->GetMouldedSource());
00740                     pDestinNode = CreateMouldPath(pSourceNodePath, pGeometry, pOp);
00741                     if (!pDestinNode) 
00742                         return FALSE;
00743 
00744                     if (pSourceNodePath->InkPath.IsStroked)
00745                     {
00746                         // This is nasty. We need to take the stroke applied to
00747                         // this object and generate a path from it, which will
00748                         // appear as another path in the tree. This will allow line
00749                         // thicknesses etc to be transformed correctly. Can we stroke a
00750                         // path to a buffer with a line attribute? Well currently I dont
00751                         // really know how to do this so we'll leave it for now.
00752 
00753                     }
00754 
00755                 }
00756                 break;
00757 
00758                 case MOULD_BITMAP:
00759                 {
00760                     NodeBitmap* pSourceBitmap = (NodeBitmap*)(pMouldItem->GetMouldedSource());
00761                     pDestinNode = CreateMouldBitmap(pSourceBitmap, pGeometry, pOp);
00762                     if (!pDestinNode) 
00763                         return FALSE; 
00764                 }
00765                 break;
00766             }
00767 
00768             // Now stick the new node inside us (ie the nodemoulder)
00769             CALL_WITH_FAIL(pOp->DoInsertNewNode(pDestinNode, this, LASTCHILD, FALSE, FALSE, FALSE, FALSE), pOp, ok);
00770             if (!ok)
00771             {
00772                 delete pDestinNode;
00773                 return FALSE;
00774             }
00775 
00776             // get the next mould item and mould it
00777             pMouldItem = pList->GetNextMouldObj(pMouldItem);
00778         }
00779     }
00780     return TRUE;
00781 }
00782 
00783 */
00784 
00785 
00786 
00787 
00788 
00789 
00790  
00791 /***********************************************************************************************
00792 
00793 >   virtual Node* NodeMoulder::SimpleCopy()
00794 
00795     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00796     Created:    2/12/94
00797     Returns:    Pointer to a Node
00798     Purpose:    Makes a copy of all the data in the node
00799 
00800 ***********************************************************************************************/
00801 
00802 Node* NodeMoulder::SimpleCopy()
00803 {
00804     // Make a new NodeMoulder and then copy things into it
00805     NodeMoulder* pCopyOfNode = new NodeMoulder();
00806     if (pCopyOfNode)
00807         CopyNodeContents(pCopyOfNode);
00808     
00809     return pCopyOfNode;
00810 }            
00811 
00812 
00813 /***********************************************************************************************
00814 
00815 >   void NodeMoulder::CopyNodeContents(NodeMoulder* pCopyOfNode)
00816 
00817     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00818     Created:    2/12/94
00819     Inputs:     pCopyOfNode - The node to copy data to
00820     Purpose:    Copies the data in this node to pCopyOfNode by first calling the 
00821                 base class to get it to copy its stuff, and then copying its own stuff
00822     Scope:      protected
00823     SeeAlso:    NodeRenderableInk::CopyNodeContents
00824 
00825 ***********************************************************************************************/
00826 
00827 void NodeMoulder::CopyNodeContents(NodeMoulder* pCopyOfNode)
00828 {
00829     NodeRenderableInk::CopyNodeContents(pCopyOfNode);
00830     // Copy contents specific to derived class here
00831 }
00832 
00833 
00834 /***********************************************************************************************
00835 >   void NodeMoulder::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
00836 
00837     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00838     Created:    18/12/2003
00839     Outputs:    -
00840     Purpose:    Polymorphically copies the contents of this node to another
00841     Errors:     An assertion failure will occur if NodeCopy is NULL
00842     Scope:      protected
00843                                      
00844 ***********************************************************************************************/
00845 
00846 void NodeMoulder::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
00847 {
00848     ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node");
00849     ENSURE(IS_A(pNodeCopy, NodeMoulder), "PolyCopyNodeContents given wrong dest node type");
00850 
00851     if (IS_A(pNodeCopy, NodeMoulder))
00852         CopyNodeContents((NodeMoulder*)pNodeCopy);
00853 }
00854 
00855 
00856 
00857 /***********************************************************************************************
00858 
00859 >   void NodeMoulder::ShowDebugTreeDetails() const
00860 
00861     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00862     Created:    2/12/94
00863     Purpose:    Displays debugging info of the tree
00864     SeeAlso:    NodeRenderableInk::ShowDebugTreeDetails
00865 
00866 ***********************************************************************************************/
00867 #ifdef _DEBUG
00868 void NodeMoulder::ShowDebugTreeDetails() const
00869 {                     
00870     TRACE( _T("Moulder"));
00871     // Display a bit of debugging info
00872     // For now, we will just call the base class version
00873     NodeRenderableInk::ShowDebugTreeDetails();  
00874 }
00875 #endif
00876 
00877 
00878 
00879 
00880 /********************************************************************************************
00881 
00882 >   void NodeMoulder::GetDebugDetails( StringBase* Str )
00883 
00884     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00885     Created:    2/12/94
00886     Outputs:    Str: String giving debug info about the node
00887     Purpose:    For obtaining debug information about the Node
00888 
00889 ********************************************************************************************/
00890 
00891 void NodeMoulder::GetDebugDetails( StringBase* Str )
00892 {
00893 #ifdef _DEBUG
00894     // Call base class
00895     NodeRenderableInk::GetDebugDetails( Str );
00896     
00897     String_256 TempStr;
00898         
00899     (*Str) += TEXT( "\r\nMoulder Data Dump\r\n" );
00900 
00901 /*  TempStr._MakeMsg(   "Mould steps = #1%ld\n"
00902                         "Index start = #2%ld\n"
00903                         "Index end   = #3%ld\n\n"
00904                         "",
00905                         IndexStart,
00906                         IndexEnd);
00907 
00908     *Str += TempStr;
00909 */
00910     DocRect BlobRect = GetBlobBoundingRect();
00911     TempStr._MakeMsg( TEXT("Blob Bounding Rect :-\r\n\t#1%ld,\t#2%ld\r\n\t#3%ld,\t#4%ld\r\n"),
00912                       BlobRect.lo.x, BlobRect.lo.y, BlobRect.hi.x, BlobRect.hi.y );
00913     (*Str) += TempStr;
00914 #endif
00915 }
00916 
00917 
00918 
00919 /********************************************************************************************
00920 
00921 >   virtual void NodeMoulder::Transform( TransformBase& Trans )
00922 
00923     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00924     Created:    2/12/94
00925     Inputs:     Trans - The transform Object
00926     Purpose:    Transforms all the paths attached to this Moulder node
00927     SeeAlso:    NodeRenderableInk::Transform()
00928 
00929 ********************************************************************************************/
00930 
00931 void NodeMoulder::Transform( TransformBase& Trans )
00932 {
00933     // the moulder node bbox is now invalid
00934     InvalidateBoundingRect();
00935     // Transform all the children
00936     // See GroupCanTransformCached()
00937     NodeGroup::Transform(Trans);
00938 }
00939 
00940 
00941 
00942 /***********************************************************************************************
00943 
00944 >   void NodeMoulder::Render(RenderRegion* pRender)
00945 
00946     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00947     Created:    11/10/94
00948     Inputs:     Pointer to a render region
00949     Purpose:    Will render the  steps of this Moulder node
00950 
00951 ***********************************************************************************************/
00952 
00953 void NodeMoulder::Render(RenderRegion* pRender)
00954 {
00955 //  pRender->SaveContext();
00956 //  RenderMoulderedObjs(pRender);       // Only supply a render region, because we're only rendering
00957 //  pRender->RestoreContext();
00958 }  
00959 
00960 
00961 /********************************************************************************************
00962 
00963 >   DocRect NodeMoulder::GetBoundingRect(BOOL DontUseAttrs=FALSE, BOOL HitTest=FALSE)
00964 
00965     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00966     Created:    2/12/94
00967     Inputs:     DontUseAttrs - TRUE if we should ignore the nodes attributes.
00968                 Defaults to FALSE
00969                 HitTest      - TRUE if being called during HitTest
00970     Returns:    The nodes bounding rect
00971     Purpose:    if the bounding rect is valid it is returned, if not, it is recalculated
00972                 and then returned.
00973     SeeAlso:    NodeMoulder::GetBlobBoundingRect
00974 
00975 ********************************************************************************************/
00976 
00977 DocRect NodeMoulder::GetBoundingRect(BOOL DontUseAttrs, BOOL HitTest)
00978 {
00979     if (!IsBoundingRectValid || DontUseAttrs)
00980     {
00981         DocRect NewRect = GetChildBBox(DontUseAttrs);
00982 
00983         // just return this rectangle as it is not the nodes true bounding rect
00984         if (DontUseAttrs) 
00985             return NewRect;
00986             
00987         // copy the new docrect into the node bounding rect
00988         BoundingRectangle = NewRect;
00989         IsBoundingRectValid = TRUE;
00990     }
00991 
00992     // Return the resulting bounding rect
00993     return BoundingRectangle;
00994 }
00995 
00996 
00997 
00998 /********************************************************************************************
00999 
01000 >   DocRect NodeMoulder::GetChildBBox(BOOL DontUseAttrs)
01001 
01002     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01003     Created:    6/12/94
01004     Inputs:     DontUseAttrs - TRUE if we should ignore the nodes attributes.
01005                 Defaults to FALSE
01006     Returns:    The bounding rectangle of all the moulder children
01007     Purpose:    Calculates the bounding rectangle of the children of a moulder object.
01008                 It does this by scanning the child objects and merging each bounded child
01009                 bbox together
01010 
01011 ********************************************************************************************/
01012 
01013 DocRect NodeMoulder::GetChildBBox(BOOL DontUseAttrs)
01014 {
01015     // Find the moulders mangled object bounds
01016     DocRect Rect(0,0,0,0);
01017     Node* pNode = FindFirstChild();
01018     while (pNode!=NULL)
01019     {
01020         // if this node is bounded, union its bounds with the others
01021         if (pNode->IsBounded())
01022             Rect = Rect.Union(((NodeRenderableBounded*)pNode)->GetBoundingRect(DontUseAttrs));
01023         pNode = pNode->FindNext();
01024     }
01025     return Rect;
01026 }
01027 
01028 
01029 
01030 
01031 /********************************************************************************************
01032 
01033 >   DocRect NodeMoulder::GetBlobBoundingRect()
01034 
01035     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01036     Created:    2/12/94
01037     Returns:    DocRect - Returns the bounding rect of the Moulder node and its blobs
01038     Purpose:    Scan through the Mouldered paths finding bounding boxes of Mouldered objects
01039 
01040 ********************************************************************************************/
01041 
01042 DocRect NodeMoulder::GetBlobBoundingRect()
01043 {
01044     return (GetBoundingRect());
01045 }
01046 
01047 
01048 
01049 
01050 /********************************************************************************************
01051 
01052 >   virtual UINT32 NodeMoulder::GetNodeSize() const
01053 
01054     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01055     Created:    2/12/94
01056     Returns:    The size of the node in bytes 
01057     Purpose:    For finding the size of the node 
01058     SeeAlso:    Node::GetSubtreeSize
01059 
01060 ********************************************************************************************/
01061 
01062 UINT32 NodeMoulder::GetNodeSize() const 
01063 {     
01064     return (sizeof(NodeMoulder)); 
01065 }  
01066 
01067 
01068 
01069 /********************************************************************************************
01070 
01071 >   BOOL NodeMoulder::OnClick( DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods,
01072                         Spread* pSpread )
01073 
01074     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01075     Created:    11/10/94
01076     Inputs:     PointerPos  - The Location of the mouse pointer at the time of the click
01077                 Click       - The type of click received (single, double, drag etc)
01078                 ClickMods   - The modifiers to the click (eg shift, control etc )
01079     Returns:    BOOL        - TRUE if the node claims the click as its own and FALSE if it is
01080                               not interested in the click
01081     Purpose:    Allows the Node to respond to clicks by selecting its blobs or starting
01082                 drags etc.
01083 
01084 ********************************************************************************************/
01085 
01086 BOOL NodeMoulder::OnClick( DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods,
01087                         Spread* pSpread )
01088 {
01089     // we did not use the click, so let someone else try
01090     return FALSE;
01091 }
01092 
01093 
01094 /********************************************************************************************
01095 
01096 >   virtual BOOL NodeMoulder::CanBecomeA(BecomeA* pBecomeA) 
01097 
01098     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01099     Created:    2/12/94
01100     Inputs:     InkClass: The class of object
01101                 pNumObjects = ptr to place number of objects of type pClass that will be created (Note: can be NULL).
01102                               *pNumObects in undefined on entry
01103     Returns:    TRUE if the node, or any of its children can transmogrify themselves to become 
01104                 an InkClass object
01105     Purpose:    This function is used by the convert to shapes operation. It determines if 
01106                 the node or any of its children can convert themselves into an InkClass object. 
01107 
01108                 The number you put into pNumObjects (if it's not NULL) should exactly equal the total number
01109                 of pClass objects you create.  It should NOT contain any additional objects you may produce
01110                 such as group objects for containing the pClass object, or attributes.
01111 
01112                 Also, the entry value of *pNumObjects cannot be assumed to be 0.
01113 
01114 ********************************************************************************************/
01115 
01116 BOOL NodeMoulder::CanBecomeA(BecomeA* pBecomeA)
01117 {
01118     // The NodeMoulder can become a NodePath
01119     if (pBecomeA->BAPath())
01120     {
01121         if (pBecomeA->IsCounting())
01122         {
01123             // Count the number of NodePaths that are children of this NodeMoulder
01124             Node* pNode = FindFirstChild();
01125             while (pNode != NULL)
01126             {
01127                 pNode->CanBecomeA(pBecomeA);        // Increments count
01128 
01129                 pNode = pNode->FindNext();
01130             }
01131         }
01132 
01133         return TRUE;
01134     }
01135 
01136     return FALSE;
01137 }
01138 
01139            
01140 /********************************************************************************************
01141 
01142 >   virtual BOOL NodeMoulder::DoBecomeA(BecomeA* pBecomeA)
01143 
01144     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01145     Created:    5/12/94
01146     Inputs:     pBecomeA =  ptr to a class that contains all the info needed to become a new
01147                             type of node.
01148     Outputs:    -
01149     Returns:    TRUE if the object has been transformed, FALSE if we run out of memory
01150 
01151     Purpose:    Transforms the object into another type of object. 
01152                 This converts all its children, and replaces itself in the tree with a NodeGroup
01153     Errors:     -
01154     SeeAlso:    Node::CanBecomeA
01155 
01156 ********************************************************************************************/
01157 
01158 BOOL NodeMoulder::DoBecomeA(BecomeA* pBecomeA)
01159 {
01160     // Check for a NULL entry param
01161     ERROR2IF_PF(pBecomeA == NULL,FALSE,("NodeMoulder::DoBecomeA() called with a NULL ptr"));
01162 
01163     switch (pBecomeA->GetReason())
01164     {
01165         case BECOMEA_REPLACE:
01166         {
01167             // If replacing the moulder with shapes, hide the moulder, create a group, and move all the children
01168             // so they become children of the new group node
01169             ERROR2IF(pBecomeA->GetUndoOp() == NULL,FALSE,"Trying to replace a NodeMoulder, but pUndoOp == NULL");
01170             UndoableOperation* pUndoOp = pBecomeA->GetUndoOp();
01171             BOOL ok;
01172 
01173             // If being repaced in the tree, deselect the node
01174             BOOL IsSelected=this->IsSelected();
01175             SetSelected(FALSE);
01176 
01177             // Pass on this message to our child ink nodes first
01178             Node* pNode = FindFirstChild();
01179             while (pNode != NULL)
01180             {
01181                 Node* pThisNode = pNode;
01182                 pNode = pNode->FindNext();
01183                 pThisNode->DoBecomeA(pBecomeA);
01184             }
01185 
01186             // Allocate a new NodeGroup node
01187             NodeGroup* pNodeGroup;
01188             ALLOC_WITH_FAIL(pNodeGroup, (new NodeGroup), pUndoOp); 
01189             if (pNodeGroup == NULL)
01190                 return FALSE;
01191 
01192             // Insert the NodeGroup where the NodeMoulder used to be
01193             if (!pUndoOp->DoInsertNewNode(pNodeGroup,this,NEXT,FALSE,FALSE,FALSE,FALSE))
01194                 return FALSE;
01195 
01196             // if we were selected the lets select our group
01197             if (IsSelected)
01198             {
01199                 // Select the group
01200                 if (!pUndoOp->DoSelectNode(pNodeGroup,FALSE))
01201                     return FALSE;
01202             }
01203 
01204             // localise common child attributes before moving objects!
01205             if (!pUndoOp->DoLocaliseCommonAttributes(this))
01206                 return FALSE;
01207 
01208             // Now move each node in turn.
01209             pNode = FindLastChild();
01210             while (pNode != NULL)
01211             {                                                          
01212                 // Find the next node to move before we shift up the children
01213                 Node* pPrevNode = pNode->FindPrevious(); 
01214                 if (pNode->IsAnObject())
01215                 {
01216                     CALL_WITH_FAIL(pUndoOp->DoMoveNode(pNode, pNodeGroup, FIRSTCHILD), pUndoOp, ok);
01217                     if (!ok)
01218                         return FALSE;
01219                 }
01220                 pNode = pPrevNode;  
01221             }
01222 
01223             // factor up on the group.
01224             if (!pUndoOp->DoFactorOutCommonChildAttributes(pNodeGroup))
01225                 return FALSE;
01226 
01227             // Hide the moulder node
01228             NodeHidden* pNodeHidden; 
01229             if (!pUndoOp->DoHideNode(this, FALSE, &pNodeHidden, FALSE))
01230                 return FALSE;                
01231 
01232             // and finally remove any nasty perspective fills from the result
01233             NodeMould::RemovePerspectiveFills(pNodeGroup, pUndoOp);
01234     
01235         }
01236         break;
01237 
01238         case BECOMEA_PASSBACK:
01239         {
01240             // We have been called to becomea passback on the moulder.
01241             // We cannot allow paths to be put in the tree with perspective fills
01242             // in them so we must hide the fills and replace them with standard ones
01243             // We should not do this on the clipboard however as undo/redo fails and
01244             // pasting clipboard contents wont work after!
01245             Document* pOwner = (Document*)FindOwnerDoc();
01246             if (pOwner == NULL || pOwner->IsNotAClipboard())
01247                 NodeMould::RemovePerspectiveFills(this, pBecomeA->GetUndoOp());
01248 
01249             // Sequentially ask the children of the moulder to DoBecomeA
01250             // This is all that's required because the child objects are only passing back
01251             // the new node type, and NOT replacing themselves in the tree
01252             // This also ensures the receipient gets the list of paths in render order
01253             Node* pNode = FindFirstChild();
01254             while (pNode != NULL)
01255             {
01256                 if (!pNode->DoBecomeA(pBecomeA))
01257                     return FALSE;
01258 
01259                 pNode = pNode->FindNext();
01260             }
01261         }
01262         break;
01263 
01264         default:
01265             ERROR3_PF(("Unknown BecomeA reason %d",pBecomeA->GetReason()));
01266             break;
01267     }
01268 
01269 
01270     // If this is a Perspective Mould, then we need to ensure
01271     // that any perspective fills are removed, as it is 
01272     // dangerous to allow the user to edit a shape containing
01273     // a perspectivised fill.
01274     return TRUE;
01275 }
01276 
01277 
01278 
01279 
01280 
01281 
01282 
01283 /***********************************************************************************************
01284 
01285 > BOOL NodeMoulder::Snap(DocCoord* pDocCoord)
01286 
01287     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01288     Created:    2/12/94
01289     Inputs:     pDocCoord   = a coord in Spread coords
01290     Outputs:    
01291     Returns:    TRUE    - the DocCoord has been snapped .
01292                 FALSE   - the DocCoord has not been processed.
01293                                                          
01294     Purpose:    Snaps to given coord to the nearest point on the Moulder node.
01295                 Just returns FALSE currently
01296     Errors:        
01297     Scope:      public
01298            
01299 **********************************************************************************************/
01300 
01301 //BOOL NodeMoulder::Snap(DocCoord* pDocCoord)
01302 //{
01303 //  return FALSE;
01304 //}
01305 
01306 
01307 
01308 /********************************************************************************************
01309 
01310 >   BOOL NodeMoulder::NeedsToExport(RenderRegion* pRender, BOOL VisibleLayersOnly = FALSE,
01311                                     BOOL CheckSelected = FALSE)
01312 
01313     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01314     Created:    23/03/95
01315     Inputs:     pRender - A pointer to the current export region
01316                 VisibleLayersOnly - TRUE => remove nodes which are on invisible layers
01317                                    - FALSE => export everything
01318                 CheckSelected - TRUE => we check if object selected and only export selected bjects
01319                               - FALSE => we don't bother checking for selection or not
01320     Returns:    TRUE => please export me.
01321     Purpose:    Virtual function - this version will return FALSE for exporting to native
01322                 EPS documents. We dont need the moulded objects in these docs.
01323 
01324 ********************************************************************************************/
01325 
01326 BOOL NodeMoulder::NeedsToExport(RenderRegion* pRender, BOOL VisibleLayersOnly,
01327                                 BOOL CheckSelected)
01328 {
01329 #ifdef DO_EXPORT
01330     if (pRender==NULL)
01331         return TRUE;
01332 
01333     // dont export to native documents
01334     if (pRender->IS_KIND_OF(NativeRenderRegion))
01335         return FALSE;
01336 
01337     // If we have the check selection flag on then see if this moulder node is:-
01338     // - selected or not = render it
01339     // - a child of the selection e.g. part of selected group where we are an item in the
01340     //   group and hence are not directly selected but still need to be exported
01341     // - a parent of the selected item e.g. selected inside item of group and we are at the
01342     //   group and hence need to include the group in the range 
01343     // Otherwise just return True as this is a moulder node and always needs to be exported
01344     // unless of course some node overrides this or the test above fails.
01345     if (CheckSelected)
01346         return (IsSelected() || IsChildOfSelected() || IsParentOfSelected());
01347     else
01348         return TRUE;
01349 #else
01350     return FALSE;
01351 #endif
01352 }
01353 
01354 
01355 /*********************************************************************************************
01356 
01357 >    void NodeMoulder::PreExportRender(RenderRegion* pRegion)
01358 
01359      Author:    Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01360      Created:   14/03/95
01361      Inputs:    pRegion = ptr to the export render region to export to
01362      Outputs:   
01363      Returns:   
01364      Purpose:   Called before this node or any of its children have been rendered to the 
01365                 export region. This outputs the "start mould destin objects" command.
01366                 Supports ArtWorks EPS and Camelot EPS
01367      Errors:    
01368 
01369 **********************************************************************************************/
01370  
01371 void NodeMoulder::PreExportRender(RenderRegion* pRegion)
01372 {
01373 #ifdef DO_EXPORT
01374     if (pRegion->IS_KIND_OF(CamelotEPSRenderRegion))
01375     {
01376         PreExportCAMEPS(pRegion);
01377         return;
01378     } 
01379 
01380     if (pRegion->IS_KIND_OF(ArtWorksEPSRenderRegion))
01381     {
01382         PreExportAWEPS(pRegion);
01383         return;
01384     }
01385 #endif
01386 }
01387 
01388 /*********************************************************************************************
01389 
01390 >    BOOL NodeMoulder::ExportRender(RenderRegion* pRegion)
01391 
01392      Author:    Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01393      Created:   14/03/95
01394      Inputs:    pRegion = ptr to the export render region to export to
01395      Outputs:   
01396      Returns:   TRUE if ok, FALSE if something went wrong
01397      Purpose:   Called after this node and all of its children have been rendered to the
01398                 export region. This outputs the "end mould destin objs" command.
01399                 Supports ArtWorks EPS and Camelot EPS
01400      Errors:    
01401 
01402 **********************************************************************************************/
01403  
01404 BOOL NodeMoulder::ExportRender(RenderRegion* pRegion) 
01405 {
01406 #ifdef DO_EXPORT
01407     if (pRegion->IS_KIND_OF(CamelotEPSRenderRegion))
01408         return PostExportCAMEPS(pRegion);
01409 
01410     if (pRegion->IS_KIND_OF(ArtWorksEPSRenderRegion))
01411         return PostExportAWEPS(pRegion);
01412 #endif  
01413     return FALSE;
01414 }
01415 
01416 
01417 /*********************************************************************************************
01418 
01419     BOOL NodeMoulder::Pre/Post ExportCAMEPS(RenderRegion* pRegion)
01420 
01421     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01422     Created:    14/03/95
01423     Purpose:    Export delimiter tokens for this particular object.
01424                 The format is defined as
01425                     csmp
01426                         path description
01427                     cemp
01428 
01429 **********************************************************************************************/
01430 
01431 void NodeMoulder::PreExportCAMEPS(RenderRegion* pRegion)
01432 {
01433 #ifdef DO_EXPORT
01434     // Make sure this token goes out only in Native documents
01435     if (pRegion->IS_KIND_OF(NativeRenderRegion))
01436     {
01437         EPSExportDC *pDC = (EPSExportDC *) pRegion->GetRenderDC();
01438         pDC->OutputToken(_T("csdo"));           // Camelot "start mould destin" token
01439         pDC->OutputNewLine();
01440     }
01441 #endif
01442 }
01443 
01444 
01445 BOOL NodeMoulder::PostExportCAMEPS(RenderRegion* pRegion)
01446 {
01447 #ifdef DO_EXPORT
01448     // Make sure this token goes out only in Native documents
01449     if (pRegion->IS_KIND_OF(NativeRenderRegion))
01450     {
01451         EPSExportDC *pDC = (EPSExportDC *) pRegion->GetRenderDC();
01452         pDC->OutputToken(_T("cedo"));           // Camelot "end mould destin" token
01453         pDC->OutputNewLine();
01454         return TRUE;
01455     }
01456 #endif
01457     // Otherwise render as paths (e.g. in EPS)
01458     return FALSE;
01459 }
01460 
01461 
01462 /*********************************************************************************************
01463 
01464     void NodeMoulder::Pre/Post ExportAWEPS(RenderRegion* pRegion)
01465 
01466     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01467     Created:    14/03/95
01468 
01469 **********************************************************************************************/
01470 
01471 void NodeMoulder::PreExportAWEPS(RenderRegion* pRegion)
01472 {
01473 }
01474 
01475 BOOL NodeMoulder::PostExportAWEPS(RenderRegion* pRegion)
01476 {
01477     return FALSE;
01478 }
01479 
01480 
01481 
01482 /********************************************************************************************
01483 
01484 >   virtual BOOL NodeMoulder::AllowOp(  ObjChangeParam* pParam,
01485                                         BOOL SetOpPermissionState = TRUE,
01486                                         DoPreTriggerEdit = TRUE)
01487 
01488     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>; Karim 20/01/2000
01489     Created:    30/6/95
01490     Inputs:     pParam - pointer to the change parameter object
01491                 SetOpPermissionState - TRUE to set the Nodes permission flags
01492                 DoPreTriggerEdit     - if TRUE then calls NameGallery::PreTriggerEdit.
01493                                        *Must* be TRUE if the calling Op may make any nodes
01494                                        change their bounds, eg move, line width, cut.
01495                                        Use TRUE if unsure.
01496 
01497     Returns:    TRUE if the operation can proceede, FALSE to stop it
01498     Purpose:    Generic AllowOp() for all moulder nodes.
01499 
01500 ********************************************************************************************/
01501 
01502 BOOL NodeMoulder::AllowOp(ObjChangeParam* pParam, BOOL SetOpPermissionState,
01503                                                   BOOL DoPreTriggerEdit)
01504 {
01505     ERROR2IF(pParam==NULL,FALSE,"Node::AllowOp() - pParam==NULL");
01506 
01507     // if not called by a child AllowOp(), ensure AllowOp() called for all nodes in compound nodes,
01508     if (pParam->GetDirection()!=OBJCHANGE_CALLEDBYCHILD)
01509     {
01510         BOOL AnyAllowed=AllowOp_AccountForCompound( pParam,
01511                                                     SetOpPermissionState,
01512                                                     DoPreTriggerEdit );
01513         // if called by a parent, just pass this result back
01514         if (pParam->GetDirection()==OBJCHANGE_CALLEDBYPARENT)
01515             return AnyAllowed;
01516     }
01517     else
01518     {
01519         // clean out the calling-child ptr, so it doesn't get passed around unintentionally.
01520         pParam->SetCallingChild(NULL);
01521     }
01522 
01523     // at this point we must have been called directly by the op or via a child AllowOp()
01524 
01525     // decide if we allow it, we dont allow very much at the moment, the only thing you can
01526     // actually do to children of a moulder is to copy them
01527     BOOL allowed=TRUE;
01528     ObjChangeFlags Flags=pParam->GetChangeFlags();
01529     if ((pParam->GetDirection()==OBJCHANGE_CALLEDBYCHILD) ||
01530         (pParam->GetDirection()==OBJCHANGE_CALLEDBYOP))
01531 //      if (Flags.DeleteNode || Flags.ReplaceNode || Flags.MoveNode || Flags.Attribute || Flags.MultiReplaceNode || Flags.TransformNode)
01532         {
01533             pParam->SetReasonForDenial(_R(IDS_MOULD_CANT_OP_ON_CHILDREN));
01534             allowed=FALSE;
01535         }
01536 
01537     // if we allowed it, see if our parents do ...
01538     if (allowed && Parent!=NULL)
01539     {
01540         ObjChangeDirection OldDirection=pParam->GetDirection();
01541         pParam->SetCallingChild(this);
01542         pParam->SetDirection(OBJCHANGE_CALLEDBYCHILD);
01543         allowed=Parent->AllowOp(pParam,SetOpPermissionState,DoPreTriggerEdit);
01544         pParam->SetDirection(OldDirection);
01545     }
01546 
01547     // if setting permisions ...
01548     if (SetOpPermissionState)
01549     {
01550         // if allowed, mark parent accordingly, else mark child as denied and update parents
01551         if (allowed)
01552             Parent->SetOpPermission(PERMISSION_ALLOWED);
01553         else
01554             SetOpPermission(PERMISSION_DENIED,TRUE);
01555     }
01556 
01557     // if we're ok so far and were asked to do a PreTriggerEdit, then
01558     // determine whether the Op may change the bounds of some nodes.
01559     // If it may, then call NameGallery::PreTriggerEdit.
01560     if (allowed && DoPreTriggerEdit)
01561     {
01562         // if the Op is non-NULL then query its MayChangeNodeBounds() method.
01563         UndoableOperation* pChangeOp = pParam->GetOpPointer();
01564         if (pChangeOp != NULL && pChangeOp->MayChangeNodeBounds())
01565         {
01566             if (NameGallery::Instance())
01567                 allowed = NameGallery::Instance()->PreTriggerEdit(pChangeOp, pParam, this);
01568         }
01569     }
01570 
01571     // return result (directly, or indirectly via a child AllowOp()) to op
01572     return allowed;
01573 }
01574 
01575 
01576 /********************************************************************************************
01577 
01578 >   virtual ChangeCode NodeMoulder::OnChildChange(ObjChangeParam* pParam)
01579 
01580     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01581     Created:    09/01/95
01582     Inputs:     pParam  = pointer to a object change parameter class
01583     Returns:    CC_OK       if we have successfully processed the change.
01584                 CC_FAIL     if we cannot handle this particular change and must prevent the
01585                             child from continuing
01586     Purpose:    This function should be overridden in derived object classes.
01587                 Composite objects can use this function to respond to one of their children
01588                 undergoing a change. They should return CC_FAIL whenever they are unable to
01589                 cope with the change.
01590     SeeAlso:    WarnParentOfChange();
01591 
01592 ********************************************************************************************/
01593 
01594 ChangeCode NodeMoulder::OnChildChange(ObjChangeParam* pParam)
01595 {
01596     return CC_OK;
01597 }
01598 
01599 /********************************************************************************************
01600 
01601 >   virtual BOOL NodeMoulder::WritePreChildrenWeb(BaseCamelotFilter* pFilter)
01602 
01603     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01604     Created:    18/7/96
01605     Inputs:     pFilter = ptr to the filter to write to
01606     Returns:    TRUE is a record has been written, FALSE otherwise
01607     Purpose:    Writes out a records associated with this node
01608 
01609                 NodeMoulders do NOT save anything out in the current version of Camelot.
01610 
01611 ********************************************************************************************/
01612 
01613 BOOL NodeMoulder::WritePreChildrenWeb(BaseCamelotFilter* pFilter)
01614 {
01615     return FALSE;
01616 }
01617 
01618 //------------------------------------------------------------------
01619 // See comments for NodeMoulder::WritePreChildrenWeb(BaseCamelotFilter* pFilter)
01620 BOOL NodeMoulder::WritePreChildrenNative(BaseCamelotFilter* pFilter)
01621 {
01622     return WritePreChildrenWeb(pFilter);
01623 }
01624 
01625 /********************************************************************************************
01626 
01627 >   virtual BOOL NodeMoulder::CanWriteChildrenWeb(BaseCamelotFilter* pFilter)
01628 
01629     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01630     Created:    18/7/96
01631     Inputs:     pFilter = ptr to the filter to write to
01632     Returns:    TRUE if children can be written automatically, FALSE otherwise
01633     Purpose:    This allows a node to stop the filter from writing out the child nodes automatically.
01634 
01635                 NodeMoulders do NOT save anything out in the current version of Camelot.
01636                 Therefore, none of it's children can be saved out either.
01637 
01638 ********************************************************************************************/
01639 
01640 BOOL NodeMoulder::CanWriteChildrenWeb(BaseCamelotFilter* pFilter)
01641 {
01642     return FALSE;
01643 }
01644 
01645 //------------------------------------------------------------------
01646 // See comments for NodeMoulder::CanWriteChildrenNative(BaseCamelotFilter* pFilter)
01647 BOOL NodeMoulder::CanWriteChildrenNative(BaseCamelotFilter* pFilter)
01648 {
01649     return CanWriteChildrenWeb(pFilter);
01650 }
01651 

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