layermgr.cpp

Go to the documentation of this file.
00001 // $Id: layermgr.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 
00099 /* Implementation of the following classes
00100     LyrDetails
00101     LayerManager
00102     OpLayerChange
00103 */ 
00104 
00105 // Include files 
00106 #include "camtypes.h"
00107 #include "layermgr.h"
00108 //#include "fixst256.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 //#include "mainfrm.h" 
00111 #include "infobar.h" 
00112 //#include "simon.h"
00113 //#include "mario.h"
00114 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00115 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00116 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00117 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00118 //#include "ink.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00119 #include "bubbleid.h"
00120 //#include "sliceres.h" // for the resource id move to active layer
00121 #include "objchge.h" // for the allow op flags
00122 //#include "bars.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00123 
00124 //#include "will2.h"
00125 //#include "selop.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00126 
00127 DECLARE_SOURCE("$Revision: 1282 $");
00128 
00129 // Declare class for memory tracking etc
00130 CC_IMPLEMENT_DYNCREATE(OpLayerChange, UndoableOperation) 
00131 CC_IMPLEMENT_DYNCREATE(ChangeLyrAttribAction, Action)
00132 CC_IMPLEMENT_MEMDUMP(LyrDetails, ListItem)
00133 CC_IMPLEMENT_DYNCREATE(OpMoveToLayer, SelOperation) 
00134 #define new CAM_DEBUG_NEW    
00135 
00136 /********************************************************************************************
00137 
00138 >   LyrDetails::LyrDetails()
00139 
00140     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00141     Created:    14/1/94
00142     Inputs:     -
00143     Outputs:    -
00144     Returns:    -
00145     Purpose:    LyrDetails constructor
00146     Errors:     -
00147     SeeAlso:    -
00148 
00149 ********************************************************************************************/
00150 
00151 LyrDetails::LyrDetails()
00152 {
00153 }
00154 
00155 /********************************************************************************************
00156 
00157 >   LayerManager::LayerManager()
00158 
00159     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00160     Created:    10/1/94
00161     Inputs:     -
00162     Outputs:    -
00163     Returns:    -
00164     Purpose:    LayerManager Constructor, initially the LayerManager has no CurrentSpread. 
00165     Errors:     -
00166     SeeAlso:    -
00167 
00168 ********************************************************************************************/
00169 
00170 LayerManager::LayerManager()
00171 {
00172     CurrentSpread = NULL; // There is no current spread 
00173 }
00174 
00175 /********************************************************************************************
00176 
00177 >   LayerManager::~LayerManager()
00178 
00179     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00180     Created:    10/1/94
00181     Inputs:     -
00182     Outputs:    -
00183     Returns:    -
00184     Purpose:    LayerManager destructor 
00185     Errors:     -
00186     SeeAlso:    -
00187 
00188 ********************************************************************************************/
00189 
00190 LayerManager::~LayerManager()
00191 {
00192     DeleteLayerDetList(); // Delete the layer details list  
00193 }
00194 
00195 /********************************************************************************************
00196 
00197 >    String_256 LayerManager::CreateUniqueLayerID()
00198 
00199     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00200     Created:    10/1/94
00201     Inputs:     -
00202     Outputs:    -
00203     Returns:    A LayerID which is unique for the current spread. 
00204     Purpose:    Used to generate a LayerID which is unique for the current spread. The name 
00205                 generated is normally of the form "Layer n", where n is the number of layers 
00206                 in the LyrDetList + 1. If "Layer n" already exists on the current spread then 
00207                 "Layer m" is generated where m is the smallest integer greater than n such 
00208                 that the id is unique.     
00209     Errors:     -
00210     SeeAlso:    -
00211 
00212 ********************************************************************************************/
00213 
00214 String_256 LayerManager::CreateUniqueLayerID()
00215 {
00216     // We can't generate a unique id if there is no current spread 
00217     ENSURE(CurrentSpread != NULL, "There is no current spread"); 
00218 
00219     String_256 UniqueLayerID; 
00220     INT32 NumLayers = 0; 
00221 
00222     ListItem* Lyr = LyrDetList.GetHead(); 
00223 
00224     // Calculate how many layers are on the current spread, we must ignore layers 
00225     // which have been deleted. 
00226     while (Lyr != NULL)
00227     {
00228         if (!((LyrDetails*)Lyr)->Deleted)    // Don't count deleted layers 
00229         {
00230             NumLayers++;    
00231         }
00232         Lyr = LyrDetList.GetNext(Lyr); 
00233     }
00234 
00235     ENSURE(NumLayers != 0, "The current spread has no layers"); 
00236 
00237 
00238     INT32 NewLayerNum = NumLayers+1; 
00239 
00240     BOOL Unique;  // Flag used to indicate if the id generated is unique or not 
00241     do 
00242     {
00243         // Construct a first attempt at a unique layer id 'Layer n' 
00244         // where n = the number of layers on the current spread + 1
00245      
00246         UniqueLayerID.MakeMsg(_R(IDS_LAYERMGR_LAYERNAME),NewLayerNum);   
00247     
00248         // Check that UniqueLayerID is indeed unique 
00249         Unique = TRUE; // Until we know better 
00250         Lyr = LyrDetList.GetHead(); 
00251         while (Lyr != NULL)
00252         {   
00253             if (!((LyrDetails*)Lyr)->Deleted)   // Ignore deleted layers 
00254             {
00255                 if (UniqueLayerID == ((LyrDetails*)Lyr)->Status.StringLayerID)
00256                 {
00257                     Unique = FALSE; 
00258 
00259                     // UniqueLayerID is not unique so increment NewLayerNum and try again 
00260                     NewLayerNum++;      
00261                     break; 
00262                 }
00263             }
00264             Lyr = LyrDetList.GetNext(Lyr); // Get the next layer  
00265         }
00266         
00267     } while (!Unique); 
00268     return(UniqueLayerID); 
00269 }
00270 
00271 /********************************************************************************************
00272 
00273 >   BOOL LayerManager::CommitLayerChanges()
00274 
00275     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00276     Created:    10/1/94
00277     Inputs:     -
00278     Outputs:    -
00279     Returns:    Returns TRUE if successful, else InformError gets called and FALSE returned. 
00280 
00281     Purpose:    If the layer details have changed then performs a LayerChangeOp which 
00282                 modifies the Camelot tree to reflect the changes made to the LyrDetList. 
00283 
00284     Errors:     -
00285     SeeAlso:    -
00286 
00287 ********************************************************************************************/
00288 
00289 
00290 BOOL LayerManager::CommitLayerChanges()
00291 {
00292     if (LayerDetailsChanged()) // The layer details have changed so we need to perform 
00293                                // a LayerChangeOp to commit the changes.  
00294     {
00295         // Invoke the layer change operation 
00296         // Obtain a pointer to the op descriptor for the Layer change operation 
00297         OpDescriptor* OpDesc = 
00298             OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpLayerChange)); 
00299         // Invoke the operation. 
00300         OpDesc->Invoke();
00301     }
00302     if (RefreshLayerDetails()) // We need to refresh the layer details even if the layers were 
00303                                // not changed because a new layer could have been deleted  
00304     {
00305         return TRUE; 
00306     }
00307     else return FALSE; // Failed to refresh layer details (InformError has been called)
00308 }               
00309 
00310 /********************************************************************************************
00311 
00312 >   BOOL LayerManager::NewCurrentSpread(Spread* NewCurrentSpread)               
00313 
00314     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00315     Created:    10/1/94
00316     Inputs:     NewCurrentSpread
00317     Outputs:    -
00318     Returns:    TRUE if successful, else FALSE
00319     Purpose:    Sets a new current spread. 
00320     Errors:     InformError gets called and FALSE is returned if we run out of memory
00321     SeeAlso:    -
00322 
00323 ********************************************************************************************/
00324 
00325 
00326 BOOL LayerManager::NewCurrentSpread(Spread* NewCurrentSpread)               
00327 {
00328     ENSURE(NewCurrentSpread != NULL, "The new current spread is NULL"); 
00329     BOOL ok = TRUE;
00330     
00331     if (CurrentSpread != NULL)  // There is already a current spread 
00332     {
00333         
00334         // The LayerDetList should never be empty 
00335         ENSURE(!LyrDetList.IsEmpty(), "Empty Layer details list"); 
00336 
00337         DeleteLayerDetList();  
00338     
00339     }
00340     
00341     // The LayerDetList should be empty 
00342     ENSURE(LyrDetList.IsEmpty(), "Empty Layer details list"); 
00343 
00344     CurrentSpread = NewCurrentSpread; 
00345 
00346     // Read the current spread's layer details into the LyrDetList
00347     ok = ReadSpreadLayerDetails();
00348 
00349     return (ok);
00350 }
00351 
00352 /********************************************************************************************
00353 
00354 >   Spread* LayerManager::GetCurrentSpread()
00355 
00356     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00357     Created:    18/1/94
00358     Inputs:     -
00359     Outputs:    -
00360     Returns:    The LayerManagers current spread
00361     Purpose:    For finding the current spread
00362     Errors:     -
00363     SeeAlso:    -
00364 
00365 ********************************************************************************************/
00366 
00367 Spread* LayerManager::GetCurrentSpread()
00368 {
00369     return CurrentSpread; 
00370 }
00371 
00372 /********************************************************************************************
00373 
00374 >   void LayerManager::UpdateInterface()
00375 
00376     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00377     Created:    17/1/94
00378     Inputs:     -
00379     Outputs:    -
00380     Returns:    -
00381     Purpose:    Updates the interface after layers have changed. 
00382     Errors:     -
00383     SeeAlso:    -
00384 
00385 ********************************************************************************************/
00386 
00387 void LayerManager::UpdateInterface()
00388 {
00389 //  BroadcastNewCurrentSpread(); 
00390 }
00391 
00392 /********************************************************************************************
00393 
00394 >   void LayerManager::BroadcastNewCurrentSpread()
00395 
00396 
00397     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00398     Created:    10/1/94
00399     Inputs:     -
00400     Outputs:    -
00401     Returns:    -
00402     Purpose:    This private function gets called from NewCurrentSpread. It informs all 
00403                 subsystems (that need to know) that the Current Spread  has changed. The 
00404                 LyrDetList contains the new current spread's details before this function is 
00405                 called.  
00406 
00407     Errors:     -
00408     Scope:      private
00409     SeeAlso:    -
00410 
00411 ********************************************************************************************/
00412 
00413 /*
00414 void LayerManager::BroadcastNewCurrentSpread()
00415 {
00416     // The InfoBar needs to know that the current spread has changed so that it can update
00417     // the layer list gadget. 
00418 
00419 //  4/5/94 - Markn changed this as infobar can now be NULL
00420 //  ENSURE(CMainFrame::pInfoBar != NULL, "Infobar pointer is NULL in main frame");  
00421 //  CMainFrame::pInfoBar->NewCurrentSpread(); 
00422 
00423     if (CMainFrame::pInfoBar != NULL)
00424         CMainFrame::pInfoBar->NewCurrentSpread();
00425 }
00426 */
00427 
00428 /********************************************************************************************
00429 
00430 >   BOOL LayerManager::CancelLayerChanges()
00431 
00432     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00433     Created:    10/1/94
00434     Inputs:     -
00435     Outputs:    -
00436     Returns:    TRUE if successful, FALSE otherwise
00437     Purpose:    Causes the changes made to the LyrDetList to be discarded, and new values read. 
00438     Errors:     If memory runs out then InformError is called and the function returns FALSE
00439     SeeAlso:    -
00440 
00441 ********************************************************************************************/
00442 
00443 BOOL LayerManager::CancelLayerChanges()
00444 {
00445     DeleteLayerDetList();     // Delete details including any changes whioch may have been made
00446     if (ReadSpreadLayerDetails()) // Read new values 
00447     {
00448         return TRUE; 
00449     }
00450     else 
00451     {
00452         return FALSE; 
00453     }
00454 } 
00455 
00456 /********************************************************************************************
00457 
00458 >   BOOL LayerManager::RefreshLayerDetails()
00459 
00460     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00461     Created:    17/1/94
00462     Inputs:     -
00463     Outputs:    -
00464     Returns:    Returns TRUE if successful, else calls InformError and returns FALSE
00465     Purpose:    Reads in new layer details and updates the interface. 
00466     Errors:     -
00467     SeeAlso:    -
00468 
00469 ********************************************************************************************/
00470 
00471 BOOL LayerManager::RefreshLayerDetails()
00472 {
00473     // Make sure that no changes have been made 
00474     DeleteLayerDetList();     // Delete details including any changes whioch may have been made
00475     if (ReadSpreadLayerDetails()) // Read new values 
00476     {
00477         UpdateInterface();  
00478         return TRUE;    
00479     }
00480     else return FALSE;   // InformError has been called 
00481 }
00482 
00483 
00484 /********************************************************************************************
00485 
00486 >   void LayerManager::DeleteLayerDetList()
00487 
00488     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00489     Created:    10/1/94
00490     Inputs:     -
00491     Outputs:    -
00492     Returns:    -
00493     Purpose:    Deletes the contents of the LyrDetList 
00494     Errors:     -
00495     Scope:      private
00496     SeeAlso:    -
00497 
00498 ********************************************************************************************/
00499 
00500 void LayerManager::DeleteLayerDetList()
00501 { 
00502     // Delete all current spread details 
00503     ListItem* Current = LyrDetList.GetHead(); 
00504     while (Current != NULL)
00505     {
00506         delete (LyrDetList.RemoveItem(Current)); 
00507         Current = LyrDetList.GetHead(); 
00508     }                
00509 }
00510 
00511 
00512 /********************************************************************************************
00513 
00514 >   BOOL LayerManager::ReadSpreadLayerDetails()
00515 
00516     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00517     Created:    10/1/94
00518     Inputs:     -
00519     Outputs:    -
00520     Returns:    TRUE if successful, else FALSE
00521     Purpose:    Read the current spread's layer details into the LyrDetList. If 
00522                 memory runs out then InformError is called and FALSE is returned. 
00523 
00524     Errors:     -
00525     Scope:      private
00526     SeeAlso:    -
00527 
00528 ********************************************************************************************/
00529 
00530 BOOL LayerManager::ReadSpreadLayerDetails() 
00531 {
00532     ENSURE(CurrentSpread != NULL, "Trying to read the details of a NULL current spread"); 
00533     ENSURE(LyrDetList.IsEmpty(), "Layer details list not empty"); 
00534 
00535     LyrDetails* LayerDet; 
00536 
00537     Layer* Current = CurrentSpread->FindFirstLayer(); 
00538     while (Current != NULL) 
00539     {
00540         // Found a layer so record the details 
00541         LayerDet = new LyrDetails(); 
00542         if (LayerDet == NULL)
00543         {
00544             // Inform an error - The error will already be set by new
00545             InformError();
00546             return FALSE; 
00547         }
00548         LayerDet->Status = (Current)->GetLayerStatus(); // record the layer status  
00549         LayerDet->m_pLayer = Current; 
00550         LayerDet->New = FALSE; 
00551         LayerDet->Deleted = FALSE; 
00552 
00553         LyrDetList.AddTail(LayerDet); // Add the layers details to the tail of the layer 
00554                                        // detail list, so preserving the correct z-order. 
00555         Current = Current->FindNextLayer(); 
00556     }
00557     ENSURE(!LyrDetList.IsEmpty(), "No layers found on the current spread"); 
00558     return TRUE; 
00559 }
00560 
00561 /********************************************************************************************
00562 
00563 >   BOOL LayerManager::LayerDetailsChanged()
00564 
00565     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00566     Created:    21/1/94
00567     Inputs:     -
00568     Outputs:    -
00569     Returns:    TRUE if the LayerDetails list has changed 
00570     Purpose:    This function compares the current spread's layers against the Layer details 
00571                 list. If the layers have changed in any way, then the function returns TRUE. 
00572                 Otherwise the function returns FALSE. 
00573                 
00574     Scope:      private
00575     Errors:     -
00576     SeeAlso:    -
00577 
00578 ********************************************************************************************/
00579 
00580 BOOL LayerManager::LayerDetailsChanged()
00581 {
00582     LyrDetails* CurrentLyrDet = (LyrDetails*)LyrDetList.GetHead();    
00583     Layer* CurrentLyr = CurrentSpread->FindFirstLayer(); // Get the first layer node 
00584     
00585     ENSURE(CurrentLyrDet != NULL, "There are no layer details on the layer details list"); 
00586     ENSURE(CurrentLyr != NULL, "The LayerManager's current spread has no layers"); 
00587     
00588     while (CurrentLyrDet != NULL) 
00589     {
00590         // We ignore deleted new layers because they don't change anything 
00591         if (!(CurrentLyrDet->New && CurrentLyrDet->Deleted))    
00592         {       
00593             if (CurrentLyr != CurrentLyrDet->m_pLayer) // z-order change 
00594             {
00595                 return TRUE; 
00596             }                                   
00597             else if ((CurrentLyrDet->New) || (CurrentLyrDet->Deleted)) 
00598             {
00599                 return TRUE; // New layer created or existing layer deleted 
00600             }
00601             else if (!(CurrentLyrDet->Status == CurrentLyr->GetLayerStatus()))
00602             {   
00603                 // The layer's status has changed 
00604                 return TRUE; 
00605             }  
00606             CurrentLyrDet =  (LyrDetails*)(LyrDetList.GetNext(CurrentLyrDet));
00607             CurrentLyr = (CurrentLyr->FindNextLayer()); 
00608         }   
00609         else    
00610             CurrentLyrDet = (LyrDetails*)(LyrDetList.GetNext(CurrentLyrDet)); 
00611     }      
00612     // Sanity check 
00613     ENSURE (CurrentLyr == NULL, "CurrentLyr ptr should be NULL"); 
00614     return FALSE; // Nothing has changed    
00615 }
00616 
00617 // Methods for the OpLayerChange
00618 
00619 /********************************************************************************************
00620 
00621 >   OpLayerChange::OpLayerChange() 
00622 
00623     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00624     Created:    29/9/93
00625     Inputs:     -
00626     Outputs:    -
00627     Returns:    -
00628     Purpose:    OpLayerChange constructor (Creates an undoable operation)
00629     Errors:     -
00630     SeeAlso:    -
00631 
00632 ********************************************************************************************/
00633             
00634             
00635 OpLayerChange::OpLayerChange(): UndoableOperation()                             
00636 {                              
00637 }
00638 
00639  /********************************************************************************************
00640 
00641 >   BOOL OpLayerChange::Init()
00642 
00643     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00644     Created:    28/9/93
00645     Inputs:     -
00646     Outputs:    -
00647     Returns:    TRUE if the operation could be successfully initialised 
00648                 FALSE if no more memory could be allocated 
00649                 
00650     Purpose:    OpLayerChange initialiser method
00651     Errors:     ERROR will be called if there was insufficient memory to allocate the 
00652                 operation.
00653     SeeAlso:    -
00654 
00655 ********************************************************************************************/
00656 
00657 BOOL OpLayerChange::Init()
00658 {
00659     return (RegisterOpDescriptor(
00660                                 0,
00661                                 _R(IDS_LAYERCHANGEOP),
00662                                 CC_RUNTIME_CLASS(OpLayerChange),
00663                                 OPTOKEN_LYRCHNG,
00664                                 OpLayerChange::GetState,
00665                                 0,  /* help ID */
00666                                 _R(IDBBL_LAYERCHANGEOP),
00667                                 0   /* bitmap ID */));
00668 }               
00669     
00670 /********************************************************************************************
00671 
00672 >   OpState OpLayerChange::GetState(String_256*, OpDescriptor*)
00673 
00674     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00675     Created:    28/9/93
00676     Inputs:     -
00677     Outputs:    -
00678     Returns:    The state of the OpLayerChange operation
00679     Purpose:    For finding the OpLayerChange's state. 
00680     Errors:     -
00681     SeeAlso:    -
00682 
00683 ********************************************************************************************/
00684 
00685 OpState OpLayerChange::GetState(String_256* UIDescription, OpDescriptor*)
00686 {
00687     OpState OpSt;  
00688     return(OpSt);   
00689 }
00690 
00691 /********************************************************************************************
00692 
00693 >   void OpLayerChange::Do(OpDescriptor*)
00694 
00695     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00696     Created:    16/8/93
00697     Inputs:     OpDescriptor (unused)
00698     Outputs:    -
00699     Returns:    -
00700     Purpose:    Performs the layer change operation 
00701                 this operation reads the layer details list of the current documents layer 
00702                 manager, and changes the document tree to reflect any changes which have 
00703                 been made. 
00704     Errors:     -
00705     SeeAlso:    -
00706 
00707 ********************************************************************************************/
00708 // The bounding rectangle of the current layer must be invalidated in all the following cases. 
00709 
00710 // If the visible status has changed 
00711 // If the Quality level has changed 
00712 // If the layer has been deleted 
00713 // If the z-order of the layer has changed
00714 
00715             
00716 void OpLayerChange::Do(OpDescriptor*)
00717 {   
00718     ENSURE(FALSE,"This shouldn't have been called");
00719 /*
00720     Spread* pSpread = Document::GetCurrent()->GetLayerMgr().GetCurrentSpread(); 
00721     // Find the first layer on the spread. All siblings of the first layer node should
00722     // be layer nodes
00723     Node* CurrentTreeLayer = pSpread->FindFirstLayer(); // skips over page nodes 
00724 
00725     ENSURE(CurrentTreeLayer->GetRuntimeClass() == CC_RUNTIME_CLASS(Layer), 
00726             "A next sibling of a layer node is not a layer"); 
00727 
00728 
00729     // Get the first layer details record 
00730     LyrDetails* CurLyrDet = (LyrDetails*)
00731         (Document::GetCurrent()->GetLayerMgr()).LyrDetList.GetHead(); 
00732     
00733     BOOL InvalidateLayersRgn; // Flag used to decide if we should invalidate
00734                               // a layers region
00735     BOOL RemoveSelections;    // Flag used to indicate if we should remove all
00736                               // selections from the layer 
00737 
00738     // loop while there are more changes to be made 
00739     while (CurLyrDet != NULL) 
00740     {
00741         InvalidateLayersRgn = FALSE;
00742         RemoveSelections = FALSE; 
00743 
00744         // We can ignore all new layers which have been deleted 
00745         if (!((CurLyrDet->New) && (CurLyrDet->Deleted)))
00746         {
00747             // Is the layer a new layer ? 
00748             if (CurLyrDet->New)
00749             {
00750                 // Attempt to create a new layer node 
00751                 Layer* NewLyr; 
00752                 ALLOC_WITH_FAIL(NewLyr, (new Layer()), this);         
00753                 if (NewLyr == NULL)
00754                 {
00755                     goto EndOperation; // We were unable to create a new layer so 
00756                                        // abort the operation 
00757                 }
00758                 // Set the new layer's status  
00759                 NewLyr->SetLayerStatus(CurLyrDet->Status); 
00760            
00761                 // Create a hide node action to hide the new node when we undo/redo
00762                 HideNodeAction* UndoHideNodeAction; 
00763                 // ** Change !!!    
00764                 if (!HideNodeAction::Init(this,                    
00765                                           &UndoActions,
00766                                           NewLyr, 
00767                                           TRUE, 
00768                                           ( Action**)(&UndoHideNodeAction))      
00769                                           != AC_FAIL)
00770                 {
00771                     delete NewLyr;     // We won't be needing this 
00772                     goto EndOperation;      
00773                 }
00774                 // All is well 
00775                 if (CurrentTreeLayer != NULL)
00776                 {
00777                     // Add the new layer to the tree as a previous sibling of 
00778                     // the CurrentTreeLayer 
00779                     NewLyr->AttachNode(CurrentTreeLayer, PREV); 
00780                 }
00781                 else 
00782                 {
00783                     // Add the new layer as a last child of the spread 
00784                     NewLyr->AttachNode(Document::GetCurrent()->
00785                         GetLayerMgr().GetCurrentSpread(), LASTCHILD); 
00786                 }
00787             }
00788 
00789             // Has the layer been deleted 
00790             else if (CurLyrDet->Deleted)
00791             {
00792                 if ( CurLyrDet->Layer == CurrentTreeLayer )
00793                 {
00794                     // We are about to hide the CurrentTreeLayer so we need to find the 
00795                     // next layer before we do this 
00796                     CurrentTreeLayer = ((Layer*)CurrentTreeLayer)->FindNextLayer(); 
00797                 }
00798                 
00799                 // If a layer has been deleted then we ignore all attribute changes 
00800                 // which may have been made prior to the layer being deleted. 
00801                 // Change 
00802                 if (!DoHideNode(CurLyrDet->Layer, 
00803                                 TRUE                // Include subtree size 
00804                                 )) // Hide the node 
00805                     goto EndOperation; 
00806                 InvalidateLayersRgn = TRUE; // We will need to invalidate the hidden 
00807                                             // layers bounding region. 
00808                 RemoveSelections = TRUE;    
00809             }
00810             else 
00811             {
00812                 // Have the attributes of the layer changed 
00813                 if ( !(CurLyrDet->Status == CurLyrDet->Layer->GetLayerStatus()) )   
00814                 {
00815         
00816                     // Determine if the attribute changes mean that the layer's 
00817                     // bounding rectangle must be invalidated. 
00818                     LayerStatus Old = CurLyrDet->Layer->GetLayerStatus(); 
00819                     LayerStatus New = CurLyrDet->Status; 
00820                     if (
00821                          (New.Flags.Visible != Old.Flags.Visible) || 
00822                          (New.LayerQualityLevel != Old.LayerQualityLevel)  
00823                        )  
00824                     {
00825                         InvalidateLayersRgn = TRUE; 
00826                     } 
00827 
00828                     // Determine if the attribute changes mean that we should remove
00829                     // the selections on the layer 
00830                     if ( 
00831                         ((New.Flags.Visible != Old.Flags.Visible) && 
00832                          (!New.Flags.Visible)
00833                         ) || 
00834                         ((New.Flags.Locked != Old.Flags.Locked) && 
00835                          (New.Flags.Locked)
00836                         )
00837                        )
00838                     {
00839                         RemoveSelections = TRUE;  
00840                     } 
00841             
00842                     // Try to create an action to restore the attribute changes we 
00843                     // are about to make 
00844                     ChangeLyrAttribAction* UndoAttribChngAction;                          
00845 
00846                     if ( ChangeLyrAttribAction::Init(this,                    
00847                                                   &UndoActions,
00848                                                   sizeof(InvalidateRegionAction),  
00849                                                   CurLyrDet->Layer->GetLayerStatus(),
00850                                                   CurLyrDet->Layer, 
00851                                                   ( Action**)(&UndoAttribChngAction))
00852                                                   != AC_FAIL) 
00853                     {
00854                         // Change the layer's attributes 
00855                         CurLyrDet->Layer->SetLayerStatus(CurLyrDet->Status);    
00856                     }
00857                     else 
00858                         goto EndOperation; // We have failed 
00859             
00860                 }
00861                 // Has the current layers z-position changed ? 
00862                 if (CurLyrDet->Layer != CurrentTreeLayer)
00863                 {
00864                     // I don't think the CurrentTreeLayer can ever be NULL in this situation !
00865                     ENSURE(CurrentTreeLayer != NULL, "The current tree layer is NULL"); 
00866                     // Move the node to its correct tree position 
00867                     // *** Change 
00868                     if(!DoMoveNode(CurLyrDet->Layer, 
00869                                    CurrentTreeLayer, 
00870                                    PREV               // The correct tree position 
00871                                    ))
00872                     {
00873                         goto EndOperation; 
00874                     }                 
00875                 }
00876                 else // The layer is in the correct position in the tree
00877                 {
00878                     CurrentTreeLayer = ((Layer*)CurrentTreeLayer)->FindNextLayer(); 
00879                 }
00880             }
00881             // Do we want to remove the layer's selections 
00882             if (RemoveSelections)
00883             {
00884                 NodeRenderableInk::DeselectAllOnLayer(CurLyrDet->Layer); 
00885             }
00886 
00887             // Do we want to invalidate the bounding rectangle of the layer ? 
00888             if (InvalidateLayersRgn) 
00889             {
00890                 DocRect Bounds = CurLyrDet->Layer->GetBoundingRect();
00891                 // Don't bother if the bounding rectangle is empty 
00892                 if (!Bounds.IsEmpty())
00893                 {                                                     
00894                     // Create an InvalidateRegionAction  
00895                     if (!DoInvalidateNodeRegion(CurLyrDet->Layer, FALSE))
00896                     {
00897                         goto EndOperation; 
00898                     }
00899                 }
00900             }
00901         }
00902         // Process the next layer 
00903         CurLyrDet = (LyrDetails*)
00904             (Document::GetCurrent()->GetLayerMgr()).LyrDetList.GetNext(CurLyrDet); 
00905     }
00906     EndOperation:
00907 */
00908     End(); 
00909 }
00910 
00911 /********************************************************************************************
00912 
00913 >   void OpLayerChange::Undo() 
00914 
00915     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00916     Created:    17/1/94
00917     Inputs:     -
00918     Outputs:    -
00919     Returns:    -
00920     Purpose:    The overloaded Undo operation refreshes the layer details in the layer 
00921                 manager   
00922     Errors:     -
00923     SeeAlso:    -
00924 
00925 ********************************************************************************************/
00926 
00927 BOOL OpLayerChange::Undo() 
00928 {
00929     BOOL Result = Operation::Undo(); 
00930     if (Result)
00931     {
00932         //Document::GetCurrent()->GetLayerMgr().RefreshLayerDetails(); 
00933     }
00934     return (Result); 
00935  
00936 }       
00937 
00938 /********************************************************************************************
00939 
00940 >   void OpLayerChange::Redo()
00941 
00942     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00943     Created:    17/1/94
00944     Inputs:     -
00945     Outputs:    -
00946     Returns:    -
00947     Purpose:    The overloaded Redo operation refreshes the layer details in the layer
00948                 manager 
00949     Errors:     -
00950     SeeAlso:    -
00951 
00952 ********************************************************************************************/
00953 
00954 BOOL OpLayerChange::Redo()
00955 {
00956     BOOL Result = Operation::Redo(); 
00957     if (Result)
00958     {
00959         //Document::GetCurrent()->GetLayerMgr().RefreshLayerDetails(); 
00960     }
00961     return (Result); 
00962 }
00963 
00964 //------------------------------------------------------------------------------------------
00965 //ChangeLyrAttribAction methods 
00966 
00967 /********************************************************************************************
00968 
00969 >   ChangeLyrAttribAction::ChangeLyrAttribAction()
00970 
00971     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00972     Created:    14/9/93
00973     Inputs:     -
00974     Outputs:    -
00975     Returns:    -
00976     Purpose:    ChangeLyrAttribAction constructor
00977     Errors:     -
00978     SeeAlso:    -
00979 
00980 ********************************************************************************************/
00981     
00982 ChangeLyrAttribAction::ChangeLyrAttribAction()
00983 {
00984 }
00985 
00986 /********************************************************************************************
00987 
00988 >   ChangeLyrAttribAction::~ChangeLyrAttribAction() 
00989 
00990     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00991     Created:    13/1/94
00992     Inputs:     -
00993     Outputs:    -
00994     Returns:    -
00995     Purpose:    ChangeLyrAttribAction destructor 
00996     Errors:     -
00997     SeeAlso:    -
00998 
00999 ********************************************************************************************/
01000 
01001 
01002 
01003 ChangeLyrAttribAction::~ChangeLyrAttribAction() 
01004 { 
01005 
01006 }   
01007 
01008 
01009  
01010 /********************************************************************************************
01011 
01012 >   virtual ActionCode ChangeLyrAttribAction::Execute()
01013 
01014     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
01015     Created:    16/8/93
01016     Inputs:     -
01017     Outputs:    ActionCode indicating if the action was successfully executed or not
01018     Returns:    -
01019     Purpose:    Executes the ChangeLyrAttribAction 
01020     Errors:     -
01021     SeeAlso:    -
01022     
01023     
01024 ********************************************************************************************/
01025  
01026 ActionCode ChangeLyrAttribAction::Execute()
01027 {  
01028    ChangeLyrAttribAction ChngLyrAct; 
01029    ActionCode ActCode;  
01030 
01031      // Create an action to restore the changes we are about to make  
01032     if ((ActCode = ChangeLyrAttribAction::Init(pOperation,                    
01033                                                pOppositeActLst,  
01034                                                sizeof(ChangeLyrAttribAction),  
01035                                                ChangeLayer->GetLayerStatus(),  // The current status
01036                                                ChangeLayer,       
01037                                                ( Action**)(&ChngLyrAct))) != AC_FAIL) 
01038     { 
01039         // Remove the layers selection blobs if we are about to make the layer invisible,
01040         // or if we are about to lock the layer. 
01041         //if ((Status.Flags.Locked) || 
01042         //   (!(Status.Flags.Visible)))
01043         //{
01044         //  NodeRenderableInk::DeselectAllOnLayer( ChangeLayer );
01045         //}
01046 
01047         // Preserve the Active flag of the changing layer
01048         LayerStatus CurrentStatus = ChangeLayer->GetLayerStatus();
01049         //Status.Flags.Active = CurrentStatus.Flags.Active;
01050 
01051         // Change the layer's status  
01052         ChangeLayer->SetLayerStatus(Status); 
01053     }             
01054     return (ActCode);                
01055 }     
01056 
01057 
01058 /********************************************************************************************
01059 
01060 >   static ActionCode ChangeLyrAttribAction::Init(Operation* const pOp, 
01061                                                   ActionList* pActionList,  
01062                                                   UINT32 ActionSize, 
01063                                                   LayerStatus& Status, 
01064                                                   Layer* Layer,
01065                                                   Action** NewAction)   
01066 
01067     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
01068     Created:    14/9/93  
01069     
01070     Inputs:     pOp: The operation to which the action should be added
01071                 
01072                 pActionList: The action list in the operation object
01073                 
01074                 ActionSize:  The size of the action in bytes. This should be the total  
01075                              size of the action (including any objects pointed to by the
01076                              action).  
01077                 
01078                 Status:      The status which is restored when executed  
01079                 Layer:       The layer to change when we execute 
01080                              
01081                              
01082     Outputs:    NewAction:   A pointer to the action if it could be allocated. 
01083 
01084     Returns:    AC_FAIL:     There was not enough room in the operation history for the 
01085                              action and the user did not wish to continue. Usually 
01086                              End() should be called in this situation. 
01087                          
01088                 AC_NORECORD: There was not enough room in the operation history for
01089                              the action, but the user requested that he wished to 
01090                              continue without undo. 
01091                 
01092                 AC_OK      : The action was successfully initialised and added to the 
01093                              operation. 
01094                          
01095                            
01096     Purpose:    To check that there is sufficient room for the action in the operation
01097                 history, and if there is, then to add the action to the operations 
01098                 action list. 
01099                 
01100                 The function calls the Action::Init function passing the runtime class 
01101                 of a ChangeLyrAttribAction.
01102     Errors:     -
01103     SeeAlso:    Action::Init
01104 
01105 ********************************************************************************************/
01106    
01107 ActionCode ChangeLyrAttribAction::Init(Operation* const pOp, 
01108                                          ActionList* pActionList,   
01109                                          UINT32 ActionSize,  
01110                                          LayerStatus& Status,  // The layer status which 
01111                                                                // should be restored 
01112                                                                // when we execute the action. 
01113                                          Layer* Layer,         // The layer to change when we execute 
01114                 
01115                                          Action** NewAction)
01116 {    
01117 
01118     ActionCode Ac = (Action::Init(pOp,
01119                      pActionList,
01120                      ActionSize,
01121                      CC_RUNTIME_CLASS(ChangeLyrAttribAction), 
01122                      NewAction));
01123                          
01124     if (*NewAction != NULL) // The action has been allocated 
01125     {
01126         ((ChangeLyrAttribAction*)(*NewAction))->ChangeLayer = Layer;
01127         ((ChangeLyrAttribAction*)(*NewAction))->Status = Status; 
01128     }
01129     return (Ac); 
01130 }
01131     
01132 
01133 
01134 
01135 
01136 /********************************************************************************************
01137 
01138 >   BOOL OpDelBar::Init()
01139 
01140     Author:     Simon_Knight (Xara Group Ltd) <camelotdev@xara.com>
01141     Created:    3/5/00
01142     Returns:    TRUE if the operation could be successfully initialised 
01143                 FALSE if no more memory could be allocated 
01144     Purpose:    OpDelBar initialiser method
01145     Errors:     ERROR will be called if there was insufficient memory to allocate the 
01146                 operation.
01147     SeeAlso:    -
01148 
01149 ********************************************************************************************/
01150 BOOL OpMoveToLayer::Init()
01151 {
01152     return  (RegisterOpDescriptor(0,
01153                                 _R(IDS_MOVE_SEL_TO_ACTIVE_LAYER),
01154                                 CC_RUNTIME_CLASS(OpMoveToLayer),
01155                                 OPTOKEN_MOVE_SEL_TO_ACTIVE_LAYER,
01156                                 OpMoveToLayer::GetState,
01157                                 0,                  // help ID 
01158                                 0,                  // bubble help
01159                                 0,                  // resource ID
01160                                 0,                  // control ID
01161                                 SYSTEMBAR_ILLEGAL,  // Bar ID
01162                                 TRUE,               // Receive messages
01163                                 FALSE,
01164                                 FALSE,
01165                                 0,
01166                                 (GREY_WHEN_NO_CURRENT_DOC | DONT_GREY_WHEN_SELECT_INSIDE) ));
01167 }
01168 
01169 
01170 
01171 /********************************************************************************************
01172 
01173 >   OpState OpMoveToLayer::GetState(String_256* UIDescription, OpDescriptor *Bob)
01174 
01175     Author:     Simon_Knight (Xara Group Ltd) <camelotdev@xara.com> 
01176     Created:    3/5/00
01177     Purpose:    For finding the operations state.  
01178 
01179 ********************************************************************************************/
01180 OpState OpMoveToLayer::GetState(String_256* UIDescription, OpDescriptor *Bob)
01181 {
01182     OpState OpSt;
01183     return(OpSt);   
01184 }
01185 
01186 
01187 /********************************************************************************************
01188 
01189 >   void OpMoveToLayer::Do(OpDescriptor*)
01190 
01191     Author:     Simon_Knight (Xara Group Ltd) <camelotdev@xara.com> 
01192     Created:    3/5/00
01193     Purpose:    This takes the selection and moves it to the active layer. This is a more
01194                 powerful operation than the move forward/backward a layer
01195 
01196 ********************************************************************************************/
01197 void OpMoveToLayer::Do(OpDescriptor*)
01198 {
01199     if (DoStartSelOp(FALSE,TRUE))
01200     {
01201         // get the selection
01202         Range Sel(*(GetApplication()->FindSelection()));
01203 
01204         // set the range flags so it includes shadow and bevel manager nodes
01205         RangeControl rg = Sel.GetRangeControlFlags();
01206         rg.PromoteToParent = TRUE;
01207         Sel.Range::SetRangeControl(rg);
01208 
01209         // Prepare an ObjChangeParam so we can mark which nodes will allow this op to happen to them
01210         ObjChangeFlags cFlags;
01211         cFlags.MoveNode = TRUE;
01212         ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
01213 
01214         // add items directly after the layer node as its first child
01215         Node * pTail = (Node *) (Document::GetCurrent()->GetInsertionPosition());
01216         AttachNodeDirection TailAttachDirection = PREV;
01217         Spread* pSpread = Document::GetSelectedSpread();
01218 
01219         if (!pTail)
01220         {
01221             if (pSpread)
01222             {
01223                 pTail = pSpread->FindActiveLayer();
01224                 // AttachNodeDirection TailAttachDirection = LASTCHILD; <--- AMB removed this and inserted the next line 2006-04-10 presuming bug
01225                 TailAttachDirection = LASTCHILD;
01226             }
01227             else
01228             {
01229                 FailAndExecute();
01230                 End();
01231                 return; // nowhere to put the nodes
01232             }
01233         }
01234 
01235 
01236         // Mark nodes that will allow this to happen, and error if no nodes will let it happen
01237         if (!Sel.AllowOp(&ObjChange))
01238         {
01239             FailAndExecute();
01240             End();
01241             return; // op not allowed
01242         }
01243 
01244         // get a list from which to move the nodes (fixes job #10781 - the re-selection of 
01245         // moved nodes caused an infinite loop)
01246 
01247         List* pNodeList = Sel.MakeListOfNodes(FALSE);
01248         NodeListItem* CurItem = (NodeListItem*)(pNodeList->GetHead());
01249         while (CurItem)
01250         {
01251             Node* pNode = CurItem->pNode;
01252 
01253             // Make sure the current owner Layer is told about the changes
01254             // and given the chance to release any cached info it may be
01255             // holding about the selected object
01256             // (I know that the original position coincides with the destination position
01257             //  but this is hte simplest way to get the original parent layer uncached
01258             //  and to get a record in the undo history so that the layer cacheing will
01259             //  be dealt with properly during gundo/redo)
01260             DoInvalidateNodeRegion((NodeRenderableBounded*) pNode, TRUE, FALSE);
01261 
01262             // localise attribs for this node
01263             DoLocaliseForAttrChange((NodeRenderableInk*) pNode, (AttrTypeSet *)NULL, (ObjectSet*) NULL);
01264             DoMoveNode(pNode, pTail, TailAttachDirection);
01265             // factor out common attribs
01266             if (pNode->IsCompound())
01267                 DoFactorOutCommonChildAttributes((NodeRenderableInk*) pNode);
01268             else
01269                 DoFactorOutAfterAttrChange((NodeRenderableInk*) pNode, (AttrTypeSet *)NULL);
01270 
01271             // make the nodes region be redrawn
01272             DoInvalidateNodeRegion((NodeRenderableBounded*) pNode, TRUE, FALSE);
01273 
01274             CurItem = (NodeListItem*)(pNodeList->GetNext(CurItem));
01275         }
01276         // delete the the list objects 
01277         pNodeList->DeleteAll();
01278         delete pNodeList;
01279 
01280         // the selection will have changed - after all we just deleted it
01281         BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::NONCOLOURATTCHANGED));
01282         GetApplication()->UpdateSelection();
01283 
01284         ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this);
01285         UpdateChangedNodes(&ObjChange);
01286         // end the op
01287         End();
01288 
01289         // update the bars
01290         DialogBarOp::SetSystemStateChanged();
01291         DialogBarOp::UpdateStateOfAllBars(); 
01292     }
01293     else
01294     {
01295         // give up and go home
01296         FailAndExecute();
01297         End();
01298     }
01299 }

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