00001 // $Id: ops.h 877 2006-04-24 17:15:07Z 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 Declaration of the following classes: 00100 00101 ActionList: Class used by an Operation to store UNDO, REDO, and Smart Duplicate actions 00102 Operation: Class from which all Camelot operations are derived 00103 Action: Class from which all operations actions are derived 00104 00105 */ 00106 00107 00108 /* 00109 * */ 00110 00111 #ifndef INC_OPS 00112 #define INC_OPS 00113 00114 #include "listitem.h" 00115 #include "list.h" 00116 #include "binds.h" 00117 #include "clikmods.h" 00118 #include "doccoord.h" 00119 #include "docrect.h" 00120 #include "opdesc.h" 00121 #include "range.h" 00122 //#include "basedoc.h" 00123 #include "selstate.h" 00124 00125 //#include "bars.h" 00126 00127 class Document; 00128 class DocView; 00129 class View; 00130 class OperationHistory; 00131 class Spread; 00132 class Node; 00133 class NodeHidden; 00134 class TransformBase; 00135 class KeyPress; 00136 class Action; 00137 class BaseDocument; 00138 00139 00140 /******************************************************************************************* 00141 00142 < SystemBarType 00143 00144 Comment: A number of hidden bars are created by the kernel during startup to group 00145 together OpDescriptors in sensible groups for the user. This enum allows each of those 00146 hidden bars to be uniquely identified. 00147 00148 enum SystemBarType { SYSTEMBAR_ILLEGAL = 0, 00149 SYSTEMBAR_FILE, 00150 SYSTEMBAR_EDIT, 00151 SYSTEMBAR_ATTRIBUTE, 00152 SYSTEMBAR_ARRANGE, 00153 SYSTEMBAR_UTILITIES, 00154 SYSTEMBAR_WINDOW, 00155 SYSTEMBAR_VIEW = SYSTEMBAR_WINDOW, 00156 SYSTEMBAR_HELP, 00157 SYSTEMBAR_DEBUG 00158 SYSTEMBAR_FEATHER 00159 }; 00160 00161 SeeAlso: SystemBarOp::FindType 00162 00163 ********************************************************************************************/ 00164 00165 enum SystemBarType { SYSTEMBAR_ILLEGAL = 0, 00166 SYSTEMBAR_FILE, 00167 SYSTEMBAR_EDIT, 00168 SYSTEMBAR_ATTRIBUTE, 00169 SYSTEMBAR_ARRANGE, 00170 SYSTEMBAR_UTILITIES, 00171 SYSTEMBAR_WINDOW, 00172 SYSTEMBAR_VIEW = SYSTEMBAR_WINDOW, // Alias VIEW to WINDOW for now... 00173 SYSTEMBAR_HELP, 00174 SYSTEMBAR_ANIMATION, 00175 SYSTEMBAR_TYPESETTING, 00176 SYSTEMBAR_DEBUG, 00177 SYSTEMBAR_FEATHER 00178 }; 00179 00180 00181 /******************************************************************************************** 00182 00183 > class ActionList: public List 00184 00185 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00186 Created: 6/7/93 00187 Purpose: An ActionList is a list object which holds actions which can be 00188 executed. It is used by Operation objects to hold UNDO, REDO and Smart 00189 duplicate actions. 00190 00191 SeeAlso: Operation 00192 SeeAlso: Action 00193 00194 ********************************************************************************************/ 00195 00196 class CCAPI ActionList: public List 00197 { 00198 CC_DECLARE_MEMDUMP( ActionList ) 00199 public: 00200 ActionList(); 00201 ~ActionList(); 00202 BOOL ExecuteForwards(BOOL AllButLast); 00203 BOOL ExecuteBackwards(BOOL AllButLast, BOOL bIgnoreSelectActions = FALSE); 00204 00205 // This function can be used to search the action list to see if it contains an action 00206 // with a specific runtime class. 00207 Action* FindActionOfClass(CCRuntimeClass* ClassOfActionToFind, Action* LastAction = NULL); 00208 00209 }; 00210 00211 // The Opflags structure is used by the operation class to hold information about 00212 // how an operation should behave when it ends. 00213 struct CCAPI OpFlgsStr 00214 { // TRUE when: 00215 BOOL Failed : 1; // Action could not be created 00216 BOOL ExecuteOnEnd : 1; // Execute all actions in End 00217 BOOL AllButLast : 1; // Execute all acts but last one in End 00218 BOOL KeepOnEnd : 1; // Not deleted in End 00219 BOOL UnwindingActions:1; // Op is being unwound 00220 BOOL HasOwnTimeIndicator:1; // Usually FALSE by default, however when TRUE indicates that 00221 // the operation should not use the default hourglass 00222 BOOL SucceedAndDiscard:1; // After the operation has finished all undo actions will be discarded 00223 BOOL DeleteOnEnd : 1; // After the operation has ended it will be deleted 00224 BOOL IgnoreSelectActions : 1; // Ignore selections when executing (for use when executing undo due to selection changes) 00225 00226 }; 00227 00228 00229 // Current status of operation:- 00230 enum OperationStatus { UNDO, REDO, DO }; 00231 00232 /******************************************************************************************** 00233 > class CUniversalParam 00234 00235 Author: Luke_Hart (Xara Group Ltd) <camelotdev@xara.com> 00236 Created: 14/10/05 00237 00238 Purpose: Simple class that makes it possible to have parameters that can either be 00239 a pointer or an INT32 in a 64bit safe manner. 00240 00241 ********************************************************************************************/ 00242 00243 class CUniversalParam 00244 { 00245 private: 00246 union 00247 { 00248 void *m_pVal; 00249 INT32 m_lVal; 00250 }; 00251 00252 public: 00253 CUniversalParam() : m_pVal( NULL ) 00254 {} 00255 CUniversalParam( void *p ) : m_pVal( p ) 00256 {} 00257 CUniversalParam( INT32 l ) : m_lVal( l ) 00258 {} 00259 00260 void *operator =( void *p ) 00261 { 00262 return m_pVal = p; 00263 } 00264 INT32 operator =( INT32 l ) 00265 { 00266 return m_lVal = l; 00267 } 00268 00269 operator void *() 00270 { 00271 return m_pVal; 00272 } 00273 operator INT32() 00274 { 00275 return m_lVal; 00276 } 00277 }; 00278 00279 /******************************************************************************************** 00280 > class OpParam 00281 00282 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00283 Created: 9/6/94 00284 00285 Purpose: Operation parameter structure. The meaning of the structure's fields are 00286 defined by each operation. Note that sensible Operations will derive a 00287 special OpParam for their own specific needs, so you should use the 00288 derived class where it is available. 00289 00290 SeeAlso: Operation::DoWithParam 00291 00292 ********************************************************************************************/ 00293 00294 class OpParam : public CCObject 00295 { 00296 CC_DECLARE_DYNAMIC(OpParam) 00297 00298 public: 00299 OpParam() { Param1 = Param2 = INT32(0); Output = NULL; } 00300 OpParam(CUniversalParam P1, CUniversalParam P2) { Param1 = P1; Param2 = P2; Output = 0; } 00301 OpParam(CUniversalParam P1, CUniversalParam P2, BOOL* Out) { Param1 = P1; Param2 = P2; Output = Out; } 00302 CUniversalParam Param1; 00303 CUniversalParam Param2; 00304 00305 BOOL *Output; 00306 }; 00307 00308 /******************************************************************************************** 00309 00310 > class Operation : public MessageHandler 00311 00312 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00313 Created: 6/7/93 00314 Purpose: This abstract class represents an operation which is a single job initiated 00315 by the user. You should derive all non undoable operations directly from 00316 this base class. 00317 00318 SeeAlso: OperationHistory 00319 SeeAlso: UndoableOperation 00320 00321 ********************************************************************************************/ 00322 00323 class CCAPI Operation : public MessageHandler 00324 { 00325 CC_DECLARE_DYNCREATE( Operation ) 00326 00327 public: 00328 virtual void OnClickWhileDragging(OilCoord PointerPos, ClickType Click, ClickModifiers Mods, BOOL bSolidDrag); 00329 00330 Operation(CCRuntimeClass* MsgHandlerClass = CC_RUNTIME_CLASS(Operation)); 00331 virtual ~Operation(); 00332 00333 static BOOL Initialise(); 00334 00335 virtual void End(); 00336 00337 // Mark H 00338 virtual Matrix GetCurrentMatrix() { return Matrix(); }; 00339 00340 UINT32 GetSize(); 00341 00342 static Operation* GetCurrentDragOp(); 00343 virtual BOOL SnappingDrag() { return TRUE; } 00344 00345 // Event handler functions called by DocView/CCamView... 00346 virtual void DragPointerMove( DocCoord PointerPos, 00347 ClickModifiers ClickMods, Spread *pSpread, BOOL bSolidDrag); 00348 virtual void DragPointerIdle( DocCoord PointerPos, 00349 ClickModifiers ClickMods, Spread *pSpread, BOOL bSolidDrag); 00350 virtual void DragFinished( DocCoord PointerPos, 00351 ClickModifiers ClickMods, Spread *pSpread, 00352 BOOL Success, BOOL bSolidDrag); 00353 virtual BOOL DragKeyPress(KeyPress* pKeyPress, BOOL bSolidDrag); 00354 virtual void DragModeChanged(BOOL bSolidDrag); 00355 00356 // Function to translate coord from one spread to another. 00357 DocCoord MakeRelativeToSpread(Spread *Dest, Spread *Src, DocCoord); 00358 00359 // Function to allow operations to render something during a drag 00360 virtual void RenderDragBlobs(DocRect, Spread*, BOOL bSolidDrag); 00361 00362 // Function called on idle events if required 00363 virtual BOOL OnIdleEvent(); 00364 00365 // These Fail functions tell the Op what to do when it ends. 00366 void FailAndExecute(); 00367 void FailAndExecuteAllButLast(); 00368 void FailAndDiscard(); 00369 void FailAndExecuteIgnoreSelActions(); 00370 00371 // When called operation will not be undoable 00372 void SucceedAndDiscard(); 00373 00374 // These two functions execute the appropriate action list. 00375 virtual BOOL Undo(); 00376 virtual BOOL Redo(); 00377 00378 // This function asks the operation to Do itself again. Notice that DoSmart 00379 // can be polymorphic because no smart functions can take params - they 00380 // all work on the selection. 00381 virtual void DoSmart(); 00382 00383 // This function is the polymorphic one to be used to Do all simple Operations. All subclasses 00384 // of Operation will implement there own DO function maintaining the same interface as 00385 // below in order for the Do function to work with all simple Operations. (This will be 00386 // particularly useful for implementing Menu Operations!) 00387 virtual void Do(OpDescriptor*); 00388 00389 // Same as Do except it allows a parameter to be passed - Yes I know this is a bit yuk 00390 // but at least is saves me changing every Do function in Camelot. 00391 virtual void DoWithParam(OpDescriptor*, OpParam* pOpParam); 00392 00393 OpFlgsStr GetOpFlgs(); 00394 BOOL OpHasFailed() const {return OpFlags.Failed;} 00395 void DeleteOnEnd(); 00396 void KeepOnEnd() {OpFlags.KeepOnEnd = TRUE;} 00397 00398 ActionList* GetUndoActionList(); 00399 ActionList* GetRedoActionList(); 00400 00401 OperationStatus OpStatus; // When doing the operation for the first time equals DO 00402 // When UNDOING the operation equals UNDO 00403 // when REDOING the operation equals REDO 00404 00405 // Utility methods required by the ALLOC_WITH_FAIL macro 00406 BOOL UserWantsToDeleteUndoOps(); 00407 void OperationMemoryFailure(); 00408 00409 // Find out which document/(doc)view this operation is working on. 00410 Document *GetWorkingDoc() { return pOurDoc; } 00411 View *GetWorkingView() { return pOurView; } 00412 DocView *GetWorkingDocView(); 00413 00414 // Retrieve The Operations Name 00415 virtual void GetOpName(String_256*); 00416 00417 // interogates the current (drag) Operation for statusLine text 00418 virtual BOOL GetStatusLineText(String_256* pText, Spread* pSpread, DocCoord DocPos, ClickModifiers ClickMods); 00419 00420 // Call this function from the Operation's Init method to register the operations OpDescriptor 00421 static BOOL RegisterOpDescriptor( 00422 UINT32 toolID, // Module (Tool) Identifier 00423 UINT32 txID, // String Resource ID 00424 CCRuntimeClass* RuntimeClass, // The operations runtime class 00425 TCHAR* tok, // pointer to the token string 00426 pfnGetState gs, // pointer to the GetState function 00427 UINT32 helpId = 0, // help identifier 00428 UINT32 bubbleID = 0, // string resource for bubble help 00429 UINT32 resourceID = 0, // resource ID 00430 UINT32 controlID = 0, // control ID 00431 SystemBarType GroupBarID = SYSTEMBAR_ILLEGAL, // group bar ID 00432 BOOL ReceiveMessages = TRUE, // BODGE 00433 BOOL Smart = FALSE, 00434 BOOL Clean = TRUE, 00435 OpDescriptor *pVertOpDesc = NULL, 00436 UINT32 OneOpenInstID = 0, 00437 UINT32 AutoStateFlags = 0, 00438 BOOL fCheckable = FALSE 00439 ); 00440 00441 // These functions should be used in conjuction with Node::AllowOp() or Range::AllowOp() to allow 00442 // the op to work when select-inside is present. 00443 // Calling these functions should ensure that parent nodes update themselves when an op is applied to 00444 // their children 00445 virtual BOOL UpdateChangedNodes(ObjChangeParam* pParam,Spread* pSpread = NULL); 00446 virtual BOOL UpdateChangedNode(ObjChangeParam* pParam,Node* pNode); 00447 00448 // This varient will update all nodes in all the docs in the application 00449 virtual BOOL UpdateAllChangedNodes(ObjChangeParam* pParam); 00450 // This will update all nodes in the given document 00451 virtual BOOL UpdateChangedNodes(ObjChangeParam* pParam,Document* pDoc); 00452 00453 // Dumps the undo/redo action lists to the debugger 00454 virtual void Dump(); 00455 00456 static BOOL GetQuickRender(Node* pNode); 00457 static void SetQuickRender(BOOL bNewState, Operation* pQROp = NULL); 00458 00459 protected: 00460 00461 // Functions called by subclasses of Operation... 00462 BOOL StartDrag( DragType type, 00463 DocRect* MoveBBox = NULL, 00464 DocCoord* StartPos = NULL, 00465 BOOL KeepAccuracy = TRUE, 00466 BOOL bSolidDragSupported = FALSE); 00467 BOOL EndDrag(void); 00468 00469 void EndOp(); // The old End() function 00470 00471 // Operation flags structure 00472 OpFlgsStr OpFlags; 00473 00474 // Points to the document/view this Operation is associated with when "live". 00475 // 00476 // NB. pOurView is usually NULL as many operations don't care which or many views are 00477 // associated with the document, but some do - e.g. changing rendering quality, 00478 // zooming in and out, etc. 00479 Document* pOurDoc; 00480 View* pOurView; 00481 00482 // UNDO/REDO lists. 00483 // Note: At any given time ONE of these lists MUST be empty. This means that there is no 00484 // need to store flags to indicate if the operation is for UNDO or REDO. If UndoActions 00485 // contains any actions then the operation can be undone, else the operation can be 00486 // redone. 00487 00488 ActionList UndoActions; 00489 ActionList RedoActions; 00490 00491 // Actions for smart duplicate 00492 ActionList SmartActions; 00493 00494 public: 00495 // Somebody might want to invoke an action given an undoable op pointer. At this point, they 00496 // will need access to the action lists. So give them a public access function. 00497 // Only use these if you know what you are doing! 00498 // Should be const but of course then nothing would work! 00499 ActionList * GetUndoActions() { return &UndoActions; } 00500 ActionList * GetRedoActions() { return &RedoActions; } 00501 ActionList * GetSmartActions() { return &SmartActions; } 00502 00503 private: 00504 00505 // The string OpName should be defined in a subclass of operation and be returned 00506 // by the GetName() function. It is not defined for the operation class. 00507 00508 // static String OpName; // The name of the operation object 00509 00510 // For drag operations CurrentDragOp will be a pointer to the Operation which should 00511 // receive mouse movement events during the drag. It will ensure that only one 00512 // operation can perform a drag at a time and that keypress events cannot change the 00513 // state of the document while a drag is taking place. 00514 00515 static Operation* CurrentDragOp; 00516 00517 // The DeleteUndoOpsToMake space flag is set to TRUE after the user responds YES to the 00518 // question "do you want to delete undo operations to make space for the current operation ?". 00519 // It is required so that the user is not asked the same question more than once in performing 00520 // the operation (The next time YES will be taken as the default). It will be reset to FALSE 00521 // when the operation ends. 00522 BOOL DeleteUndoOpsToMakeSpace; 00523 00524 00525 // In the operations End method if pDocToInformOfOpStatus is not NULL then 00526 // If the operation has failed AbortComponent copy is called on the document 00527 // else EndComponentCopy is called. 00528 BaseDocument* pDocToInformOfOpStatus; 00529 00530 // Vars to do with stopping auto-repeat keys during drags 00531 static INT32 CurKeyboardSpeed; 00532 static BOOL ResetKeyboardSpeed; 00533 static BOOL KeyboardRepeatOffDuringDrags; 00534 00535 static BOOL s_bQuickRender; 00536 00537 public: 00538 void InformDocComponentsOfOperationsOutcome(BaseDocument* pDoc) { pDocToInformOfOpStatus = pDoc; }; 00539 00540 }; 00541 00542 00543 enum ActionCode { AC_FAIL, AC_OK, AC_NORECORD }; 00544 00545 /******************************************************************************************** 00546 00547 > class Action: public ListItem 00548 00549 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00550 Created: 6/7/93 00551 Purpose: This class represents an Action which is an individual job which is executed 00552 to accomplish an operation. An operation contains lists of actions to 00553 perform Undo, Redo and Smart Duplication. 00554 00555 SeeAlso: Operation 00556 00557 ********************************************************************************************/ 00558 00559 class CCAPI Action: public ListItem 00560 { 00561 CC_DECLARE_DYNCREATE( Action ) 00562 00563 friend class OperationHistory; 00564 00565 public: 00566 00567 Action(); 00568 virtual ~Action(); 00569 virtual void Slaughter(); // A more extreme form of destruction 00570 virtual ActionCode Execute(); 00571 static ActionCode Init(Operation* pOp, 00572 ActionList* pActionList, 00573 UINT32 Size, 00574 CCRuntimeClass* ActionClass, 00575 Action** NewAction); 00576 00577 // If IsDiscardableAction returns TRUE then it indicates that it can be deleted after the 00578 // operation ends. It indicates that the action never does anything and so is dead-wood. 00579 virtual BOOL IsADiscardableAction() { return FALSE; } 00580 00581 // Find out which document/(doc)view this action is working on. 00582 Document *GetWorkingDoc() { return pOperation->GetWorkingDoc(); } 00583 View *GetWorkingView() { return pOperation->GetWorkingView(); } 00584 DocView *GetWorkingDocView() { return pOperation->GetWorkingDocView(); } 00585 00586 UINT32 GetSize(); 00587 00588 // Dumps the action list to the dubugger 00589 virtual void Dump(); 00590 00591 BOOL TransferToOtherOp(Operation* pOtherOp, ActionList* pAddActions, ActionList* pOtherActions); 00592 00593 protected: 00594 00595 Operation* pOperation; // Pointer to the operation to which the action is attached. It 00596 // is neccessary to store this because executing an action will 00597 // usually cause a new action to be created, and Operation is 00598 // required as an argument to the new action's Init method. 00599 00600 ActionList* pOppositeActLst; // A pointer to the opposite action list. This is really useful 00601 // to know, especially when an Action is used both to Undo and Redo. 00602 // If the action is on the UndoActionList then pOppositeActLst 00603 // will point to the RedoActionList, and visa versa. 00604 00605 UINT32 Size; // The total size of the action in bytes. It is neccessary to 00606 // store this because before the action is deleted the size of the 00607 // operation history needs to be reduced by the size of the action. 00608 00609 00610 // *** This is what LastDiscardableAction USED to be - see below for it's new friendly 00611 // purpose. 00612 // When an Action fails in the Init function this can be due to either there not being 00613 // enough system memory, or because there is not enough space in the Operation History for 00614 // the Action. In the later case an instance of the action will exist and 00615 // LastDiscardable action will be set to point at the action. When Init is called the next 00616 // time it will be deleted. 00617 00618 00619 00620 //static Action* LastDiscardableAction; 00621 00622 }; 00623 00624 00625 /******************************************************************************************** 00626 00627 > ALLOC_WITH_FAIL(Ptr, AllocExpr, pOp) \ 00628 00629 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00630 Created: 4/8/93 00631 Inputs: Ptr: The pointer or handle to the object being allocated 00632 AllocExpr: The expression to allocate memory (e.g. new Blobby(x,y,z) ) 00633 pOp: A pointer to the operation for which memory is being allocated. 00634 Outputs: - 00635 Returns: - 00636 Purpose: This macro should be used whenever you want to allocate any memory in an 00637 operation.It initially tries to allocate system memory, if it fails then it 00638 prompts the user to see if they want to delete undo operations to try and make 00639 room. If after deleting undo operations memory still cannot be allocated then 00640 FailAndExecute() is called and a NULL Ptr is returned. 00641 00642 The macro is fairly long and may be replaced by a series of functions 00643 one for each type of memmory allocation. 00644 00645 Errors: - 00646 SeeAlso: CALL_WITH_FAIL 00647 00648 ********************************************************************************************/ 00649 00650 00651 #define ALLOC_WITH_FAIL(Ptr, AllocExpr, pOp) \ 00652 { \ 00653 (Ptr) = (AllocExpr); \ 00654 if ( (Ptr) == NULL && (pOp) != NULL ) \ 00655 { \ 00656 OperationHistory& OpHist = pOp->GetWorkingDoc()->GetOpHistory(); \ 00657 /* If the operation is unwinding then we can't afford the luxury of asking the */ \ 00658 /* user */ \ 00659 if (((pOp)->GetOpFlgs().UnwindingActions) || ((pOp)->UserWantsToDeleteUndoOps())) \ 00660 { \ 00661 /* The user wants to try deleting undo records to make space for the action*/ \ 00662 BOOL NoMoreUndoOpsToDelete = FALSE; \ 00663 /* Repeatedly delete undo operations to try and create enough room for the \ 00664 allocation. */ \ 00665 do \ 00666 { \ 00667 /* Reduce the size of the operation history by deleting a single undo */ \ 00668 /* operation */ \ 00669 if ((OpHist.ReduceSize((OpHist.GetSize()-1), TRUE)) == FALSE) \ 00670 NoMoreUndoOpsToDelete = TRUE; \ 00671 \ 00672 } while ( (((Ptr) = (AllocExpr)) == NULL) \ 00673 && (!NoMoreUndoOpsToDelete) ); \ 00674 \ 00675 if (NoMoreUndoOpsToDelete) \ 00676 (pOp)->OperationMemoryFailure(); \ 00677 } \ 00678 else \ 00679 { \ 00680 pOp->FailAndExecute(); \ 00681 } \ 00682 } \ 00683 } 00684 00685 /******************************************************************************************** 00686 00687 > CALL_WITH_FAIL(fn, pOp, Success) 00688 00689 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00690 Created: 4/8/93 00691 Inputs: fn: the function to call 00692 pOp: A pointer to the operation for which memory is being allocated. 00693 00694 Outputs: Success: A BOOL variable which is TRUE if the function could be executed 00695 with a TRUE return value. 00696 Returns: - 00697 Purpose: This MACRO is the same as the ALLOC_WITH_FAIL except that it repeatedly 00698 calls a function which tries to allocate memory. The function must 00699 return a TRUE/FALSE success status. 00700 00701 00702 Errors: - 00703 SeeAlso: ALLOC_WITH_FAIL 00704 00705 ********************************************************************************************/ 00706 00707 00708 #define CALL_WITH_FAIL(fn,pOp,Success) \ 00709 { \ 00710 Success = FALSE; \ 00711 if ( !(fn) ) \ 00712 { \ 00713 if ( (pOp) != NULL ) \ 00714 { \ 00715 OperationHistory& OpHist = (pOp)->GetWorkingDoc()->GetOpHistory(); \ 00716 if ( ((pOp)->GetOpFlgs().UnwindingActions) || (pOp)->UserWantsToDeleteUndoOps()) \ 00717 { \ 00718 /* The user wants to try deleting undo records to make space for the action*/ \ 00719 BOOL NoMoreUndoOpsToDelete = FALSE; \ 00720 /* Repeatedly delete undo operations to try and create enough room for the \ 00721 allocation. */ \ 00722 do \ 00723 { \ 00724 /* Reduce the size of the operation history by deleting a single undo */ \ 00725 /* operation */ \ 00726 if ((OpHist.ReduceSize((OpHist.GetSize()-1), TRUE)) == FALSE) \ 00727 NoMoreUndoOpsToDelete = TRUE; \ 00728 \ 00729 } while ( (!(fn)) \ 00730 && (!NoMoreUndoOpsToDelete) ); \ 00731 \ 00732 if (NoMoreUndoOpsToDelete) \ 00733 { \ 00734 (pOp)->OperationMemoryFailure(); \ 00735 } \ 00736 else \ 00737 { \ 00738 Success = TRUE; \ 00739 } \ 00740 } \ 00741 else \ 00742 { \ 00743 (pOp)->FailAndExecute(); \ 00744 } \ 00745 } \ 00746 } \ 00747 else \ 00748 { \ 00749 Success = TRUE; \ 00750 } \ 00751 } \ 00752 00753 /******************************************************************************************** 00754 00755 > class InvalidateRegionAction: public Action 00756 00757 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00758 Created: 13/9/93 00759 Purpose: When executed this action will Force a redraw of the bounding rectangles of 00760 each node in a range. 00761 SeeAlso: - 00762 00763 ********************************************************************************************/ 00764 00765 class CCAPI InvalidateRegionAction: public Action 00766 { 00767 CC_DECLARE_DYNCREATE( InvalidateRegionAction ) 00768 00769 public: 00770 InvalidateRegionAction(); 00771 virtual ActionCode Execute(); 00772 00773 static ActionCode Init(Operation* const pOp, 00774 ActionList* pActionList, 00775 Range nodeRange, // The range on nodes we want to invalidate 00776 Spread* pSpread, 00777 BOOL includeBlobs, 00778 Action** NewAction); 00779 protected: 00780 Range NodeRange; 00781 BOOL IncludeBlobs:1; 00782 Spread* pSpread; // We need to be able to invalidate the region of a hidden node, 00783 // so we must store a copy of the spread. 00784 }; 00785 00786 /******************************************************************************************** 00787 00788 > class InvalidateRegionIfBgRedrawAction: public InvalidateRegionAction 00789 00790 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00791 Created: 10/5/95 00792 Purpose: When executed this action will Force a redraw of the bounding rectangles of 00793 each node in a range. 00794 This version will only invalidate the region if Background Redraw is 00795 in progress. 00796 SeeAlso: - 00797 00798 ********************************************************************************************/ 00799 00800 class InvalidateRegionIfBgRedrawAction: public InvalidateRegionAction 00801 { 00802 CC_DECLARE_DYNCREATE( InvalidateRegionIfBgRedrawAction ) 00803 00804 public: 00805 InvalidateRegionIfBgRedrawAction(); 00806 virtual ActionCode Execute(); 00807 00808 static ActionCode Init(Operation* const pOp, 00809 ActionList* pActionList, 00810 Range nodeRange, // The range on nodes we want to invalidate 00811 Spread* pSpread, 00812 BOOL includeBlobs, 00813 Action** NewAction); 00814 }; 00815 00816 /******************************************************************************************** 00817 00818 > class HideNodeAction: public Action 00819 00820 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00821 Created: 13/9/93 00822 Purpose: When executed this action will hide a node. It will 00823 also generate a ShowNodeAction action adding it to the opposite Action list. 00824 00825 SeeAlso: ShowNodeAction 00826 00827 ********************************************************************************************/ 00828 00829 class CCAPI HideNodeAction: public Action 00830 { 00831 CC_DECLARE_DYNCREATE( HideNodeAction ) 00832 00833 public: 00834 HideNodeAction(); 00835 virtual ActionCode Execute(); 00836 static ActionCode Init(Operation* const pOp, 00837 ActionList* pActionList, 00838 Node* NodeToHide, 00839 BOOL IncludeSubtreeSize, 00840 Action** NewAction, 00841 BOOL TellSubtree = TRUE); 00842 00843 CCRuntimeClass* GetClassOfAttrNodeToHide() const 00844 { return ClassOfAttributeToHide; } 00845 00846 void RecordTag(Node* NodeToHide); 00847 00848 private: 00849 00850 // When we generate a HideNodeAction for a non attribute node, we need to simply store 00851 // a pointer to the node, as we can be sure that this node will be around when we come to 00852 // execute this action. 00853 00854 // However if we are generating a HideNodeAction for an attribute then things are different. 00855 // During attribute optimisation attribute nodes can get deleted, so storing a pointer to 00856 // the attribute node is a bad idea. Instead we store a pointer to the attribute's parent (which can't 00857 // be an attribute, so can't get deleted), and the RuntimeClass of the attribute. We can then 00858 // find the attribute by searching for it. 00859 00860 Node* node; // node which should be hidden when HideNodeAction is executed. If the node 00861 // to be hidden is an attribute however then this node will be the attribute's 00862 // parent (see the notes below). 00863 00864 CCRuntimeClass* ClassOfAttributeToHide; // If the node being hidden is a NodeAttribute then 00865 // node will point to the attribute's parent (see above) 00866 // and ClassOfAttributeToHide will be the runtime class 00867 // of the attribute which should be hidden. When this 00868 // action is executed if ClassOfAttributeToHide is 00869 // non NULL then we know that it is an attribute that we 00870 // must hide, so we search for it. 00871 00872 TAG m_nHiddenWixAttrTag; // If the node being hidden is a Wix attribute then this 00873 // holds its tag so it can be properly identified by the 00874 // Execute() function. Wix attributes are not optimised 00875 // and also unlike other attributes, more than one of the 00876 // same kind can apply to an object. 00877 00878 // The size of a HideNodeAction is always sizeof(HideNodeAction), however the 00879 // IncludeSubtreeSize flag is required to pass to the twin ShowNodeAction. 00880 00881 BOOL IncludeSubtreeSize:1; 00882 BOOL TellSubtree:1; 00883 BOOL m_bEffect:1; 00884 }; 00885 00886 00887 /******************************************************************************************** 00888 00889 > class ShowNodeAction: public Action 00890 00891 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00892 Created: 13/9/93 00893 Purpose: When executed this action will show a node. It will also generate a 00894 HideNodeAction action adding it to the opposite Action list. 00895 00896 SeeAlso: HideNodeAction 00897 00898 ********************************************************************************************/ 00899 00900 class CCAPI ShowNodeAction: public Action 00901 { 00902 CC_DECLARE_DYNCREATE( ShowNodeAction ) 00903 00904 public: 00905 ShowNodeAction(); 00906 virtual ~ShowNodeAction(); 00907 virtual void Slaughter(); 00908 virtual ActionCode Execute(); 00909 static ActionCode Init(Operation* const pOp, 00910 ActionList* pActionList, 00911 NodeHidden* HiddenToShow, 00912 BOOL IncludeSubtreeSize, 00913 Action** NewAction, 00914 BOOL TellSubtree = TRUE); 00915 private: 00916 NodeHidden* node; 00917 00918 // We need to store an IncludeSubtreeSize flag because when we create the twin 00919 // HideNodeAction it is required as a parameter. 00920 BOOL IncludeSubtreeSize:1; 00921 BOOL TellSubtree:1; 00922 }; 00923 00924 00925 00926 00927 /******************************************************************************************** 00928 00929 > class UnApplyAction: public Action 00930 00931 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00932 Created: 26/07/2005 00933 Purpose: When executed this action will hide a node. It will 00934 also generate a ShowNodeAction action adding it to the opposite Action list. 00935 00936 SeeAlso: ShowNodeAction 00937 00938 ********************************************************************************************/ 00939 00940 class CCAPI UnApplyAction: public Action 00941 { 00942 CC_DECLARE_DYNCREATE( UnApplyAction ) 00943 00944 friend class OpApplyAttrInteractive; 00945 00946 public: 00947 UnApplyAction(); 00948 ~UnApplyAction(); 00949 virtual ActionCode Execute(); 00950 static ActionCode Init(Operation* const pOp, 00951 ActionList* pActionList, 00952 Node* pActionNode, 00953 NodeAttribute* pActionAttribute, 00954 BOOL IncludeSubtreeSize, 00955 Action** NewAction, 00956 BOOL TellSubtree = TRUE); 00957 00958 // CCRuntimeClass* GetClassOfAttrNodeToHide() const 00959 // { return ClassOfAttributeToHide; } 00960 00961 void RecordTag(NodeAttribute* pAttr); 00962 00963 private: 00964 Node* m_pApplyNode; 00965 NodeAttribute* m_pAttribute; 00966 TAG m_nAttrTag; // If the node being hidden is a Wix attribute then this 00967 // holds its tag so it can be properly identified by the 00968 // Execute() function. Wix attributes are not optimised 00969 // and also unlike other attributes, more than one of the 00970 // same kind can apply to an object. 00971 00972 // The size of a HideNodeAction is always sizeof(HideNodeAction), however the 00973 // IncludeSubtreeSize flag is required to pass to the twin ShowNodeAction. 00974 00975 BOOL IncludeSubtreeSize:1; 00976 BOOL TellSubtree:1; 00977 }; 00978 00979 00980 00981 00982 /******************************************************************************************** 00983 00984 > class ApplyAction: public Action 00985 00986 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00987 Created: 26/07/2005 00988 Purpose: When executed this action will show a node. It will also generate a 00989 HideNodeAction action adding it to the opposite Action list. 00990 00991 SeeAlso: HideNodeAction 00992 00993 ********************************************************************************************/ 00994 00995 class CCAPI ApplyAction: public Action 00996 { 00997 CC_DECLARE_DYNCREATE( ApplyAction ) 00998 00999 friend class OpApplyAttrInteractive; 01000 01001 public: 01002 ApplyAction(); 01003 virtual ~ApplyAction(); 01004 virtual ActionCode Execute(); 01005 static ActionCode Init(Operation* const pOp, 01006 ActionList* pActionList, 01007 Node* pActionApplyNode, 01008 NodeAttribute* pActionAttribute, 01009 BOOL IncludeSubtreeSize, 01010 Action** NewAction, 01011 BOOL TellSubtree = TRUE); 01012 private: 01013 Node* m_pApplyNode; 01014 NodeAttribute* m_pAttribute; 01015 01016 // We need to store an IncludeSubtreeSize flag because when we create the twin 01017 // HideNodeAction it is required as a parameter. 01018 BOOL IncludeSubtreeSize:1; 01019 BOOL TellSubtree:1; 01020 }; 01021 01022 01023 01024 01025 /******************************************************************************************** 01026 01027 > class RestoreSelectionsAction: public Action 01028 01029 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 01030 Created: 13/9/93 01031 Purpose: When executed this action will restore the selection state of the document. 01032 It will also spawn another identical RestoreSelectionsAction adding and add it to 01033 the opposite action list. 01034 01035 SeeAlso: - 01036 01037 ********************************************************************************************/ 01038 01039 class CCAPI RestoreSelectionsAction: public Action 01040 { 01041 CC_DECLARE_DYNCREATE( RestoreSelectionsAction ) 01042 01043 public: 01044 RestoreSelectionsAction(); 01045 ~RestoreSelectionsAction(); 01046 void Slaughter(); 01047 virtual ActionCode Execute(); 01048 static ActionCode Init(Operation* const pOp, 01049 ActionList* pActionList, 01050 SelectionState* SelState, 01051 BOOL Toggle, 01052 BOOL ToggleStatus, 01053 BOOL SelStateShared, 01054 BOOL RenderStartBlobs, 01055 BOOL RenderEndBlobs, 01056 BOOL StartRestore, 01057 Action** NewAction); 01058 01059 SelectionState* GetSelState() { return SelState; }; 01060 01061 private: 01062 SelectionState* SelState; // Selection state which will be restored when the action is 01063 // executed. 01064 01065 // If toggle is true then the ToggleStatus determines if the selections are restored 01066 // or not. See Init method if you are confused. 01067 BOOL toggle:1; 01068 BOOL toggleStatus:1; 01069 BOOL SelStateShared:1; // If the SelState is shared by a pair of RestoreSelActions 01070 // then the SelState will only be deleted when ToggleStatus = TRUE 01071 01072 BOOL RenderStartBlobs:1; 01073 BOOL RenderEndBlobs:1; 01074 01075 BOOL StartRestore:1; // Is this the first restore executed when the operation is undone/redone 01076 }; 01077 01078 01079 /******************************************************************************************** 01080 01081 > class SelectDeselectAction: public Action 01082 01083 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 01084 Created: 13/9/93 01085 Purpose: When executed this action will render node's selection blobs (which could remove them) 01086 and set it's selection state. If the node is currently selected then the 01087 node is deselected. If the node is currently deselected it is selected. 01088 It creates a second SelectDeselectAction for the node and adds it to the 01089 opposite action list. 01090 01091 SeeAlso: - 01092 01093 ********************************************************************************************/ 01094 01095 class CCAPI SelectDeselectAction: public Action 01096 { 01097 CC_DECLARE_DYNCREATE( SelectDeselectAction ) 01098 01099 public: 01100 SelectDeselectAction(); 01101 ~SelectDeselectAction(); 01102 virtual ActionCode Execute(); 01103 static ActionCode Init(Operation* const pOp, 01104 ActionList* pActionList, 01105 Node* SelDeNode, 01106 Spread* pSpread, 01107 Action** NewAction); 01108 01109 Node* node; // The node which will be selected/deselected 01110 Spread *Parent; 01111 }; 01112 01113 01114 /******************************************************************************************** 01115 01116 > class TransformNodeAction: public Action 01117 01118 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 01119 Created: 13/9/93 01120 Purpose: When executed this action will transform a range of NodeRenderableInk nodes. 01121 It also creates another TransformNodeAction to 'undo' the transformation just 01122 performed. It adds this action to the opposite action list. 01123 01124 SeeAlso: - 01125 01126 ********************************************************************************************/ 01127 01128 01129 class CCAPI TransformNodeAction: public Action 01130 { 01131 CC_DECLARE_DYNCREATE( TransformNodeAction ) 01132 01133 public: 01134 TransformNodeAction(); 01135 ~TransformNodeAction(); 01136 void Slaughter(); 01137 01138 virtual ActionCode Execute(); 01139 static ActionCode Init(Operation* const pOp, 01140 ActionList* pActionList, 01141 Range NodeRangeIn, 01142 TransformBase* Trans, 01143 List * pNodeList, 01144 Action** NewAction); 01145 01146 // For op merging 01147 void CombineWith(TransformNodeAction* pMatrixTransformAction); 01148 TransformBase* GetTransform(); 01149 const Range* GetActionRange() const {return &NodeRange;} 01150 01151 private: 01152 01153 Range NodeRange; 01154 01155 // the list of parent-promoted nodes in the first range 01156 List * m_pNodeList; 01157 01158 TransformBase* pTrans; // The transform to apply to every node in the range 01159 }; 01160 01161 #endif 01162 01163