moldtool.cpp

Go to the documentation of this file.
00001 // $Id: moldtool.cpp 1282 2006-06-09 09:46:49Z 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 // Implementation of the mould tool
00099 
00100 /*
00101 */
00102 
00103 #include "camtypes.h"
00104 //#include "resource.h"
00105 #include "oilfiles.h"
00106 #include "csrstack.h"
00107 //#include "viewrc.h"
00108 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 //#include "markn.h"
00111 //#include "mike.h"
00112 #include "moldtool.h"
00113 #include "osrndrgn.h"
00114 #include "nodeshap.h"
00115 //#include "opdesc.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00116 //#include "paths.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00117 #include "moldpers.h"
00118 #include "moldenv.h"
00119 #include "moldedit.h"
00120 //#include "mouldbar.h"
00121 #include "progress.h"
00122 #include "blobs.h"
00123 #include "ndmldpth.h"
00124 #include "clipint.h"
00125 #include "layer.h"
00126 #include "objchge.h"
00127 #include "keypress.h"
00128 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00129 #include "attrmap.h"
00130 #include "ophist.h"
00131 
00132 //#include "will2.h"
00133 
00134 //class NodeRenderableInk;
00135 
00136 DECLARE_SOURCE( "$Revision: 1282 $" );
00137 
00138 CC_IMPLEMENT_MEMDUMP( MouldTool,Tool_v1 )
00139 CC_IMPLEMENT_MEMDUMP( CreateMouldParam, OpParam )
00140 CC_IMPLEMENT_DYNCREATE( MouldInfoBarOp,InformationBarOp )
00141 CC_IMPLEMENT_DYNCREATE( OpCreateNewMould, OpMouldLibSel )
00142 CC_IMPLEMENT_DYNCREATE( OpRectangularEnvelope, OpMouldLibSel )
00143 CC_IMPLEMENT_DYNCREATE( OpRectangularPerspective, OpMouldLibSel )
00144 CC_IMPLEMENT_DYNCREATE( OpRemoveMould, OpMouldLibSel )
00145 CC_IMPLEMENT_DYNCREATE( OpCopyMouldShape, OpMouldLibSel )
00146 CC_IMPLEMENT_DYNCREATE( OpPasteMouldShape, OpMouldLibSel )
00147 CC_IMPLEMENT_DYNCREATE( OpPasteEnvelope, OpPasteMouldShape )
00148 CC_IMPLEMENT_DYNCREATE( OpPastePerspective, OpPasteMouldShape )
00149 CC_IMPLEMENT_DYNCREATE( OpToggleMouldGrid, Operation )
00150 CC_IMPLEMENT_DYNCREATE( OpDetachMould, UndoableOperation )
00151 CC_IMPLEMENT_DYNCREATE( OpRotateMould, OpMouldLib )
00152 CC_IMPLEMENT_MEMDUMP( MouldBecomeA, BecomeA )
00153 
00154 // Must come after the last CC_IMPLEMENT.. macro
00155 #define new CAM_DEBUG_NEW     
00156 
00157 // These are still char* while we wait for resource technology to be developed for modules
00158 TCHAR* MouldTool::FamilyName    = _T("Mould Tools");
00159 TCHAR* MouldTool::ToolName  = _T("Mould Tool");
00160 TCHAR* MouldTool::Purpose   = _T("Mould manipulation");
00161 TCHAR* MouldTool::Author    = _T("Mike");
00162 
00163 // Init those other useful static vars
00164 BOOL            MouldTool::CurrentTool          = FALSE;
00165 MouldInfoBarOp* MouldTool::pMouldInfoBarOp      = NULL;
00166 
00167 
00168 
00169 /********************************************************************************************
00170 
00171 >   MouldTool::MouldTool()
00172 
00173     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00174     Created:    30/11/94
00175     Purpose:    Default Constructor.
00176                 Other initialisation is done in MouldTool::Init which is called by the Tool Manager
00177     SeeAlso:    MouldTool::Init
00178 
00179 ********************************************************************************************/
00180 
00181 MouldTool::MouldTool()
00182 {
00183     pcCurrentCursor = NULL;
00184 }
00185 
00186 /********************************************************************************************
00187 
00188 >   MouldTool::~MouldTool()
00189 
00190     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00191     Created:    30/11/94
00192     Purpose:    Destructor (Virtual). Does nothing.
00193 
00194 ********************************************************************************************/
00195 
00196 MouldTool::~MouldTool()
00197 {
00198 }
00199 
00200 
00201 /********************************************************************************************
00202 
00203 >   BOOL MouldTool::Init( INT32 Pass )
00204 
00205     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00206     Created:    30/11/94
00207     Returns:    FALSE if it does not want to be created, TRUE otherwise
00208     Purpose:    Used to check if the Tool was properly constructed
00209     SeeAlso:    MouldTool::MouldTool
00210 
00211 ********************************************************************************************/
00212 
00213 BOOL MouldTool::Init()
00214 {
00215     // Declare all your ops here and only succeed if all declarations succeed
00216 
00217     BOOL ok = TRUE;
00218 
00219     // register our mould tool operations
00220             ok = OpCreateNewMould::Init();
00221     if (ok) ok = OpRemoveMould::Init(); 
00222     if (ok) ok = OpCopyMouldShape::Init();
00223     if (ok) ok = OpPasteEnvelope::Init();
00224     if (ok) ok = OpPastePerspective::Init();
00225     if (ok) ok = OpToggleMouldGrid::Init();
00226     if (ok) ok = OpDetachMould::Init();
00227     if (ok) ok = OpRotateMould::Init();
00228     if (ok) ok = OpRectangularEnvelope::Init();
00229     if (ok) ok = OpRectangularPerspective::Init();
00230 
00231 #if 0
00232     if (ok)
00233     {
00234         // This section reads in the infobar definition and creates an instance of
00235         // MouldInfoBarOp.  Also pMouldInfoBarOp, the ptr to the tool's infobar, is set up
00236         // after the infobar is successfully read and created.
00237         CCResTextFile       file;               // Resource File
00238         MouldInfoBarOpCreate BarCreate;         // Object that creates MouldInfoBarOp objects
00239 
00240                 ok = file.open(_R(IDM_MOULDTOOL_BAR), _R(IDT_INFO_BAR_RES));    // Open resource
00241         if (ok) ok = DialogBarOp::ReadBarsFromFile(file,BarCreate);     // Read and create info bar
00242         if (ok) file.close();                                           // Close resource
00243 
00244         ENSURE(ok,"Unable to load mouldbar.ini from resource\n"); 
00245     }
00246 
00247     if (ok)
00248     {
00249         // Info bar now exists.  Now get a pointer to it
00250         String_32 str = String_32(_R(IDS_MOLDTOOL_INFOBARNAME));
00251         DialogBarOp* pDialogBarOp = DialogBarOp::FindDialogBarOp(str);
00252 
00253 
00254                 ok = (pDialogBarOp != NULL);
00255         if (ok) ok = pDialogBarOp->IsKindOf(CC_RUNTIME_CLASS(MouldInfoBarOp));
00256         if (ok) pMouldInfoBarOp = (MouldInfoBarOp*)pDialogBarOp;
00257         if (ok) pMouldInfoBarOp->SetTool(this);             // Set a pointer from the op to this tool
00258 
00259         ENSURE(ok,"Error finding the mould tool info bar");
00260     }
00261 #endif
00262 
00263     if (ok)
00264     {
00265         pMouldInfoBarOp = new MouldInfoBarOp();
00266         ok = (pMouldInfoBarOp != NULL);
00267 
00268         if (ok) pMouldInfoBarOp->SetTool(this);             // Set a pointer from the op to this tool
00269     }
00270 
00271     return (ok);
00272 }
00273 
00274 
00275 /********************************************************************************************
00276 
00277 >   void MouldTool::Describe(void *InfoPtr)
00278 
00279     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00280     Created:    30/11/94
00281     Inputs:     InfoPtr -   A pointer to a tool info block. It is passed cast to void* as
00282                             the version of the tool is unknown at this point. Later versions 
00283                             of the Tool class may have more items in this block, that this 
00284                             tool will not use
00285     Outputs:    InfoPtr -   The structure pointed to by InfoPtr will have had all the info
00286                             that this version of the Tool knows about
00287     Purpose:    Allows the tool manager to extract information about the tool
00288 
00289 ********************************************************************************************/
00290 
00291 void MouldTool::Describe(void *InfoPtr)
00292 {
00293     // Cast structure into the latest one we understand.
00294     ToolInfo_v1 *Info = (ToolInfo_v1 *) InfoPtr;
00295 
00296     Info->InfoVersion = 1;
00297     
00298     Info->InterfaceVersion = GetToolInterfaceVersion();  // You should always have this line.
00299         
00300     // These are all arbitrary at present.
00301     Info->Version = 1;
00302     Info->ID      = GetID();
00303     Info->TextID  = _R(IDS_MOULD_TOOL);
00304 
00305     Info->Family  = FamilyName;
00306     Info->Name    = ToolName;
00307     Info->Purpose = Purpose;
00308     Info->Author  = Author;
00309 
00310     Info->BubbleID = _R(IDBBL_MOULD_TOOL);
00311 }
00312 
00313 /********************************************************************************************
00314 
00315 >   virtual void MouldTool::SelectChange(BOOL isSelected)
00316 
00317     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00318     Created:    30/11/94
00319     Inputs:     isSelected  - TRUE  = tool has been selected
00320                             - FALSE = tool has been deselected
00321     Outputs:    -
00322     Returns:    -
00323     Purpose:    Starts up and closes down the mould tool
00324     Errors:     Debug warning if creating the cursor fails.
00325     SeeAlso:    -
00326 
00327 ********************************************************************************************/
00328 
00329 void MouldTool::SelectChange(BOOL isSelected)
00330 {
00331     if (isSelected)
00332     {
00333         // This tool has just been selected.  Create an appropriate cursor, and push it
00334         // onto the top of the cursor stack so it'll appear when the pointer moves into
00335         // our window.
00336 
00337         if (!CreateCursors()) return;
00338 
00339         // Push cursor but don't display now
00340         CurrentCursorID = CursorStack::GPush(pcNormalMouldCursor, FALSE);       
00341         pcCurrentCursor = pcNormalMouldCursor;
00342 
00343         // This tool is now the current one
00344         MouldTool::CurrentTool = TRUE;
00345 
00346         // Create and display the tool's info bar
00347         if (pMouldInfoBarOp != NULL)
00348             pMouldInfoBarOp->Create();
00349 
00350         // Which blobs do I want displayed
00351         BlobManager* BlobMgr = GetApplication()->GetBlobManager();
00352         if (BlobMgr != NULL)
00353         {
00354             // Decide which blobs we will display
00355             BlobStyle MyBlobs;
00356             MyBlobs.Object = TRUE;
00357 
00358             // Tell the blob manager
00359             BlobMgr->ToolInterest(MyBlobs);
00360         }
00361 
00362 
00363     }
00364     else
00365     {
00366         // Deselection - destroy the tool's cursors, if they exist.
00367         if (pcCurrentCursor != NULL)
00368         {
00369             CursorStack::GPop(CurrentCursorID);
00370             pcCurrentCursor = NULL;
00371             CurrentCursorID = 0;
00372         }
00373         DestroyCursors();
00374 
00375         // Remove the info bar from view by deleting the actual underlying window
00376         if (pMouldInfoBarOp != NULL)
00377             pMouldInfoBarOp->Delete();
00378 
00379         // ensure any tool object blobs are removed.
00380         BlobManager* BlobMgr = GetApplication()->GetBlobManager();
00381         if (BlobMgr != NULL)
00382         {
00383             BlobStyle bsRemoves;
00384             bsRemoves.ToolObject = TRUE;
00385             BlobMgr->RemoveInterest(bsRemoves);
00386         }
00387 
00388         // We're no longer the current tool
00389         MouldTool::CurrentTool = FALSE;
00390     }
00391 }
00392 
00393 /********************************************************************************************
00394 
00395 >   BOOL MouldTool::CreateCursors()
00396 
00397     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00398     Created:    30/11/94
00399     Inputs:     -
00400     Outputs:    -
00401     Returns:    TRUE if all the mould tool cursors have been successfully created
00402     Purpose:    Creates all the mould tool cursors
00403     SeeAlso:    -
00404 
00405 ********************************************************************************************/
00406 
00407 BOOL MouldTool::CreateCursors()
00408 {
00409     // This tool has just been selected.  Create the cursors.
00410     pcNormalMouldCursor = new Cursor(this, _R(IDC_MOULDDEFAULTCURSOR)); // _R(IDCSR_SEL_NORMAL)
00411         pcTransCoordCursor  = new Cursor(this, _R(IDC_MOVEMOULDCURSOR));
00412     pcTransOriginCursor = new Cursor(this, _R(IDCSR_SEL_GRADPOINT));
00413 
00414     if ( pcNormalMouldCursor==NULL ) goto bincursors;
00415     if ( pcTransCoordCursor==NULL) goto bincursors;
00416     if ( pcTransOriginCursor==NULL ) goto bincursors;
00417         
00418     if (!pcNormalMouldCursor->IsValid()) goto bincursors;
00419     if (!pcTransCoordCursor->IsValid()) goto bincursors;
00420     if (!pcTransOriginCursor->IsValid()) goto bincursors;
00421 
00422     return TRUE;
00423 
00424 bincursors:
00425     DestroyCursors();
00426     return FALSE;
00427 }
00428 
00429 /********************************************************************************************
00430 
00431 >   void MouldTool::DestroyCursors()
00432 
00433     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00434     Created:    30/11/94
00435     Inputs:     -
00436     Outputs:    -
00437     Returns:    -
00438     Purpose:    Destroys all the mould tool cursors
00439     SeeAlso:    -
00440 
00441 ********************************************************************************************/
00442 
00443 void MouldTool::DestroyCursors()
00444 {
00445     if (pcNormalMouldCursor != NULL) delete pcNormalMouldCursor;
00446     if (pcTransCoordCursor != NULL) delete pcTransCoordCursor;
00447     if (pcTransOriginCursor != NULL) delete pcTransOriginCursor;
00448 
00449     pcNormalMouldCursor = NULL;
00450     pcTransCoordCursor = NULL;
00451     pcTransOriginCursor = NULL;
00452 }
00453 
00454 
00455 
00456 /********************************************************************************************
00457 
00458 >   void MouldTool::ChooseCursor(INT32 ctype)
00459 
00460     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00461     Created:    07/02/95
00462     Inputs:     Mould cursor ID of the cursor you want to flip to
00463     Outputs:    -
00464     Returns:    -
00465     Purpose:    Returns a pointer to the correct cursor given a mould cursor type
00466 
00467 ********************************************************************************************/
00468 
00469 Cursor* MouldTool::ChooseCursor(INT32 ctype)
00470 {
00471     switch (ctype)
00472     {
00473         case 1:
00474             return pcNormalMouldCursor;
00475             break;
00476         case 2:
00477             return pcTransOriginCursor;
00478             break;
00479         case 3:
00480             return pcTransCoordCursor;
00481             break;
00482     }
00483     return pcNormalMouldCursor;
00484 }
00485 
00486 
00487 /********************************************************************************************
00488 
00489 >   void MouldTool::ChangeCursor(Cursor* cursor)
00490 
00491     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00492     Created:    30/11/94
00493     Inputs:     ID of the cursor you want to flip to
00494     Outputs:    -
00495     Returns:    -
00496     Purpose:    Changes to the specified cursor. Will only change the cursor if it isn't 
00497                 already this cursor, so it doesn't flicker.
00498     Errors:     can fail if the cursor cannot be created - the cursor code will fail.
00499     SeeAlso:    -
00500 
00501 ********************************************************************************************/
00502 
00503 void MouldTool::ChangeCursor(Cursor* cursor)
00504 {
00505     // only change if this cursor is different from the current cursor
00506     if (cursor != pcCurrentCursor)
00507     {
00508         // set this cursor as the current cursor and immediately display it
00509         CursorStack::GSetTop(cursor, CurrentCursorID);
00510         // remember this is our current cursor
00511         pcCurrentCursor = cursor;
00512     }
00513 }
00514 
00515 
00516 
00517 
00518 /********************************************************************************************
00519 
00520 >   void MouldTool::OnClick( DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods,
00521                         Spread* pSpread )
00522 
00523     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00524     Created:    30/11/94
00525     Inputs:     PointerPos  -   The DocCoord of the point where the mouse button was clicked
00526                 Click       -   Describes the type of click that was detected. 
00527                 ClickMods   -   Indicates which buttons caused the click and which modifers were
00528                                 pressed at the same time
00529                 pSpread     -   The spread in which the click happened
00530     Returns:    -
00531     Purpose:    To handle a Mouse Click event for the Mould Tool.
00532     SeeAlso:    Tool::MouseClick; ClickType; ClickModifiers
00533 
00534 ********************************************************************************************/
00535 
00536 void MouldTool::OnClick( DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods,
00537                         Spread* pSpread )
00538 {
00539     if (ClickMods.Menu) return;                         // Don't do anything if the user clicked the Menu button
00540 
00541     // Now scan through the selected paths, and see if we've clicked on any moulds
00542     DocView* pDocView = DocView::GetCurrent();
00543     ENSURE( pDocView != NULL, "MouldTool::BroadcastClick() Can't find current DocView");
00544     if (pDocView==NULL)
00545         return;
00546 
00547     // Find the selected range of objects
00548     SelRange* Selected = GetApplication()->FindSelection();
00549     Node* pNode = Selected->FindFirst();
00550     Node* pNext;
00551     BOOL claimed = FALSE;
00552 
00553     while ((pNode != NULL) && (!claimed))
00554     {
00555         // Find the next selected node
00556         pNext = Selected->FindNext(pNode);
00557         if (pNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodeMould))
00558             claimed = ((NodeMould*)pNode)->OnClick(PointerPos, Click, ClickMods, pSpread);
00559         pNode = pNext;
00560     }
00561 
00562     if (!claimed)
00563     {
00564         // call the base class ....
00565 
00566         DragTool::OnClick (PointerPos, Click, ClickMods, pSpread);
00567     }
00568 }
00569 
00570 
00571 
00572 /********************************************************************************************
00573 
00574 >   void MouldTool::OnMouseMove( DocCoord PointerPos,Spread* pSpread, ClickModifiers ClickMod )
00575 
00576     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00577     Created:    30/11/94
00578     Inputs:     PointerPos  -   The DocCoord of the point where the mouse has moved to
00579                 pSpread     -   The spread in which the move occurred
00580                 ClickMods   -   The state of the various modifiers at the time of the mouse move
00581     Returns:    TRUE if it handled the Click, FALSE otherwise
00582     Purpose:    To handle a Mouse Move event for the Mould Tool.
00583     SeeAlso:    Tool::MouseClick; ClickType; ClickModifiers
00584 
00585 ********************************************************************************************/
00586 
00587 void MouldTool::OnMouseMove(DocCoord PointerPos,Spread* pSpread,ClickModifiers ClickMods)
00588 {
00589     // Now scan through the selected moulds, and pass the move on
00590     DocView* pDocView = DocView::GetSelected();
00591     ENSURE( pDocView != NULL, "MouldTool::OnMouseMove() Can't find selected DocView");
00592     if (pDocView==NULL)
00593         return;
00594 
00595     INT32 ctype,msgres;
00596 
00597     BOOL claimed = DetermineClickEffect(PointerPos, pSpread, ClickMods, &ctype, &msgres);
00598 
00599     if (!claimed)
00600     {
00601         ctype=1;
00602         msgres=1;
00603     }
00604 
00605     // update the cursor if someones changed it
00606     Cursor* pCursor = ChooseCursor(ctype);
00607     if (pCursor!=NULL)
00608         ChangeCursor(pCursor);
00609 
00610     String_256 StatusMsg("");
00611     GenerateStatusLineText(msgres, &StatusMsg);
00612     GetApplication()->UpdateStatusBarText(&StatusMsg);
00613 }
00614 
00615 
00616 /**************************************************************************************************************
00617 
00618 > BOOL MouldTool::DetermineClickEffect(DocCoord PointerPos, Spread* pSpread,ClickModifiers ClickMods,  INT32* ctype, INT32* msgres)
00619 
00620     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00621     Created:    07/02/95
00622     Inputs:     PointerPos is the mouse position
00623                 pSpread is a pointer to the spread containing the mouse position
00624     Outputs:    ctype  = an INT32 value indicating what resource cursor to use.
00625                 msgres = an INT32 value indicating what resource message to use.
00626     Returns:    TRUE if
00627     Purpose:    Used when single clicking. This routine determines what effect a click will have.
00628                 In this tool, clicking will add a segment to the end of a line, adjust the last element of
00629                 a path or start a new path entirely.
00630 
00631 ***************************************************************************************************************/
00632 
00633 BOOL MouldTool::DetermineClickEffect(DocCoord PointerPos,Spread* pSpread,ClickModifiers ClickMods, INT32* ctype, INT32* msgres)
00634 {
00635     // Find the selected range of objects
00636     SelRange* Selected = GetApplication()->FindSelection();
00637     Node* pNode = Selected->FindFirst();
00638     Node* pNext;
00639     BOOL claimed = FALSE;
00640 
00641     // Set up a default value first
00642     (*msgres)=0;
00643         
00644     while ((pNode != NULL) && (!claimed))
00645     {
00646         // Find the next selected node
00647         pNext = Selected->FindNext(pNode);
00648         if (pNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodeMould))
00649             claimed = ((NodeMould*)pNode)->OnMouseMove(PointerPos, pSpread, ClickMods, ctype, msgres);
00650         pNode = pNext;
00651     }
00652 
00653     return claimed;
00654 }
00655 
00656 
00657 
00658 
00659 /********************************************************************************************
00660 
00661 >   virtual BOOL MouldTool::GetStatusLineText(String_256* ptext,
00662                                               Spread* pSpread,
00663                                               DocCoord DocPos, 
00664                                               ClickModifiers ClickMods)
00665 
00666     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00667     Created:    07/02/95
00668     Inputs:     pSpread   - pointer to spread under mouse (else NULL)
00669                 DocPos    - position of mouse in doc (in spread coords)
00670                 ClickMods - mouse click modifiers
00671     Outputs:    ptext - text for status line
00672     Returns:    TRUE if outputting valid text
00673     Purpose:    generate up-to-date text for the status line (called on idles)
00674     Errors:     ERROR1 if ptext is NULL
00675 
00676 ********************************************************************************************/
00677 
00678 BOOL MouldTool::GetStatusLineText(String_256* ptext, Spread* pSpread, DocCoord coord, ClickModifiers mods)
00679 {
00680     ERROR2IF(ptext==NULL,FALSE,"MouldTool::GetStatusLineText() passed a NULL text buffer");
00681 
00682     *ptext = "";
00683 
00684     // find what type of click we will generate
00685     INT32 ctype,msgres;
00686     DetermineClickEffect(coord, pSpread, mods, &ctype, &msgres);
00687     GenerateStatusLineText(msgres, ptext);
00688 
00689     return TRUE;
00690 }
00691 
00692 
00693 
00694 
00695 /********************************************************************************************
00696 
00697 >   void MouldTool::GenerateStatusLineText(INT32 msgres, String_256* pStatusMsg)
00698 
00699     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00700     Created:    07/02/95
00701     Inputs:     msgres      = identifier of message resource
00702                 pStatusMsg  = pointer to a 256 character text buffer
00703                 
00704     Outputs:    pStatusMsg  - holds a text string
00705     Returns:    -
00706     Purpose:    Loads up an appropriate help string into the text buffer
00707                 pointed to by pStatusMsg, using the msgres resource identifier
00708     Errors:     -
00709 
00710 ********************************************************************************************/
00711 
00712 void MouldTool::GenerateStatusLineText(INT32 msgres, String_256* pStatusMsg)
00713 {
00714     switch (msgres)
00715     {
00716         case 2:
00717             pStatusMsg->Load(_R(IDS_DRAGVPOINT), Tool::GetModuleID(GetID()));
00718             return;
00719             break;
00720         case 3:
00721             pStatusMsg->Load(_R(IDS_DRAGCOORD), Tool::GetModuleID(GetID()));
00722             return;
00723             break;
00724 
00725         default:
00726             pStatusMsg->Load(_R(IDS_MOULDDEFAULT), Tool::GetModuleID(GetID()));
00727             return;
00728             break;
00729     }
00730 }
00731 
00732 
00733 
00734 
00735 
00736 
00737 /********************************************************************************************
00738 
00739 >   void MouldTool::RenderToolBlobs(Spread* pSpread,DocRect* pDocRect)
00740 
00741     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00742     Created:    30/11/94
00743     Inputs:     pSpread  = ptr to a spread
00744                 pDocRect = ptr to DocRect of spread to render in
00745     Returns:    -
00746     Purpose:    Handles the RenderToolBlobs method.
00747                 Renders the tool's blobs into the current doc view.
00748     SeeAlso:    
00749 
00750 ********************************************************************************************/
00751 
00752 void MouldTool::RenderToolBlobs(Spread* pSpread,DocRect* pDocRect)
00753 {
00754     // Render into the selected doc view
00755     DocView* pDocView = DocView::GetSelected();
00756     if (pDocView != NULL)
00757     {
00758         // render you tool's blobs (if any) here
00759     }
00760 }
00761 
00762 
00763 /********************************************************************************************
00764 
00765 >   static void MouldTool::DisplayStatusBarHelp(UINT32 StatusID)
00766 
00767     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00768     Created:    30/11/94
00769     Inputs:     StatusID = ID of status help string
00770     Outputs:    -
00771     Returns:    -
00772     Purpose:    Displays the given status help string in the status bar
00773     SeeAlso:    -
00774 
00775 ********************************************************************************************/
00776 
00777 void MouldTool::DisplayStatusBarHelp(UINT32 StatusID)
00778 {
00779     String_256 StatusMsg("");
00780     StatusMsg.Load(StatusID);
00781     GetApplication()->UpdateStatusBarText(&StatusMsg);
00782 }
00783 
00784 
00785 /********************************************************************************************
00786 
00787 >   void MouldTool::CreateEnvelope(EnvelopeType EnvType)
00788 
00789     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00790     Created:    12/12/94
00791     Purpose:    Calls the CREATENEWMOULD operation with a default rectangular envelope
00792                 shape
00793 
00794 ********************************************************************************************/
00795 
00796 void MouldTool::CreateEnvelope(EnvelopeType EnvType)
00797 {
00798     // Make sure we have the operation ready
00799     OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_CREATENEWMOULD);
00800     if (pOpDesc)
00801     {
00802         // Create a manifold to use
00803         Path* pDefShape = new Path;
00804         if (pDefShape!=NULL)
00805         {
00806             BOOL LockAspect = FALSE;
00807 
00808             if (pDefShape->Initialise(12,12))
00809             {
00810                 BOOL ok = FALSE;
00811 
00812                 switch (EnvType)
00813                 {
00814                     case ENV_DEFAULT:
00815                         ok = EnvelopeShapes::Rectangular(pDefShape);
00816                         break;
00817 
00818                     case ENV_CIRCULAR:
00819                         ok = EnvelopeShapes::Circular(pDefShape);
00820                         LockAspect = TRUE;
00821                         break;
00822 
00823                     case ENV_ELLIPTICAL:
00824                         ok = EnvelopeShapes::Circular(pDefShape);
00825                         break;
00826 
00827                     case ENV_CONCAVE:
00828                         ok = EnvelopeShapes::Concave(pDefShape);
00829                         break;
00830 
00831                     case ENV_BANNER:
00832                         ok = EnvelopeShapes::Banner(pDefShape);
00833                         break;
00834                 }
00835 
00836                 if (ok)
00837                 {
00838                     // now build the correct mould parameter and invoke the operation               
00839                     CreateMouldParam Param(pDefShape,MOULDSPACE_ENVELOPE,TRUE,LockAspect);
00840                     pOpDesc->Invoke(&Param);
00841                 }
00842             }
00843         }
00844         delete pDefShape;
00845     }
00846 }
00847 
00848 /********************************************************************************************
00849 
00850 >   void MouldTool::CreateEnvelope2x2(EnvelopeType EnvType)
00851 
00852     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00853     Created:    12/12/94
00854     Purpose:    Calls the CREATENEWMOULD operation with a default rectangular envelope
00855                 shape
00856 
00857 ********************************************************************************************/
00858 
00859 void MouldTool::CreateEnvelope2x2(EnvelopeType EnvType)
00860 {
00861     // Make sure we have the operation ready
00862     OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_CREATENEWMOULD);
00863     if (pOpDesc)
00864     {
00865         // Create a manifold to use
00866         Path* pDefShape = new Path;
00867         if (pDefShape!=NULL)
00868         {
00869             BOOL LockAspect = FALSE;
00870 
00871             if (pDefShape->Initialise(12,12))
00872             {
00873                 BOOL ok = FALSE;
00874 
00875                 switch (EnvType)
00876                 {
00877                     case ENV_DEFAULT:
00878                         ok = EnvelopeShapes::Rectangular2x2(pDefShape);
00879                         break;
00880 
00881                     default:
00882                         break;
00883                 }
00884 
00885                 if (ok)
00886                 {
00887                     // now build the correct mould parameter and invoke the operation               
00888                     CreateMouldParam Param(pDefShape,MOULDSPACE_ENVELOPE2X2,TRUE,LockAspect);
00889                     pOpDesc->Invoke(&Param);
00890                 }
00891             }
00892         }
00893         delete pDefShape;
00894     }
00895 }
00896 
00897 
00898 /********************************************************************************************
00899 
00900 >   void MouldTool::CreatePerspective(PerspectiveType PerType)
00901 
00902     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00903     Created:    12/12/94
00904     Purpose:    Calls the CREATENEWMOULD operation with a default rectangular perspective
00905                 shape
00906 
00907 ********************************************************************************************/
00908 
00909 void MouldTool::CreatePerspective(PerspectiveType PerType)
00910 {
00911     // Make sure we have the operation ready
00912     OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_CREATENEWMOULD);
00913     if (pOpDesc)
00914     {
00915         // Create a manifold to use 
00916         Path* pDefShape = new Path;
00917         if (pDefShape!=NULL)
00918         {
00919             BOOL LockAspect = FALSE;
00920 
00921             if (pDefShape->Initialise(12,12))
00922             {
00923                 BOOL ok = FALSE;
00924 
00925                 switch (PerType)
00926                 {
00927                     case PER_DEFAULT:
00928                         ok = PerspectiveShapes::Rectangular(pDefShape);
00929                         break;
00930                     case PER_LEFT:
00931                         ok = PerspectiveShapes::LeftWall(pDefShape);
00932                         break;
00933                     case PER_RIGHT:
00934                         ok = PerspectiveShapes::RightWall(pDefShape);
00935                         break;
00936                     case PER_FLOOR:
00937                         ok = PerspectiveShapes::Floor(pDefShape);
00938                         break;
00939                     case PER_ROOF:
00940                         ok = PerspectiveShapes::Ceiling(pDefShape);
00941                         break;
00942                 }
00943 
00944                 if (ok)
00945                 {
00946                     // now build the correct mould parameter and invoke the operation               
00947                     CreateMouldParam Param(pDefShape,MOULDSPACE_PERSPECTIVE,TRUE,LockAspect);
00948                     pOpDesc->Invoke(&Param);
00949                 }
00950             }
00951         }
00952         delete pDefShape;
00953     }
00954 }
00955 
00956 
00957 
00958 /********************************************************************************************
00959 
00960 >   MouldInfoBarOp::MouldInfoBarOp()
00961 
00962     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00963     Created:    13/01/96
00964     Inputs:     -
00965     Outputs:    -
00966     Returns:    -
00967     Purpose:    Constructor for the mould tool information bar operation.
00968 
00969 ********************************************************************************************/
00970 
00971 MouldInfoBarOp::MouldInfoBarOp()
00972 {
00973     DlgResID = _R(IDD_MOULDTOOLBAR);
00974     DetachState=FALSE;
00975 }
00976 
00977 
00978 /********************************************************************************************
00979 
00980 >   void MouldInfoBarOp::SetTool(MouldTool* pTool)
00981 
00982     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00983     Created:    12/12/94
00984     Inputs:     pTool, the pointer to the mould tool instance
00985     Outputs:    -
00986     Returns:    -
00987     Purpose:    Sets the mould info bar tool pointer private variable
00988 
00989 ********************************************************************************************/
00990 
00991 void MouldInfoBarOp::SetTool(MouldTool* pTool)
00992 {
00993     pMouldTool = pTool;
00994 }
00995 
00996 
00997 /********************************************************************************************
00998 
00999 >   MsgResult MouldInfoBarOp::Message(Msg* Message) 
01000 
01001     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01002     Created:    30/11/94
01003     Inputs:     Message = The message to handle
01004     Outputs:    -
01005     Returns:    -
01006     Purpose:    Mould info bar dialog message handler
01007     Errors:     -
01008     SeeAlso:    -
01009 
01010 ********************************************************************************************/
01011 
01012 MsgResult MouldInfoBarOp::Message(Msg* Message) 
01013 {
01014     if (IS_OUR_DIALOG_MSG(Message))
01015     {
01016         DialogMsg* Msg = (DialogMsg*)Message;
01017 
01018         // Check if the message is a CANCEL
01019         switch (Msg->DlgMsg)
01020         {
01021             case DIM_CANCEL:
01022                 Close(); // Close the dialog 
01023                 break;
01024 
01025             case DIM_CREATE:
01026                 // Initialise the infobar controls here
01027                 // This is sent when you create the infobar in your tool startup code
01028                 break;
01029 
01030             case DIM_LFT_BN_CLICKED:
01031             {
01032                 if (pMouldTool !=NULL)
01033                 {
01034                     if (FALSE) {}
01035                     else if (Msg->GadgetID == _R(IDC_BTN_DEFAULTENVELOPE))
01036                     {
01037                         pMouldTool->CreateEnvelope(ENV_DEFAULT);
01038                         //pMouldTool->CreateEnvelope2x2(ENV_DEFAULT);
01039                     }
01040                     else if (Msg->GadgetID == _R(IDC_BTN_CIRCULARENVELOPE))
01041                     {
01042                         pMouldTool->CreateEnvelope(ENV_CIRCULAR);
01043                     }
01044                     else if (Msg->GadgetID == _R(IDC_BTN_ELLIPTICENVELOPE))
01045                     {
01046                         pMouldTool->CreateEnvelope(ENV_ELLIPTICAL);
01047                     }
01048                     else if (Msg->GadgetID == _R(IDC_BTN_CONCAVEENVELOPE))
01049                     {
01050                         pMouldTool->CreateEnvelope(ENV_CONCAVE);
01051                     }
01052                     else if (Msg->GadgetID == _R(IDC_BTN_BANNERENVELOPE))
01053                     {
01054                         pMouldTool->CreateEnvelope(ENV_BANNER);
01055                     }
01056                     else if (Msg->GadgetID == _R(IDC_BTN_DEFAULTPERSPECTIVE))
01057                     {
01058                         pMouldTool->CreatePerspective(PER_DEFAULT);
01059                     }
01060                     else if (Msg->GadgetID == _R(IDC_BTN_LEFTPERSPECTIVE))
01061                     {
01062                         pMouldTool->CreatePerspective(PER_LEFT);
01063                     }
01064                     else if (Msg->GadgetID == _R(IDC_BTN_RIGHTPERSPECTIVE))
01065                     {
01066                         pMouldTool->CreatePerspective(PER_RIGHT);
01067                     }
01068                     else if (Msg->GadgetID == _R(IDC_BTN_FLOORPERSPECTIVE))
01069                     {
01070                         pMouldTool->CreatePerspective(PER_FLOOR);
01071                     }
01072                     else if (Msg->GadgetID == _R(IDC_BTN_ROOFPERSPECTIVE))
01073                     {
01074                         pMouldTool->CreatePerspective(PER_ROOF);
01075                     }
01076                     else if (Msg->GadgetID ==_R(IDC_BTN_DETACHMOULD))
01077                     {
01078                         OpDetachMould* pOpDetachMould = new OpDetachMould;
01079                         if (pOpDetachMould)
01080                             pOpDetachMould->Do(NULL);
01081                         SetDetachState(!DetachState);
01082                     }
01083                     
01084                 }
01085             }
01086             break;
01087 
01088             case DIM_SELECTION_CHANGED:
01089             {
01090             }
01091             break;
01092 
01093             default:
01094                 break;
01095         }
01096     }
01097     // Pass the message on to the immediate mould class
01098     return (DialogBarOp::Message(Message));
01099 }    
01100 
01101 
01102 
01103 /********************************************************************************************
01104 
01105 >   virtual void MouldInfoBarOp::UpdateState()
01106 
01107     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01108     Created:    12/11/94
01109     Purpose:    Overrides the empty UpdateState function provided by InformationBarOp
01110                 making a call to the function in DialogBarOp.
01111 
01112 *********************************************************************************************/
01113 
01114 void MouldInfoBarOp::UpdateState()
01115 {
01116     // check that our tool is enabled and is current
01117     if (!pMouldTool) return;
01118     if (!pMouldTool->IsCurrent()) return;
01119 
01120     DialogBarOp::UpdateState();
01121     BOOL Selection = CheckSelection();
01122     UpdateDefEnvButton(Selection);
01123     UpdateDefPerButton(Selection);
01124     UpdateDetachButton(Selection);
01125 }
01126 
01127 
01128 
01129 /********************************************************************************************
01130 
01131 >   void MouldInfoBarOp::UpdateDefEnvButton(BOOL Selection)
01132 
01133     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01134     Created:    12/11/94
01135     Inputs:     -
01136     Purpose:    Sets the grey and select status of the default envelope button
01137                 on the infobar.
01138 
01139 ********************************************************************************************/
01140 
01141 void MouldInfoBarOp::UpdateDefEnvButton(BOOL Selection)
01142 {
01143     // Check for the existance of an info bar first
01144     if (WindowID)
01145     {
01146         if (!CanMouldSelection())
01147         {
01148             // if we can't mould the selection, then disable all gadgets
01149             Selection = FALSE;
01150         }
01151         
01152         EnableGadget(_R(IDC_BTN_DEFAULTENVELOPE), Selection);
01153         EnableGadget(_R(IDC_BTN_CIRCULARENVELOPE), Selection);
01154         EnableGadget(_R(IDC_BTN_ELLIPTICENVELOPE), Selection);
01155         EnableGadget(_R(IDC_BTN_CONCAVEENVELOPE), Selection);
01156         EnableGadget(_R(IDC_BTN_BANNERENVELOPE), Selection);
01157 
01158         // if we have NOT enabled any of the above, then we should NOT allow you to paste a mould either!
01159         // This is a BODGE - that works!  There is basically something wrong with the AllowOp mechanism,
01160         // and I do not have enough time to fix it ....
01161 
01162         if (!Selection)
01163         {
01164             EnableGadget(_R(IDC_BTN_PASTEENVELOPE), Selection);
01165         }
01166         else
01167         {
01168             String_256 Desc; 
01169             OpDescriptor* OpDesc = OpDescriptor::FindOpDescriptor (CC_RUNTIME_CLASS (OpPasteEnvelope));
01170 
01171             if (OpDesc != NULL)
01172             {
01173                 OpState NewState = OpDesc->GetOpsState(&Desc);
01174 
01175                 if (NewState.Greyed == FALSE)
01176                 {
01177                     EnableGadget(_R(IDC_BTN_PASTEENVELOPE), Selection);
01178                 }
01179             }
01180         }
01181     }
01182 }
01183 
01184 /********************************************************************************************
01185 
01186 >   BOOL MouldInfoBarOp::CanMouldSelection()
01187 
01188     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
01189     Created:    30/7/99
01190     Inputs:     -
01191     Returns:    TRUE for the selection being able to be moulded, FALSE otherwise
01192     Purpose:    Tests the selection to see if all nodes can be moulded
01193                 Mainly tests for NeedsParent() nodes - if any exist in the selection, then
01194                 we can't mould !
01195 
01196 ********************************************************************************************/
01197 BOOL MouldInfoBarOp::CanMouldSelection()
01198 {
01199     Range * pRng = GetApplication()->FindSelection();
01200 
01201     Node * pParent = NULL;
01202     Node * pNode = pRng->FindFirst(FALSE);
01203     Node * pChild = NULL;
01204 
01205     while (pNode)
01206     {
01207         pParent = pNode->FindParent();
01208 
01209         if (pParent)
01210         {
01211             if (pNode->NeedsParent(pParent))
01212             {
01213                 return FALSE;
01214             }
01215         }
01216 
01217         // check for any needs parent nodes in the node's child list
01218         pChild = pNode->FindFirstDepthFirst();
01219 
01220         while (pChild)
01221         {
01222             if (pChild->NeedsParent(NULL))
01223             {
01224                 return FALSE;
01225             }
01226 
01227             pChild = pChild->FindNextDepthFirst(pNode);
01228         }
01229 
01230         pNode = pRng->FindNext(pNode, FALSE);
01231     }
01232 
01233     return TRUE;
01234 }
01235 
01236 /********************************************************************************************
01237 
01238 >   void MouldInfoBarOp::UpdateDefPerButton()
01239 
01240     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01241     Created:    12/11/94
01242     Inputs:     -
01243     Purpose:    Sets the grey and select status of the default perspective button 
01244                 on the infobar.
01245 
01246 ********************************************************************************************/
01247 
01248 void MouldInfoBarOp::UpdateDefPerButton(BOOL Selection)
01249 {
01250     // Check for the existance of an info bar first
01251     if (WindowID)
01252     {
01253         if (!CanMouldSelection())
01254         {
01255             // if we can't mould the selection, then disable all gadgets
01256             Selection = FALSE;
01257         }
01258 
01259         EnableGadget(_R(IDC_BTN_DEFAULTPERSPECTIVE), Selection);
01260         EnableGadget(_R(IDC_BTN_LEFTPERSPECTIVE), Selection);
01261         EnableGadget(_R(IDC_BTN_RIGHTPERSPECTIVE), Selection);
01262         EnableGadget(_R(IDC_BTN_FLOORPERSPECTIVE), Selection);
01263         EnableGadget(_R(IDC_BTN_ROOFPERSPECTIVE), Selection);
01264 
01265         // if we have NOT enabled any of the above, then we should NOT allow you to paste a mould either!
01266         // This is a BODGE - that works!  There is basically something wrong with the AllowOp mechanism,
01267         // and I do not have enough time to fix it ....
01268 
01269         if (!Selection)
01270         {
01271             EnableGadget(_R(IDC_BTN_PASTEPERSPECTIVE), Selection);
01272         }
01273         else
01274         {
01275             String_256 Desc; 
01276             OpDescriptor* OpDesc = OpDescriptor::FindOpDescriptor (CC_RUNTIME_CLASS (OpPastePerspective));
01277 
01278             if (OpDesc != NULL)
01279             {
01280                 OpState NewState = OpDesc->GetOpsState(&Desc);
01281 
01282                 if (NewState.Greyed == FALSE)
01283                 {
01284                     EnableGadget(_R(IDC_BTN_PASTEPERSPECTIVE), Selection);
01285                 }
01286             }
01287         }
01288     }
01289 }
01290 
01291 
01292 /********************************************************************************************
01293 
01294 >   void MouldInfoBarOp::UpdateDetachButton()
01295 
01296     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01297     Created:    20/03/95
01298     Inputs:     -
01299     Purpose:    Sets the grey and select status of the detach button on the infobar.
01300 
01301 ********************************************************************************************/
01302 
01303 void MouldInfoBarOp::UpdateDetachButton(BOOL Selection)
01304 {
01305     if (WindowID!=NULL)
01306     {
01307         if (!CanMouldSelection())
01308         {
01309             // if we can't mould the selection, then disable all gadgets
01310             Selection = FALSE;
01311         }
01312 
01313         EnableGadget(_R(IDC_BTN_DETACHMOULD), Selection);
01314         // if the button is enabled then set its state
01315         if (Selection)
01316         {       
01317             NodeMould* pLastMould;
01318             INT32 nmoulds = SelInfo(&pLastMould);
01319 
01320             // Set the detach button dependent on how many moulds are selected.
01321             BOOL Enabled = (nmoulds>0);
01322             BOOL PressedIn = ((nmoulds==1) && pLastMould->IsDetached());
01323 
01324             EnableGadget(_R(IDC_BTN_DETACHMOULD), Enabled);
01325             SetDetachState(PressedIn);
01326         }
01327     }
01328 }
01329 
01330 /********************************************************************************************
01331 
01332 >   void MouldInfoBarOp::SetDetachState()
01333 
01334     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01335     Created:    20/03/95
01336     Inputs:     -
01337     Purpose:    Sets the detach button state. As we have no sensible button that clicks
01338                 down then
01339 
01340 ********************************************************************************************/
01341 
01342 void MouldInfoBarOp::SetDetachState(BOOL state)
01343 {
01344     // Is it down or up?
01345     SetLongGadgetValue(_R(IDC_BTN_DETACHMOULD), state);
01346     DetachState = state;
01347 }
01348 
01349 
01350 
01351 /********************************************************************************************
01352 
01353 >   INT32 MouldInfoBarOp::SelInfo(NodeMould** pMould)
01354 
01355     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01356     Created:    20/03/95
01357     Inputs:     pMould = a pointer to a mould object pointer to be used as a return parameter
01358     Outputs:    pMould = a pointer to the last selected mould object
01359     Returns:    The number of mould objects selected
01360     Purpose:    Find out how many moulds are selected and return a pointer to the last
01361                 selected mould.
01362 
01363 ********************************************************************************************/
01364 
01365 INT32 MouldInfoBarOp::SelInfo(NodeMould** pMould)
01366 {
01367     SelRange* Selection = GetApplication()->FindSelection();
01368     Node* pNode = Selection->FindFirst();
01369     NodeMould* pLastMould=NULL;
01370 
01371     INT32 num = 0;
01372     while (pNode!=NULL)
01373     {
01374         if (IS_A(pNode, NodeMould) && pNode->IsSelected())
01375         {
01376             num++;
01377             pLastMould = (NodeMould*)pNode;
01378         }
01379         pNode = Selection->FindNext(pNode);
01380     }
01381 
01382     (*pMould)=pLastMould;
01383     return num;
01384 }    
01385 
01386 
01387 /********************************************************************************************
01388 
01389 >   void MouldInfoBarOp::CheckSelection()
01390 
01391     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01392     Created:    12/11/94
01393     Inputs:     -
01394     Returns:    TRUE if there are selected objects in the current document
01395                 FALSE if nothing is selected
01396     Purpose:    Checks for selected objects in the current document and returns whether
01397                 there are any or not
01398 
01399 ********************************************************************************************/
01400 
01401 BOOL MouldInfoBarOp::CheckSelection()
01402 {
01403     BOOL Enabled = FALSE;
01404 
01405 /*
01406     if (Document::GetCurrent() != NULL)
01407     {
01408         SelRange* Selected = GetApplication()->FindSelection();
01409         Node* pNode = Selected->FindFirst();
01410         Enabled = (pNode!=NULL);
01411     }
01412 */
01413 
01414     // Get the selection and the number of selected objects
01415     SelRange* Selected = GetApplication()->FindSelection();
01416     INT32 Count = 0;
01417     if (Document::GetSelected() != NULL)
01418         Count = Selected->Count();
01419 
01420     // Are there any selected objects?
01421     if (Count > 0)
01422     {
01423         ObjChangeFlags cFlags;
01424 
01425         // If only one node selected, then it will just be replaced in the tree with another NodeRenderableInk node
01426         // Otherwise, the selected node could be moved, and if the node is a child of another node, effectively
01427         // delete a child node of a parent.
01428         /*
01429         if (Count == 1)
01430             cFlags.ReplaceNode = TRUE;
01431         else
01432             cFlags.DeleteNode  = TRUE;
01433         */
01434         // **** Above code commented out due to imcomplete implementation
01435         //
01436         // For now, just pretend that the op is as severe as deleting to get the mould tool buttons to grey out
01437         // when the mould is selected inside the blend. (Haven't got time to do this properly at the moment)
01438         cFlags.MultiReplaceNode  = TRUE;
01439 
01440         ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,NULL);
01441 
01442         Node* pNode = Selected->FindFirst();
01443     
01444         Enabled = TRUE;
01445         while (pNode != NULL && Enabled)
01446         {
01447             Enabled = pNode->AllowOp(&ObjChange,FALSE);
01448             pNode = Selected->FindNext(pNode);
01449         }
01450     }
01451 
01452     return Enabled;
01453 }
01454 
01455 
01456 
01457 /********************************************************************************************
01458 
01459 >   OpCreateNewMould::OpCreateNewMould() 
01460 
01461     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01462     Created:    11/12/94
01463     Purpose:    OpCreateNewMould() constructor
01464     SeeAlso:    -
01465 
01466 ********************************************************************************************/
01467 
01468 OpCreateNewMould::OpCreateNewMould()
01469 {
01470     m_space = MOULDSPACE_UNDEFINED;
01471 }
01472 
01473 
01474 
01475 
01476 /********************************************************************************************
01477 
01478 >   BOOL OpCreateNewMould::Init()
01479 
01480     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01481     Created:    11/12/94
01482     Inputs:     -
01483     Outputs:    -
01484     Returns:    TRUE if the operation could be successfully initialised 
01485                 FALSE if no more memory could be allocated 
01486                 
01487     Purpose:    OpDeletePoints initialiser method
01488     Errors:     ERROR will be called if there was insufficient memory to allocate the 
01489                 operation.
01490     SeeAlso:    -
01491 
01492 ********************************************************************************************/
01493 
01494 BOOL OpCreateNewMould::Init()
01495 {
01496     return (RegisterOpDescriptor(0,                                 // tool ID
01497                                 _R(IDS_CREATENEWMOULD),                 // string resource ID
01498                                 CC_RUNTIME_CLASS(OpCreateNewMould), // runtime class for Op
01499                                 OPTOKEN_CREATENEWMOULD,             // Ptr to token string
01500                                 OpCreateNewMould::GetState,         // GetState function
01501                                 0,                                  // help ID
01502                                 _R(IDBBL_CREATENEWMOULD),               // bubble help ID
01503                                 0                                   // resource ID
01504                                 ));
01505 
01506 }               
01507 
01508   
01509 /********************************************************************************************
01510 
01511 >   void OpCreateNewMould::GetOpName(String_256* OpName)
01512 
01513     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01514     Created:    11/12/94
01515     Inputs:     -
01516     Outputs:    The undo string for the operation
01517     Returns:    
01518     Purpose:    The GetOpName fn is overridden so that we return back a description
01519                 appropriate to the type of attribute that the operation applies.
01520                     
01521     Errors:     -
01522     SeeAlso:    -
01523 
01524 ********************************************************************************************/
01525 
01526 void OpCreateNewMould::GetOpName(String_256* OpName)
01527 {
01528     switch (m_space)
01529     {
01530         case MOULDSPACE_ENVELOPE:
01531             *OpName = String_256(_R(IDS_UNDO_ENVELOPE));
01532             break;
01533         case MOULDSPACE_ENVELOPE2X2:
01534             *OpName = String_256(_R(IDS_UNDO_ENVELOPE));
01535             break;
01536         case MOULDSPACE_PERSPECTIVE:
01537             *OpName = String_256(_R(IDS_UNDO_PERSPECTIVE));
01538             break;
01539         default:
01540             *OpName = String_256(_R(IDS_UNDO_CREATENEWMOULD));
01541             break;
01542     }
01543 }
01544 
01545 
01546 /********************************************************************************************
01547 
01548 >   OpState OpCreateNewMould::GetState(String_256*, OpDescriptor*)
01549 
01550     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01551     Created:    11/12/94
01552     Inputs:     -
01553     Outputs:    -
01554     Returns:    The state of the OpCreateNewMould
01555     Purpose:    For finding the OpCreateNewMould state. 
01556 
01557 ********************************************************************************************/
01558 
01559 OpState OpCreateNewMould::GetState(String_256* UIDescription, OpDescriptor*)
01560 {
01561     OpState OpSt;
01562     OpSt.Greyed = TRUE;
01563 
01564     // only ungrey if we have a selection
01565     SelRange* pSelRange = GetApplication()->FindSelection();
01566     if (pSelRange && pSelRange->FindFirst() != NULL)
01567         OpSt.Greyed=FALSE;
01568 
01569     return OpSt;   
01570 }
01571 
01572 
01573 /********************************************************************************************
01574 
01575 > void OpCreateNewMould::DoWithParam(OpDescriptor* pOpDescr, OpParam* pOpParam)
01576 
01577     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>       
01578     Created:    11/12/94
01579     Inputs:     pOpDescr = pointer to an OpDescriptor (unused)
01580                 pOpParam = pointer to an OpParam
01581     Outputs:    -
01582     Returns:    -
01583     Purpose:    This operation will create a new mould object, and thus start off quite
01584                 a complicated chain of events.
01585                 First off, a mouldgroup node is created and all objects are moved into it as
01586                 children, along with any inherited attributes.
01587                 Secondly a mould object is created and initialise with the shape passed to
01588                 this do function.
01589                 The mouldgroup node is now added to the mould node as a first child.
01590                 A moulder object is then created and added as the last child of the mould
01591                 node. It is not added to the next object of the mouldgroup, as there may be
01592                 more than one moulder object.
01593                 The moulder object is then asked to initialise itself. In doing so it will
01594                 scan the mould group children and ask them to make shapes of themselves.
01595                 These shapes are stored in a list within the moulder class, (not in the tree). 
01596                 Having constructed the moulder, a mould operation is triggered, whence all current
01597                 moulder list objects are mangled by the mould shape class functions (held
01598                 within the mould parent class). These mangled objects are added as children
01599                 of the moulder object.
01600                 Having done all this without running out of memory, the mouldgroup object is
01601                 hidden.
01602 
01603     Errors:     failandexecute will be called if the operation fails in some way, most
01604                 likely when no memory is available. 
01605 
01606 ********************************************************************************************/
01607 
01608 void OpCreateNewMould::DoWithParam(OpDescriptor* pOpDescr, OpParam* pParam)
01609 {
01610     ERROR3IF(pParam == NULL, "OpCreateNewMould::DoWithParam - NULL Param passed in");
01611 
01612     BeginSlowJob();
01613 
01614     // Initialise ourselves from the supplied parameters
01615     CreateMouldParam* CreateMould = (CreateMouldParam*)pParam;
01616 
01617     if (!CreateNewMould(CreateMould->ParamShape, 
01618                         CreateMould->ParamSpace,
01619                         CreateMould->FitSelection,
01620                         CreateMould->LockAspect))
01621         FailAndExecute();
01622 
01623     End();
01624 }
01625 
01626 
01627 
01628 
01629 /********************************************************************************************
01630 
01631 >   OpRemoveMould::OpRemoveMould() 
01632 
01633     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01634     Created:    18/01/95
01635     Purpose:    Constructor for remove mould shape operation
01636     SeeAlso:    -
01637 
01638 ********************************************************************************************/
01639 
01640 OpRemoveMould::OpRemoveMould()
01641 {
01642     // Dummy constructor
01643 }
01644   
01645 
01646 
01647 /********************************************************************************************
01648 
01649 >   BOOL OpRemoveMould::Init()
01650 
01651     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01652     Created:    18/01/95
01653     Inputs:     -
01654     Outputs:    -
01655     Returns:    TRUE if the operation could be successfully initialised 
01656                 FALSE if no more memory could be allocated 
01657     Purpose:    Initialise the remove mould operation so that it can be accessed from the
01658                 interface.
01659 
01660     Errors:     ERROR will be called if there was insufficient memory to allocate the 
01661                 operation.
01662     SeeAlso:    -
01663 
01664 ********************************************************************************************/
01665 
01666 BOOL OpRemoveMould::Init()
01667 {
01668     return (RegisterOpDescriptor(0,                                 // tool ID
01669                                 _R(IDS_REMOVEMOULD),                    // string resource ID
01670                                 CC_RUNTIME_CLASS(OpRemoveMould),    // runtime class for Op
01671                                 OPTOKEN_REMOVEMOULD,                // Ptr to token string
01672                                 OpRemoveMould::GetState,            // GetState function
01673                                 0,                                  // help ID
01674                                 _R(IDBBL_REMOVEMOULD),              // bubble help ID
01675                                 _R(IDC_REMOVEMOULD),                // resource ID
01676                                 _R(IDC_REMOVEMOULD)                 // control ID
01677                                 ));
01678 }               
01679 
01680 
01681 /********************************************************************************************
01682 
01683 >   OpState OpRemoveMould::GetState(String_256*, OpDescriptor*)
01684 
01685     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01686     Created:    18/01/95
01687     Inputs:     -
01688     Outputs:    -
01689     Returns:    The state of the OpRemoveMould
01690     Purpose:    For finding the OpRemoveMould state. 
01691 
01692 ********************************************************************************************/
01693 
01694 OpState OpRemoveMould::GetState(String_256* UIDescription, OpDescriptor*)
01695 {
01696     OpState OpSt;
01697     String_256 DisableReason; 
01698     OpSt.Greyed = TRUE;
01699     
01700 //  if (!IsAMouldSelected(NULL))
01701 //      OpSt.Greyed=TRUE;
01702 
01703     ObjChangeFlags cFlags;
01704     cFlags.MultiReplaceNode = TRUE;
01705     ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,NULL);
01706     
01707     SelRange* pSelRange = GetApplication()->FindSelection();
01708     Node* pNode = pSelRange->FindFirst();
01709 
01710     while (pNode != NULL && OpSt.Greyed)
01711     {
01712         if (IS_A(pNode,NodeMould))
01713             OpSt.Greyed = !(pNode->AllowOp(&ObjChange,FALSE));
01714 
01715         pNode = pSelRange->FindNext(pNode);
01716     }
01717 
01718     return (OpSt);   
01719 }
01720 
01721 
01722 
01723 /********************************************************************************************
01724 
01725 >   void OpRemoveMould::GetOpName(String_256* OpName)
01726 
01727     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01728     Created:    18/01/95
01729     Inputs:     -
01730     Outputs:    The undo string for the operation
01731     Returns:    
01732     Purpose:    The GetOpName fn is overridden so that we return back a description
01733                 appropriate to the type of attribute that the operation applies.
01734 
01735 ********************************************************************************************/
01736 
01737 void OpRemoveMould::GetOpName(String_256* OpName)
01738 {
01739     *OpName = String_256(_R(IDS_UNDO_REMOVEMOULD));
01740 }
01741 
01742 
01743 
01744 
01745 
01746 
01747 /********************************************************************************************
01748 
01749 > void OpRemoveMould::Do(OpDescriptor* opDesc)
01750 
01751     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>       
01752     Created:    18/01/95
01753     Inputs:     pointer to an OpDescriptor (unused)
01754     Outputs:    -
01755     Returns:    -
01756     Purpose:    
01757     Errors:     failandexecute will be called if the operation fails in some way, most
01758                 likely when no memory is available. 
01759 
01760 ********************************************************************************************/
01761 
01762 void OpRemoveMould::Do(OpDescriptor*)
01763 {
01764     BeginSlowJob();
01765 
01766     // remember the selection before the operation
01767     if (DoStartSelOp(FALSE,FALSE))
01768     {
01769         // Obtain the current selections 
01770         SelRange* Selected = GetApplication()->FindSelection();
01771         if (Selected)
01772         {
01773             // compile a list of the selected objects
01774             DocRect Bounds = Selected->GetBoundingRect();
01775             List* pNodeList = Selected->MakeListOfNodes();
01776 
01777             // remove all mould objects in the list
01778             BOOL success = DoRemoveAllMoulds(pNodeList);
01779 
01780             // delete all elements in our compiled list
01781             while (!pNodeList->IsEmpty())
01782                 delete (NodeListItem*)(pNodeList->RemoveHead());
01783             delete pNodeList;
01784 
01785             // update the selection
01786             if (success)
01787             {
01788                 // Update all the changed parents.
01789                 ObjChangeFlags cFlags;
01790                 cFlags.MultiReplaceNode = TRUE;
01791                 ObjChangeParam ObjChange(OBJCHANGE_FINISHED,cFlags,NULL,this);
01792                 if (!UpdateChangedNodes(&ObjChange))
01793                     FailAndExecute();                   
01794             }
01795             else
01796                 FailAndExecute();
01797         }
01798         else
01799             FailAndExecute();
01800     }
01801     else
01802         FailAndExecute();
01803 
01804     End();
01805 }
01806 
01807 
01808 
01809 
01810 
01811 
01812 /********************************************************************************************
01813 
01814 >   OpCopyMouldShape::OpCopyMouldShape() 
01815 
01816     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01817     Created:    18/01/95
01818     Purpose:    Constructor for copy mould shape operation
01819     SeeAlso:    -
01820 
01821 ********************************************************************************************/
01822 
01823 OpCopyMouldShape::OpCopyMouldShape()
01824 {
01825     // Dummy constructor
01826 }
01827   
01828 
01829 
01830 /********************************************************************************************
01831 
01832 >   BOOL OpCopyMouldShape::Init()
01833 
01834     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01835     Created:    18/01/95
01836     Inputs:     -
01837     Outputs:    -
01838     Returns:    TRUE if the operation could be successfully initialised 
01839                 FALSE if no more memory could be allocated 
01840     Purpose:    Initialise the copy mould operation so that it can be accessed from the
01841                 interface.
01842 
01843     Errors:     ERROR will be called if there was insufficient memory to allocate the 
01844                 operation.
01845     SeeAlso:    -
01846 
01847 ********************************************************************************************/
01848 
01849 BOOL OpCopyMouldShape::Init()
01850 {
01851     return (RegisterOpDescriptor(0,                                 // tool ID
01852                                 _R(IDS_COPYMOULD),                      // string resource ID
01853                                 CC_RUNTIME_CLASS(OpCopyMouldShape), // runtime class for Op
01854                                 OPTOKEN_COPYMOULD,                  // Ptr to token string
01855                                 OpCopyMouldShape::GetState,         // GetState function
01856                                 0,                                  // help ID
01857                                 _R(IDBBL_COPYMOULD),                    // bubble help ID
01858                                 _R(IDD_MOULDTOOLBAR),                   // resource ID
01859                                 _R(IDC_BTN_COPYMOULD),                  // control ID
01860                                 SYSTEMBAR_EDIT,                     // Group bar ID
01861                                 TRUE,                               // Receive messages
01862                                 FALSE,                              // Smart
01863                                 FALSE,                              // Clean
01864                                 0,                                  // One open Instance ID
01865                                 (GREY_WHEN_NO_CURRENT_DOC | GREY_WHEN_NO_SELECTION)
01866                                 )); 
01867 
01868 }               
01869 
01870 
01871 /********************************************************************************************
01872 
01873 >   OpState OpCopyMouldShape::GetState(String_256*, OpDescriptor*)
01874 
01875     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01876     Created:    18/01/95
01877     Inputs:     -
01878     Outputs:    -
01879     Returns:    The state of the OpCopyMouldShape
01880     Purpose:    For finding the OpCopyMouldShape state. 
01881 
01882 ********************************************************************************************/
01883 
01884 OpState OpCopyMouldShape::GetState(String_256* UIDescription, OpDescriptor*)
01885 {
01886     OpState OpSt;
01887     String_256 DisableReason; 
01888     OpSt.Greyed = FALSE;
01889 
01890     if (!IsAMouldSelected(NULL))
01891         OpSt.Greyed=TRUE;
01892 
01893     return (OpSt);   
01894 }
01895 
01896 
01897 
01898 /********************************************************************************************
01899 
01900 >   void OpCopyMouldShape::GetOpName(String_256* OpName)
01901 
01902     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01903     Created:    18/01/95
01904     Inputs:     -
01905     Outputs:    The undo string for the operation
01906     Returns:    
01907     Purpose:    The GetOpName fn is overridden so that we return back a description
01908                 appropriate to the type of attribute that the operation applies.
01909 
01910 ********************************************************************************************/
01911 
01912 void OpCopyMouldShape::GetOpName(String_256* OpName)
01913 {
01914     *OpName = String_256(_R(IDS_UNDO_COPYMOULD));
01915 }
01916 
01917 
01918 
01919 
01920 
01921 
01922 /********************************************************************************************
01923 
01924 > void OpCopyMouldShape::Do(OpDescriptor* opDesc)
01925 
01926     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>       
01927     Created:    18/01/95
01928     Inputs:     pointer to an OpDescriptor (unused)
01929     Outputs:    -
01930     Returns:    -
01931     Purpose:    Copies the mould node path to the clipboard so it can be used as a template
01932                 object for further moulds.
01933     Errors:     failandexecute will be called if the operation fails in some way, most
01934                 likely when no memory is available. 
01935 
01936 ********************************************************************************************/
01937 
01938 void OpCopyMouldShape::Do(OpDescriptor*)
01939 {
01940     NodeMould* pNodeMould;
01941     NodeMouldPath* pMouldPath;
01942 
01943     if (!DoStartSelOp(TRUE,TRUE))
01944         goto Failed;
01945 
01946     if (IsAMouldSelected(&pNodeMould))
01947     {
01948         // find the actual shape we need to copy.
01949         pMouldPath = pNodeMould->GetPathShape();
01950         if (pMouldPath==NULL)
01951             goto Failed;
01952 
01953         // RangeControl Cntrl = Selected + Unselected + don't cross layers  
01954         Range CopyRange(pMouldPath,pMouldPath,RangeControl(TRUE,TRUE,FALSE));
01955         if (!DoCopyNodesToClipboard(CopyRange))
01956             goto Failed;
01957     }
01958     End();
01959     return;
01960 
01961 Failed:
01962     FailAndExecute();
01963     End();
01964     return;
01965 }
01966 
01967 
01968 
01969 
01970 /********************************************************************************************
01971 
01972 >   OpPasteMouldShape::OpPasteMouldShape() 
01973 
01974     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01975     Created:    18/01/95
01976     Purpose:    Constructor for paste mould shape operation
01977     SeeAlso:    -
01978 
01979 ********************************************************************************************/
01980 
01981 OpPasteMouldShape::OpPasteMouldShape()
01982 {
01983     // Dummy constructor
01984 }
01985   
01986 /********************************************************************************************
01987 
01988 >   BOOL OpPasteMouldShape::FindPasteObject(Node** pReturnNode)
01989 
01990     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01991     Created:    09/02/95
01992     Inputs:     pReturnNode, a pointer to a pointer, which can be null if no return
01993                 node is required.
01994     Outputs:    pReturnNode holds a pointer to the node to be pasted, if a suitable node
01995                 has been found and the pointer pointer is none null on entry 
01996     Returns:    TRUE if a suitable paste object has been found
01997                 FALSE if none
01998     Purpose:    This function scans for objects on the clipboard. It tries to find the
01999                 first object which 
02000                     Is a NodeRenderableInk
02001                     Can become a nodepath
02002                 If there is such an object the function will return true, and set the
02003                 return pointer to point at the object if the return pointer exists ie is
02004                 a none null receptor.
02005 
02006 ********************************************************************************************/
02007 
02008 BOOL OpPasteMouldShape::FindPasteObject(Node** pReturnNode)
02009 {
02010     BOOL found=FALSE;
02011 
02012     // find the first object
02013     Node* pNode = InternalClipboard::GetInsertionLayer()->FindFirstChild();
02014     while (pNode && !found)
02015     {
02016         // ok lets check what we've got here
02017         BecomeA TestBecomeAPath(BECOMEA_TEST, CC_RUNTIME_CLASS(NodePath));
02018         if ((pNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk))) &&
02019             (pNode->CanBecomeA(&TestBecomeAPath))
02020            )
02021             found=TRUE;
02022         else
02023             pNode=pNode->FindNext();
02024     }
02025 
02026     if (found && pReturnNode)
02027         *pReturnNode=pNode;
02028 
02029     return found;
02030 }
02031 
02032 
02033 
02034 /********************************************************************************************
02035 
02036 > void OpPasteMouldShape::Do(MouldSpace mSpace)
02037 
02038     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>       
02039     Created:    18/01/95
02040     Inputs:     mSpace = the mould space to paste as
02041     Outputs:    -
02042     Returns:    -
02043     Purpose:    Take the contents of the clipboard and try to use whatever shape exists
02044                 there as a mould shape. The mould space type is passed to this function 
02045                 as a parameter. The function will find the first renderable object on the
02046                 clipboard, try to make shapes of it and use the first shape returned as
02047                 the mould space object. 
02048     Errors:     failandexecute will be called if the operation fails in some way, most
02049                 likely when no memory is available. 
02050 
02051 ********************************************************************************************/
02052 
02053 void OpPasteMouldShape::Do(MouldSpace mSpace)
02054 {
02055     BeginSlowJob();
02056 
02057     Node* pPasteNode;
02058     BOOL Constrain=KeyPress::IsConstrainPressed();
02059 
02060     // Obtain the current selections 
02061     SelRange* Selected = GetApplication()->FindSelection();
02062     if (!Selected)
02063     {
02064         FailAndExecute(); End(); return;
02065     }
02066 
02067     // is there a suitable object on the clipboard?
02068     if (!FindPasteObject(&pPasteNode))
02069     {
02070         FailAndExecute(); End(); return;
02071     }
02072 
02073     // HERE
02074 
02075     // If so lets force the object to become a nodepath
02076     // Do this none undoably because we are doing things on the clipboard.
02077     // If we DoBecomeA passback on a perspectivised filled object, it hides
02078     // the original?
02079     MouldBecomeA ParamBecomeA(  BECOMEA_PASSBACK, 
02080                                 CC_RUNTIME_CLASS(NodePath),
02081                                 NULL);
02082 
02083     // Get pNode to generate its paths for us
02084     BOOL ok = pPasteNode->DoBecomeA(&ParamBecomeA);
02085     // whip the resulting mould path out of the do becomea param class
02086     NodePath* pNodePath = ParamBecomeA.GetMouldPath();
02087     if ((!ok) || pNodePath==NULL)
02088     {
02089         FailAndExecute(); End(); return;
02090     }
02091 
02092     // remember the selection before the operation
02093     if (!DoStartSelOp(TRUE,TRUE))
02094     {
02095         FailAndExecute(); End(); return;
02096     }
02097 
02098     ObjChangeFlags cFlags;
02099     cFlags.DeleteNode  = TRUE;
02100     ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
02101 
02102     if (!Selected->AllowOp(&ObjChange))
02103     {
02104         ERROR3("AllowOp() returned FALSE, i.e. op should have been greyed out");
02105         FailAndExecute(); End(); return;
02106     }
02107 
02108     // Trash the selection bounds
02109     Range Rnge = (*Selected);
02110     if (!DoInvalidateNodesRegions(Rnge,TRUE,TRUE))
02111     {
02112         FailAndExecute(); End(); return;
02113     }
02114 
02115     // Calculate the destination paste position
02116     DocRect Bounds  = Selected->GetBoundingRect();
02117     DocRect sBounds = pNodePath->GetBoundingRect();
02118 
02119     Node* pNode = Selected->FindFirst();
02120     if (pNode==NULL)
02121     {
02122         FailAndExecute(); End(); return;
02123     }
02124     
02125     if (!Constrain)
02126     {
02127         // If we're not constraining, then we might have to force constrain
02128         // on to ensure the object pastes within the bounds of the spread.
02129         // We'll try to expand the pasteboard, and if that fails, we'll
02130         // turn constrain on
02131         
02132         // find the spread of the destination selected node (fix to Jason bug)
02133         Spread *pSpread = pNode->FindParentSpread();
02134         if (pSpread == NULL || !pSpread->ExpandPasteboardToInclude(sBounds))
02135             Constrain=TRUE;
02136     }
02137 
02138     if (Constrain)
02139     {
02140         // if 'control' constrain is pressed then paste the mould
02141         // shape centred over the selection otherwise leave it where
02142         // it is.
02143         INT32 tx = (Bounds.lo.x+Bounds.hi.x)/2 - (sBounds.lo.x+sBounds.hi.x)/2;
02144         INT32 ty = (Bounds.lo.y+Bounds.hi.y)/2 - (sBounds.lo.y+sBounds.hi.y)/2;
02145         Trans2DMatrix trans(tx,ty);
02146         pNodePath->Transform(trans);
02147     }
02148 
02149     // Grab the ink path from its node
02150     Path* pShape = &(pNodePath->InkPath);
02151 
02152     // using this list create or replace the mould bits
02153     ok = DoCreateOrReplaceMould(Selected, pShape, mSpace, TRUE, FALSE);
02154     if (!ok)
02155         FailAndExecute();
02156 
02157     // Update all the changed nodes, i.e. tell all the parents of the children that have been effected
02158     ObjChange.Define (OBJCHANGE_FINISHED,cFlags,NULL,this);
02159     UpdateChangedNodes(&ObjChange);
02160 
02161     End();
02162 }
02163 
02164 
02165 /********************************************************************************************
02166 
02167 >   MouldBecomeA::~MouldBecomeA()
02168 
02169     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02170     Created:    25/09/96
02171     Purpose:    Destructor for the MouldBecomeA parameter
02172     SeeAlso:    -
02173 
02174 ********************************************************************************************/
02175 
02176 MouldBecomeA::~MouldBecomeA()
02177 {
02178     Destroy();
02179 }
02180 
02181 
02182 /***********************************************************************************************
02183 
02184 >   virtual BOOL MouldBecomeA::PassBack(NodeRenderableInk* pNewNode, 
02185                                         NodeRenderableInk* pCreatedByNode,
02186                                         CCAttrMap* pAttrMap)
02187 
02188     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02189     Created:    09/02/95
02190     Inputs:     pNewNode       = ptr to Node that been generated by a node via its 
02191                                  DoBecomeA() method
02192                 pCreatedByNode = ptr to the node that created pNewNode
02193     Outputs:    -
02194     Returns:    TRUE if Successful, FALSE otherwise
02195 
02196     Purpose:    From the call     ProducerObj->DoBecomeA( MouldBecomeA(ObjectType) )
02197                 this function being a member of MouldBecomeA will be passed objects of ObjectType
02198                 created by ProducerObj. We store the first object passed to us and ignore the
02199                 rest as we really can only use one thanks very much. Most simple producers will
02200                 probably return single objects anyway.
02201     
02202 ***********************************************************************************************/
02203 
02204 BOOL MouldBecomeA::PassBack(NodeRenderableInk* pNewNode,
02205                             NodeRenderableInk* pCreatedByNode, 
02206                             CCAttrMap* pAttrMap)
02207 {
02208     if ( (MouldBecomeA::pNodePath==NULL) && (pNewNode->IsKindOf(CC_RUNTIME_CLASS(NodePath))) )
02209         MouldBecomeA::pNodePath=(NodePath*)pNewNode;
02210     else
02211     {
02212         // remember on a pass back we own this object so we 
02213         // really need to delete it if we're not going to use it!
02214         pNewNode->CascadeDelete(); 
02215         delete pNewNode;
02216         pNewNode = NULL;
02217     }   
02218 
02219     return TRUE;
02220 }
02221 
02222 /********************************************************************************************
02223 
02224 >   void MouldBecomeA::Destroy()
02225 
02226     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02227     Created:    18/01/95
02228     Purpose:    Destroy the contents of the mould become a object
02229     SeeAlso:    -
02230 
02231 ********************************************************************************************/
02232 
02233 void MouldBecomeA::Destroy()
02234 {
02235     // remember on a pass back we own this object so we 
02236     // really need to delete it if we're not going to use it!
02237     if (pNodePath)
02238     {
02239         pNodePath->CascadeDelete(); 
02240         delete pNodePath;
02241         pNodePath = NULL;
02242     }
02243 }
02244 
02245 
02246 /********************************************************************************************
02247 
02248 >   OpPasteEnvelope::OpPasteEnvelope() 
02249 
02250     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02251     Created:    18/01/95
02252     Purpose:    Constructor for paste envelope operation
02253     SeeAlso:    -
02254 
02255 ********************************************************************************************/
02256 
02257 OpPasteEnvelope::OpPasteEnvelope()
02258 {
02259     // Dummy constructor
02260 }
02261 
02262 
02263 /********************************************************************************************
02264 
02265 >   BOOL OpPasteEnvelope::Init()
02266 
02267     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02268     Created:    18/01/95
02269     Inputs:     -
02270     Outputs:    -
02271     Returns:    TRUE if the operation could be successfully initialised 
02272                 FALSE if no more memory could be allocated 
02273     Purpose:    Initialise the paste mould operation so that it can be accessed from the
02274                 interface.
02275 
02276     Errors:     ERROR will be called if there was insufficient memory to allocate the 
02277                 operation.
02278     SeeAlso:    -
02279 
02280 ********************************************************************************************/
02281 
02282 BOOL OpPasteEnvelope::Init()
02283 {
02284     return (RegisterOpDescriptor(0,                                 // tool ID
02285                                 _R(IDS_PASTEENVELOPE),                  // string resource ID
02286                                 CC_RUNTIME_CLASS(OpPasteEnvelope),  // runtime class for Op
02287                                 OPTOKEN_PASTEENVELOPE,              // Ptr to token string
02288                                 OpPasteEnvelope::GetState,          // GetState function
02289                                 0,                                  // help ID
02290                                 _R(IDBBL_PASTEENVELOPE),                // bubble help ID
02291                                 _R(IDD_MOULDTOOLBAR),                   // resource ID
02292                                 _R(IDC_BTN_PASTEENVELOPE),              // control ID
02293                                 SYSTEMBAR_EDIT,                     // Group bar ID
02294                                 TRUE,                               // Receive messages
02295                                 FALSE,                              // Smart
02296                                 FALSE,                              // Clean
02297                                 0,                                  // One open Instance ID
02298                                 (GREY_WHEN_NO_CURRENT_DOC | GREY_WHEN_NO_SELECTION)
02299                                 )); 
02300 }               
02301 
02302 
02303 /********************************************************************************************
02304 
02305 >   OpState OpPasteEnvelope::GetState(String_256*, OpDescriptor*)
02306 
02307     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02308     Created:    18/01/95
02309     Inputs:     -
02310     Outputs:    -
02311     Returns:    The state of the OpPasteMouldShape
02312     Purpose:    For finding the OpPasteMouldShape state. 
02313 
02314 ********************************************************************************************/
02315 
02316 OpState OpPasteEnvelope::GetState(String_256* UIDescription, OpDescriptor*)
02317 {
02318     OpState OpSt;
02319 //  String_256 DisableReason; 
02320 //  OpSt.Greyed=(!FindPasteObject(NULL));
02321 
02322     OpSt.Greyed = TRUE;
02323 
02324     if (FindPasteObject(NULL))
02325     {
02326         // Get the selection and the number of selected objects
02327         SelRange* Selected = GetApplication()->FindSelection();
02328         INT32 Count = Selected->Count();
02329 
02330         // Are there any selected objects?
02331         if (Count > 0)
02332         {
02333             ObjChangeFlags cFlags;
02334             cFlags.DeleteNode  = TRUE;
02335             OpPasteEnvelope* op = new OpPasteEnvelope ();       // need an op to do correct processing
02336             ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,op);
02337 
02338             Node* pNode = Selected->FindFirst();
02339             OpSt.Greyed = FALSE;
02340             while (pNode != NULL && !OpSt.Greyed)
02341             {
02342                 OpSt.Greyed = !pNode->AllowOp(&ObjChange,FALSE);
02343                 pNode = Selected->FindNext(pNode);
02344             }
02345             delete (op);
02346         }
02347     }
02348 
02349     return(OpSt);   
02350 }
02351 
02352 
02353 
02354 
02355 /********************************************************************************************
02356 
02357 >   void OpPasteEnvelope::GetOpName(String_256* OpName)
02358 
02359     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02360     Created:    18/01/95
02361     Inputs:     -
02362     Outputs:    The undo string for the operation
02363     Returns:    
02364     Purpose:    The GetOpName fn is overridden so that we return back a description
02365                 appropriate to the type of attribute that the operation applies.
02366 
02367 ********************************************************************************************/
02368 
02369 void OpPasteEnvelope::GetOpName(String_256* OpName)
02370 {
02371     *OpName = String_256(_R(IDS_UNDO_PASTEENVELOPE));
02372 }
02373 
02374 
02375 
02376 
02377 /********************************************************************************************
02378 
02379 > void OpPasteEnvelope::Do(OpDescriptor* opDesc)
02380 
02381     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>       
02382     Created:    18/01/95
02383     Inputs:     pointer to an OpDescriptor (unused)
02384                 pointer to a pastemould parameter block
02385     Outputs:    -
02386     Returns:    -
02387     Purpose:    
02388     Errors:     failandexecute will be called if the operation fails in some way, most
02389                 likely when no memory is available. 
02390 
02391 ********************************************************************************************/
02392 
02393 void OpPasteEnvelope::Do(OpDescriptor* pOpDescr)
02394 {
02395     // just call the parent class
02396     OpPasteMouldShape::Do(MOULDSPACE_ENVELOPE);
02397 }
02398 
02399 
02400 
02401 
02402 /********************************************************************************************
02403 
02404 >   OpPastePerspective::OpPastePerspective() 
02405 
02406     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02407     Created:    18/01/95
02408     Purpose:    Constructor for paste envelope operation
02409     SeeAlso:    -
02410 
02411 ********************************************************************************************/
02412 
02413 OpPastePerspective::OpPastePerspective()
02414 {
02415     // Dummy constructor
02416 }
02417 
02418 
02419 /********************************************************************************************
02420 
02421 >   BOOL OpPastePerspective::Init()
02422 
02423     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02424     Created:    18/01/95
02425     Inputs:     -
02426     Outputs:    -
02427     Returns:    TRUE if the operation could be successfully initialised 
02428                 FALSE if no more memory could be allocated 
02429     Purpose:    Initialise the paste mould operation so that it can be accessed from the
02430                 interface.
02431 
02432     Errors:     ERROR will be called if there was insufficient memory to allocate the 
02433                 operation.
02434     SeeAlso:    -
02435 
02436 ********************************************************************************************/
02437 
02438 BOOL OpPastePerspective::Init()
02439 {
02440     return (RegisterOpDescriptor(0,                                 // tool ID
02441                                 _R(IDS_PASTEPERSPECTIVE),               // string resource ID
02442                                 CC_RUNTIME_CLASS(OpPastePerspective),   // runtime class for Op
02443                                 OPTOKEN_PASTEPERSPECTIVE,           // Ptr to token string
02444                                 OpPastePerspective::GetState,       // GetState function
02445                                 0,                                  // help ID
02446                                 _R(IDBBL_PASTEPERSPECTIVE),             // bubble help ID
02447                                 _R(IDD_MOULDTOOLBAR),                   // resource ID
02448                                 _R(IDC_BTN_PASTEPERSPECTIVE),               // control ID
02449                                 SYSTEMBAR_EDIT,                     // Group bar ID
02450                                 TRUE,                               // Receive messages
02451                                 FALSE,                              // Smart
02452                                 FALSE,                              // Clean
02453                                 0,                                  // One open Instance ID
02454                                 (GREY_WHEN_NO_CURRENT_DOC | GREY_WHEN_NO_SELECTION)
02455                                 )); 
02456 }               
02457 
02458 
02459 /********************************************************************************************
02460 
02461 >   OpState OpPastePerspective::GetState(String_256*, OpDescriptor*)
02462 
02463     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02464     Created:    18/01/95
02465     Inputs:     -
02466     Outputs:    -
02467     Returns:    The state of the OpPasteMouldShape
02468     Purpose:    For finding the OpPasteMouldShape state. 
02469 
02470 ********************************************************************************************/
02471 
02472 OpState OpPastePerspective::GetState(String_256* UIDescription, OpDescriptor*)
02473 {
02474     OpState OpSt;
02475 //  String_256 DisableReason; 
02476 //  OpSt.Greyed=(!FindPasteObject(NULL));
02477 
02478     OpSt.Greyed = TRUE;
02479 
02480     if (FindPasteObject(NULL))
02481     {
02482         // Get the selection and the number of selected objects
02483         SelRange* Selected = GetApplication()->FindSelection();
02484         INT32 Count = Selected->Count();
02485 
02486         // Are there any selected objects?
02487         if (Count > 0)
02488         {
02489             ObjChangeFlags cFlags;
02490             cFlags.DeleteNode  = TRUE;
02491             OpPasteEnvelope* op = new OpPasteEnvelope ();       // need an op to do correct processing
02492             ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,op);
02493 
02494             Node* pNode = Selected->FindFirst();
02495             OpSt.Greyed = FALSE;
02496             while (pNode != NULL && !OpSt.Greyed)
02497             {
02498                 OpSt.Greyed = !pNode->AllowOp(&ObjChange,FALSE);
02499                 pNode = Selected->FindNext(pNode);
02500             }
02501             delete (op);
02502         }
02503     }
02504 
02505     return(OpSt);   
02506 }
02507 
02508 
02509 
02510 
02511 /********************************************************************************************
02512 
02513 >   void OpPastePerspective::GetOpName(String_256* OpName)
02514 
02515     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02516     Created:    18/01/95
02517     Inputs:     -
02518     Outputs:    The undo string for the operation
02519     Returns:    
02520     Purpose:    The GetOpName fn is overridden so that we return back a description
02521                 appropriate to the type of attribute that the operation applies.
02522 
02523 ********************************************************************************************/
02524 
02525 void OpPastePerspective::GetOpName(String_256* OpName)
02526 {
02527     *OpName = String_256(_R(IDS_UNDO_PASTEPERSPECTIVE));
02528 }
02529 
02530 
02531 
02532 
02533 /********************************************************************************************
02534 
02535 > void OpPastePerspective::Do(OpDescriptor* opDesc)
02536 
02537     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>       
02538     Created:    18/01/95
02539     Inputs:     pointer to an OpDescriptor (unused)
02540                 pointer to a pastemould parameter block
02541     Outputs:    -
02542     Returns:    -
02543     Purpose:    
02544     Errors:     failandexecute will be called if the operation fails in some way, most
02545                 likely when no memory is available. 
02546 
02547 ********************************************************************************************/
02548 
02549 void OpPastePerspective::Do(OpDescriptor* pOpDescr)
02550 {
02551     // just call the parent class
02552     OpPasteMouldShape::Do(MOULDSPACE_PERSPECTIVE);
02553 }
02554 
02555 
02556 
02557 
02558 
02559 /********************************************************************************************
02560 
02561 >   OpToggleMouldGrid::OpToggleMouldGrid() 
02562 
02563     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02564     Created:    18/01/95
02565     Purpose:    Constructor for toggle mould grid operation
02566     SeeAlso:    -
02567 
02568 ********************************************************************************************/
02569 
02570 OpToggleMouldGrid::OpToggleMouldGrid()
02571 {
02572     // Dummy constructor
02573 }
02574   
02575 
02576 
02577 /********************************************************************************************
02578 
02579 >   BOOL OpToggleMouldGrid::Init()
02580 
02581     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02582     Created:    18/01/95
02583     Inputs:     -
02584     Outputs:    -
02585     Returns:    TRUE if the operation could be successfully initialised 
02586                 FALSE if no more memory could be allocated 
02587     Purpose:    Initialise the toggle mould grid operation so that it can be accessed from the
02588                 interface.
02589 
02590     Errors:     ERROR will be called if there was insufficient memory to allocate the 
02591                 operation.
02592     SeeAlso:    -
02593 
02594 ********************************************************************************************/
02595 
02596 BOOL OpToggleMouldGrid::Init()
02597 {
02598     return (RegisterOpDescriptor(0,                                     // tool ID
02599                                 _R(IDS_TOGGLEMOULDGRID),                    // string resource ID
02600                                 CC_RUNTIME_CLASS(OpToggleMouldGrid),    // runtime class for Op
02601                                 OPTOKEN_TOGGLEMOULDGRID,                // Ptr to token string
02602                                 OpToggleMouldGrid::GetState,            // GetState function
02603                                 0,                                      // help ID
02604                                 _R(IDBBL_TOGGLEMOULDGRID),                  // bubble help ID
02605                                 _R(IDD_MOULDTOOLBAR),                       // resource ID
02606                                 _R(IDC_BTN_TOGGLEMOULDGRID),                // control ID
02607                                 SYSTEMBAR_EDIT,                         // Group bar ID
02608                                 TRUE,                                   // Receive messages
02609                                 FALSE,                                  // Smart
02610                                 FALSE,                                  // Clean
02611                                 0,                                      // One open Instance ID
02612                                 (GREY_WHEN_NO_CURRENT_DOC | GREY_WHEN_NO_SELECTION)
02613                                 )); 
02614 }               
02615 
02616 
02617 /********************************************************************************************
02618 
02619 >   OpState OpToggleMouldGrid::GetState(String_256*, OpDescriptor*)
02620 
02621     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02622     Created:    18/01/95
02623     Inputs:     -
02624     Outputs:    -
02625     Returns:    The state of the OpToggleMouldGrid
02626     Purpose:    For finding the OpToggleMouldGrid state. 
02627 
02628 ********************************************************************************************/
02629 
02630 OpState OpToggleMouldGrid::GetState(String_256* UIDescription, OpDescriptor*)
02631 {
02632     OpState OpSt;
02633     String_256 DisableReason; 
02634     OpSt.Greyed = FALSE;
02635 
02636 /*
02637     if (Document::GetCurrent() != NULL)
02638     {
02639         SelRange* Selected = GetApplication()->FindSelection();
02640         if (Selected)
02641             if (!Selected->FindObject(CC_RUNTIME_CLASS(NodeMould), NULL))
02642                 OpSt.Greyed = TRUE;
02643     }
02644 */
02645 
02646     BOOL Sel = FALSE;
02647     if (Document::GetCurrent() != NULL)
02648     {
02649         SelRange* Selected = GetApplication()->FindSelection();
02650         if (Selected)
02651         {
02652             Node* pNode = Selected->FindFirst();
02653             while ((pNode!=NULL) && (!Sel))
02654             {
02655                 if (pNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodeMould))
02656                     Sel=TRUE;
02657 
02658                 pNode = Selected->FindNext(pNode);
02659             }
02660         }
02661     }
02662 
02663     if (!Sel)
02664         OpSt.Greyed = TRUE;
02665 
02666     return (OpSt);   
02667 }
02668 
02669 
02670 /********************************************************************************************
02671 
02672 > void OpToggleMouldGrid::Do(OpDescriptor* opDesc)
02673 
02674     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>       
02675     Created:    18/01/95
02676     Inputs:     pointer to an OpDescriptor (unused)
02677     Outputs:    -
02678     Returns:    -
02679     Purpose:    
02680     Errors:     failandexecute will be called if the operation fails in some way, most
02681                 likely when no memory is available. 
02682 
02683 ********************************************************************************************/
02684 
02685 void OpToggleMouldGrid::Do(OpDescriptor*)
02686 {
02687     // Get a snapshot of the selection
02688     SelRange* Selected = GetApplication()->FindSelection();
02689     Node* pNode = Selected->FindFirst();
02690     while (pNode)
02691     {
02692         if (pNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodeMould))
02693         {
02694             NodeMould* pMould = (NodeMould*)pNode;
02695             MouldGeometry* pGeometry = pMould->GetGeometry();
02696             if (pGeometry!=NULL)
02697             {
02698                 Spread* pSpread = pNode->FindParentSpread();
02699                 if (pSpread)
02700                     pGeometry->ToggleControlBlobs(pSpread);
02701             }
02702         }
02703         pNode = Selected->FindNext(pNode);
02704     }
02705     End();
02706 }
02707 
02708 
02709 
02710 
02711 
02712 
02713 /********************************************************************************************
02714 
02715 >   OpDetachMould::OpDetachMould() 
02716 
02717     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02718     Created:    20/03/95
02719     Purpose:    Constructor for Detach mould operation
02720     SeeAlso:    -
02721 
02722 ********************************************************************************************/
02723 
02724 OpDetachMould::OpDetachMould()
02725 {
02726     // Dummy constructor
02727 }
02728   
02729 
02730 
02731 /********************************************************************************************
02732 
02733 >   BOOL OpDetachMould::Init()
02734 
02735     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02736     Created:    20/03/95
02737     Inputs:     -
02738     Outputs:    -
02739     Returns:    TRUE if the operation could be successfully initialised 
02740                 FALSE if no more memory could be allocated 
02741     Purpose:    Initialise the detach mould operation so that it can be accessed from the
02742                 interface.
02743 
02744     Errors:     ERROR will be called if there was insufficient memory to allocate the 
02745                 operation.
02746     SeeAlso:    -
02747 
02748 ********************************************************************************************/
02749 
02750 BOOL OpDetachMould::Init()
02751 {
02752     return (RegisterOpDescriptor(0,                                 // tool ID
02753                                 _R(IDS_DETACHMOULD),                    // string resource ID
02754                                 CC_RUNTIME_CLASS(OpDetachMould),    // runtime class for Op
02755                                 OPTOKEN_DETACHMOULD,                // Ptr to token string
02756                                 OpDetachMould::GetState,            // GetState function
02757                                 0,                                  // help ID
02758                                 _R(IDBBL_DETACHMOULD),                  // bubble help ID
02759                                 0
02760                                 ));
02761 }               
02762 
02763 
02764 /********************************************************************************************
02765 
02766 >   OpState OpDetachMould::GetState(String_256*, OpDescriptor*)
02767 
02768     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02769     Created:    20/03/95
02770     Inputs:     -
02771     Outputs:    -
02772     Returns:    The state of the OpDetachMould
02773     Purpose:    For finding the OpDetachMould state. 
02774 
02775 ********************************************************************************************/
02776 
02777 OpState OpDetachMould::GetState(String_256* UIDescription, OpDescriptor*)
02778 {
02779     OpState OpSt;
02780     String_256 DisableReason; 
02781 
02782     NodeMould* pLastMould;
02783     INT32 nmoulds = MouldInfoBarOp::SelInfo(&pLastMould);
02784 
02785     // Set the detach operation tick and grey fields correctly
02786     OpSt.Greyed = (nmoulds==0);
02787     OpSt.Ticked = ((nmoulds==1) && pLastMould->IsDetached());
02788 
02789     return (OpSt);   
02790 }
02791 
02792 /********************************************************************************************
02793 
02794 >   void OpDetachMould::GetOpName(String_256* OpName)
02795 
02796     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02797     Created:    18/01/95
02798     Inputs:     -
02799     Outputs:    The undo string for the operation
02800     Returns:    
02801     Purpose:    The GetOpName fn is overridden so that we return back a description
02802                 appropriate to the type of attribute that the operation applies.
02803 
02804 ********************************************************************************************/
02805 
02806 void OpDetachMould::GetOpName(String_256* OpName)
02807 {
02808     *OpName = String_256(_R(IDS_UNDO_DETACHMOULD));
02809 }
02810 
02811 
02812 
02813 /********************************************************************************************
02814 
02815 > void OpDetachMould::Do(OpDescriptor*)
02816 
02817     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>       
02818     Created:    20/03/95
02819     Inputs:     pointer to an OpDescriptor (unused)
02820     Outputs:    -
02821     Returns:    -
02822     Purpose:    
02823     Errors:     failandexecute will be called if the operation fails in some way, most
02824                 likely when no memory is available. 
02825 
02826 ********************************************************************************************/
02827 
02828 void OpDetachMould::Do(OpDescriptor*)
02829 {
02830     BeginSlowJob();
02831 
02832     // Note, I only spent the whole afternoon trying to work out why DoStartSelOp(XX,YY)
02833     // Was completely screwing up the selection here. Anyway, the solution was to
02834     // derive this op from UndoableOperation, not SelOperation which solved the problem
02835     // immediately. The morel is, if the selection is not changing, dont use SelOperation!
02836     // + It stops lots of flashing of blobs too.
02837 
02838     // Scan the selection
02839     SelRange* Selected = GetApplication()->FindSelection();
02840     Node* pNode = Selected->FindFirst();
02841     while (pNode)
02842     {
02843         if (pNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodeMould))
02844         {
02845             NodeMould* pMould = (NodeMould*)pNode;
02846 
02847             SaveDetachAction* pSaveDetAct;
02848             ALLOC_WITH_FAIL(pSaveDetAct, (new SaveDetachAction), this);
02849             if (pSaveDetAct==NULL)
02850             {
02851                 FailAndExecute(); End(); return;
02852             }
02853             
02854             if ((pSaveDetAct->Save(this, pMould))==AC_FAIL)
02855             {
02856                 FailAndExecute(); End(); return;
02857             }
02858 
02859             // toggle the detach type
02860             pMould->ToggleDetachFlag();
02861 
02862             if (!pMould->IsDetached())
02863             {
02864                 if (!DoInvalidateNodeRegion(pMould,TRUE))
02865                 {
02866                     FailAndExecute(); End(); return;
02867                 }
02868 
02869                 if (pMould->StartSaveContext(this,REC_REBUILD)!=CC_OK)
02870                 {
02871                     FailAndExecute(); End(); return;
02872                 }
02873 
02874                 if (pMould->RemouldAll(this)!=CC_OK)
02875                 {
02876                     FailAndExecute(); End(); return;
02877                 }
02878 
02879                 if (pMould->EndSaveContext(this,REC_REBUILD)!=CC_OK)
02880                 {
02881                     FailAndExecute(); End(); return;
02882                 }
02883             }
02884         }
02885         pNode = Selected->FindNext(pNode);
02886     }
02887 
02888     End();
02889 }
02890 
02891 
02892 
02893 
02894 /********************************************************************************************
02895 
02896 >   OpRotateMould::OpRotateMould() 
02897 
02898     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02899     Created:    20/02/95
02900     Purpose:    Constructor for Detach mould operation
02901     SeeAlso:    -
02902 
02903 ********************************************************************************************/
02904 
02905 OpRotateMould::OpRotateMould()
02906 {
02907     // Dummy constructor
02908 }
02909   
02910 
02911 
02912 /********************************************************************************************
02913 
02914 >   BOOL OpRotateMould::Init()
02915 
02916     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02917     Created:    20/03/95
02918     Inputs:     -
02919     Outputs:    -
02920     Returns:    TRUE if the operation could be successfully initialised 
02921                 FALSE if no more memory could be allocated 
02922     Purpose:    Initialise the rotate mould operation so that it can be accessed from the
02923                 interface.
02924     Errors:     ERROR will be called if there was insufficient memory to allocate the 
02925                 operation.
02926 
02927 ********************************************************************************************/
02928 
02929 BOOL OpRotateMould::Init()
02930 {
02931     return (RegisterOpDescriptor(0,                                 // tool ID
02932                                 _R(IDS_ROTATEMOULD),                    // string resource ID
02933                                 CC_RUNTIME_CLASS(OpRotateMould),    // runtime class for Op
02934                                 OPTOKEN_ROTATEMOULD,                // Ptr to token string
02935                                 OpRotateMould::GetState,            // GetState function
02936                                 0,                                  // help ID
02937                                 _R(IDBBL_ROTATEMOULD),                  // bubble help ID
02938                                 _R(IDD_MOULDTOOLBAR),                   // resource ID
02939                                 _R(IDC_BTN_ROTATEMOULD),                // control ID
02940                                 SYSTEMBAR_EDIT,                     // Group bar ID
02941                                 TRUE,                               // Receive messages
02942                                 FALSE,                              // Smart
02943                                 FALSE,                              // Clean
02944                                 0,                                  // One open Instance ID
02945                                 (GREY_WHEN_NO_CURRENT_DOC | GREY_WHEN_NO_SELECTION)
02946                                 )); 
02947              
02948 }               
02949 
02950 
02951 /********************************************************************************************
02952 
02953 >   OpState OpRotateMould::GetState(String_256*, OpDescriptor*)
02954 
02955     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02956     Created:    20/03/95
02957     Inputs:     -
02958     Outputs:    -
02959     Returns:    The state of the OpRotateMould
02960     Purpose:    For finding the OpRotateMould state. 
02961 
02962 ********************************************************************************************/
02963 
02964 OpState OpRotateMould::GetState(String_256* UIDescription, OpDescriptor*)
02965 {
02966     OpState OpSt;
02967     String_256 DisableReason; 
02968     OpSt.Greyed = FALSE;
02969 
02970     BOOL Sel = FALSE;
02971     if (Document::GetCurrent() != NULL)
02972     {
02973         SelRange* Selected = GetApplication()->FindSelection();
02974         if (Selected)
02975         {
02976             Node* pNode = Selected->FindFirst();
02977             while ((pNode!=NULL) && (!Sel))
02978             {
02979                 // only rotate mould objects if they're not detached.
02980                 if (pNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodeMould))
02981                 {
02982                     if ( !((NodeMould*)pNode)->IsDetached() )
02983                         Sel=TRUE;
02984                 }
02985                 pNode = Selected->FindNext(pNode);
02986             }
02987         }
02988     }
02989 
02990     if (!Sel)
02991         OpSt.Greyed = TRUE;
02992 
02993     return (OpSt);   
02994 }
02995 
02996 /********************************************************************************************
02997 
02998 >   void OpRotateMould::GetOpName(String_256* OpName)
02999 
03000     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
03001     Created:    18/01/95
03002     Inputs:     -
03003     Outputs:    The undo string for the operation
03004     Returns:    
03005     Purpose:    The GetOpName fn is overridden so that we return back a description
03006                 appropriate to the type of attribute that the operation applies.
03007 
03008 ********************************************************************************************/
03009 
03010 void OpRotateMould::GetOpName(String_256* OpName)
03011 {
03012     *OpName = String_256(_R(IDS_UNDO_ROTATEMOULD));
03013 }
03014 
03015 /********************************************************************************************
03016 
03017 > void OpRotateMould::Do(OpDescriptor* opDesc)
03018 
03019     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>       
03020     Created:    18/01/95
03021     Inputs:     pointer to an OpDescriptor (unused)
03022     Outputs:    -
03023     Returns:    -
03024     Purpose:    Scan through the selection finding mould objects. Each mould will have
03025                 its contents remoulded, having has its mould path rotated around
03026                 logically by one element. The result will be to spin the orientation
03027                 of the moulded objects around.
03028     Errors:     failandexecute will be called if the operation fails in some way, most
03029                 likely when no memory is available. 
03030 
03031 ********************************************************************************************/
03032 
03033 void OpRotateMould::Do(OpDescriptor*)
03034 {
03035     BeginSlowJob();
03036     SelRange* Selected = GetApplication()->FindSelection();
03037     Node* pNode = Selected->FindFirst();
03038     while (pNode)
03039     {
03040         if (pNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodeMould))
03041         {
03042             NodeMould* pMould = (NodeMould*)pNode;
03043 
03044             if (!DoInvalidateNodeRegion(pMould,TRUE))
03045             {
03046                 FailAndExecute(); End(); return;
03047             }
03048 
03049             if (!DoRotateMould(pMould))
03050             {
03051                 FailAndExecute(); End(); return;
03052             }
03053         }
03054         pNode = Selected->FindNext(pNode);
03055     }
03056     End();
03057 }
03058 
03059 
03060 
03061 
03062 
03063 /********************************************************************************************
03064 
03065 >   OpRectangularEnvelope::OpRectangularEnvelope() 
03066 
03067     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
03068     Created:    20/02/95
03069     Purpose:    Constructor for Detach mould operation
03070     SeeAlso:    -
03071 
03072 ********************************************************************************************/
03073 
03074 OpRectangularEnvelope::OpRectangularEnvelope()
03075 {
03076     // Dummy constructor
03077 }
03078   
03079 
03080 
03081 /********************************************************************************************
03082 
03083 >   BOOL OpRectangularEnvelope::Init()
03084 
03085     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
03086     Created:    20/03/95
03087     Inputs:     -
03088     Outputs:    -
03089     Returns:    TRUE if the operation could be successfully initialised 
03090                 FALSE if no more memory could be allocated 
03091     Purpose:    Initialise the rotate mould operation so that it can be accessed from the
03092                 interface.
03093     Errors:     ERROR will be called if there was insufficient memory to allocate the 
03094                 operation.
03095 
03096 ********************************************************************************************/
03097 
03098 BOOL OpRectangularEnvelope::Init()
03099 {
03100     return (RegisterOpDescriptor(0,                                     // tool ID
03101                                 _R(IDS_RECTANGULARENVELOPE),                // string resource ID
03102                                 CC_RUNTIME_CLASS(OpRectangularEnvelope),// runtime class for Op
03103                                 OPTOKEN_RECTANGULARENVELOPE,            // Ptr to token string
03104                                 OpRectangularEnvelope::GetState,        // GetState function
03105                                 0,                                      // help ID
03106                                 _R(IDBBL_RECTANGULARENVELOPE)
03107                                 )); 
03108 }               
03109 
03110 
03111 /********************************************************************************************
03112 
03113 >   OpState OpRectangularEnvelope::GetState(String_256*, OpDescriptor*)
03114 
03115     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
03116     Created:    20/03/95
03117     Inputs:     -
03118     Outputs:    -
03119     Returns:    The state of the OpRotateMould
03120     Purpose:    For finding the OpRotateMould state. 
03121 
03122 ********************************************************************************************/
03123 
03124 OpState OpRectangularEnvelope::GetState(String_256* UIDescription, OpDescriptor*)
03125 {
03126     OpState OpSt;
03127     String_256 DisableReason; 
03128     OpSt.Greyed = TRUE;
03129     
03130     ObjChangeFlags cFlags;
03131     cFlags.MultiReplaceNode = TRUE;
03132     ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,NULL);
03133     
03134     SelRange* pSelRange = GetApplication()->FindSelection();
03135     Node* pNode = pSelRange->FindFirst();
03136 
03137     while (pNode != NULL && OpSt.Greyed)
03138     {
03139         OpSt.Greyed = !(pNode->AllowOp(&ObjChange,FALSE));
03140         pNode = pSelRange->FindNext(pNode);
03141     }
03142 
03143     return (OpSt);   
03144 }
03145 
03146 /********************************************************************************************
03147 
03148 >   void OpRectangularEnvelope::GetOpName(String_256* OpName)
03149 
03150     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
03151     Created:    18/01/95
03152     Inputs:     -
03153     Outputs:    The undo string for the operation
03154     Returns:    
03155     Purpose:    The GetOpName fn is overridden so that we return back a description
03156                 appropriate to the type of attribute that the operation applies.
03157 
03158 ********************************************************************************************/
03159 
03160 void OpRectangularEnvelope::GetOpName(String_256* OpName)
03161 {
03162     *OpName = String_256(_R(IDS_UNDO_RECTANGULARENVELOPE));
03163 }
03164 
03165 /********************************************************************************************
03166 
03167 > void OpRectangularEnvelope::Do(OpDescriptor* opDesc)
03168 
03169     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>       
03170     Created:    18/01/95
03171     Inputs:     pointer to an OpDescriptor (unused)
03172     Outputs:    -
03173     Returns:    -
03174     Purpose:    Scan through the selection finding mould objects. Each mould will have
03175                 its contents remoulded, having has its mould path rotated around
03176                 logically by one element. The result will be to spin the orientation
03177                 of the moulded objects around.
03178     Errors:     failandexecute will be called if the operation fails in some way, most
03179                 likely when no memory is available. 
03180 
03181 ********************************************************************************************/
03182 
03183 void OpRectangularEnvelope::Do(OpDescriptor*)
03184 {
03185     BeginSlowJob();
03186 
03187     // Assume faied until proven otherwise.
03188     BOOL Failed=TRUE;
03189 
03190     // Create a manifold to use 
03191     Path* pDefShape = new Path;
03192     if (pDefShape!=NULL)
03193     {
03194         if (pDefShape->Initialise(12,12))
03195         {
03196             if (EnvelopeShapes::Rectangular(pDefShape))
03197             {
03198                 Failed=!CreateNewMould(pDefShape, MOULDSPACE_ENVELOPE, TRUE, FALSE);
03199             }
03200         }
03201         // remove the shape once used
03202         delete pDefShape;
03203     }
03204 
03205     if (Failed)
03206         FailAndExecute();
03207 
03208     End();
03209 }
03210 
03211 
03212 
03213 
03214 
03215 /********************************************************************************************
03216 
03217 >   OpRectangularPerspective::OpRectangularPerspective() 
03218 
03219     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
03220     Created:    20/02/95
03221     Purpose:    Constructor for Detach mould operation
03222     SeeAlso:    -
03223 
03224 ********************************************************************************************/
03225 
03226 OpRectangularPerspective::OpRectangularPerspective()
03227 {
03228     // Dummy constructor
03229 }
03230   
03231 
03232 
03233 /********************************************************************************************
03234 
03235 >   BOOL OpRectangularPerspective::Init()
03236 
03237     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
03238     Created:    20/03/95
03239     Inputs:     -
03240     Outputs:    -
03241     Returns:    TRUE if the operation could be successfully initialised 
03242                 FALSE if no more memory could be allocated 
03243     Purpose:    Initialise the rotate mould operation so that it can be accessed from the
03244                 interface.
03245     Errors:     ERROR will be called if there was insufficient memory to allocate the 
03246                 operation.
03247 
03248 ********************************************************************************************/
03249 
03250 BOOL OpRectangularPerspective::Init()
03251 {
03252     return (RegisterOpDescriptor(0,                                         // tool ID
03253                                 _R(IDS_RECTANGULARPERSPECTIVE),                 // string resource ID
03254                                 CC_RUNTIME_CLASS(OpRectangularPerspective), // runtime class for Op
03255                                 OPTOKEN_RECTANGULARPERSPECTIVE,             // Ptr to token string
03256                                 OpRectangularPerspective::GetState,         // GetState function
03257                                 0,                                          // help ID
03258                                 _R(IDBBL_RECTANGULARPERSPECTIVE)
03259                                 )); 
03260 }               
03261 
03262 
03263 /********************************************************************************************
03264 
03265 >   OpState OpRectangularPerspective::GetState(String_256*, OpDescriptor*)
03266 
03267     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
03268     Created:    20/03/95
03269     Inputs:     -
03270     Outputs:    -
03271     Returns:    The state of the OpRotateMould
03272     Purpose:    For finding the OpRotateMould state. 
03273 
03274 ********************************************************************************************/
03275 
03276 OpState OpRectangularPerspective::GetState(String_256* UIDescription, OpDescriptor*)
03277 {
03278     OpState OpSt;
03279     String_256 DisableReason; 
03280     OpSt.Greyed = TRUE;
03281     
03282     ObjChangeFlags cFlags;
03283     cFlags.MultiReplaceNode = TRUE;
03284     ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,NULL);
03285     
03286     SelRange* pSelRange = GetApplication()->FindSelection();
03287     Node* pNode = pSelRange->FindFirst();
03288 
03289     while (pNode != NULL && OpSt.Greyed)
03290     {
03291         OpSt.Greyed = !(pNode->AllowOp(&ObjChange,FALSE));
03292         pNode = pSelRange->FindNext(pNode);
03293     }
03294 
03295     return (OpSt);   
03296 }
03297 
03298 /********************************************************************************************
03299 
03300 >   void OpRectangularPerspective::GetOpName(String_256* OpName)
03301 
03302     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
03303     Created:    18/01/95
03304     Inputs:     -
03305     Outputs:    The undo string for the operation
03306     Returns:    
03307     Purpose:    The GetOpName fn is overridden so that we return back a description
03308                 appropriate to the type of attribute that the operation applies.
03309 
03310 ********************************************************************************************/
03311 
03312 void OpRectangularPerspective::GetOpName(String_256* OpName)
03313 {
03314     *OpName = String_256(_R(IDS_UNDO_RECTANGULARPERSPECTIVE));
03315 }
03316 
03317 /********************************************************************************************
03318 
03319 > void OpRectangularPerspective::Do(OpDescriptor* opDesc)
03320 
03321     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>       
03322     Created:    18/01/95
03323     Inputs:     pointer to an OpDescriptor (unused)
03324     Outputs:    -
03325     Returns:    -
03326     Purpose:    Scan through the selection finding mould objects. Each mould will have
03327                 its contents remoulded, having has its mould path rotated around
03328                 logically by one element. The result will be to spin the orientation
03329                 of the moulded objects around.
03330     Errors:     failandexecute will be called if the operation fails in some way, most
03331                 likely when no memory is available. 
03332 
03333 ********************************************************************************************/
03334 
03335 void OpRectangularPerspective::Do(OpDescriptor*)
03336 {
03337     BeginSlowJob();
03338 
03339     // Assume faied until proven otherwise.
03340     BOOL Failed=TRUE;
03341 
03342     // Create a manifold to use 
03343     Path* pDefShape = new Path;
03344     if (pDefShape!=NULL)
03345     {
03346         if (pDefShape->Initialise(12,12))
03347         {
03348             if (PerspectiveShapes::Rectangular(pDefShape))
03349             {
03350                 Failed=!CreateNewMould(pDefShape, MOULDSPACE_PERSPECTIVE, TRUE, FALSE);
03351             }
03352         }
03353         // remove the shape once used
03354         delete pDefShape;
03355     }
03356 
03357     if (Failed)
03358         FailAndExecute();
03359 
03360     End();
03361 }
03362 
03363 

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