nodeshap.cpp

Go to the documentation of this file.
00001 // $Id: nodeshap.cpp 1361 2006-06-25 16:43:38Z 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 // NodeSimpleShape class. This provides a base class for all simple primitve shapes
00099 // eg, Rectangles and Ellipses.
00100 
00101 /*
00102 */
00103 
00104 
00105 #include "camtypes.h"
00106 #include "nodeshap.h"
00107 //#include "osrndrgn.h"
00108 #include "nodepath.h"
00109 //#include "ops.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 #include "snap.h"
00112 //#include "becomea.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "blobs.h"
00114 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00115 #include "extender.h"
00116 
00117 #include "ophist.h"
00118 
00119 // Put my version Number into the About box
00120 DECLARE_SOURCE( "$Revision: 1361 $" );
00121 
00122 
00123 CC_IMPLEMENT_DYNCREATE(NodeSimpleShape, NodeRenderableInk)
00124 
00125 // Declare smart memory handling in Debug builds
00126 #define new CAM_DEBUG_NEW
00127 
00128 
00129 
00130 /***********************************************************************************************
00131 
00132 >   NodeSimpleShape::NodeSimpleShape(Node*  ContextNode,
00133                         AttachNodeDirection Direction,
00134                         const DocRect&      BoundingRect,
00135                         BOOL                Locked = FALSE,
00136                         BOOL                Mangled = FALSE,
00137                         BOOL                Marked = FALSE,
00138                         BOOL                Selected = FALSE,
00139                         BOOL                Renderable = FALSE
00140                         )
00141 
00142     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
00143     Created:    22/9/93
00144     
00145     Inputs:     ContextNode: Pointer to a node which this node is to be attached to.
00146                 MonoOn Direction: MonoOff
00147                 Specifies the direction in which the node is to be attached to the
00148                 ContextNode. The values this variable can take are as follows:
00149                                   
00150                 PREV      : Attach node as a previous sibling of the context node
00151                 NEXT      : Attach node as a next sibling of the context node
00152                 FIRSTCHILD: Attach node as the first child of the context node
00153                 LASTCHILD : Attach node as a last child of the context node
00154 
00155                 BoundingRect: Bounding rectangle
00156 
00157                 The remaining inputs specify the status of the node:
00158             
00159                 Locked:     Is node locked ?
00160                 Mangled:    Is node mangled ?
00161                 Marked:     Is node marked ?
00162                 Selected:   Is node selected ?
00163 
00164     Purpose:    This constructor initialises the nodes flags and links it to ContextNode in the
00165                 direction specified by Direction. All neccesary tree links are updated.
00166     Note:       SetUpPath() must be called before the NodeSimpleShape is in a state in which it can be used.
00167                 
00168     SeeAlso: SetUpPath   
00169     Errors: An assertion error will occur if ContextNode is NULL
00170 
00171 ***********************************************************************************************/
00172 
00173 NodeSimpleShape::NodeSimpleShape(Node* ContextNode,  
00174                     AttachNodeDirection Direction,  
00175                     BOOL Locked, 
00176                     BOOL Mangled,  
00177                     BOOL Marked, 
00178                     BOOL Selected    
00179               ):NodeRenderableInk(ContextNode, Direction, Locked, Mangled, Marked, Selected )  
00180 {                         
00181 }                        
00182  
00183 /*********************************************************************************************
00184 
00185 >   NodeSimpleShape::NodeSimpleShape() 
00186 
00187     Author:     Mario_Shamtani (Xara Group Ltd) <camelotdev@xara.com>
00188     Created:    22/9/93
00189     Purpose:    This constructor creates a NodeSimpleShape linked to no other with all status
00190                 flags false and an uninitialized bounding rectangle.           
00191     Note:       SetUpPath() must be called before the NodeSimpleShape is in a state in which it can be 
00192                 used.       
00193     SeeAlso:    SetUpPath                                                        
00194 
00195 **********************************************************************************************/
00196 /* Technical Notes:   
00197     The default constructor is required so that SimpleCopy will work 
00198 */  
00199 
00200 NodeSimpleShape::NodeSimpleShape(): NodeRenderableInk()
00201 {
00202 }
00203 
00204 /***********************************************************************************************
00205 
00206 >   virtual Node* NodeSimpleShape::SimpleCopy()
00207 
00208     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00209     Created:    26/5/93
00210     Returns:    Pointer to a Node
00211     Purpose:    Makes a copy of all the data in the node
00212 
00213 ***********************************************************************************************/
00214 
00215 Node* NodeSimpleShape::SimpleCopy()
00216 {
00217     // Make a new NodeSimpleShape and then copy things into it
00218     TRACE( _T("NodeSimpleShape::SimpleCopy() - Should not be called\n"));
00219     NodeSimpleShape* NodeCopy = new NodeSimpleShape();
00220     if (NodeCopy)
00221         CopyNodeContents(NodeCopy);
00222     
00223     return NodeCopy;
00224 }            
00225 
00226 
00227 /***********************************************************************************************
00228 
00229 >   void NodeSimpleShape::CopyNodeContents(NodeSimpleShape* NodeCopy)
00230 
00231     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00232     Created:    26/5/93
00233     Inputs:     NodeCopy - The node to copy
00234     Purpose:    Copies the data in the node by first calling the base class to get it to
00235                 copy its stuff, and then copying its own stuff
00236     Scope:      protected
00237     SeeAlso:    NodeRenderableInk::CopyNodeContents
00238 
00239 ***********************************************************************************************/
00240 
00241 void NodeSimpleShape::CopyNodeContents(NodeSimpleShape* NodeCopy)
00242 {
00243     NodeRenderableInk::CopyNodeContents(NodeCopy);
00244     
00245     //Copy contents specific to derived class here
00246     if (NodeCopy->InkPath.Initialise(InkPath.GetNumCoords(),12))
00247     {
00248         // Copy the path data
00249         NodeCopy->InkPath.CopyPathDataFrom(&InkPath);
00250 
00251         // copy the parralleogram data
00252         NodeCopy->Parallel[0] = Parallel[0];
00253         NodeCopy->Parallel[1] = Parallel[1];
00254         NodeCopy->Parallel[2] = Parallel[2];
00255         NodeCopy->Parallel[3] = Parallel[3];
00256     }
00257 }
00258 
00259 
00260 
00261 /***********************************************************************************************
00262 >   void NodeSimpleShape::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
00263 
00264     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00265     Created:    18/12/2003
00266     Outputs:    -
00267     Purpose:    Polymorphically copies the contents of this node to another
00268     Errors:     An assertion failure will occur if NodeCopy is NULL
00269     Scope:      protected
00270                                      
00271 ***********************************************************************************************/
00272 
00273 void NodeSimpleShape::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
00274 {
00275     ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node");
00276     ENSURE(IS_A(pNodeCopy, NodeSimpleShape), "PolyCopyNodeContents given wrong dest node type");
00277 
00278     if (IS_A(pNodeCopy, NodeSimpleShape))
00279         CopyNodeContents((NodeSimpleShape*)pNodeCopy);
00280 }
00281 
00282 
00283 
00284 /***********************************************************************************************
00285 
00286 >   void NodeSimpleShape::ShowDebugTreeDetails() const
00287 
00288     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00289     Created:    26/5/93
00290     Purpose:    Displays debugging info of the tree
00291     SeeAlso:    NodeRenderableInk::ShowDebugTreeDetails
00292 
00293 ***********************************************************************************************/
00294 #ifdef _DEBUG
00295 void NodeSimpleShape::ShowDebugTreeDetails() const
00296 {                     
00297     TRACE( _T("SimpleShape ")); 
00298     // Display a bit of debugging info
00299     // For now, we will just call the base class version
00300     NodeRenderableInk::ShowDebugTreeDetails();  
00301 }
00302 #endif
00303 
00304 /********************************************************************************************
00305 
00306 >   void NodeSimpleShape::GetDebugDetails( StringBase* Str )
00307 
00308     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00309     Created:    21/9/93
00310     Outputs:    Str: String giving debug info about the node
00311     Purpose:    For obtaining debug information about the Node
00312 
00313 ********************************************************************************************/
00314 
00315 void NodeSimpleShape::GetDebugDetails( StringBase* Str )
00316 {
00317 #ifdef _DEBUG
00318     // Call base class
00319     NodeRenderableInk::GetDebugDetails( Str );
00320     
00321     InkPath.FindStartOfPath();
00322     String_256 TempStr;
00323         
00324     (*Str) += TEXT( "\r\nEllipse Path Data Dump\r\n" );
00325 
00326     TempStr._MakeMsg( TEXT( "Parallelogram :-\r\n\t#1%ld,\t#2%ld\r\n")
00327                         TEXT("\t#3%ld,\t#4%ld\r\n")
00328                         TEXT("\t#5%ld,\t#6%ld\r\n")
00329                         TEXT("\t#7%ld,\t#8%ld\r\n"),
00330                         Parallel[0].x, Parallel[0].y,
00331                         Parallel[1].x, Parallel[1].y,
00332                         Parallel[2].x, Parallel[2].y,
00333                         Parallel[3].x, Parallel[3].y );
00334     (*Str) += TempStr;
00335 
00336     DocRect BlobRect = GetBlobBoundingRect();
00337     TempStr._MakeMsg( TEXT("Blob Bounding Rect :-\r\n\t#1%ld,\t#2%ld\r\n\t#3%ld,\t#4%ld\r\n"),
00338                       BlobRect.lo.x, BlobRect.lo.y, BlobRect.hi.x, BlobRect.hi.y );
00339     (*Str) += TempStr;
00340     
00341     if ( InkPath.IsFilled )
00342         (*Str) += TEXT( "The Path is Filled\r\n" );
00343 
00344     (*Str) += TEXT( "\r\nNum\tType\tX Coord\tY Coord\r\n" );
00345     PathVerb* Verbs  = InkPath.GetVerbArray();
00346     DocCoord* Coords = InkPath.GetCoordArray();
00347 //  PathFlags* Flags = InkPath.GetFlagArray();
00348     for (INT32 i=0; i<InkPath.GetNumCoords(); i++)
00349     {
00350         // Add the info to the string
00351         TempStr._MakeMsg( TEXT("#1%d.\t#2%d\t#3%ld,\t#4%ld\r\n"),
00352                           i, Verbs[i], Coords[i].x, Coords[i].y );
00353         (*Str) += TempStr;
00354     }
00355 #endif
00356 }
00357 
00358 
00359 
00360 /***********************************************************************************************
00361 
00362 >   BOOL NodeSimpleShape::SetUpPath(INT32 RequiredSize=12, INT32 BlockSize=12)
00363 
00364     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00365     Created:    04/5/93
00366     Inputs:     RequiredSize - The size of the initial block of memory to be allocated to the
00367                 path.
00368                 BlockSize - The size of the block asked for by the path object when it
00369                 runs out of space. 
00370     Returns:    TRUE if the path was init'ed ok, FALSE otherwise
00371     Purpose:    To initialise the path used by the shape into a state that can be used,
00372                 by allocating memory, setting up member variables properly.
00373 
00374 ***********************************************************************************************/
00375 
00376 BOOL NodeSimpleShape::SetUpPath(INT32 RequiredSize, INT32 BlockSize)
00377 {
00378     return (InkPath.Initialise(RequiredSize, BlockSize)); 
00379 }
00380 
00381 
00382 
00383 /********************************************************************************************
00384 
00385 >   virtual void NodeSimpleShape::Transform( TransformBase& Trans )
00386 
00387     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00388     Created:    20/10/93
00389     Inputs:     Trans - The transform Object
00390     Purpose:    Transforms the shapes parallelogram and then re-builds the shape to fit it.
00391     SeeAlso:    NodeRenderableInk::Transform()
00392 
00393 ********************************************************************************************/
00394 
00395 void NodeSimpleShape::Transform( TransformBase& Trans )
00396 {
00397     // Transform the Shape
00398     Trans.Transform((DocCoord*)Parallel, 4);
00399 
00400     // re-create the path and update its bounding rectangle
00401     UpdateShape();
00402 
00403     // Mark the bounding rect as invalid
00404     InvalidateBoundingRect();
00405 
00406     // Transform all the children...
00407     TransformChildren(Trans);
00408 }
00409 
00410 
00411 
00412 
00413 /***********************************************************************************************
00414 
00415 >   void NodeSimpleShape::CreateShape(DocRect ARect)
00416 
00417     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00418     Created:    22/9/93                          
00419     Inputs:     DocRect - representing the rectangle to be created.
00420     Purpose:    Should create a the shape to fit the current parallelogram. This version does
00421                 nothing as there should always be a derived class version.
00422 
00423 ***********************************************************************************************/
00424 
00425 void NodeSimpleShape::CreateShape(DocRect NewRect)
00426 {
00427     // You are not supposed to be calling this. You should have called a
00428     // derived classes version of this function
00429     ENSURE(FALSE, "NodeSimpleShape::CreateShape - You called the base class version");
00430 }
00431 
00432 /***********************************************************************************************
00433 
00434 >   void NodeSimpleShape::UpdateShape(DocRect ARect)
00435 
00436     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00437     Created:    22/9/93                          
00438     Inputs:     DocRect - representing the rectangle to be created.
00439     Purpose:    Should update the the shape to the current parallelogram. This version does
00440                 nothing as there should always be a derived class version.
00441 
00442 ***********************************************************************************************/
00443 
00444 void NodeSimpleShape::UpdateShape()
00445 {
00446     // You are not supposed to be calling this. You should have called a
00447     // derived classes version of this function
00448     ENSURE(FALSE, "NodeSimpleShape::UpdateShape - You called the base class version");
00449 }
00450 
00451 
00452 
00453 
00454 /***********************************************************************************************
00455 
00456 >   void NodeSimpleShape::Render(RenderRegion* pRender)
00457 
00458     Author:     Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
00459     Created:    31/5/93
00460     Inputs:     Pointer to a render region
00461     Purpose:    Will render the path contained within the object to the given render region
00462 
00463 ***********************************************************************************************/
00464 
00465 void NodeSimpleShape::Render(RenderRegion* pRender)
00466 {            
00467     // render the path
00468     pRender->DrawPath(&InkPath);
00469 }  
00470 
00471 
00472 
00473 /********************************************************************************************
00474 
00475 >   void NodeSimpleShape::RenderEorDrag( RenderRegion* pRender )
00476 
00477     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00478     Created:    22/10/93
00479     Inputs:     pRender - A Pointer to the current RenderRegion
00480     Purpose:    Renders a version of the path for EORed dragging of shapes.
00481     SeeAlso:    NodePath::Render; NodeRenderableInk::RenderEorDrag
00482 
00483 ********************************************************************************************/
00484 
00485 void NodeSimpleShape::RenderEorDrag( RenderRegion* pRender )
00486 {
00487     // Render an EORed version of the shape. For a simple object such
00488     // as this we can render it as normal
00489     pRender->DrawPath(&InkPath);
00490 }
00491 
00492 
00493 
00494 
00495 /********************************************************************************************
00496 
00497 >   void NodeSimpleShape::RenderObjectBlobs(RenderRegion* pRender)
00498 
00499     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00500     Created:    23/6/94
00501     Inputs:     pRender - the region to render the blobs to
00502     Purpose:    Renders the Object blobs for a Node Shape
00503     SeeAlso:    BlobManager
00504 
00505 ********************************************************************************************/
00506 
00507 void NodeSimpleShape::RenderObjectBlobs(RenderRegion* pRender)
00508 {
00509 #if !defined(EXCLUDE_FROM_RALPH)
00510     // Set the line colours etc as we need them
00511     pRender->SetLineColour(COLOUR_NONE);
00512     pRender->SetFillColour(COLOUR_UNSELECTEDBLOB);
00513 
00514     // Render the blobs on the path
00515     pRender->DrawBlob(Parallel[0], BT_UNSELECTED);
00516     pRender->DrawBlob(Parallel[1], BT_UNSELECTED);
00517     pRender->DrawBlob(Parallel[2], BT_UNSELECTED);
00518     pRender->DrawBlob(Parallel[3], BT_UNSELECTED);
00519 #endif
00520 }
00521 
00522 
00523 
00524 /********************************************************************************************
00525 
00526 >   void NodeSimpleShape::RenderTinyBlobs(RenderRegion* pRender)
00527 
00528     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00529     Created:    23/6/94
00530     Inputs:     pRender - the region to render the blobs to
00531     Purpose:    Renders the Tiny blobs for a Node Shape
00532     SeeAlso:    BlobManager
00533 
00534 ********************************************************************************************/
00535 
00536 void NodeSimpleShape::RenderTinyBlobs(RenderRegion* pRender)
00537 {
00538 #if !defined(EXCLUDE_FROM_RALPH)
00539     // Set the line colours etc as we need them
00540     pRender->SetLineColour(COLOUR_NONE);
00541     pRender->SetFillColour(COLOUR_UNSELECTEDBLOB);
00542 
00543     // Find out about the path that the shape is made from
00544     DocCoord* Coords = InkPath.GetCoordArray();
00545 
00546     // Render the blobs on the path
00547     if (InkPath.GetNumCoords()>0)
00548         pRender->DrawBlob(Coords[0], BT_UNSELECTED);
00549 #endif
00550 }
00551 
00552 
00553 
00554 /********************************************************************************************
00555 
00556 >   DocRect NodeSimpleShape::GetBoundingRect(BOOL DontUseAttrs=FALSE, BOOL HitTest=FALSE)
00557 
00558     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00559     Created:    17/02/94
00560     Inputs:     DontUseAttrs - TRUE if we should ignore the nodes attributes.
00561                 Defaults to FALSE
00562                 HitTest      - TRUE if being called during HitTest
00563     Returns:    The nodes bounding rect
00564     Purpose:    if the bounding rect is valid it is returned, if not, it is recalculated
00565                 and then returned.
00566     SeeAlso:    NodeSimpleShape::GetBlobBoundingRect
00567 
00568 ********************************************************************************************/
00569 
00570 DocRect NodeSimpleShape::GetBoundingRect(BOOL DontUseAttrs, BOOL HitTest)
00571 {
00572     if (!IsBoundingRectValid || DontUseAttrs)
00573     {
00574         // Something to put the new bounding rectangle in
00575         DocRect NewBoundingRect;
00576 
00577         // Find out what the paths bounding rect is now
00578         if (!CalculatePathBoundingRect(InkPath, DontUseAttrs, &NewBoundingRect))
00579         {
00580             // GDraw failed to find out how big the bounding rect
00581             // we will have to make do with the bounding rect of the coords
00582             NewBoundingRect = InkPath.GetBoundingRect();
00583         }
00584 
00585         // we have a new bounding rect - decide what to do with it
00586         if (DontUseAttrs)
00587         {
00588             // but it is not the real bounding rect, so just return it
00589             return NewBoundingRect;
00590         }
00591 
00592         // Update the Nodes bounding rectangle
00593         BoundingRectangle = NewBoundingRect;
00594 
00595         // Mark the rect as valid
00596         IsBoundingRectValid = TRUE;
00597     }
00598 
00599     // return the current state of the bounding rect
00600     return BoundingRectangle;
00601 }
00602 
00603 
00604 /********************************************************************************************
00605 
00606 >   DocRect NodeSimpleShape::GetBlobBoundingRect()
00607 
00608     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00609     Created:    17/02/94
00610     Returns:    DocRect - Returns the bounding rect of the path and its blobs
00611     Purpose:    This calculates the bounding box of the path and adds in the influence of
00612                 the selection blobs. It does not consider if the blobs are visible or not,
00613                 it just gives the bounding box that they would occupy if they were visible
00614 
00615 ********************************************************************************************/
00616 
00617 DocRect NodeSimpleShape::GetBlobBoundingRect()
00618 {
00619 #if !defined(EXCLUDE_FROM_RALPH)
00620     // Find the Shapes bounding rectangle
00621     DocRect Rect = GetBoundingRect();
00622 
00623     // Find the blob manager
00624     BlobManager* pBlobMgr = GetApplication()->GetBlobManager();
00625 
00626     // And if we can find the current view, add on the size of a selection blob
00627     if (pBlobMgr!= NULL)
00628     {
00629         // Wee need to add in each of the blobs. there is a blob on each corner
00630         // of the parallelogram
00631         DocRect BlobSize;
00632         pBlobMgr->GetBlobRect(Parallel[0], &BlobSize);
00633         Rect = Rect.Union(BlobSize);
00634         
00635         // Next corner of the parallelogram
00636         pBlobMgr->GetBlobRect(Parallel[1], &BlobSize);
00637         Rect = Rect.Union(BlobSize);
00638 
00639         // and the next
00640         pBlobMgr->GetBlobRect(Parallel[2], &BlobSize);
00641         Rect = Rect.Union(BlobSize);
00642 
00643         // and the last one
00644         pBlobMgr->GetBlobRect(Parallel[3], &BlobSize);
00645         Rect = Rect.Union(BlobSize);
00646     }
00647 
00648     // Make sure we include the Bounds of our children
00649     IncludeChildrensBoundingRects(&Rect);
00650 
00651     // return the rectangle with the blobs included
00652     return Rect;
00653 #else
00654     return DocRect(0,0,0,0);
00655 #endif
00656 }
00657 
00658 
00659 
00660 
00661 /********************************************************************************************
00662 
00663 >   virtual UINT32 NodeSimpleShape::GetNodeSize() const
00664 
00665     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00666     Created:    6/10/93
00667     Returns:    The size of the node in bytes 
00668     Purpose:    For finding the size of the node 
00669     SeeAlso:    Node::GetSubtreeSize
00670 
00671 ********************************************************************************************/
00672 
00673 UINT32 NodeSimpleShape::GetNodeSize() const 
00674 {     
00675     return (sizeof(NodeSimpleShape)); 
00676 }  
00677 
00678 
00679 
00680 /********************************************************************************************
00681 
00682 >   BOOL NodeSimpleShape::OnClick( DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods,
00683                         Spread* pSpread )
00684 
00685     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00686     Created:    2/6/94
00687     Inputs:     PointerPos - The Location of the mouse pointer at the time of the click
00688                 Click - The type of click received (single, double, drag etc)
00689                 ClickMods - The modifiers to the click (eg shift, control etc )
00690     Returns:    BOOL - TRUE if the node claims the click as its own and FALSE if it is
00691                 not interested in the click
00692     Purpose:    Allows the Node to respond to clicks by selecting its blobs or starting
00693                 drags etc.
00694                 This functions should be overridden in the all the NodeRenderableInk classes
00695                 so that this version never gets called. Eg the NodePath class might claim
00696                 the click if it happened over one of its unselected blobs.
00697 
00698 ********************************************************************************************/
00699 
00700 BOOL NodeSimpleShape::OnClick( DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods,
00701                         Spread* pSpread )
00702 {
00703     PORTNOTETRACE("other","NodeSimpleShape::OnClick - do nothing");
00704 
00705 #if !defined(EXCLUDE_FROM_RALPH)
00706     // we only handle the click if we can confirm that object blobs are being displayed.
00707     BlobManager* pBlobMgr = GetApplication()->GetBlobManager();
00708     if (pBlobMgr == NULL)
00709         return FALSE;
00710     if (!pBlobMgr->GetCurrentInterest().Object)
00711         return FALSE;
00712 
00713     INT32 ClickCorner;
00714 
00715     if (IsNearControlHandle(PointerPos, &ClickCorner))
00716     {
00717         // The click was over a control point, so start the drag and tell it the opposite corner
00718         if (Click==CLICKTYPE_DRAG)
00719             HandleBlobDrag(Parallel[ClickCorner], pSpread, (ClickCorner+2)%4 ); 
00720             
00721         // we have used that click up, so tell the world
00722         return TRUE;
00723     }
00724 #endif
00725     // did not use the click
00726     return FALSE;
00727 }
00728 
00729 
00730 
00731 /********************************************************************************************
00732 
00733 >   BOOL NodeSimpleShape::IsNearControlHandle(DocCoord Coord, INT32* CoordNum)
00734 
00735     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00736     Created:    9/11/94
00737     Inputs:     Coord - The Coordinate that we want to test
00738     Outputs:    CoordNum - The number of the control point that the coord was close to.
00739                 This parameter is only changed it the function returns TRUE.
00740     Returns:    TRUE if the Coord was close to one of the control points, FALSE otherwise
00741     Purpose:    This function tests to see if the Coord passed in is close to any of the 
00742                 control points in the Ellipse. If it is, the number of the control point
00743                 is set in CoordNum and TRUE is returned. If not, the value of CoordNum
00744                 is left unchanged and FALSE is returned.
00745 
00746 ********************************************************************************************/
00747 
00748 BOOL NodeSimpleShape::IsNearControlHandle(DocCoord Coord, INT32* CoordNum)
00749 {
00750 #if !defined(EXCLUDE_FROM_RALPH)
00751     // Find the blob manager
00752     BlobManager* pBlobMgr = GetApplication()->GetBlobManager();
00753     if (pBlobMgr==NULL)
00754         return FALSE;
00755 
00756     // Find out about the size of a blob
00757     DocRect BlobRect;
00758     pBlobMgr->GetBlobRect(Coord, &BlobRect);
00759 
00760     // Check to see if it is near any of the blobs
00761     for (INT32 i=0; i<4; i++)
00762     {
00763         // Check for collision with the control points
00764         if (BlobRect.ContainsCoord(Parallel[i]))
00765         {
00766             // Tell them which control point it waas over
00767             *CoordNum = i;
00768 
00769             // we have used that click up, so tell the world
00770             return TRUE;
00771         }
00772     }
00773 #endif  
00774     // was not over any of the control points
00775     return FALSE;
00776 }
00777 
00778 
00779 /********************************************************************************************
00780 
00781 >   void NodeSimpleShape::HandleBlobDrag(DocCoord& PointerPos, Spread* pSpread, INT32 FixedCorner)
00782 
00783     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00784     Created:    2/6/94
00785     Inputs:     PointerPos - The position the mouse pointer clicked
00786                 pSpread - the spread that the click was on
00787                 FixedCorner - The corner of the parallelogram that will stay fixed during
00788                 the drag
00789     Purpose:    This is the base class version of this function, which does nothing. All the
00790                 work should be done in the derived classes. These should do as follows.
00791                 When a drag is started on one of the paths blobs this is called. It tries to
00792                 fire up an operation that will perform a drag of all the selected points, 
00793                 including all the EORing of the relavent parts of the curve. If it fails it
00794                 will inform the user and not bother.
00795 
00796 ********************************************************************************************/
00797 
00798 void NodeSimpleShape::HandleBlobDrag(DocCoord& PointerPos, Spread* pSpread, INT32 FixedCorner)
00799 {
00800     ENSURE( FALSE, "NodeSimpleShape::HandleBlobDrag() called. Derived class should have been used");
00801 }
00802 
00803 
00804 
00805 
00806 
00807 /********************************************************************************************
00808 
00809 >   virtual BOOL NodeSimpleShape::CanBecomeA(BecomeA* pBecomeA)
00810 
00811     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00812     Created:    29/4/94
00813     Inputs:     InkClass: The class of object
00814                 pNumObjects = ptr to place number of objects of type pClass that will be created (Note: can be NULL).
00815                               *pNumObects in undefined on entry
00816     Returns:    TRUE if the node, or any of its children can transmogrify themselves to become 
00817                 an InkClass object
00818     Purpose:    This function is used by the convert to shapes operation. It determines if 
00819                 the node or any of its children can convert themselves into an InkClass object. 
00820 
00821                 The number you put into pNumObjects (if it's not NULL) should exactly equal the total number
00822                 of pClass objects you create.  It should NOT contain any additional objects you may produce
00823                 such as group objects for containing the pClass object, or attributes.
00824 
00825                 Also, the entry value of *pNumObjects cannot be assumed to be 0.
00826 ********************************************************************************************/
00827 
00828 BOOL NodeSimpleShape::CanBecomeA(BecomeA* pBecomeA)
00829 {
00830     // The NodeSimpleShape can become a NodePath
00831     if (pBecomeA->BAPath())
00832     {
00833         pBecomeA->AddCount(1);
00834 
00835         return TRUE;
00836     }
00837 
00838     return FALSE;
00839 }
00840 
00841            
00842 /********************************************************************************************
00843 
00844 >   virtual BOOL NodeSimpleShape::DoBecomeA(CCRuntimeClass* InkClass, UndoableOperation* pOp) 
00845 
00846     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00847     Created:    29/4/94
00848     Inputs:     pBecomeA =  ptr to a class that contains all the info needed to become a new
00849                             type of node.
00850     Outputs:    -
00851     Returns:    TRUE if the object has been transformed, FALSE if we run out of memory
00852 
00853     Purpose:    Transforms the object into another type of object. 
00854                 Note: changed 7/10/94 by MarkN to take the pBecomeA param, so that more data could be passed
00855                 to these functions in the future without causing massive rebuilds due to the editing of
00856                 node.h
00857     SeeAlso:    NodeSimpleShape::CanBecomeA
00858 
00859 ********************************************************************************************/
00860 
00861 BOOL NodeSimpleShape::DoBecomeA(BecomeA* pBecomeA)
00862 {
00863     // Check for a NULL entry param
00864     ERROR2IF_PF(pBecomeA == NULL,FALSE,("pBecomeA is NULL"));
00865 
00866     // This lump checks that the Reason is one that we understand
00867     // It also makes sure that we don't have a NULL UndoOp ptr
00868     BOOL ValidReason = (pBecomeA->GetReason() == BECOMEA_REPLACE || pBecomeA->GetReason() == BECOMEA_PASSBACK);
00869     ERROR2IF_PF(!ValidReason,FALSE,("Unkown BecomeA reason %d",pBecomeA->GetReason()));
00870 
00871     // pBecomeA->Reason is one that we understand.
00872 
00873     BOOL        Success = TRUE;         // Our success flag (Important that this defaults to TRUE)
00874     NodePath*   pNewNodePath = NULL;    // Ptr to a new NodePath, if we get to make one.
00875 
00876     if (pBecomeA->BAPath())
00877     {
00878         // We need to create a new NodePath, no matter what the reason.
00879         
00880         // Allocate a new NodePath node
00881         ALLOC_WITH_FAIL(pNewNodePath, (new NodePath), pBecomeA->GetUndoOp()); 
00882         Success = (pNewNodePath != NULL);
00883 
00884         // Initialise the path
00885         if (Success) CALL_WITH_FAIL(pNewNodePath->InkPath.Initialise(InkPath.GetNumCoords(),12), pBecomeA->GetUndoOp(), Success);
00886         if (Success) CALL_WITH_FAIL(pNewNodePath->InkPath.CopyPathDataFrom(&InkPath), pBecomeA->GetUndoOp(), Success);
00887 
00888         // If Success is TRUE, then we now have a new NodePath object that contains this shape's path
00889 
00890         if (Success)
00891         {
00892             switch (pBecomeA->GetReason())
00893             {
00894                 case BECOMEA_REPLACE :
00895                 {
00896                     // It's a BECOMEA_REPLACE, so replace this node with the new NodePath in an undoable way
00897 
00898                     // Can't do it in an undoable way without an Undo Op
00899                     ERROR2IF_PF(pBecomeA->GetUndoOp() == NULL,FALSE,("GetUndoOp() returned NULL"));
00900 
00901                     // Firstly, hide this node
00902                     NodeHidden* pNodeHidden; 
00903                     Success = pBecomeA->GetUndoOp()->DoHideNode(this, TRUE, &pNodeHidden);
00904 
00905                     if (Success)
00906                     {
00907                         // Insert the new NodePath into the tree, next to the hidden node
00908                         pNewNodePath->AttachNode(pNodeHidden,NEXT);
00909 
00910                         // Copy the node's attributes
00911                         CALL_WITH_FAIL(CopyChildrenTo(pNewNodePath), pBecomeA->GetUndoOp(), Success); 
00912 
00913                         if (Success)
00914                         {
00915                             // Set the bounds  
00916                             pNewNodePath->InvalidateBoundingRect();
00917                             pNewNodePath->SetSelected(IsSelected());
00918 
00919                             // Create a hide node action to hide the node when we undo 
00920                             HideNodeAction* UndoHideNodeAction;     
00921                             Success = (HideNodeAction::Init(pBecomeA->GetUndoOp(),
00922                                                      pBecomeA->GetUndoOp()->GetUndoActionList(),
00923                                                      pNewNodePath, 
00924                                                      TRUE,       // Include subtree size 
00925                                                      ( Action**)(&UndoHideNodeAction))
00926                                                      != AC_FAIL);
00927                         }
00928                     }
00929 
00930                     if (Success)
00931                         pBecomeA->PassBack(pNewNodePath, this);
00932                 }
00933                 break;
00934 
00935                 case BECOMEA_PASSBACK :
00936                     Success = pBecomeA->PassBack(pNewNodePath,this);
00937                 break;
00938 
00939                 default:
00940                     break;
00941             }
00942         }
00943     }
00944 
00945     if (!Success)
00946     {
00947         if (pNewNodePath != NULL)
00948         {
00949             // Delete all the NodePath's children (if it has any) and unlink it from the tree (if it's linked)
00950             // This is all done by CascadeDelete()
00951             pNewNodePath->CascadeDelete(); 
00952             delete pNewNodePath;
00953             pNewNodePath = NULL;
00954         }
00955     }
00956 
00957     return Success;
00958 }
00959 
00960 
00961 
00962 /***********************************************************************************************
00963 
00964 > BOOL NodeSimpleShape::Snap(DocCoord* pDocCoord)
00965 
00966     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00967     Created:    20/9/94
00968     Inputs:     pDocCoord   = a coord in Spread coords
00969     Outputs:    
00970     Returns:    TRUE    - the DocCoord has been snapped to the path.
00971                 FALSE   - the DocCoord has not been processed.
00972                                                          
00973     Purpose:    Snaps to given coord to the nearest point on the path.  If it is not appropriate to snap
00974                 the coord to the path (at the moment this means the coord is too far awawy), then FALSE is returned.
00975     Errors:        
00976     Scope:      public
00977            
00978 **********************************************************************************************/
00979 
00980 BOOL NodeSimpleShape::Snap(DocCoord* pDocCoord)
00981 {
00982 #if !defined(EXCLUDE_FROM_RALPH)
00983     BOOL Snapped = FALSE;
00984 
00985     MILLIPOINT SnapDist    = CSnap::GetSnapDist();
00986     MILLIPOINT SqrSnapDist = SnapDist*SnapDist;
00987 
00988     INT32 NearEl;
00989     double mu;
00990     double SqrDist = InkPath.SqrDistanceToPoint(*pDocCoord,&NearEl,&mu);
00991 
00992     if (SqrDist <= SqrSnapDist)
00993     {
00994         *pDocCoord = InkPath.ClosestPointTo(mu,NearEl);
00995         Snapped = TRUE;
00996     }
00997 
00998     return (Snapped);
00999 #else
01000     return FALSE;
01001 #endif
01002 }
01003 
01004 /***********************************************************************************************
01005 
01006 > BOOL NodeSimpleShape::Snap(DocRect* pDocRect,const DocCoord& PrevCoord,const DocCoord& CurCoord)
01007 
01008     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01009     Created:    21/9/94
01010     Inputs:     pDocCoord   - the rectangle to snap
01011                 StartDrag   - Start coord of drag
01012                 EndDrag     - End coord of drag
01013     Outputs:    
01014     Returns:    TRUE    - the DocRect been snapped to the grid.
01015                 FALSE   - the DocRect has not been processed.
01016                                                          
01017     Purpose:    Snaps the given rect to the nearest position on the grid, preserving its width
01018                 and height.
01019                 The coords of the rect used for the snapping are determined by the PrevCoord and
01020                 CurCoord coords supplied.  This is done to allow the user to control how a
01021                 selection rectangle is snapped to the grid by the direction of his/her last mouse 
01022                 movement.
01023                 To force the bottom left hand corner of the rect to be snapped, 
01024                 supply PrevCoord=(0,0) and CurCoord(-1,-1).
01025     Scope:      public
01026            
01027 **********************************************************************************************/
01028 
01029 BOOL NodeSimpleShape::Snap(DocRect* pDocRect,const DocCoord& PrevCoord,const DocCoord& CurCoord)
01030 {
01031 #if !defined(EXCLUDE_FROM_RALPH)
01032     TRACEUSER( "MarkN", _T("NodeSimpleShape::Snap(DocRect)\n") );
01033 #endif
01034     return FALSE;
01035 }
01036 
01037 
01038 
01039 /********************************************************************************************
01040 
01041 >   BOOL NodeSimpleShape::SnapToCoords(DocCoord* pDocCoord)
01042 
01043     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
01044     Created:    21/11/94
01045     Inputs:     pDocCoord - The Coord to try and snap
01046     Outputs:    pDocCoord - The snapped verison of the coord
01047     Returns:    TRUE if the input coord was snapped, FALSE if not
01048     Purpose:    This function tries to magnetically snap the supplied coord to the shape.
01049                 This version of the function tries to snap to coords at the centre of the
01050                 shape and in the middle of each of the edges.
01051     SeeAlso:    NodeRenderableBounded::SnapToCoords
01052 
01053 ********************************************************************************************/
01054 
01055 BOOL NodeSimpleShape::SnapToCoords(DocCoord* pDocCoord)
01056 {
01057 #if !defined(EXCLUDE_FROM_RALPH)
01058     // Work out the coords to snap to
01059     DocCoord TestPoint;
01060 
01061     // Snap to the Centre of the Shape
01062     TestPoint.x = (Parallel[0].x + Parallel[2].x) / 2;
01063     TestPoint.y = (Parallel[0].y + Parallel[2].y) / 2;
01064     
01065     // Test to see if the points are close together, and update pDocCoord if they are
01066     if (IsMagneticallyClose(&TestPoint, pDocCoord))
01067         return TRUE;
01068 
01069     // Try and snap to the middle of each of the edges
01070     for (INT32 i=0; i<4; i++)
01071     {
01072         // Find test coord
01073         INT32 NextPoint = (i+1) % 4;
01074         TestPoint.x = (Parallel[i].x + Parallel[NextPoint].x) / 2;
01075         TestPoint.y = (Parallel[i].y + Parallel[NextPoint].y) / 2;
01076         
01077         // Test to see if the points are close together, and update pDocCoord if they are
01078         if (IsMagneticallyClose(&TestPoint, pDocCoord))
01079             return TRUE;
01080     }
01081 #endif
01082     // Did not snap to anything.
01083     return FALSE;
01084 }
01085 
01086 
01087 
01088 /********************************************************************************************
01089 
01090 >   double NodeSimpleShape::GetRotationAngle()
01091 
01092     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
01093     Created:    24/1/95
01094     Inputs:     -
01095     Outputs:    -
01096     Returns:    The rotation angle of this simple shape  NodeRenderableInk
01097     Purpose:    Returns the current angle of rotation of the simple shape.  This is calculated
01098                 as the angle from the midpoint of the upper paralleogram line to the positive
01099                 x-axis.
01100     SeeAlso:    NodeRenderableBounded::GetRotationAngle
01101 
01102 ********************************************************************************************/
01103 
01104 double NodeSimpleShape::GetRotationAngle()
01105 {
01106     DocCoord MidPoint((Parallel[0].x + Parallel[1].x)/2, (Parallel[0].y + Parallel[1].y)/2);
01107 
01108     DocRect Bounds(Parallel[0],Parallel[0]);
01109     Bounds.IncludePoint(Parallel[1]);
01110     Bounds.IncludePoint(Parallel[2]);
01111     Bounds.IncludePoint(Parallel[3]);
01112     DocCoord Centre((Bounds.LowCorner().x+Bounds.HighCorner().x)/2,
01113                                             (Bounds.LowCorner().y+Bounds.HighCorner().y)/2);
01114 
01115     DocCoord Offset = MidPoint - Centre;
01116 
01117     double Angle = atan2((double)Offset.y, (double)Offset.x);
01118     if (Angle == HUGE_VAL)
01119         Angle = 0.0;
01120 
01121     return Angle;
01122 }
01123 
01124 
01125 
01126 /********************************************************************************************
01127 
01128 >   DocRect NodeSimpleShape::ValidateExtend(const ExtendParams& ExtParams)
01129 
01130     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
01131     Created:    25/11/1999
01132     Inputs:     ExtParams       parameters describing the extension.
01133     Outputs:    
01134     Returns:    TRUE if this simple shape can be validly extended,
01135                 FALSE otherwise.
01136     Purpose:    Tests to see whether this shape's centre-point is positioned so as to make
01137                 an extend operation irreversible.
01138     Errors:     
01139     See also:   
01140 
01141 ********************************************************************************************/
01142 DocRect NodeSimpleShape::ValidateExtend(const ExtendParams& ExtParams)
01143 {
01144     DocCoord doccArray[1] = { FindExtendCentre() };
01145     DocRect drMinExtend = Extender::ValidateControlPoints(1, doccArray, ExtParams);
01146 
01147     // if we didn't invalidate the extension, we must call the base class
01148     // implementation, which will validate our children.
01149     if (drMinExtend.lo.x == INT32_MAX &&
01150         drMinExtend.lo.y == INT32_MAX &&
01151         drMinExtend.hi.x == INT32_MAX &&
01152         drMinExtend.hi.y == INT32_MAX)
01153         drMinExtend = Node::ValidateExtend(ExtParams);
01154 
01155     return drMinExtend;
01156 }
01157 
01158 
01159 
01160 /********************************************************************************************
01161 
01162 >   void NodeSimpleShape::Extend(const ExtendParams& ExtParams)
01163 
01164     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
01165     Created:    25/11/1999
01166     Inputs:     ExtParams       parameters describing the extension.
01167     Outputs:    this NodeSimpleShape will be extended in accordance with ExtParams.
01168     Returns:    
01169     Purpose:    Perform an Extend operation on this shape. Behaviour is as follows:
01170 
01171                 * the shape extends separately along each axis.
01172                 * if the shape is asked to stretch, it scales along the corresponding axes.
01173                 * if the shape is asked to extend, it is translated as a whole, as described
01174                                                                                 by ExtParams.
01175     Errors:     
01176     See also:   class Extender
01177 
01178 ********************************************************************************************/
01179 void NodeSimpleShape::Extend(const ExtendParams& ExtParams)
01180 {
01181     // do the extension operations on ourself.
01182     TransformStretchObject(ExtParams);
01183     TransformTranslateObject(ExtParams);
01184 
01185     // do the base-class implementation to extend our children.
01186     Node::Extend(ExtParams);
01187 }

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