UndoableOperation Class Reference

All Undoable operations should be derived from this class. More...

#include <undoop.h>

Inheritance diagram for UndoableOperation:

Operation MessageHandler ListItem CCObject SimpleCCObject BfxOp BlobbyOp OpApplyNamesToOne OpApplyNameToNone OpBackground OpChangeBarExtends OpChangeBarProperty OpChangeBrushDefinition OpChangeContourWidth OpChangeFeatherProfile OpChangeFeatherSize OpChangeLayerColour OpChangeSetProperty OpColourChange OpCreateNodeBitmap OpDeactivateBrush OpDeleteNamesFromAll OpDetachMould OpDragOrigin OpGrid OpGridResize OpGuideline OpHideColours OpInsertFloater OpLayerChange OpLayerGalChange OpMakeColourLocalToFrame OpMakeNodesShapes OpMouldLib OpRemoveFloater OpRenameAll OpSelectPathPoints OpShowState SelOperation TransOperation List of all members.

Public Member Functions

BOOL DoInvalidateNodesRegions (Range NodeRange, BOOL IncludeBlobs, BOOL UndoBlobs=FALSE, BOOL IfBgRedraw=FALSE, BOOL bForceRecache=TRUE)
 This low level Do function invalidates a region which is the union of the bounding rectangles of each node in the range. When the includeBlobs flag is TRUE the region which gets invalidated includes the objects blobs.
BOOL DoInvalidateNodeRegion (NodeRenderableBounded *Node, BOOL IncludeBlobs, BOOL UndoBlobs=FALSE, BOOL IfBgRedraw=FALSE, BOOL bForceRecache=TRUE)
 Invalidates the nodes bounding rectangle, or blob bounding rectangle.
BOOL DoInvalidateRegion (Spread *pSpread, const DocRect &InvalidRegion)
 Invalidates the region specified and adds the appropriate action to the action list for the current operation. If you are invalidating a region associated with a node in the tree then you should be using DoInvalidateNodeRegion() or DoInvalidateNodesRegion().
BOOL DoSaveCopyOfNode (NodeRenderable *Node)
 This fn saves a copy of the node in the operation history. When the operation is undone the copy is restored.
BOOL DoSaveCopyOfNodes (Range NodeRange)
 This fn takes a copy of the nodes in the range. The copies are restored when the operation is undone.
BOOL DoHideNode (Node *NodeToHide, BOOL IncludeSubtreeSize, NodeHidden **nodeHidden=NULL, BOOL TellSubtree=TRUE)
 This low level Do function hides the subtree with root NodeToHide.
BOOL DoHideNodes (Range NodeRange, BOOL IncludeSubtreeSize, BOOL TellSubtree=TRUE)
 This low level Do function hides a range of the subtrees.
BOOL DoHideComplexRange (Range &RangeToHide)
 This function is a pre process to DoHideNodes(). It calls each object in the range to hide themselves in a complex way. It may be that no objects in the selection require this facility, which means the RangeToHide object will be returned from this function unaffected. DoHideNodes() will then go through hidding all nodes in the range itself. If however a node responds to ComplexHide() and hides itself, the node will be removed from the range. This allows complex group nodes to control how they are hidden. Note, it is expected that ComplexHide() responders will hide nodes themselves This will have the automatic effect of removing them from the range. Hidden nodes do not appear in ranges.
BOOL DoInsertNewNode (NodeRenderableBounded *NewNode, Spread *pSpread, BOOL InvalidateRgn, BOOL ClearSelection=TRUE, BOOL SelectNewObject=TRUE, BOOL NormaliseAttributes=TRUE)
 Inserts the node as a last child of the active layer of the pSpread. If the NewNode is a NodeRenderableInk then the node becomes selected and all other nodes are deselected. If pSpread is NULL then the object is inserted on the selected spread.
BOOL DoInsertNewNode (NodeRenderableBounded *NewNode, Node *ContextNode, AttachNodeDirection Direction, BOOL InvalidateRegion, BOOL ClearSelection=TRUE, BOOL SelectNewObject=TRUE, BOOL NormaliseAttributes=TRUE)
 This high level do function attaches the node to ContextNode in the direction specified. If the NewNode is a NodeRenderableInk then the node becomes selected and all other nodes are deselected.
BOOL DoMoveNode (Node *MoveNode, Node *Destination, AttachNodeDirection Direction)
 This high level function moves NodeToMove from its current position in the tree, and attaches it to Destination in the direction specified by Direction.
BOOL DoMoveNodes (Range NodeRange, Node *Destination, AttachNodeDirection Direction)
 This high level function moves the range of nodes from their current position in the tree, and attaches them to the Destination node in the direction specified by Direction.
BOOL DoTransformNode (NodeRenderableInk *NodeToTransform, TransformBase *T)
 This high level Do function applies the transform Trans to the NodeToTransform.
BOOL DoTransformNodes (Range NodeRange, TransformBase *T)
 This high level Do function applies the transform Trans to each object in the range.
BOOL DoMakeShapes (Range NodeRange)
 This low level Do function calls the DoBecomeA virtual function on all SelectedNodes. It is the node's DoBecomeA function which is responsible for generating actions.
BOOL DoFlattenRange (Range NodeRange)
 Not implemented yet.
BOOL DoCopyNodesToClipboard (Range NodeRange)
 This Do function copies all nodes in the range to the internal clipboard. The objects are made attribute complete prior to being moved.
BOOL DoRemoveAttrTypeFromSubtree (Node *Subtree, CCRuntimeClass *NodeClass, Node *pExceptThis=NULL)
 Searches the subtree and every attribute which has type AttrType is hidden.
BOOL DoChangeSelection (NodePath *ThisNode, INT32 Index, BOOL NewState)
 This 'Do' function changes the selected state of a particular element in a path it creates all the necessary undo information so that the selection can be undone.
BOOL DoDeletePathSection (NodePath *ThisNode, INT32 Index, INT32 NumElements, BOOL RedrawPath=TRUE)
 This 'Do' function changes the selected state of a particular element in a path it creates all the necessary undo information so that the selection can be undone.
BOOL DoAlterPathElement (NodePath *ThisNode, INT32 Index, DocCoord NewCoord, PathFlags NewFlags, PathVerb NewVerb, BOOL RedrawPath=TRUE)
 This 'Do' function changes the selected element, recording undo information.
BOOL DoInsertPathElement (NodePath *ThisPath, INT32 Index, DocCoord NewCoord, PathFlags NewFlags, PathVerb NewVerb, BOOL RedrawPath=TRUE)
 This 'Do' function adds an element into a path, recording undo information.
BOOL DoReversePath (NodePath *ThisPath, BOOL RedrawPath=TRUE)
 This 'Do' function reverse a path, recording undo information.
BOOL DoSmoothNodePath (NodePath *pThisNode, double smoothacc)
 This function will smooth a node path given an accuracy. It will create a new node in the tree after the node specified and hide node passed if all is succesfull.
BOOL DoMakeNodeFromPath (NodePath *pParentNode, Path *pParentPath, AttachNodeDirection Direction, BOOL CopyAttributes)
 This functio will create a new nodepath and attach it in the specified direction to the context node specified. It will also copy attributes applied as children of the ConextNode to the new node if required.
BOOL DoLocaliseForAttrChange (NodeRenderableInk *Object, AttrTypeSet *pAffectedAttrTypes, ObjectSet *pLocalisedCompounds)
 This Do function must be called on an object prior to a set of attributes being applied to it. It globally localises those attributes which have a type in the pAffectedAttrTypes set.
BOOL DoLocaliseForAttrChange (NodeRenderableInk *Object, CCRuntimeClass *pAffectedAttrType, ObjectSet *pLocalisedCompounds)
 This Do function must be called on an object prior to an attribute being applied to it. If you are going to apply multiple attributes to the Object then it is more efficient to call the other version of this function which takes a set of attribute types.
BOOL DoLocaliseForAttrChange (Range *pRange, AttrTypeSet *pAffectedAttrTypes, BOOL ExcludeTextObjects=FALSE)
 This Do function must be called on a range prior to a set of attributes being applied to it. It globally localises those attributes which have a type in the pAffectedAttrTypes set.
BOOL DoLocaliseForAttrChange (Range *pRange, CCRuntimeClass *pAffectedAttrType)
 This Do function must be called on a range prior to an attribute being applied to it. If you are going to apply multiple attributes to the range then it is more efficient to call the other version of this function which takes a set of attribute types.
BOOL DoFactorOutAfterAttrChange (NodeRenderableInk *Object, AttrTypeSet *pAffectedAttrTypes)
 This Do function must be called on an object after attributes have being applied to it.
BOOL DoFactorOutAfterAttrChange (NodeRenderableInk *Object, CCRuntimeClass *pAffectedAttrType)
 This Do function must be called on an object after an attribute being applied to it. If you have applied multiple attributes to the Object then it is more efficient to call the other version of this function which takes a set of attribute types.
BOOL DoFactorOutAfterAttrChange (Range *pRange, AttrTypeSet *pAffectedAttrTypes)
 This Do function must be called on the range after attributes have being applied to it.
BOOL DoFactorOutAfterAttrChange (Range *pRange, CCRuntimeClass *pAffectedAttrType)
 This Do function must be called on the range after an attribute being applied to it. If you have applied multiple attributes to the range then it is more efficient to call the other version of this function which takes a set of attribute types.
BOOL DoFactorOutAfterAttrChange (ObjectSet *pLocalisedCompounds, AttrTypeSet *pAffectedAttrTypes)
 This Do function is designed to be called after all attributes in the pAffectedAttrTypes set have been localised on all compound nodes in the pLocalisedCompounds set.
BOOL DoFactorOutAfterAttrChange (ObjectSet *pLocalisedCompounds, CCRuntimeClass *pAffectedAttrType)
 This Do function is designed to be called after pAffectedAttrType has been localised on all compound nodes in the pLocalisedCompounds set.
BOOL DoFactorOutCommonChildAttributes (NodeRenderableInk *CompoundObject, BOOL Global=FALSE, AttrTypeSet *pAffectedAttrTypes=NULL)
 This function is an information gatherer for the DoFactorOutAfterDeletion function. See this function for a full description of its purpose. Whenever we delete a range of objects, if any objects in the range have compound parents then we must adjust the common attributes on these compounds. This function factors out all attributes which are common to all children of the compound object. All common attributes become first children of the compound object.
BOOL DoFactorOutCommonAttributes (NodeRenderableInk *pRootNode, BOOL bGlobal=FALSE, AttrTypeSet *pAffectedAttrTypes=NULL)
 Just a wrapper to get function name consistency and do the common IsCompound test to prevent DFOCCA from barfing...
BOOL DoLocaliseCommonAttributes (NodeRenderableInk *CompoundObject, BOOL CheckForDuplicates=FALSE, BOOL Global=FALSE, AttrTypeSet *pAffectedAttrTypes=NULL)
 This function is the opposite of DoFactorOutCommonChildAttributes it copies all attributes common to the compound object to each child object within the group which requires each attribute. The groups common attributes are deleted.
BOOL DoSelectNode (NodeRenderableInk *NodeToSelect, Spread *Parent=NULL)
 The function selects NodeToSelect. It also generates an action which will deselect the node when executed.
BOOL DoDeselectNode (NodeRenderableInk *NodeToDeselect, Spread *Parent=NULL)
 The function de-selects NodeToDeselect. It also generates an action which will select the node when executed.
 UndoableOperation ()
 Constructs a new undoable operation object:.
virtual ~UndoableOperation ()
 UndoableOperation destructor.
virtual void PerformMergeProcessing ()
 This function gets called from the Operation::EndOp method after the operation has ended successfuly and been added to the operation history. If the operation could potentially merge itself with the previous operation then perform this merging here.
void MergeWithPrevious ()
 Moves all the actions in this operation to the end of the previous action, then deletes this action.
virtual BOOL UpdateChangedNodes (ObjChangeParam *pParam, Spread *pSpread=NULL)
 This function overrides its namesake in Operation, calling the base function first and then adding a call to NameGallery::PostTriggerEdit if this Op admits it may change the bounds of nodes within the tree.
virtual BOOL NoStretchUpdateChangedNodes (ObjChangeParam *pParam, Document *pDoc)
 This is *not* an override of Operation::UpdateChangedNodes(..., Document*), although it performs *almost* exactly the same job. It is provided solely for NameGallery::PostTriggerEdit to call in order to get all affected nodes to update themselves correctly after a stretch. PostTriggerEdit is itself called in response to normal UpdateChangedNodes calls, so this avoids recursion problems.
virtual BOOL MayChangeNodeBounds () const
virtual BOOL GetStarted () const

Static Public Member Functions

static BOOL RegisterOpDescriptor (UINT32 toolID, UINT32 txID, CCRuntimeClass *RuntimeClass, TCHAR *tok, pfnGetState gs, UINT32 helpId=0, UINT32 bubbleID=0, UINT32 resourceID=0, UINT32 controlID=0, SystemBarType GroupBarID=SYSTEMBAR_ILLEGAL, BOOL ReceiveMessages=TRUE, BOOL Smart=FALSE, BOOL Clean=FALSE, UINT32 OneOpenInstID=0, UINT32 AutoStateFlags=0)
 This function should be called from the operations Init method. It creates an OpDescriptor for the operation.

Static Public Attributes

static BOOL MovingNode = FALSE

Private Member Functions

RangeIncludeParentTransformNodesInRange (Range *Rng)
 Transforms the node, checking if any parents need to transform too.

Private Attributes

BOOL WarnInsertObjsOntoLockedLayers

Detailed Description

All Undoable operations should be derived from this class.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
9/3/94
See also:
Operation

Definition at line 195 of file undoop.h.


Constructor & Destructor Documentation

UndoableOperation::UndoableOperation  ) 
 

Constructs a new undoable operation object:.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
9/3/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
Operation::Operation

Definition at line 294 of file undoop.cpp.

00294                                     : Operation()
00295 {   
00296     // This var is a flag that ensures that this warning will only appear once for the lifetime of this op
00297     WarnInsertObjsOntoLockedLayers = TRUE;
00298 }

UndoableOperation::~UndoableOperation  )  [virtual]
 

UndoableOperation destructor.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
9/3/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
-

Definition at line 317 of file undoop.cpp.

00318 {
00319 }


Member Function Documentation

BOOL UndoableOperation::DoAlterPathElement NodePath ThisPath,
INT32  Index,
DocCoord  NewCoord,
PathFlags  NewFlags,
PathVerb  NewVerb,
BOOL  RedrawPath = TRUE
 

This 'Do' function changes the selected element, recording undo information.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
27/7/94
Parameters:
ThisPath points at the NodePath whose state we want to change [INPUTS] Index is the element we want to change NewCoord is the new coordinate value NewFlags is the new flags value NewVerb is the new verb value RedrawPath - TRUE if the screen area of the path should be invalidated, FALSE if not
- [OUTPUTS]
Returns:
TRUE if succeeded, FALSE otherwise

Errors: -

See also:
-

Definition at line 2126 of file undoop.cpp.

02132 {
02133 #ifndef STANDALONE
02134 
02135     // Here we're changing an element, so we have to change the element in the path,
02136     // recording undo information at the same time.
02137     ModifyElementAction* ModAction = NULL;
02138     
02139     // Get pointers to all the arrays of the path
02140     PathVerb* Verbs = NULL;
02141     DocCoord* Coords = NULL;
02142     PathFlags* Flags = NULL;
02143     ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
02144 
02145     // Create an undo action for this action, which is a ModifyElementAction
02146     ActionCode Act;
02147     Act = ModifyElementAction::Init(this, 
02148                                     &UndoActions, 
02149                                     Verbs[Index],
02150                                     Flags[Index],
02151                                     Coords[Index],
02152                                     Index,
02153                                     ThisPath,
02154                                     (Action**)(&ModAction));
02155     if (Act == AC_FAIL)
02156         return FALSE;
02157 
02158     Document* pDocument = GetWorkingDoc();
02159     ERROR2IF(pDocument == NULL, FALSE, "There was no Document when deleteing path elements");
02160     Spread* pSpread = ThisPath->FindParentSpread();
02161     ERROR2IF(pSpread == NULL, FALSE, "Path had no parent spread");
02162 
02163     // Force a re-draw of the place where the path used to be
02164     if (RedrawPath)
02165     {
02166         DocRect Invalid = ThisPath->GetUnionBlobBoundingRect();
02167         // Mark the region as requiring object to recache any cached
02168         // data they may be holding because the Op may have changed it
02169         pDocument->ForceRedraw( pSpread, Invalid, FALSE, ThisPath );
02170     }
02171 
02172     // Update the coords
02173     Verbs[Index] = NewVerb;
02174     Flags[Index] = NewFlags;
02175     Coords[Index] = NewCoord;
02176 
02177     // The bounding rect may have changed
02178     ThisPath->InvalidateBoundingRect();
02179 
02180     // redraw the new area
02181     if (RedrawPath)
02182     {
02183         // redraw the new area
02184         DocRect Invalid = ThisPath->GetUnionBlobBoundingRect();
02185         // Mark the region as requiring object to recache any cached
02186         // data they may be holding because the Op may have changed it
02187         pDocument->ForceRedraw( pSpread, Invalid, FALSE, ThisPath );
02188     }
02189 
02190 #endif
02191     return TRUE;
02192 }

BOOL UndoableOperation::DoChangeSelection NodePath ThisNode,
INT32  Index,
BOOL  NewState
 

This 'Do' function changes the selected state of a particular element in a path it creates all the necessary undo information so that the selection can be undone.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
19/7/94
Parameters:
ThisNode points at the NodePath whose state we want to change [INPUTS] Index is the element we want to change NewState is the new state of selection we want to set
- [OUTPUTS]
Returns:
TRUE if succeeded, FALSE otherwise

Errors: -

See also:
-

Definition at line 1978 of file undoop.cpp.

01979 {
01980 #ifndef STANDALONE
01981 
01982     ModifyFlagsAction* UnAction;
01983     PathFlags* Flags = ThisNode->InkPath.GetFlagArray();
01984     if (Flags[Index].IsSelected != NewState)
01985     {
01986         ActionCode Act = ModifyFlagsAction::Init(this, 
01987                                                     &UndoActions,
01988                                                     Flags[Index],
01989                                                     Index,
01990                                                     ThisNode,
01991                                                     (Action**)&UnAction);
01992         if (Act == AC_FAIL)
01993             return FALSE;
01994         
01995         Flags[Index].IsSelected = NewState;
01996         return TRUE;
01997     }
01998 
01999 #endif
02000 
02001     return TRUE;
02002 }

BOOL UndoableOperation::DoCopyNodesToClipboard Range  NodeRange  ) 
 

This Do function copies all nodes in the range to the internal clipboard. The objects are made attribute complete prior to being moved.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
03/05/94
Parameters:
NodeRange,: The Range of nodes to copy [INPUTS]
Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)
Before the copy begins StartComponentCopy is called on each DocComponent in the clipboard.

The nodes are then copied to the clipboard

CopyComponentData is then called on each node which has been copied to allow component data to be copied to the clipboard.

In the operations End method: If the operation has not failed then EndComponentCopy is called on each doc component do give them a chance to commit changes. If the operation has failed then AbortComponentCopy is called instead.

Returns:
Errors: -
See also:
NodeRenderableInk::MakeAttributeComplete

Definition at line 1830 of file undoop.cpp.

01831 {
01832     BOOL CopiedOK;
01833     BOOL ok;
01834 
01835     InternalClipboard* pInternalClip = InternalClipboard::Instance();
01836 
01837     // After the operation ends we will need to inform all DocComponents in the clipboard
01838     // of the outcome.
01839     InformDocComponentsOfOperationsOutcome(pInternalClip); 
01840 
01841 
01842     // Inform all DocComponents in the clipboard that a copy is about to take place
01843     CALL_WITH_FAIL(pInternalClip->StartComponentCopy(), this, ok)
01844     if (!ok)
01845     {
01846         // Start Component copy has failed so abort operation
01847         // Note that AbortComponentCopy will get called in the ops end method
01848         return FALSE;
01849     } 
01850 
01851     // Try to copy the selection to the clipboard
01852     CALL_WITH_FAIL(InternalClipboard::CopyObjects(NodeRange, this), this, CopiedOK)
01853 
01854     if (!CopiedOK)
01855     {
01856         return FALSE; 
01857     }
01858 
01859     // Now try and copy accross the component data
01860 
01861     CALL_WITH_FAIL(InternalClipboard::CopyComponentData(pOurDoc), this, CopiedOK)
01862 
01863     if (!CopiedOK)
01864     {
01865         return FALSE; 
01866     }
01867 
01868 
01869     // Create action, this action will do nothing for undo but it's twin redo action will
01870     // copy the selection to the clipboard.
01871     CopyObjectsToClipboardAction* UndoCopyObjectsToClipboardAction;                          
01872 
01873     if ( CopyObjectsToClipboardAction::Init(this, 
01874                                        &UndoActions, 
01875                                        NodeRange,  
01876                                       ( Action**)(&UndoCopyObjectsToClipboardAction)) == AC_FAIL)  
01877     {
01878         return FALSE;  // Failed to create action 
01879     } 
01880     return TRUE; // Success
01881 }

BOOL UndoableOperation::DoDeletePathSection NodePath ThisPath,
INT32  Index,
INT32  NumElements,
BOOL  RedrawPath = TRUE
 

This 'Do' function changes the selected state of a particular element in a path it creates all the necessary undo information so that the selection can be undone.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
19/7/94
Parameters:
ThisPath points at the NodePath whose state we want to change [INPUTS] Index is the element we want to change NumElements is the number of elements to be deleted RedrawPath - TRUE if the path ares should be redrawn, FALSE if the caller will do it
- [OUTPUTS]
Returns:
TRUE if succeeded, FALSE otherwise

Errors: -

See also:
-

Definition at line 2023 of file undoop.cpp.

02024 {
02025 #ifndef STANDALONE
02026 
02027     InsertPathElementAction* UnAction = NULL;
02028     ActionCode Act;
02029     Act = InsertPathElementAction::Init(this, &UndoActions, NumElements, Index,
02030                                             (Action**)(&UnAction));
02031     if (Act == AC_FAIL)
02032         return FALSE;
02033 
02034     Document* pDocument = GetWorkingDoc();
02035     ERROR2IF(pDocument == NULL, FALSE, "There was no Document when deleteing path elements");
02036     Spread* pSpread = ThisPath->FindParentSpread();
02037     ERROR2IF(pSpread == NULL, FALSE, "Path had no parent spread");
02038 
02039     // Force a re-draw of the place where the path used to be
02040     if (RedrawPath)
02041     {
02042         DocRect Invalid = ThisPath->GetUnionBlobBoundingRect();
02043         // Mark the region as requiring object to recache any cached
02044         // data they may be holding because the Op may have changed it
02045         pDocument->ForceRedraw(pSpread, Invalid, FALSE, ThisPath);
02046     }
02047 
02048     if ((Act != AC_NORECORD) && (UnAction != NULL))
02049     {
02050         // I have to claim some memory to store the elements I'm deleting...
02051         PathVerb* ChangedVerbs = NULL;
02052         DocCoord* ChangedCoords = NULL;
02053         PathFlags* ChangedFlags = NULL;
02054         ALLOC_WITH_FAIL(ChangedVerbs,(PathVerb*) CCMalloc(NumElements * sizeof(PathVerb)),this);
02055         ALLOC_WITH_FAIL(ChangedCoords,(DocCoord*) CCMalloc(NumElements * sizeof(DocCoord)),this);
02056         ALLOC_WITH_FAIL(ChangedFlags,(PathFlags*) CCMalloc(NumElements * sizeof(PathFlags)),this);
02057 
02058         if (!ChangedVerbs || !ChangedCoords || !ChangedFlags)
02059         {
02060             if (ChangedVerbs) CCFree(ChangedVerbs);
02061             if (ChangedCoords) CCFree(ChangedCoords);
02062             if (ChangedFlags) CCFree(ChangedFlags);
02063             return FALSE;
02064         }
02065 
02066         // Get pointers to all the arrays of the path
02067         PathVerb* Verbs = NULL;
02068         DocCoord* Coords = NULL;
02069         PathFlags* Flags = NULL;
02070         ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
02071 
02072         // Now copy the data from the path into the arrays
02073         for (INT32 i=0;i<NumElements;i++)
02074         {
02075             ChangedVerbs[i] = Verbs[Index+i];
02076             ChangedCoords[i] = Coords[Index+i];
02077             ChangedFlags[i] = Flags[Index+i];
02078         }
02079 
02080         // Now pass these arrays to the Insert action
02081         UnAction->RecordPath(ChangedVerbs, ChangedFlags, ChangedCoords, ThisPath);
02082     }
02083 
02084     // Now we've recorded the data we're about to delete, let's delete it
02085     ThisPath->InkPath.DeleteSection(Index, NumElements);
02086 
02087     if (RedrawPath)
02088     {
02089         DocRect Invalid = ThisPath->GetUnionBlobBoundingRect();
02090         // Accumulate this invalid region in a pending list until the Op
02091         // finishes
02092         // Mark the region as requiring object to recache any cached
02093         // data they may be holding because the Op may have changed it
02094         pDocument->ForceRedraw(pSpread, Invalid, FALSE, ThisPath);
02095     }
02096 
02097 #endif
02098     return TRUE;
02099 }

BOOL UndoableOperation::DoDeselectNode NodeRenderableInk NodeToDeselect,
Spread Parent = NULL
 

The function de-selects NodeToDeselect. It also generates an action which will select the node when executed.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/10/93
Parameters:
NodeToDeselect,: The node that is to be de-selected [INPUTS]
- [OUTPUTS]
Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)

Errors: -

See also:
UndoableOperation::DoDeselectNode

Definition at line 1733 of file undoop.cpp.

01734 {   
01735     SelectDeselectAction* UndoSelectDeselectAction; 
01736     // Create an action to deselect the NodeToSelect when we undo. 
01737     if ( SelectDeselectAction::Init(this, 
01738                                     &UndoActions, 
01739                                     NodeToDeselect,
01740                                     Parent,
01741                                     (Action**)(&UndoSelectDeselectAction))
01742                                     != AC_FAIL)  
01743     {                   
01744         // We shall be able to select the object if we fail so deselect it. 
01745         NodeToDeselect->DeSelect(FALSE);  
01746         return (TRUE);      
01747     }               
01748     else
01749         return (FALSE); 
01750 } 

BOOL UndoableOperation::DoFactorOutAfterAttrChange ObjectSet pLocalisedCompounds,
CCRuntimeClass pAffectedAttrType
 

This Do function is designed to be called after pAffectedAttrType has been localised on all compound nodes in the pLocalisedCompounds set.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/5/95
Parameters:
pLocalisedCompounds,: A set of compound nodes which have localised their [INPUTS] pAffectedAttrType attributes.
pAffectedAttrType: The type of the attribute that have just been applied to the range.

Parameters:
- [OUTPUTS]
Returns:
TRUE if successful, FALSE if we run out of memory. Tidyup then call End()
The function globally factors out the attribute which has type pAffectedAttrType

Before calling the function you should have localised the attribute by calling DoLocaliseForAttrChange.

See also:
AttrTypeSet

NodeAttribute::GetAttributeType

UndoableOperation::DoLocaliseForAttrChange

Definition at line 3316 of file undoop.cpp.

03318 {
03319     ERROR3IF(!pLocalisedCompounds, "DoFactorOutAfterAttrChange called with a NULL compound set");  
03320     ERROR3IF(!pAffectedAttrType, "DoFactorOutAfterAttrChange called with a NULL attr type"); 
03321 
03322 
03323     // Scan the range
03324     ObjectItem* pObjItem = (ObjectItem*)(pLocalisedCompounds->GetHead());
03325     NodeRenderableInk* pCurrent;
03326 
03327     // We need an attribute type set
03328     AttrTypeSet Set; 
03329 
03330     // Add the attributes type to the set
03331     if (!(Set.AddToSet(pAffectedAttrType)))
03332     {
03333         return FALSE; 
03334     }
03335 
03336     while (pObjItem)
03337     {
03338         pCurrent = pObjItem->pObject;
03339         ERROR3IF(!(pCurrent->IsCompound()), "Set should only contain compound objects");
03340         if (pCurrent->IsCompound())
03341         {   
03342             if (!DoFactorOutCommonChildAttributes((NodeRenderableInk*)pCurrent, 
03343                                                      TRUE,     // Global
03344                                                      &Set))
03345             {
03346                 Set.DeleteAll();
03347                 return FALSE; 
03348             }
03349         }
03350         pObjItem = (ObjectItem*)pLocalisedCompounds->GetNext(pObjItem);
03351     }
03352 
03353     Set.DeleteAll(); 
03354     return TRUE; 
03355 }

BOOL UndoableOperation::DoFactorOutAfterAttrChange ObjectSet pLocalisedCompounds,
AttrTypeSet pAffectedAttrTypes
 

This Do function is designed to be called after all attributes in the pAffectedAttrTypes set have been localised on all compound nodes in the pLocalisedCompounds set.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/5/95
Parameters:
pLocalisedCompounds,: A set of compound nodes which have localised their [INPUTS] pAffectedAttrTypes attributes
pAffectedAttrTypes: The types of the attributes that have been applied to the range.

Parameters:
- [OUTPUTS]
Returns:
TRUE if successful, FALSE if we run out of memory. Tidyup then call End()
The function globally factors out the attributes which have a type which is in the pAffectedAttrTypes set.

Before calling the function you should have localised the attribute by calling DoLocaliseForAttrChange.

See also:
AttrTypeSet

NodeAttribute::GetAttributeType

UndoableOperation::DoLocaliseForAttrChange

Definition at line 3248 of file undoop.cpp.

03250 {
03251     ERROR3IF(!pLocalisedCompounds, "DoFactorOutAfterAttrChange called with a NULL compound set");  
03252     //ERROR3IF(!pAffectedAttrTypes, "DoFactorOutAfterAttrChange called with a NULL attr type set"); 
03253 
03254     // Scan the range
03255     ObjectItem* pObjItem = (ObjectItem*)(pLocalisedCompounds->GetHead());
03256     NodeRenderableInk* pCurrent;
03257 
03258     while (pObjItem)
03259     {
03260         pCurrent = pObjItem->pObject;
03261         ERROR3IF(!(pCurrent->IsCompound()), "Set should only contain compound objects");
03262         if (pCurrent->IsCompound())
03263         {   
03264             if (!DoFactorOutCommonChildAttributes((NodeRenderableInk*)pCurrent, 
03265                                                      TRUE,     // Global
03266                                                      pAffectedAttrTypes))
03267             {
03268                 return FALSE; 
03269             }
03270         }
03271         pObjItem = (ObjectItem*)pLocalisedCompounds->GetNext(pObjItem);
03272     }
03273 
03274     return TRUE; 
03275 
03276 }

BOOL UndoableOperation::DoFactorOutAfterAttrChange Range pRange,
CCRuntimeClass pAffectedAttrType
 

This Do function must be called on the range after an attribute being applied to it. If you have applied multiple attributes to the range then it is more efficient to call the other version of this function which takes a set of attribute types.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/5/95
Parameters:
pRange,: The objects that need their attributes factoring out [INPUTS]
pAffectedAttrType: The type of the attribute that have just been applied to the range.

Parameters:
- [OUTPUTS]
Returns:
TRUE if successful, FALSE if we run out of memory. Tidyup then call End()
The function globally factors out the attribute which has type pAffectedAttrType

Before calling the function you should have localised the attribute by calling DoLocaliseForAttrChange.

If an object in the range Discards its attribute children then its attributes are ignored when factoring (eg. the caret)

Note: When applying an attribute, we are not always going to apply it to the object itself, sometimes we need to apply it to the object's parent. Eg. when we apply a line based attribute to a text character the attributes will get applied to the parent TextLine.

In this situation we do not factor out the objects attributes, but its parents attributes instead.

Note: When applying attributes, we are not always going to apply the attributes to the object itself, sometimes we need to apply them to the object's parent. Eg. when we apply a line based attribute to a text character the attributes will get applied to the parent TextLine.

In this situation we do not factor out the object's attributes, but its parents attributes instead.

See also:
AttrTypeSet

NodeAttribute::GetAttributeType

UndoableOperation::DoLocaliseForAttrChange

Range::DoLocaliseForAttrChange

Range::DoFactorOutAfterAttrChange

Definition at line 2740 of file undoop.cpp.

02742 {
02743     ERROR3IF(pRange->Count() == 0, "Range::DoFactorOutAfterAttrChange called on an empty range");  
02744     // Scan the range
02745 
02746     // Iterate over the top of any liveeffects applied to the selection
02747     // Its important that this iteration matches those used in DoApplyAttribute functions
02748     // so that attributes are put in the places where mutation will find them
02749     ListRange* pLevel = EffectsStack::GetNewLevelRange(pRange, FALSE);  // We DO own this range
02750     Node* pCurrent = pLevel->FindFirst();
02751 
02752     // There is no need to factor out the attributes on a compound more than once, so we 
02753     // remember the last compound node which has had its attributes factored out 
02754     NodeRenderableInk* pFactoredOutCompound = NULL;
02755 
02756     Node* pParent;
02757     Node* pObject;                  
02758     while (pCurrent)
02759     {
02760         pObject = pCurrent;
02761         // Get the object that the attribute has been applied to
02762         ERROR3IF(!pAffectedAttrType, "AttrType is NULL");  
02763         pObject = ((NodeRenderableInk*)pObject)->GetObjectToApplyTo(pAffectedAttrType);
02764 
02765         // If the object can discard its attribute children then we should not try to factor
02766         // out its attributes
02767 
02768         {
02769 
02770             // We only need to factor out attributes on nodes which have a compound parent
02771             pParent = pObject->FindParent(); 
02772             ERROR3IF(pParent == NULL, "Range::DoFactorOutAfterAttrChange, node found without a parent"); 
02773         
02774             // Only factor out attribs if  the parent has not already had its attribs factored out
02775             if ((pParent->IsCompound()) && (pParent != pFactoredOutCompound))
02776             {
02777                 // Attempt to localise the compound
02778                 if (!DoFactorOutAfterAttrChange((NodeRenderableInk*)pObject, pAffectedAttrType))
02779                 {
02780                     delete pLevel;
02781                     return FALSE;
02782                 }
02783                  
02784                 pFactoredOutCompound = (NodeRenderableInk*)pParent;  // Remember that it's been localised
02785             }
02786         }
02787         pCurrent = pLevel->FindNext(pCurrent);
02788     }
02789 
02790     delete pLevel;
02791     return TRUE;
02792 }

BOOL UndoableOperation::DoFactorOutAfterAttrChange Range pRange,
AttrTypeSet pAffectedAttrTypes
 

This Do function must be called on the range after attributes have being applied to it.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/5/95
Parameters:
pRange,: The objects that need their attributes factoring out [INPUTS]
pAffectedAttrTypes: The types of the attributes that have just been applied to the range.

Parameters:
- [OUTPUTS]
Returns:
TRUE if successful, FALSE if we run out of memory. Tidyup then call End()
The function globally factors out those attributes which have a type in the pAffectedAttrTypes set.

Before calling the function you should have localised attributes by calling DoLocaliseForAttrChange.

If an object in the range Discards its attribute children then its attributes are ignored when factoring (eg. the caret)

Note: When applying attributes, we are not always going to apply the attributes to the object itself, sometimes we need to apply them to the object's parent. Eg. when we apply a line based attribute to a text character the attributes will get applied to the parent TextLine.

In this situation we do not factor out the objects attributes, but its parents attributes instead.

Warning ~~~~~~~

All attribute types in the AttrTypeSet must have been localised (and so need factoring out) on the same compound node. This means for example that the AttrType set cannot contain a Bold and a Line space attribute. If we need to do this in future then the routine will need to be changed.

See also:
AttrTypeSet

NodeAttribute::GetAttributeType

UndoableOperation::DoFactorOutAfterAttrChange

Range::DoLocaliseForAttrChange

Definition at line 2625 of file undoop.cpp.

02627 {
02628     ERROR3IF(pRange->Count() == 0, "Range::DoFactorOutAfterAttrChange called on an empty range");  
02629 
02630     // Iterate over the top of any liveeffects applied to the selection
02631     // Its important that this iteration matches those used in DoApplyAttribute functions
02632     // so that attributes are put in the places where mutation will find them
02633     ListRange* pLevel = EffectsStack::GetNewLevelRange(pRange, FALSE);  // We DO own this range
02634     Node* pCurrent = pLevel->FindFirst();
02635 
02636     // There is no need to factor out the attributes on a compound more than once, so we 
02637     // remember the last compound node which has had its attributes factored out 
02638     NodeRenderableInk* pFactoredOutCompound = NULL;
02639 
02640     Node* pParent;
02641     Node* pObject;
02642                         
02643     while (pCurrent)
02644     {
02645         // If the object can discard its attribute children then we should not try to factor
02646         // out its attributes
02647         CCRuntimeClass* AttrType;
02648         
02649         pObject = pCurrent;
02650         if (pAffectedAttrTypes && (!pAffectedAttrTypes->IsEmpty()))
02651         {
02652             AttrType = ((AttrTypeItem*)pAffectedAttrTypes->GetHead())->AttributeType;
02653             ERROR3IF(!AttrType, "AttrType set contains NULL attribute type");  
02654             pObject = ((NodeRenderableInk*)pObject)->GetObjectToApplyTo(AttrType);
02655         }
02656 
02657         // DY added test for NULL, which can occur with bevels
02658         if ((pObject != NULL))
02659         {
02660             // We only need to factor out attributes on nodes which have a compound parent
02661             pParent = pObject->FindParent(); 
02662             ERROR3IF(pParent == NULL, "Range::DoFactorOutAfterAttrChange, node found without a parent"); 
02663         
02664             // Only factor out attribs if  the parent has not already had its attribs factored out
02665             if ((pParent->IsCompound()) && (pParent != pFactoredOutCompound))
02666             {
02667                 // Attempt to localise the compound
02668                 if (!DoFactorOutAfterAttrChange((NodeRenderableInk*)pObject, pAffectedAttrTypes))
02669                 {
02670                     delete pLevel;
02671                     return FALSE;
02672                 }
02673                  
02674                 pFactoredOutCompound = (NodeRenderableInk*)pParent;  // Remember that it's been localised
02675             }
02676         }
02677         
02678         pCurrent = pLevel->FindNext(pCurrent);
02679     }
02680 
02681     delete pLevel;
02682     return TRUE;
02683 }

BOOL UndoableOperation::DoFactorOutAfterAttrChange NodeRenderableInk Object,
CCRuntimeClass pAffectedAttrType
 

This Do function must be called on an object after an attribute being applied to it. If you have applied multiple attributes to the Object then it is more efficient to call the other version of this function which takes a set of attribute types.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/5/95
Parameters:
Object,: The object that you have just applied attributes to [INPUTS]
pAffectedAttrType: The types of the attribute that have just been applied to the object.

Parameters:
- [OUTPUTS]
Returns:
TRUE if successful, FALSE if we run out of memory. Tidyup then call End()
The function globally factors out the attribute with type pAffectedAttrType

If the function is called on a object which does not have a compound parent then there will be no attributes to factor out so the function will simply return TRUE without having done anything.

Before calling the function you should have localised attributes by calling DoLocaliseForAttrChange.

If the object discards its attribute children then the routine does nothing (eg. the caret)

Note: When applying attributes, we are not always going to apply the attributes to the object itself, sometimes we need to apply them to the object's parent. Eg. when we apply a line based attribute to a text character the attributes will get applied to the parent TextLine.

In this situation we do not factor out the objects attributes, but its parents attributes instead.

See also:
AttrTypeSet

NodeAttribute::GetAttributeType

UndoableOperation::DoLocaliseForAttrChange

Range::DoLocaliseForAttrChange

Range::DoFactorOutAfterAttrChange

Definition at line 3170 of file undoop.cpp.

03172 {
03173     BOOL ok = TRUE;
03174 
03175     // Get object attr was applied to
03176     ERROR3IF(!pAffectedAttrType, "AttrType is NULL");  
03177     Object = Object->GetObjectToApplyTo(pAffectedAttrType);
03178 
03179     {   
03180 
03181         Node* pParent;
03182         pParent = Object->FindParent(); 
03183         ERROR3IF(!pParent, "UndoableOperation::DoFactorOutAfterAttrChange called on an object which has no parent"); 
03184 
03185         if (pParent->IsCompound())
03186         {
03187     
03188             // We need an attribute type set
03189             AttrTypeSet Set; 
03190 
03191             // Add the attributes type to the set
03192             if (!(Set.AddToSet(pAffectedAttrType)))
03193             {
03194                 ok = FALSE; 
03195             }
03196 
03197             if (ok)
03198             {
03199 
03200                 return (DoFactorOutCommonChildAttributes((NodeRenderableInk*)pParent, 
03201                                                          TRUE,     // Global
03202                                                          &Set));
03203             }
03204     
03205             Set.DeleteAll(); 
03206         }
03207     }
03208     return ok; 
03209 }

BOOL UndoableOperation::DoFactorOutAfterAttrChange NodeRenderableInk Object,
AttrTypeSet pAffectedAttrTypes
 

This Do function must be called on an object after attributes have being applied to it.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/5/95
Parameters:
Object,: The object that you have just applied attributes to [INPUTS]
pAffectedAttrTypes: The types of the attributes that have just been applied to the object.

Parameters:
- [OUTPUTS]
Returns:
TRUE if successful, FALSE if we run out of memory. Tidyup then call End()
The function globally factors out those attributes which have a type in the pAffectedAttrTypes set.

If the function is called on a object which does not have a compound parent then there will be no attributes to factor out so the function will simply return TRUE without having done anything.

Before calling the function you should have localised attributes by calling DoLocaliseForAttrChange.

If the object discards its attribute children then the routine does nothing (eg. the caret)

Note: When applying attributes, we are not always going to apply the attributes to the object itself, sometimes we need to apply them to the object's parent. Eg. when we apply a line based attribute to a text character the attributes will get applied to the parent TextLine.

In this situation we do not factor out the objects attributes, but its parents attributes instead.

Warning ~~~~~~~

All attribute types in the AttrTypeSet must have been localised (and so need factoring out) on the same compound node. This means for example that the AttrType set cannot contain a Bold and a Line space attribute. If we need to do this in future then the routine will need to be changed.

See also:
AttrTypeSet

NodeAttribute::GetAttributeType

UndoableOperation::DoLocaliseForAttrChange

Range::DoLocaliseForAttrChange

Range::DoFactorOutAfterAttrChange

Definition at line 3091 of file undoop.cpp.

03093 {
03094     CCRuntimeClass* AttrType;
03095 
03096     // Get object which attrib was applied to
03097     if (pAffectedAttrTypes && (!pAffectedAttrTypes->IsEmpty()))
03098     {
03099         AttrType = ((AttrTypeItem*)pAffectedAttrTypes->GetHead())->AttributeType;
03100         ERROR3IF(!AttrType, "AttrType set contains NULL attribute type");  
03101         Object = Object->GetObjectToApplyTo(AttrType);
03102     }
03103 
03104     {   
03105         Node* pParent;
03106         pParent = Object->FindParent(); 
03107         ERROR3IF(!pParent, "UndoableOperation::DoFactorOutAfterAttrChange called on an object which has no parent"); 
03108 
03109         if (pParent->IsCompound())
03110         {
03111             return (DoFactorOutCommonChildAttributes((NodeRenderableInk*)pParent, 
03112                                                      TRUE,     // Global
03113                                                      pAffectedAttrTypes));
03114         }
03115     }
03116     return TRUE;
03117 }

BOOL UndoableOperation::DoFactorOutCommonAttributes NodeRenderableInk pRootNode,
BOOL  bGlobal = FALSE,
AttrTypeSet pAffectedAttrTypes = NULL
 

Just a wrapper to get function name consistency and do the common IsCompound test to prevent DFOCCA from barfing...

Author:
Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
Date:
13/10/2004
Parameters:
CompoundObject,: The object to factor out [INPUTS] Global: When TRUE we recursively factor out attributes in all parent compounds of the CompoundObject (Bottom up) pAffectedAttrTypes: An optional set of attribute types. If this is specified then we only consider factoring out those attributes which have a type which is in this set.
Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)

Errors: -

See also:
UndoableOperation::DoLocaliseCommonAttributes

NodeRenderableInk::FactorOutCommonChildAttributes

Definition at line 3644 of file undoop.cpp.

03647 {
03648     if (pRootNode->IsCompound())
03649         DoFactorOutCommonChildAttributes(pRootNode, bGlobal, pAffectedAttrTypes);
03650         
03651     return TRUE;
03652 }

BOOL UndoableOperation::DoFactorOutCommonChildAttributes NodeRenderableInk CompoundObject,
BOOL  Global = FALSE,
AttrTypeSet pAffectedAttrTypes = NULL
 

This function is an information gatherer for the DoFactorOutAfterDeletion function. See this function for a full description of its purpose. Whenever we delete a range of objects, if any objects in the range have compound parents then we must adjust the common attributes on these compounds. This function factors out all attributes which are common to all children of the compound object. All common attributes become first children of the compound object.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
7/8/94
Parameters:
CompoundObject,: The object to factor out [INPUTS]
Global: When TRUE we recursively factor out attributes in all parent compounds of the CompoundObject (Bottom up)

pAffectedAttrTypes: An optional set of attribute types. If this is specified then we only consider factoring out those attributes which have a type which is in this set.

Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)
If the compound contains a node which can discard its attributes (like the caret) then its attributes are not considered when factoring out.

As with all Do functions actions are generated to undo/redo

Returns:
Errors: -
See also:
UndoableOperation::DoLocaliseCommonAttributes

NodeRenderableInk::FactorOutCommonChildAttributes

Definition at line 3581 of file undoop.cpp.

03584 {
03585     LocaliseCommonAttrAct* UndoAct;
03586                  
03587     if (!CompoundObject->DiscardsAttributeChildren())
03588     {
03589         // Make a copy of the attribute type set to store in the Action
03590         AttrTypeSet* pSet = NULL;
03591         if (pAffectedAttrTypes)
03592         {
03593             pSet = pAffectedAttrTypes->CopySet(); 
03594             if (!pSet)
03595                 return FALSE; // Failed to create set
03596         }
03597 
03598         // Create an action to localise attributes which have been factored out
03599         if ( LocaliseCommonAttrAct::Init(this,
03600                                          &UndoActions,
03601                                          CompoundObject,
03602                                          Global,
03603                                          pSet,
03604                                          (Action**)(&UndoAct))
03605                                           == AC_FAIL)
03606             return FALSE;
03607     }
03608 
03609     if (!CompoundObject->FactorOutCommonChildAttributes(Global, pAffectedAttrTypes))
03610     {
03611         FailAndExecuteAllButLast();
03612         return FALSE; 
03613     }
03614 
03615     return TRUE;
03616 }

BOOL UndoableOperation::DoFlattenRange Range  NodeRange  ) 
 

Not implemented yet.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
3/5/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
-

Definition at line 1898 of file undoop.cpp.

01899 {
01900     return FALSE;
01901 }

BOOL UndoableOperation::DoHideComplexRange Range RangeToHide  ) 
 

This function is a pre process to DoHideNodes(). It calls each object in the range to hide themselves in a complex way. It may be that no objects in the selection require this facility, which means the RangeToHide object will be returned from this function unaffected. DoHideNodes() will then go through hidding all nodes in the range itself. If however a node responds to ComplexHide() and hides itself, the node will be removed from the range. This allows complex group nodes to control how they are hidden. Note, it is expected that ComplexHide() responders will hide nodes themselves This will have the automatic effect of removing them from the range. Hidden nodes do not appear in ranges.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
3/5/95
Parameters:
RangeToHide = the current range of nodes which need hiding [INPUTS]
RangeToHide = the updated range of nodes which need hiding [OUTPUTS]
Returns:
TRUE then all necessary objects were hidden correctly FALSE if failed to hide one of the objects

Definition at line 850 of file undoop.cpp.

00851 {
00852     BOOL Failed=FALSE;      
00853     Node *Next, *Current = RangeToHide.FindFirst();
00854 
00855     while (Current!=NULL)
00856     {
00857         // set the next node pointer.
00858         Next=RangeToHide.FindNext(Current);
00859         INT32 success = Current->ComplexHide(this, Next);
00860         // success=-1 then error unable to hide node
00861         // success= 0 then ignore
00862         // success= 1 then node has been hidden
00863         Failed=(success<0);
00864         if (Failed)
00865             break;
00866 
00867         Current=Next;
00868     }
00869 
00870     return (!Failed);
00871 }

BOOL UndoableOperation::DoHideNode Node NodeToHide,
BOOL  IncludeSubtreeSize,
NodeHidden **  nodeHidden = NULL,
BOOL  TellSubtree = TRUE
 

This low level Do function hides the subtree with root NodeToHide.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/10/93
Parameters:
Node,: The Node to be hidden [INPUTS]
IncludeSubtreeSize: Flag indicating if the subtree being hidden should be considered as belonging to the Operation history or not. (See the note in ops.h)

Parameters:
nodeHidden,: A pointer to the NodeHidden hiding the NodeToHide. This [OUTPUTS] output is optional.
Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)

Errors: -

See also:
UndoableOperation::DoHideNodes

Definition at line 702 of file undoop.cpp.

00706 {
00707     ERROR3IF(!OpFlags.SucceedAndDiscard && NodeToHide->IsAnAttribute() && NodeToHide->FindParent()->DiscardsAttributeChildren(), "DoHide called under Caret");
00708 
00709     if (NodeToHide->DiscardsAttributeChildren())    // If the node to hide doesn't want to produce undo (CaretNode)
00710         return TRUE;                                // Then bomb out now before we do anything...
00711 
00712     // We shouldn't tell the node that it's being hidden if we are only
00713     // moving it.
00714     // Also if we are Hiding a Node Group, then there is no
00715     // need to tell anyone either.  As the children are unaffected.
00716     if (TellSubtree)
00717     {
00718         // Tell the node and it's subtree, that they are being hidden
00719         Node* pNode = NodeToHide->FindFirstDepthFirst();
00720         while (pNode!=NULL)
00721         {
00722             if (!pNode->HidingNode())
00723                 return FALSE;
00724 
00725             // And find the next node
00726             pNode = pNode->FindNextDepthFirst(NodeToHide);
00727         }
00728         // Invalidate the region, we need to do this here because we are deleting the node
00729         if (NodeToHide->IsBounded())
00730             ((NodeRenderableBounded*)NodeToHide)->InvalidateBoundingRect();
00731 
00732     }
00733 
00734 // removed by Ed 23/5/95 'cos it caused text redraw problems
00735 // and nobody could justify why just moving an object in the tree should
00736 // cause the renderable bound associated with it to be invalidated
00737 //  // Invalidate the region
00738 //  if (NodeToHide->IsBounded())
00739 //      ((NodeRenderableBounded*)NodeToHide)->InvalidateBoundingRect();
00740 
00741     // Try to hide the Node    
00742     NodeHidden* Hidden; 
00743     ALLOC_WITH_FAIL(Hidden,(new NodeHidden(NodeToHide)),this);
00744     if (Hidden == NULL)
00745     {          
00746         return (FALSE); 
00747     }
00748 
00749     // Try to create a ShowNodeAction which will show the node that we have just hidden. 
00750     
00751     ShowNodeAction* UndoShowNodeAction; 
00752 
00753     if (ShowNodeAction::Init(this,  
00754                              &UndoActions, 
00755                              Hidden, 
00756                              IncludeSubtreeSize, 
00757                              (Action**)(&UndoShowNodeAction),
00758                              TellSubtree) == AC_FAIL)
00759     {   
00760         // We must unhide the NodeToHide manually, cos no action will do it for us 
00761         Hidden->ShowNode(); // Hidden is deleted don't worry 
00762         return FALSE; 
00763     }
00764     
00765     if (NodeToHide->IsSelected())
00766     {
00767         // Update the selection range 
00768         Camelot.UpdateSelection();
00769     }
00770 
00771     // If the user provided a nodeHidden parameter then return a pointer to the NodeHidden
00772     if (nodeHidden != NULL)
00773         *nodeHidden = Hidden;    
00774 
00775 // Added by Jim: Broadcast the layerchanged message when inserting a new layer
00776 
00777     if (NodeToHide->GetRuntimeClass() == CC_RUNTIME_CLASS(Layer))
00778     {
00779         Spread* pSpread = (Spread*) Hidden->FindParent(CC_RUNTIME_CLASS(Spread)); 
00780         BROADCAST_TO_ALL(SpreadMsg(pSpread,SpreadMsg::LAYERCHANGES));
00781     }
00782     // Success  
00783     return (TRUE); 
00784 }

BOOL UndoableOperation::DoHideNodes Range  NodeRange,
BOOL  IncludeSubtreeSize,
BOOL  TellSubtree = TRUE
 

This low level Do function hides a range of the subtrees.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
03/03/94
Parameters:
NodeRange,: The Range of nodes to be hidden [INPUTS]
IncludeSubtreeSize: Flag indicating if the subtrees being hidden should be considered as belonging to the Operation history or not. (See the note in ops.h)

Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)

Errors: -

See also:
UndoableOperation::DoHideNode

Definition at line 809 of file undoop.cpp.

00810 {
00811     Node* Current = NodeRange.FindFirst(); 
00812     while (Current != NULL)
00813     {
00814         Node* Next = NodeRange.FindNext(Current);
00815         if (!DoHideNode(Current, IncludeSubtreeSize, NULL, TellSubtree))
00816         {
00817             return FALSE;    // Failure 
00818         } 
00819         Current = Next; 
00820     }
00821     return TRUE; // Success
00822 }                    

BOOL UndoableOperation::DoInsertNewNode NodeRenderableBounded NewNode,
Node ContextNode,
AttachNodeDirection  Direction,
BOOL  InvalidateRegion,
BOOL  ClearSelection = TRUE,
BOOL  SelectNewObject = TRUE,
BOOL  NormaliseAttributes = TRUE
 

This high level do function attaches the node to ContextNode in the direction specified. If the NewNode is a NodeRenderableInk then the node becomes selected and all other nodes are deselected.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
13/9/93
Parameters:
NewNode,: The new node to be added [INPUTS] ContextNode: The node to which NewNode is to be attached Direction: The direction the new node should be attached to the context node. InvalidateRgn: Invalidate the node's region (including blobs) ClearSelection: Clear all selected objects prior to the new object being inserted (Default TRUE) SelectNewObject: Select the new object (Default TRUE) NormaliseAttributes:When TRUE redundant attributes are removed from the node. If you know that the node being inserted has the correct set of attributes then you can set this to FALSE. Note: Do not set the bounding rectangle of NewNode prior to calling this function, or the bounds will not be propagated.
Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)
See also:
UndoableOperation::DoInsertNewNode

Definition at line 536 of file undoop.cpp.

00543 {
00544     // Insert the NewNode into the tree
00545     NewNode->AttachNode(ContextNode, Direction); 
00546     NewNode->SetSelected(FALSE); 
00547 
00548     // This is a brand new node, so we have to make sure that all its parents
00549     // are invalidated as well.
00550     // if this nodes bounding rect was already invalid when it was added the parent
00551     // will not be invalidated as well, so we first mark its bounds as valid.
00552     // This is very important - Ask Rik if you think it looks silly.
00553     NewNode->ValidateBoundingRect();
00554     NewNode->InvalidateBoundingRect();
00555 
00556     // If inserting a node onto a layer that is locked or invisible, warn the user before
00557     // proceeding, and ensure that the node is not selected.
00558     if (NewNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)))
00559     {
00560         Layer* pLayer = (Layer*)NewNode->FindParent(CC_RUNTIME_CLASS(Layer));
00561         if (pLayer != NULL)
00562         {
00563             if (!pLayer->IsVisible() || pLayer->IsLocked())
00564             {
00565                 if (WarnInsertObjsOntoLockedLayers)
00566                 {
00567 #if (_OLE_VER >= 0x200)
00568                     // Only warn the user if the document is visible to him/her.
00569                     if (pOurDoc && pOurDoc->GetOilDoc() && pOurDoc->GetOilDoc()->IsVisible())
00570 #endif
00571                     {
00572                         // ignore this warning on some ops - like if we have text syncing between layers
00573                         // or other bar ops that manipulate invisible layers
00574                         // or doing the right click from drag op since the msg upsets the drag
00575 PORTNOTE("text","Removed OpTextFormat reference")
00576 #ifndef EXCLUDE_FROM_XARALX
00577                         if (!IS_A(this, OpTextFormat) && !IS_A(this, OpDuplicateBar) && !IS_A(this, OpCopyAndTransform))
00578                             InformWarning(_R(IDS_WARNING_INSERTLAYER));
00579 #endif
00580                     }
00581 
00582                     // Set flag to FALSE so it won't be reported back again in this op
00583                     WarnInsertObjsOntoLockedLayers = FALSE;
00584                 }
00585                 SelectNewObject = FALSE;
00586             }
00587 
00588             // Note that this layer has been edited
00589             pLayer->SetEdited(TRUE);
00590 #ifdef _DEBUG
00591             // Tell the frame gallery to update its display of the frame
00592             BROADCAST_TO_ALL(LayerMsg(pLayer, LayerMsg::/*LayerReason::*/REDRAW_LAYER));
00593 #endif
00594         }
00595     }
00596 
00597     // Create a hide node action to hide the node when we undo 
00598     HideNodeAction* UndoHideNodeAction;     
00599     if (HideNodeAction::Init(this,                    
00600                              &UndoActions,
00601                              NewNode, 
00602                              TRUE,       // Include subtree size 
00603                              ( Action**)(&UndoHideNodeAction))      
00604                               == AC_FAIL)
00605 
00606     {   
00607         return FALSE; 
00608     }
00609 
00610     
00611 
00612     // Make it the currently selected object if it is an Ink object
00613     if ( NewNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)) )
00614     {
00615         if (ClearSelection)
00616         {
00617             NodeRenderableInk::DeselectAll();
00618             GetApplication()->UpdateSelection();
00619 
00620         }
00621 
00622         if (SelectNewObject)
00623         {
00624 
00625             // Select the new node
00626             ((NodeRenderableInk*)NewNode)->Select(FALSE);
00627         }
00628 
00629 
00630         if (NormaliseAttributes)
00631         {
00632             ((NodeRenderableInk*)NewNode)->NormaliseAttributes(); // Removes redundant attributes
00633         }
00634 
00635     
00636     }
00637 
00638     // Update the selection
00639     if (NewNode->IsSelected())
00640         GetApplication()->UpdateSelection();
00641 
00642 
00643     if ( NewNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableBounded)) )
00644     {
00645         if (InvalidateRegion)
00646         {
00647             NewNode->ReleaseCached(TRUE, FALSE, TRUE, TRUE);
00648             if (!DoInvalidateNodeRegion((NodeRenderableBounded*)NewNode, TRUE, FALSE, FALSE, FALSE))    // Don't recache automatically!
00649             {
00650                 return FALSE; 
00651             }
00652         }
00653     }
00654 
00655 //  #ifdef _DEBUG
00656 //      // If the node being Inserted is a layer then people need to know about it
00657 //      if (NewNode->GetRuntimeClass() == CC_RUNTIME_CLASS(Layer))
00658 //      {
00659 //          TRACE( _T("Layer inserted. Have you remembered to broadcast a SpreadMsg::LAYERCHANGES message?"));
00660 //          //Spread* pSpread = (Spread*) NewNode->FindParent(CC_RUNTIME_CLASS(Spread)); 
00661 //          //BROADCAST_TO_ALL(SpreadMsg(pSpread,SpreadMsg::LAYERCHANGES));
00662 //      }
00663 //  #endif
00664 
00665 // Added by Jim: Broadcast the layerchanged message when inserting a new layer
00666 
00667     if (NewNode->GetRuntimeClass() == CC_RUNTIME_CLASS(Layer))
00668     {
00669         Spread* pSpread = (Spread*) NewNode->FindParent(CC_RUNTIME_CLASS(Spread)); 
00670         BROADCAST_TO_ALL(SpreadMsg(pSpread,SpreadMsg::LAYERCHANGES));
00671     }
00672         
00673     return (TRUE);
00674 }  

BOOL UndoableOperation::DoInsertNewNode NodeRenderableBounded NewNode,
Spread pSpread,
BOOL  InvalidateRgn,
BOOL  ClearSelection = TRUE,
BOOL  SelectNewObject = TRUE,
BOOL  NormaliseAttributes = TRUE
 

Inserts the node as a last child of the active layer of the pSpread. If the NewNode is a NodeRenderableInk then the node becomes selected and all other nodes are deselected. If pSpread is NULL then the object is inserted on the selected spread.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
13/9/93
Parameters:
NewNode,: The new node to be added [INPUTS] pSpread: The spread to add the new node to Set this to NULL if you want to insert the node onto the selected spread. InvalidateRgn: Invalidate the node's region (including blobs) ClearSelection: Clear all selected objects prior to the new object being inserted (Default TRUE) SelectNewObject: Select the new object (Default TRUE) NormaliseAttributes:When TRUE redundant attributes are removed from the node. If you know that the node being inserted has the correct set of attributes then you can set this to FALSE.
Note: Do not set the bounding rectangle of NewNode prior to calling this function, or the bounds will not be propagated.
Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)
See also:
UndoableOperation::DoInsertNewNode

Definition at line 363 of file undoop.cpp.

00370 { 
00371     ENSURE( pOurDoc!=NULL, "No current document in DoInsertNode" );
00372 
00373     // Insert node as the active layer of the spread 
00374     pOurDoc->InsertNewNode(NewNode, pSpread);
00375     NewNode->SetSelected(FALSE); 
00376 
00377     // This is a brand new node, so we have to make sure that all its parents
00378     // are invalidated as well.
00379     // if this nodes bounding rect was already invalid when it was added the parent
00380     // will not be invalidated as well, so we first mark its bounds as valid.
00381     // This is very important - Ask Rik if you think it looks silly.
00382     NewNode->ValidateBoundingRect();
00383     NewNode->InvalidateBoundingRect();
00384 
00385     // If inserting a node onto a layer that is locked or invisible, warn the user before
00386     // proceeding, and ensure that the node is not selected.
00387     if (NewNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)))
00388     {
00389         Layer* pLayer = (Layer*)NewNode->FindParent(CC_RUNTIME_CLASS(Layer));
00390         if (pLayer != NULL)
00391         {
00392             if (!pLayer->IsVisible() || pLayer->IsLocked())
00393             {
00394                 if (WarnInsertObjsOntoLockedLayers)
00395                 {
00396 #if (_OLE_VER >= 0x200)
00397                     // Only warn the user if the document is visible to him/her.
00398                     if (pOurDoc && pOurDoc->GetOilDoc() && pOurDoc->GetOilDoc()->IsVisible())
00399 #endif
00400                     {
00401                         InformWarning(_R(IDS_WARNING_INSERTLAYER));
00402                     }
00403                     // Set flag to FALSE so it won't be reported back again in this op
00404                     WarnInsertObjsOntoLockedLayers = FALSE;
00405                 }
00406                 SelectNewObject = FALSE;
00407             }
00408 
00409             // Note that this layer has been edited
00410             pLayer->SetEdited(TRUE);
00411 #ifdef _DEBUG
00412             // Tell the frame gallery to update its display of the frame
00413             BROADCAST_TO_ALL( LayerMsg( pLayer, LayerMsg::REDRAW_LAYER ) );
00414 #endif
00415         }
00416     }
00417 
00418 
00419     /*
00420     if (InvalidateRgn)
00421     {
00422         if (!DoInvalidateNodeRegion((NodeRenderable*)NewNode, TRUE))
00423         {
00424             // Remove the NewNodeFrom the tree 
00425             NewNode->UnlinkNodeFromTree(); 
00426             return FALSE; 
00427         }
00428     }
00429     */
00430 
00431     // Create a hide node action to hide the node when we undo 
00432     HideNodeAction* UndoHideNodeAction;     
00433     if (HideNodeAction::Init(this,                    
00434                              &UndoActions,
00435                              NewNode, 
00436                              TRUE,       // Include subtree size 
00437                              ( Action**)(&UndoHideNodeAction))      
00438                               == AC_FAIL)
00439 
00440     {  
00441         // Remove the NewNodeFrom the tree 
00442         NewNode->UnlinkNodeFromTree(); 
00443         return FALSE; 
00444     }
00445 
00446 
00447     // Make it the currently selected object if it is an Ink object
00448     if ( NewNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)) )
00449     {
00450         if (ClearSelection)
00451         {
00452             NodeRenderableInk::DeselectAll();
00453             GetApplication()->UpdateSelection();
00454         }
00455 
00456 
00457         if (SelectNewObject)
00458         {
00459             // Select the new node, and don't redraw it yet 
00460             ((NodeRenderableInk*)NewNode)->Select(FALSE);
00461         }
00462 
00463         if (NormaliseAttributes)
00464         {
00465             ((NodeRenderableInk*)NewNode)->NormaliseAttributes(); // Removes redundant attributes
00466         }
00467 
00468 
00469     }
00470 
00471     // Update the selection
00472     if (NewNode->IsSelected())
00473         GetApplication()->UpdateSelection();
00474 
00475     if ( NewNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableBounded)) )
00476     {
00477         if (InvalidateRgn)
00478         {
00479             if (!DoInvalidateNodeRegion((NodeRenderableBounded*)NewNode, TRUE))
00480             {
00481                 return FALSE; 
00482             }
00483         }
00484     }
00485 
00486 // Added by Jim: Broadcast the layerchanged message when inserting a new layer
00487 
00488     if (NewNode->GetRuntimeClass() == CC_RUNTIME_CLASS(Layer))
00489     {
00490         Spread* pSpread = (Spread*) NewNode->FindParent(CC_RUNTIME_CLASS(Spread)); 
00491         BROADCAST_TO_ALL(SpreadMsg(pSpread,SpreadMsg::LAYERCHANGES));
00492     }
00493 
00494     return (TRUE); 
00495 }     

BOOL UndoableOperation::DoInsertPathElement NodePath ThisPath,
INT32  Index,
DocCoord  NewCoord,
PathFlags  NewFlags,
PathVerb  NewVerb,
BOOL  RedrawPath = TRUE
 

This 'Do' function adds an element into a path, recording undo information.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/9/94
Parameters:
ThisPath points at the NodePath into which we want to insert an element [INPUTS] Index - the the element will be inserted after this element NewCoord is the new element's coordinate value NewFlags is the new element's flags value NewVerb is the new element's verb value RedrawPath - TRUE if the screen area of the path should be redrawn, FALSE if the caller is responsible
- [OUTPUTS]
Returns:
TRUE if succeeded, FALSE otherwise

Errors: -

See also:
-

Definition at line 3873 of file undoop.cpp.

03879 {
03880 #ifndef STANDALONE
03881 
03882     // Create an undo action for this action, which is a RemoveElementAction
03883     RemovePathElementAction* pAction = NULL;
03884     ActionCode Act;
03885     Act = RemovePathElementAction::Init(this, 
03886                                     &UndoActions, 
03887                                     1,
03888                                     Index+1,
03889                                     (Action**)(&pAction));
03890     if (Act == AC_FAIL)
03891         return FALSE;
03892 
03893     // Tell the operation where the path is
03894     if (pAction != NULL)
03895         pAction->RecordPath(ThisPath);
03896 
03897     Document* pDocument = GetWorkingDoc();
03898     ERROR2IF(pDocument == NULL, FALSE, "There was no Document when deleteing path elements");
03899     Spread* pSpread = ThisPath->FindParentSpread();
03900     ERROR2IF(pSpread == NULL, FALSE, "Path had no parent spread");
03901 
03902     // Force a re-draw of the place where the path used to be
03903     if (RedrawPath)
03904     {
03905         DocRect Invalid = ThisPath->GetUnionBlobBoundingRect();
03906         // Mark the region as requiring object to recache any cached
03907         // data they may be holding because the Op may have changed it
03908         pDocument->ForceRedraw( pSpread, Invalid, FALSE, ThisPath );
03909     }
03910 
03911     // Insert the new element
03912     ThisPath->InkPath.InsertSection(Index,1);
03913 
03914     // Get pointers to all the arrays of the path
03915     PathVerb* Verbs = NULL;
03916     DocCoord* Coords = NULL;
03917     PathFlags* Flags = NULL;
03918     ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
03919 
03920     // Update the coords
03921     Verbs[Index+1] = NewVerb;
03922     Flags[Index+1] = NewFlags;
03923     Coords[Index+1] = NewCoord;
03924 
03925     // The bounding rect may have changed
03926     ThisPath->InvalidateBoundingRect();
03927 
03928     // Redraw the new area
03929     if (RedrawPath)
03930     {
03931         DocRect Invalid = ThisPath->GetUnionBlobBoundingRect();
03932         // Mark the region as requiring object to recache any cached
03933         // data they may be holding because the Op may have changed it
03934         pDocument->ForceRedraw( pSpread, Invalid, FALSE, ThisPath );
03935     }
03936 
03937 #endif
03938     return TRUE;
03939 }

BOOL UndoableOperation::DoInvalidateNodeRegion NodeRenderableBounded Node,
BOOL  IncludeBlobs,
BOOL  UndoBlobs = FALSE,
BOOL  IfBgRedraw = FALSE,
BOOL  bForceRecache = TRUE
 

Invalidates the nodes bounding rectangle, or blob bounding rectangle.

Parameters:
- [OUTPUTS]
Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)

Errors: -

See also:
UndoableOperation::DoInvalidateNodesRegions

Definition at line 1646 of file undoop.cpp.

01651 {   
01652     ENSURE((!OpFlags.Failed), "Calling a DO function after operation has failed");
01653 
01654     // Range = Sel nodes, Unsel nodes, cross layers, Locked layers, Ignore Non-renderables, Ignore invisible layers
01655     RangeControl        rc( TRUE, TRUE, TRUE, FALSE, TRUE, TRUE );
01656     Range               range( Node, Node, rc );
01657 
01658     return( DoInvalidateNodesRegions( range, IncludeBlobs, UndoBlobs, IfBgRedraw, bForceRecache ) ); 
01659 }

BOOL UndoableOperation::DoInvalidateNodesRegions Range  NodeRange,
BOOL  IncludeBlobs,
BOOL  UndoBlobs = FALSE,
BOOL  IfBgRedraw = FALSE,
BOOL  bForceRecache = TRUE
 

This low level Do function invalidates a region which is the union of the bounding rectangles of each node in the range. When the includeBlobs flag is TRUE the region which gets invalidated includes the objects blobs.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/2/94
Parameters:
NodeRange,: The range of nodes [INPUTS] IncludeBlobs: When TRUE we take the bounding rectangle of the objects and their blobs. UndoBlobs: TRUE, Invert the 'IncludeBlobs' for undo/redo this op. FALSE, use the same 'IncludeBlobs' for undo/redo.
- [OUTPUTS]
Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)
constraints:

All members of the range must be on the same spread No member of the range can be hidden

Returns:
Errors: An ENSURE will occur if the range of nodes is empty, in a retail build the function will return TRUE but do nothing.
See also:
UndoableOperation::DoInvalidateNodeRegion

Definition at line 1470 of file undoop.cpp.

01474 {
01475     ENSURE((!OpFlags.Failed), "Calling a DO function after operation has failed"); 
01476 
01477     if (UndoBlobs)
01478     {
01479         // Undo blobs = TRUE
01480         // We will use different 'IncludeBlobs' when we undo/redo this op
01481         // to the one we use initially.
01482         UndoBlobs = !IncludeBlobs;
01483     }
01484     else
01485     {
01486         // Undo blobs = FALSE
01487         // We will use the same 'IncludeBlobs' when we undo/redo this op
01488         // as the one we use initially.
01489         UndoBlobs = IncludeBlobs;
01490     }
01491 
01492     BOOL bOldValue = NodeRange.SetPromoteToParent(TRUE);
01493     NodeRenderableBounded* CurrentNode = (NodeRenderableBounded*)NodeRange.FindFirst(); 
01494     NodeRange.SetPromoteToParent(bOldValue);
01495 
01496     if (CurrentNode == NULL)
01497         return TRUE; // The range is empty so NOP
01498 
01499     // ENSURE the range of nodes is not empty
01500 //  ENSURE (CurrentNode != NULL, "Calling DoInvalidateNodesRegions with an empty range"); 
01501 
01502 //  ENSURE(CurrentNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderable)), 
01503 //          "Trying to invalidate a non NodeRenderable node");
01504 
01505     // Find the spread 
01506     Spread* pSpread = (Spread*)CurrentNode->FindParent(CC_RUNTIME_CLASS(Spread));
01507 
01508 
01509 
01510     // Matt 27/11/2000
01511     // OK, here's the beef... At present, if you group a shadowed object, the tree structure correctly
01512     // reflects this as a NodeShadowController with a NodeGroup parent... Now, when we've clicked on the
01513     // 'Set New Design' button, the NodeGroup is passed OK and is hidden after being copied (as was intended)
01514     // but the NodeShadowController beneath this is then tested: When asked what it's parent spread is, it
01515     // will promptly keel over, triggering the following ENSURE as its parent (the NodeGroup) no longer has
01516     // a pointer to its parent (ie it is NULL) - to cater for this, if we reach this point and we have no
01517     // parent spread, we can assume one of two things:
01518     // 1.   The node above us has been hidden, therefore we are already implicitly hidden and we shouldn't
01519     //      undertake any special work
01520     // 2.   Everything is stuffed so bad in our tree that it really doesn't matter what we do here - we're
01521     //      about to die anyhow...
01522     // Therefore, we can just return without failing with an ensure...
01523     //
01524     // ENSURE(pSpread != NULL, "Spread is NULL"); 
01525 
01526 
01527 
01528     if (pSpread)
01529     {
01530         if (IfBgRedraw)
01531         {
01532             // -------------------------------------------------------------------------------------
01533             // Try and create an InvalidateRegionAction 
01534             InvalidateRegionIfBgRedrawAction* UndoInvalidateRgnAction;                          
01535    
01536             // Create an InvalidateRegionAction  
01537             // Note that unfortunatly the action has to store the node range, rather than the 
01538             // bounding rectangle because GetBlobBoundingRect must be calculated on the fly. 
01539 
01540             if ( InvalidateRegionIfBgRedrawAction::Init(this,                    
01541                                               &UndoActions,
01542                                               NodeRange, 
01543                                               pSpread,      
01544                                               UndoBlobs,
01545                                               ( Action**)(&UndoInvalidateRgnAction)) == AC_FAIL)  
01546             {
01547                 return FALSE;  // Failed to create action 
01548             }  
01549         
01550             if (!GetApplication()->IsBgRendering())
01551             {
01552                 return TRUE;    // Ignore if no Bg Rendering in progress
01553             }
01554 
01555     //      GetApplication()->DeleteRenderRegions(DocView::GetSelected());
01556     //      GetApplication()->BgRendering = FALSE;
01557         }
01558         else
01559         {
01560             // -------------------------------------------------------------------------------------
01561             // Try and create an InvalidateRegionAction 
01562             InvalidateRegionAction* UndoInvalidateRgnAction;                          
01563    
01564             // Create an InvalidateRegionAction  
01565             // Note that unfortunatly the action has to store the node range, rather than the 
01566             // bounding rectangle because GetBlobBoundingRect must be calculated on the fly. 
01567 
01568             if ( InvalidateRegionAction::Init(this,                    
01569                                               &UndoActions,
01570                                               NodeRange, 
01571                                               pSpread,      
01572                                               UndoBlobs,
01573                                               ( Action**)(&UndoInvalidateRgnAction)) == AC_FAIL)  
01574             {
01575                 return FALSE;  // Failed to create action 
01576             }  
01577         }
01578 
01579         ENSURE(pOurDoc != 0, "There was no document in DoInvalidateNodesRegions");
01580 
01581         // Invalidate the bounds of each node in the range
01582 
01583         if (pOurDoc != NULL)
01584         {
01585             DocRect TempRect; 
01586 
01587             BOOL bOldValue = NodeRange.SetPromoteToParent(TRUE);
01588             while (CurrentNode != NULL)
01589             {
01590                 // Because we had a Range param, we could possibly be given any legal node in the tree,
01591                 // e.g. the Insert node, not just renderable bounded objects, hence this 'if' statement
01592                 if (CurrentNode->IsAnObject() || CurrentNode->IsPaper())
01593                 {
01594                     ENSURE(CurrentNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableBounded)), 
01595                         "Trying to invalidate a non NodeRenderable node");
01596 
01597                     TempRect = (IncludeBlobs ? 
01598                                     (CurrentNode->GetUnionBlobBoundingRect()):
01599                                     (CurrentNode->GetBoundingRect())
01600                                  );
01601 TempRect = TempRect.Union(CurrentNode->GetEffectStackBounds());
01602 
01603                     // Accumulate this invalid region in a pending list until the Op
01604                     // finishes
01605                     // Mark the region as requiring object to recache any cached
01606                     // data they may be holding because the Op may have changed it
01607 //                  pOurDoc->ForceRedraw(pSpread, TempRect, TRUE, bForceRecache ? CurrentNode : NULL);
01608                     pOurDoc->ForceRedraw(pSpread, TempRect, TRUE, CurrentNode, bForceRecache);
01609                 }
01610 
01611                 CurrentNode = (NodeRenderableBounded*) NodeRange.FindNext(CurrentNode); 
01612             }
01613             NodeRange.SetPromoteToParent(bOldValue);
01614         }
01615     }
01616 
01617     // Now invalidate the region
01618     return TRUE;  
01619 }

BOOL UndoableOperation::DoInvalidateRegion Spread pSpread,
const DocRect InvalidRegion
 

Invalidates the region specified and adds the appropriate action to the action list for the current operation. If you are invalidating a region associated with a node in the tree then you should be using DoInvalidateNodeRegion() or DoInvalidateNodesRegion().

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
25/8/94
Parameters:
pSpread - The spread that the region to invalidate is on [INPUTS] InvalidRegion - The region that you want to invalidate
Returns:
TRUE if it all worked, FALSE if not (TIDYUP THEN CALL End()!)
See also:
UndoableOperation::DoInvalidateNodeRegion

Definition at line 1680 of file undoop.cpp.

01681 {
01682     // make sure that things are worth doing
01683     ENSURE((!OpFlags.Failed), "Calling a DO function after operation has failed");
01684     ENSURE(pSpread!=NULL, "Attempt to invalidate a region on a null spread.");
01685 
01686     // If the region is empty we could save everyone a lot of trouble
01687     if (InvalidRegion.IsEmpty())
01688         return TRUE;
01689 
01690     // Try and create an InvalidateArbitaryRegionAction and fail if it does not work
01691     InvalidateArbitaryAction* pAction;
01692     ActionCode ActCode = InvalidateArbitaryAction::Init( this, &UndoActions, pSpread,
01693                          InvalidRegion, (Action**)(&pAction));
01694     
01695     // See if it worked
01696     if (ActCode==AC_FAIL)
01697         return FALSE;
01698 
01699     // Now we can invalidate the region for the caller
01700     // First we need a document
01701     ENSURE(pOurDoc != NULL, "There was no document in DoInvalidateRegions");
01702 
01703     // Invalidate the bounds of each node in the range
01704     if (pOurDoc != NULL)
01705         // Accumulate this invalid region in a pending list until the Op
01706         // finishes
01707         // Mark the region as requiring object to recache any cached
01708         // data they may be holding because the Op may have changed it
01709         pOurDoc->ForceRedraw(pSpread, InvalidRegion, TRUE, pSpread);
01710 
01711     // Tell them that everything worked out just fine
01712     return TRUE;
01713 }

BOOL UndoableOperation::DoLocaliseCommonAttributes NodeRenderableInk CompoundObject,
BOOL  CheckForDuplicates = FALSE,
BOOL  Global = FALSE,
AttrTypeSet pAffectedAttrTypes = NULL
 

This function is the opposite of DoFactorOutCommonChildAttributes it copies all attributes common to the compound object to each child object within the group which requires each attribute. The groups common attributes are deleted.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
7/8/94
Parameters:
CompoundObject,: The compound object to localise [INPUTS]
CheckForDuplicates: Checks for duplicate attributes being attached to children of the compound. This should never be the case as it would indicate that common attributes are incorrect.

Global: TRUE indicates that we should localise the attributes on all parent compound nodes (top down), before localising the attributes for this compound.

pAffectedAttrTypes: An optional set of attribute types. If this is specified then we only consider localising those attributes which have a type which is in this set.

Parameters:
- [OUTPUTS]
Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)
As with all Do functions actions are generated to undo/redo

Returns:
Errors: -
See also:
UndoableOperation::DoFactorOutCommonChildAttributes

NodeRenderableInk::LocaliseCommonAttributes

Definition at line 3697 of file undoop.cpp.

03701 {   
03702 
03703     FactorOutCommonChildAttrAct* UndoAct;
03704 
03705     
03706     // Create an action to localise attributes which have been factored out
03707     if (!CompoundObject->DiscardsAttributeChildren())
03708     {
03709         // Make a copy of the attribute type set to store in the Action
03710         AttrTypeSet* pSet = NULL;
03711         if (pAffectedAttrTypes)
03712         {
03713             pSet = pAffectedAttrTypes->CopySet(); 
03714             if (!pSet)
03715                 return FALSE; // Failed to create set
03716         }
03717 
03718         if ( FactorOutCommonChildAttrAct::Init(this, 
03719                                                &UndoActions, 
03720                                                CompoundObject,
03721                                                Global, 
03722                                                pSet,
03723                                                (Action**)(&UndoAct))
03724                                                == AC_FAIL)
03725             return FALSE;
03726     }
03727 
03728     if (!CompoundObject->LocaliseCommonAttributes(CheckForDuplicates, 
03729                                                       Global, 
03730                                                       pAffectedAttrTypes))
03731     {
03732         FailAndExecuteAllButLast(); 
03733         return FALSE; 
03734     }
03735 
03736     return TRUE;
03737 }

BOOL UndoableOperation::DoLocaliseForAttrChange Range pRange,
CCRuntimeClass pAffectedAttrType
 

This Do function must be called on a range prior to an attribute being applied to it. If you are going to apply multiple attributes to the range then it is more efficient to call the other version of this function which takes a set of attribute types.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
17/5/95
Parameters:
pRange,: The range of objects which need their attributes localising [INPUTS]
pAffectedAttrType: The type of the attribute that you are about to apply to the range

Parameters:
- [OUTPUTS]
Returns:
TRUE if successful, FALSE if we run out of memory. Tidyup then call End()
The function globally localises those attributes which have a type in the pAffectedAttrTypes set.

If an object in the range Discards its attribute children then its attributes are not localised.

Note: When applying an attribute, we are not always going to apply it to the object itself, sometimes we need to apply it to the object's parent. Eg. when we apply a line based attribute to a text character the attributes will get applied to the parent TextLine.

In this situation we do not localise the objects attributes, but its parents attributes instead.

Returns:
Errors: -
See also:
AttrTypeSet

NodeAttribute::GetAttributeType

UndoableOperation::DoFactorOutAfterAttrChange

UndoableOperation::DoLocaliseForAttrChange

Range::DoFactorOutAfterAttrChange

Definition at line 2518 of file undoop.cpp.

02520 {
02521     ERROR3IF(pRange->Count() == 0, "Range::DoLocaliseForAttrChange called on an empty range");  
02522 
02523     // Iterate over the top of any liveeffects applied to the selection
02524     // Its important that this iteration matches those used in DoApplyAttribute functions
02525     // so that attributes are put in the places where mutation will find them
02526     ListRange* pLevel = EffectsStack::GetNewLevelRange(pRange, FALSE);  // We DO own this range
02527     Node* pCurrent = pLevel->FindFirst();
02528 
02529     // There is no need to localise a compound more than once so we remember the last localised 
02530     NodeRenderableInk* pLocalisedCompound = NULL;
02531 
02532     Node* pParent;
02533     Node* pObject;
02534                         
02535     while (pCurrent)
02536     {
02537         pObject = pCurrent;
02538         // Determine if the attribute will get applied to this object, or an alternative object
02539         // (probably its parent)
02540         ERROR3IF(!pAffectedAttrType, "AttrType is NULL");  
02541         pObject = ((NodeRenderableInk*)pObject)->GetObjectToApplyTo(pAffectedAttrType);
02542 
02543         {
02544 
02545             // We only need to localise those nodes which have a compound parent
02546             pParent = pObject->FindParent(); 
02547             ERROR3IF(pParent == NULL, "Range::DoLocaliseForAttrChange, node found without a parent"); 
02548         
02549             // Only localise the parent if it is a compound node which has not already been localised
02550             if ((pParent->IsCompound()) && (pParent != pLocalisedCompound))
02551             {
02552                 // Attempt to localise the compound
02553                 if (!DoLocaliseForAttrChange((NodeRenderableInk*)pObject, pAffectedAttrType, NULL))
02554                 {
02555                     delete pLevel;
02556                     return FALSE;
02557                 }
02558                  
02559                 pLocalisedCompound = (NodeRenderableInk*)pParent;  // Remember that it's been localised
02560             }
02561         }
02562         pCurrent = pLevel->FindNext(pCurrent);
02563     }
02564 
02565     delete pLevel;
02566     return TRUE;
02567 }

BOOL UndoableOperation::DoLocaliseForAttrChange Range pRange,
AttrTypeSet pAffectedAttrTypes,
BOOL  ExcludeTextObjects = FALSE
 

This Do function must be called on a range prior to a set of attributes being applied to it. It globally localises those attributes which have a type in the pAffectedAttrTypes set.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
17/5/95
Parameters:
pRange,: The range of objects which need their attributes localising [INPUTS]
pAffectedAttrTypes: A set of the types of the attributes which are to be applied to the Range. This function will localise all attributes which have a type in this set.

All attriute types in this set must be localised on the same compound node (See note below).

ExcludeTextObjects: When TRUE atttributes will not be localised on Text compounds. This is useful for selection deletions, where TextStory localisation will be left to the Story itself. This is a bit unpleasant.

Parameters:
- [OUTPUTS]
Returns:
TRUE if successful, FALSE if we run out of memory. Tidyup then call End()
After the attribute has been applied you should call DoFactorOutAfterAttrChange

If an object in the range Discards its attribute children then its attributes are not localised.

Note: When applying attributes, we are not always going to apply the attributes to the object itself, sometimes we need to apply them to the object's parent. Eg. when we apply a line based attribute to a text character the attributes will get applied to the parent TextLine.

In this situation we do not localise the objects attributes, but its parents attributes instead.

Warning ~~~~~~~

All attribute types in the AttrTypeSet must be localised on the same compound node. This means for example that the AttrType set cannot contain a Bold and a Line space attribute. If we need to do this in future then the routine will need to be changed.

Returns:
Errors: -
See also:
AttrTypeSet

NodeAttribute::GetAttributeType

UndoableOperation::DoFactorOutAfterAttrChange

UndoableOperation::DoLocaliseForAttrChange

Range::DoFactorOutAfterAttrChange

Definition at line 2406 of file undoop.cpp.

02409 {
02410     ERROR3IF(pRange->Count() == 0, "Range::DoLocaliseForAttrChange called on an empty range");  
02411 
02412     // Iterate over the top of any liveeffects applied to the selection
02413     // Its important that this iteration matches those used in DoApplyAttribute functions
02414     // so that attributes are put in the places where mutation will find them
02415     ListRange* pLevel = EffectsStack::GetNewLevelRange(pRange, FALSE);  // We DO own this range
02416     Node* pCurrent = pLevel->FindFirst();
02417 
02418     // There is no need to localise a compound more than once so we remember the last localised 
02419     NodeRenderableInk* pLocalisedCompound = NULL;
02420 
02421     CCRuntimeClass* AttrType;
02422     Node* pParent;
02423     Node* pObject;
02424                         
02425     while (pCurrent)
02426     {
02427         pObject = pCurrent;
02428         // Determine if the attribute will get applied to this object, or an alternative object
02429         // (probably its parent)
02430         if (pAffectedAttrTypes && (!pAffectedAttrTypes->IsEmpty()))
02431         {
02432             AttrType = ((AttrTypeItem*)pAffectedAttrTypes->GetHead())->AttributeType;
02433             ERROR3IF(!AttrType, "AttrType set contains NULL attribute type");  
02434             pObject = ((NodeRenderableInk*)pObject)->GetObjectToApplyTo(AttrType);
02435         }
02436 
02437         if (pObject != NULL)
02438         {
02439 
02440             // We only need to localise those nodes which have a compound parent
02441             pParent = pObject->FindParent(); 
02442             ERROR3IF(pParent == NULL, "Range::DoLocaliseForAttrChange, node found without a parent"); 
02443         
02444             // Only localise the parent if it is a compound node which has not already been localised
02445             if ((pParent->IsCompound()) && (pParent != pLocalisedCompound))
02446             {
02447                 if (!(ExcludeTextObjects && ((IS_A(pParent, TextLine)) || (IS_A(pParent, TextStory)))) )
02448                 {
02449                     // Attempt to localise the compound
02450                     if (!DoLocaliseForAttrChange((NodeRenderableInk*)pObject, pAffectedAttrTypes, NULL))
02451                     {
02452                         delete pLevel;
02453                         return FALSE;
02454                     }
02455                  
02456                     pLocalisedCompound = (NodeRenderableInk*)pParent;  // Remember that it's been localised
02457                 }
02458             }
02459         }
02460         
02461         pCurrent = pLevel->FindNext(pCurrent);
02462     }
02463 
02464     delete pLevel;
02465     return TRUE;
02466 }

BOOL UndoableOperation::DoLocaliseForAttrChange NodeRenderableInk Object,
CCRuntimeClass pAffectedAttrType,
ObjectSet pLocalisedCompounds
 

This Do function must be called on an object prior to an attribute being applied to it. If you are going to apply multiple attributes to the Object then it is more efficient to call the other version of this function which takes a set of attribute types.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/5/95
Parameters:
Object,: The object that you are about to apply the attribute to [INPUTS]
pAffectedAttrType: The type of the attribute that you are about to apply to the object

pLocalisedCompounds: An optional set of compounds which have already had their pAffectedAttrType localised. If Object has a parent compound which is in this set then its attributes will not need to be localised again.

Parameters:
- [OUTPUTS]
Returns:
TRUE if successful, FALSE if we run out of memory. Tidyup then call End()
The function globally localises those attributes which have a type in the pAffectedAttrTypes set.

If the function is called on a object which does not have a compound parent then there will be no attributes to localise so the function will simply return TRUE without having done anything.

If the object discards its attribute children then the routine does nothing (eg. the caret)

Note: When applying attributes, we are not always going to apply the attributes to the object itself, sometimes we need to apply them to the object's parent. Eg. when we apply a line based attribute to a text character the attributes will get applied to the parent TextLine.

In this situation we do not localise the objects attributes, but its parents attributes instead.

See also:
AttrTypeSet

NodeAttribute::GetAttributeType

UndoableOperation::DoFactorOutAfterAttrChange

Range::DoLocaliseForAttrChange

Range::DoFactorOutAfterAttrChange

Definition at line 2973 of file undoop.cpp.

02976 {
02977     BOOL ok = TRUE;
02978     // Determine if the attribute will get applied to this object, or an alternative object
02979     // (probably its parent)
02980     ERROR3IF(!pAffectedAttrType, "AttrType is NULL");  
02981     Object = Object->GetObjectToApplyTo(pAffectedAttrType);
02982 
02983     {   
02984 
02985         Node* pParent;
02986         pParent = Object->FindParent(); 
02987         ERROR3IF(!pParent, "UndoableOperation::DoLocaliseForAttrChange called on an object which has no parent"); 
02988 
02989         if (pParent->IsCompound())
02990         {
02991     
02992             // We an attribute type set
02993             AttrTypeSet Set; 
02994         
02995             // Add the attributes type to the set
02996             if (!Set.AddToSet(pAffectedAttrType))
02997             {
02998                 ok = FALSE; 
02999             }
03000 
03001             if (ok)
03002             {
03003                 // Before we attempt to localise the compound's attributes let's check that they are not 
03004                 // already localised.
03005             
03006                 if (pLocalisedCompounds)
03007                 {
03008                     if (pLocalisedCompounds->InSet((NodeRenderableInk*)pParent))
03009                     {
03010                         return TRUE; // Attributes are already localised so there is no need to localise again !
03011                     }
03012                     else
03013                     {
03014                         pLocalisedCompounds->AddToSet((NodeRenderableInk*)pParent); // Record that the compound has been localised
03015                     }
03016                 }
03017 
03018 
03019                 ok = DoLocaliseCommonAttributes((NodeRenderableInk*)pParent,// We are localising the compound's attrs
03020                                                    FALSE,                   // No need to check for duplicates
03021                                                    TRUE,                    // Localise globally
03022                                                    &Set);                   // Only attributes of these types
03023             }
03024     
03025             // The attribute type set is no longer required
03026             Set.DeleteAll(); 
03027         }
03028     }
03029     return ok; 
03030 }

BOOL UndoableOperation::DoLocaliseForAttrChange NodeRenderableInk Object,
AttrTypeSet pAffectedAttrTypes,
ObjectSet pLocalisedCompounds
 

This Do function must be called on an object prior to a set of attributes being applied to it. It globally localises those attributes which have a type in the pAffectedAttrTypes set.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
17/5/95
Parameters:
Object,: The object that you are about to apply attributes to [INPUTS]
pAffectedAttrTypes: A set of the types of the attributes which are to be applied to the Object. This function will localise all attributes which have a type in this set.

pLocalisedCompounds: An optional set of compounds which have already had all attributes in the pAffectedAttrTypes localised. If Object has a parent compound which is in this set then its attributes will not need to be localised again.

Parameters:
- [OUTPUTS]
Returns:
TRUE if successful, FALSE if we run out of memory. Tidyup then call End()
If the function is called on a object which does not have a compound parent then there will be no attributes to localise so the function will simply return TRUE without having done anything.

After a compound object has localised its children it will be added to the pLocalisedCompounds set if this has been provided.

After the attribute has been applied you should call DoFactorOutAfterAttrChange

If the object discards its attribute children then the routine does nothing (eg. the caret)

Note: When applying attributes, we are not always going to apply the attributes to the object itself, sometimes we need to apply them to the object's parent. Eg. when we apply a line based attribute to a text character the attributes will get applied to the parent TextLine.

In this situation we do not localise the objects attributes, but its parents attributes instead.

Warning ~~~~~~~

All attribute types in the AttrTypeSet must be localised on the same compound node. This means for example that the AttrType set cannot contain a Bold and a Line space attribute. If we need to do this in future then the routine will need to be changed.

Returns:
Errors: -
See also:
AttrTypeSet

NodeAttribute::GetAttributeType

UndoableOperation::DoFactorOutAfterAttrChange

Range::DoLocaliseForAttrChange

Range::DoFactorOutAfterAttrChange

Definition at line 2864 of file undoop.cpp.

02867 {
02868     CCRuntimeClass* AttrType;
02869     // Determine if the attribute will get applied to this object, or an alternative object
02870     // (probably its parent)
02871     if (pAffectedAttrTypes && (!pAffectedAttrTypes->IsEmpty()))
02872     {
02873         AttrType = ((AttrTypeItem*)pAffectedAttrTypes->GetHead())->AttributeType;
02874         ERROR3IF(!AttrType, "AttrType set contains NULL attribute type");  
02875         Object = Object->GetObjectToApplyTo(AttrType);
02876     }
02877 
02878     {   
02879 
02880 
02881         // If the object has not got a compound parent then there will be no attributes 
02882         // to localise, so we need not do anything
02883     
02884         Node* pParent;
02885         pParent = Object->FindParent(); 
02886         ERROR3IF(!pParent, "UndoableOperation::DoLocaliseForAttrChange called on an object which has no parent"); 
02887 
02888         if (pParent->IsCompound())
02889         {
02890             // Before we attempt to localise the compound's attributes let's check that they are not 
02891             // already localised.
02892             
02893             if (pLocalisedCompounds)
02894             {
02895                 if (pLocalisedCompounds->InSet((NodeRenderableInk*)pParent))
02896                 {
02897                     return TRUE; // Attributes are already localised so there is no need to localise again !
02898                 }
02899                 else
02900                 {
02901                     pLocalisedCompounds->AddToSet((NodeRenderableInk*)pParent); // Record that the compound has been localised
02902                 }
02903             }
02904 
02905             return (DoLocaliseCommonAttributes((NodeRenderableInk*)pParent,  // We are localising the compound's attrs
02906                                                FALSE,    // No need to check for duplicates
02907                                                TRUE,     // Localise globally
02908                                                pAffectedAttrTypes)); // Only attributes of these types
02909         }
02910         
02911     }
02912     return TRUE; 
02913 }

BOOL UndoableOperation::DoMakeNodeFromPath NodePath pParentNode,
Path pParentPath,
AttachNodeDirection  Direction,
BOOL  CopyAttributes
 

This functio will create a new nodepath and attach it in the specified direction to the context node specified. It will also copy attributes applied as children of the ConextNode to the new node if required.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/11/94
Parameters:
pContextNode = pointer to a context node in the tree to attach our [INPUTS] path to direction = direction on which to attach the new NodePath object created by this call. pParentPath = Path to place in the new NodePath object created CopyAttributes = if TRUE then take the attributes applied to the context node and apply them to the new node.
- [OUTPUTS]
Returns:
TRUE if the node was created successfully FALSE if the node could not be created (out of memory)

Definition at line 2280 of file undoop.cpp.

02284 {
02285     // Create the node path object we will stick in the tree.
02286     NodePath* pChildNode;
02287 
02288     ALLOC_WITH_FAIL(pChildNode, new NodePath(), this);
02289 
02290     if (!pChildNode)
02291         return FALSE;
02292 
02293     BOOL ok;
02294     // make room for the new path in the node path.
02295     CALL_WITH_FAIL
02296     (
02297         pChildNode->SetUpPath(pParentPath->GetNumCoords(),12),
02298         this,ok
02299     );
02300 
02301     if (!ok)
02302     {
02303         delete pChildNode;
02304         return FALSE;
02305     }
02306 
02307     // now copy the path data in there.
02308     pChildNode->InkPath.CopyPathDataFrom(pParentPath);
02309 
02310     if (CopyAttributes)
02311     {
02312         CCAttrMap * AttribMap = NULL;
02313         AttribMap = CCAttrMap::MakeAppliedAttrMap(pParentNode);
02314 
02315         if (AttribMap)
02316         {
02317             AttribMap->ApplyAttributesToNode (pChildNode);
02318         }
02319     }
02320 
02321     // Now stick the new path into the tree
02322     CALL_WITH_FAIL
02323     (
02324         DoInsertNewNode(pChildNode, pParentNode, Direction, TRUE, FALSE),
02325         this,ok
02326     );
02327 
02328     // if we've failed tidy up
02329     if (!ok)
02330     {
02331         pChildNode->CascadeDelete();
02332         delete pChildNode;
02333         return FALSE;
02334     }
02335     return TRUE;
02336 }

BOOL UndoableOperation::DoMakeShapes Range  NodeRange  ) 
 

This low level Do function calls the DoBecomeA virtual function on all SelectedNodes. It is the node's DoBecomeA function which is responsible for generating actions.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
03/05/94
Parameters:
NodeRange,: The Range of nodes to make into shapes [INPUTS]
Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)

Errors: -

See also:
Node::DoBecomeA

Definition at line 1771 of file undoop.cpp.

01772 {
01773     Node* CurrentNode = NodeRange.FindFirst();
01774     Node* Next; 
01775 
01776     while (CurrentNode != NULL)
01777     {
01778 // BODGE - since the group is selected and won't be replaced by anything else, no need to reselect it
01779 // this fixes a bug where make shapes on grouped text stories/molds/blends don't leave the parent group
01780 // selected but selects the objects inside!
01781         BOOL reselect = !IS_A(CurrentNode,NodeGroup) && !IS_A(CurrentNode,NodeBlend);
01782 
01783         BecomeA BecomeAPath(BECOMEA_REPLACE,CC_RUNTIME_CLASS(NodePath), this, reselect);
01784         Next = NodeRange.FindNext(CurrentNode);
01785         if (!(CurrentNode->DoBecomeA(&BecomeAPath)))
01786         {
01787             // Operation failed
01788             return FALSE; 
01789         } 
01790         CurrentNode = Next; 
01791     }
01792     return TRUE; // Success
01793 }

BOOL UndoableOperation::DoMoveNode Node NodeToMove,
Node Destination,
AttachNodeDirection  Direction
 

This high level function moves NodeToMove from its current position in the tree, and attaches it to Destination in the direction specified by Direction.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
13/9/93
Parameters:
NodeToMove,: The node to be moved, cannot be an attribute [INPUTS] Destination: The context node Direction: The direction Node is to be attached to Destination
- [OUTPUTS]
Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)
Note: It is illegal to move an attribute in the tree. This is because it may be deleted as a result of attribute optimisation. It is unlikely that you would want to move an attribute anyway.An ERROR2 will be generated if this occurs. Update, 22/03/2005: It is legal to move an effect attribute because they are not optimised in the same way as other attributes.

Returns:
Errors: -
See also:
UndoableOperation::DoMoveNodes

Definition at line 968 of file undoop.cpp.

00972 {  
00973     ERROR2IF(NodeToMove->IsAnAttribute() && !((NodeAttribute*)NodeToMove)->IsEffectAttribute(), FALSE, "Trying to move an attribute, this is bad"); 
00974 
00975     // --------------------------------------------------------------------
00976     // We have to move attributes by copying...
00977     if (NodeToMove->IsAnAttribute())
00978     {
00979         // Copy the attribute to the destination location
00980         // Then hide the original
00981 
00982         // Copy
00983         NodeAttribute* pCopyAttr = NULL;
00984         BOOL bOK = FALSE;
00985         CALL_WITH_FAIL(((NodeAttribute*)NodeToMove)->NodeCopy((Node**)&pCopyAttr), this, bOK);
00986         if (!bOK) return FALSE; // No room to take a copy of the node
00987 
00988         // Create a hide node action to hide the node when we undo 
00989         pCopyAttr->AttachNode(Destination, Direction);
00990         HideNodeAction* UndoHideNodeAction;
00991         if (HideNodeAction::Init(this, this->GetUndoActions(), pCopyAttr, TRUE, (Action**)(&UndoHideNodeAction))
00992                 == AC_FAIL)
00993         {
00994             pCopyAttr->CascadeDelete();
00995             delete pCopyAttr;
00996             return FALSE;
00997         }
00998 
00999         // Hide
01000         if (!DoHideNode(NodeToMove, TRUE, NULL, TRUE))
01001             return FALSE;
01002 
01003         return TRUE;
01004     }
01005 
01006     // --------------------------------------------------------------------
01007     // Objects are physically moved, leaving a NodeHidden in the original location
01008     // with a "hyperspace" reference to the object in its final location.
01009     //
01010     // We must flag that we are only moving the node, so we don't
01011     // try and called the 'Hiding Node' function, which should only
01012     // be called when we are 'Really' hiding the node.
01013     MovingNode = TRUE;
01014 
01015     // Find out if the node is selected
01016     BOOL IsSelected = NodeToMove->IsSelected();
01017 
01018     // Before we move the object determine what the source layer is
01019     Layer* pSrcLayer = NULL; 
01020     if (NodeToMove->IsAnObject())
01021     {
01022         // Only consider ink nodes
01023         pSrcLayer = (Layer*) (NodeToMove->FindParent(CC_RUNTIME_CLASS(Layer)));
01024     } 
01025 
01026     // Hide it
01027     HideNodeAction* UndoHideNodeAction;  
01028 //  NodeRenderableBounded* pBounded = NULL;
01029 
01030     // hide the node
01031     if (!DoHideNode(NodeToMove, FALSE, NULL, FALSE)) 
01032         goto Failed; 
01033     
01034     // build the action
01035     if ( HideNodeAction::Init(this, 
01036                               &UndoActions, 
01037                               NodeToMove,
01038                               FALSE,                            // Don't include the 
01039                                                                 // subtree size 
01040                               (Action**)(&UndoHideNodeAction),
01041                               
01042                               FALSE)                            // Don't tell subtree
01043                                == AC_FAIL)  
01044     {   
01045         goto Failed; 
01046     };  
01047 
01048     // Move the node to its new location
01049     NodeToMove->MoveNode(Destination, Direction);
01050     if (IsSelected)
01051         NodeToMove->SetSelected(IsSelected);
01052 
01053     MovingNode = FALSE;
01054 
01055     if (NodeToMove->IsAnObject())
01056     {
01057         // If the object has moved to a new layer then we need to invalidate both old and new 
01058         // layers
01059         Layer* pDestLayer = (Layer*) (NodeToMove->FindParent(CC_RUNTIME_CLASS(Layer)));
01060         if ((pSrcLayer != pDestLayer) && pSrcLayer && pDestLayer)
01061         {
01062             pSrcLayer->InvalidateBoundingRect();
01063             pDestLayer->InvalidateBoundingRect();
01064         }
01065         
01066         if (pSrcLayer)
01067         {
01068             // Note that this layer has been edited
01069             pSrcLayer->SetEdited(TRUE);
01070 //#ifdef _DEBUG
01071 //          // Tell the frame gallery to update its display of the frame
01072 //          BROADCAST_TO_ALL(LayerMsg(pSrcLayer, LayerMsg::LayerReason::REDRAW_LAYER));
01073 //#endif
01074         }
01075 
01076         if (pDestLayer && (pSrcLayer != pDestLayer))
01077         {
01078             // Note that this layer has been edited
01079             pDestLayer->SetEdited(TRUE);
01080 //#ifdef _DEBUG
01081 //          // Tell the frame gallery to update its display of the frame
01082 //          BROADCAST_TO_ALL(LayerMsg(pDestLayer, LayerMsg::LayerReason::REDRAW_LAYER));
01083 //#endif
01084         }
01085 
01086     }
01087     // finish happy
01088     return (TRUE);
01089 
01090 Failed:
01091     MovingNode = FALSE;     // Ensure we clear this is an error occurred 
01092     return FALSE;
01093 }

BOOL UndoableOperation::DoMoveNodes Range  NodeRange,
Node Destination,
AttachNodeDirection  Direction
 

This high level function moves the range of nodes from their current position in the tree, and attaches them to the Destination node in the direction specified by Direction.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
13/9/93
Parameters:
NodeRange,: The node range to be moved [INPUTS] Destination: The context node Direction: The direction Node is to be attached to Destination
- [OUTPUTS]
Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)
The nodes in the range maintain their relative z-order when they move.

Returns:
Errors: -
See also:
UndoableOperation::DoMoveNode

Definition at line 902 of file undoop.cpp.

00905 {
00906     Node* Current = NodeRange.FindFirst(); // Get the first node to move
00907     ENSURE(Current != NULL, "Trying to move an empty range");
00908     
00909     Node* NextNode = NodeRange.FindNext(Current);
00910 
00911     // Attach the first node in the range to the Destination node in the direction specified
00912     if (!DoMoveNode(Current, Destination, Direction))
00913     {
00914         return FALSE; // Failed to move Current 
00915     }
00916     
00917     Node* PrevNode = Current; 
00918 
00919     // Get the next node in the range  
00920     Current = NextNode; 
00921 
00922     // Attach all other nodes in the range 
00923     while (Current != NULL)
00924     {
00925         NextNode = NodeRange.FindNext(Current);
00926         if (!DoMoveNode(Current, PrevNode, NEXT))
00927         {
00928             return FALSE; // Failed to move Current 
00929         }   
00930         PrevNode = Current; 
00931         Current = NextNode;  
00932     }
00933     return TRUE; 
00934 }

BOOL UndoableOperation::DoRemoveAttrTypeFromSubtree Node Subtree,
CCRuntimeClass AttrType,
Node pExceptThis = NULL
 

Searches the subtree and every attribute which has type AttrType is hidden.

BOOL UndoableOperation::DoRemoveAttrTypeFromSubtree(Node* Subtree, RuntimeClass* AttrType, Node* pExceptThis = NULL);

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/6/94
Parameters:
Subtree,: Subtree to remove nodes from [INPUTS] NodeClass: The type of attribute to remove from the subtree pExceptThis: The node that shouldn't be removed!
- [OUTPUTS]
Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)

Errors: - Scope: private

See also:
-

Definition at line 1925 of file undoop.cpp.

01926 {
01927     // Traverse the subtree depth first
01928     Node* Current = Subtree->FindFirstDepthFirst();
01929     Node* Next;
01930     while (Current != NULL)
01931     {
01932         Next =  Current->FindNextDepthFirst(Subtree); 
01933         // Determine if the Current node is to be hidden
01934         if (Current!=pExceptThis && Current->IsKindOf(CC_RUNTIME_CLASS(NodeAttribute)))
01935         {
01936             if (((NodeAttribute*)Current)->GetAttributeType() == AttrType)
01937             {
01938                 if (Current->FindParent()->DiscardsAttributeChildren())
01939                 {
01940                     Current->CascadeDelete();
01941                     delete Current;
01942                 }
01943                 else
01944                 { 
01945                     if(!DoHideNode(Current, 
01946                                    TRUE         // Include the subtree size 
01947                                    ))
01948                     {
01949                         return FALSE;           // Operation failed
01950                     } 
01951                 }
01952             }
01953         }
01954         Current = Next;
01955     }
01956     return TRUE; 
01957 }

BOOL UndoableOperation::DoReversePath NodePath ThisPath,
BOOL  RedrawPath = TRUE
 

This 'Do' function reverse a path, recording undo information.

Author:
Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/5/2000
Parameters:
ThisPath points at the NodePath that we want to reverse [INPUTS] RedrawPath - TRUE if the screen area of the path should be redrawn, FALSE if the caller is responsible
The reversed path in ThisPath->InkPath [OUTPUTS]
Returns:
TRUE if succeeded, FALSE otherwise

Errors: -

See also:
-

Definition at line 3960 of file undoop.cpp.

03961 {
03962     PathVerb* Verbs = NULL;
03963     PathFlags* Flags = NULL;
03964     DocCoord* Coords = NULL;
03965     ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
03966     INT32 NumCoords = ThisPath->InkPath.GetNumCoords();
03967     //BOOL PrevSelected = FALSE;
03968     //INT32 PrevPos = 0;
03969     
03970     Document* pDocument = GetWorkingDoc();
03971     Spread* pSpread = ThisPath->FindParentSpread();
03972     
03973     if (RedrawPath)
03974     {
03975         // Mark the region as requiring object to recache any cached
03976         // data they may be holding because the Op may have changed it
03977         DocRect Invalid = ThisPath->GetUnionBlobBoundingRect();
03978         pDocument->ForceRedraw( pSpread, Invalid, FALSE, ThisPath );
03979     }
03980 
03981     Path* NewEditPath = new Path ();
03982 
03983     if (!NewEditPath) { return (FALSE); }
03984 
03985     if (!NewEditPath->Initialise(NumCoords, 24))
03986     {
03987         return FALSE;
03988     }
03989 
03990     // for the new reversed path ....
03991 
03992     PathVerb* Verbs2 = NULL;
03993     PathFlags* Flags2 = NULL;
03994     DocCoord* Coords2 = NULL;
03995     NewEditPath->GetPathArrays(&Verbs2, &Coords2, &Flags2);
03996 
03997     NewEditPath->CopyPathDataFrom (&(ThisPath->InkPath));
03998 
03999     // the following loop as been optimised since this is the main part of the alg
04000     // (which just reverses the supplied path) ....
04001 
04002     NewEditPath->Reverse ();
04003     
04004     // now lets build an undo record ....
04005     
04006     ModifyPathAction* ModAction;                // since thats what were doing
04007     
04008     ActionCode Act;
04009     Act = ModifyPathAction::Init(this, &UndoActions, NumCoords, (Action**)(&ModAction));
04010     if (Act == AC_FAIL)
04011     {
04012         FailAndExecute();
04013         End();
04014         return FALSE;
04015     }
04016 
04017     // for use with the action ....
04018     
04019     PathVerb* ChangedVerbs = NULL;
04020     DocCoord* ChangedCoords = NULL;
04021     PathFlags* ChangedFlags = NULL;
04022     INT32* ChangedIndices = NULL;
04023 
04024     // If the function returned AC_NO_RECORD we shouldn't record any undo information in the action
04025     // NOTE - during unwind all actions return AC_OK with a NULL ModAction pointer!!
04026     if ((Act!=AC_NORECORD) && (ModAction!=NULL))
04027     {
04028         // This next bit is a bit hellish. Any one of these four allocations can fail, in which case 
04029         // we have to tidy up afterwards. Cue a lot of nested ifs and elses.
04030 
04031         ALLOC_WITH_FAIL(ChangedVerbs,(PathVerb*) CCMalloc(NumCoords * sizeof(PathVerb)),this);
04032         if (ChangedVerbs)
04033         {
04034             ALLOC_WITH_FAIL(ChangedCoords,(DocCoord*) CCMalloc(NumCoords * sizeof(DocCoord)),this);
04035             if (ChangedCoords)
04036             {
04037                 ALLOC_WITH_FAIL(ChangedFlags,(PathFlags*) CCMalloc(NumCoords * sizeof(PathFlags)),this);
04038                 if (ChangedFlags)
04039                 {
04040                     ALLOC_WITH_FAIL(ChangedIndices,(INT32*) CCMalloc(NumCoords * sizeof(INT32)),this);
04041                     if (!ChangedIndices)
04042                     {
04043                         CCFree( ChangedFlags );
04044                         CCFree( ChangedCoords );
04045                         CCFree( ChangedVerbs);
04046                         FailAndExecute();
04047                         End();
04048                         return FALSE;
04049                     }
04050                 }
04051                 else
04052                 {
04053                     CCFree( ChangedCoords );
04054                     CCFree( ChangedVerbs );
04055                     FailAndExecute();
04056                     End();
04057                     return FALSE;
04058                 }
04059             }
04060             else
04061             {
04062                 CCFree( ChangedVerbs);
04063                 FailAndExecute();
04064                 End();
04065                 return FALSE;
04066             }
04067         }
04068 
04069         // Now to put the undo data into the undo action
04070         for (INT32 loop = 0; loop < NumCoords; loop++)
04071         {
04072             ChangedVerbs [loop] = Verbs [loop];
04073             ChangedFlags [loop] = Flags [loop];
04074             ChangedCoords [loop] = Coords [loop];
04075             ChangedIndices [loop] = loop;
04076         }
04077     
04078         // Now we've allocated the arrays, let's tell the action about 'em
04079         ModAction->StoreArrays (ChangedVerbs, ChangedFlags, ChangedCoords, ChangedIndices, ThisPath);//pOrigPath);
04080 
04081     }
04082 
04084             
04085     // now we update the supplied path with the new path ....
04086 
04087     ThisPath->InkPath.CopyPathDataFrom (NewEditPath);
04088     
04089     delete (NewEditPath);       // and clean up
04090 
04091     if (ThisPath->IsANodeBlendPath ())
04092     {
04093         ((NodeBlendPath*) ThisPath)->DestroyCachedInformation ();
04094     }
04095 
04097 
04098     ThisPath->InvalidateBoundingRect();
04099 
04100     if (RedrawPath)
04101     {       
04102         DocRect Invalid = ThisPath->GetUnionBlobBoundingRect();
04103         // Mark the region as requiring object to recache any cached
04104         // data they may be holding because the Op may have changed it
04105         pDocument->ForceRedraw( pSpread, Invalid, FALSE, ThisPath );
04106     }
04107     return (TRUE);
04108 }

BOOL UndoableOperation::DoSaveCopyOfNode NodeRenderable Node  ) 
 

This fn saves a copy of the node in the operation history. When the operation is undone the copy is restored.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
7/3/94
Parameters:
Node,: [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
UndoableOperation::DoSaveCopyOfNodes

Definition at line 1186 of file undoop.cpp.

01187 {
01188     ENSURE((!OpFlags.Failed), "Calling a DO function after operation has failed");
01189     RangeControl        rc( TRUE, TRUE, TRUE ); // All nodes in range
01190     Range               range( Node, Node, rc );
01191     return DoSaveCopyOfNodes( range ); 
01192 }

BOOL UndoableOperation::DoSaveCopyOfNodes Range  NodeRange  ) 
 

This fn takes a copy of the nodes in the range. The copies are restored when the operation is undone.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
7/3/94
Parameters:
NodeRange,: The range of nodes to save [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
UndoableOperation::DoSaveCopyOfNode

Definition at line 1115 of file undoop.cpp.

01116 {
01117     Node* Current = NodeRange.FindFirst();
01118     BOOL CopiedOK;
01119     Node* TheCopy;  
01120     HideNodeAction* UndoHideNodeAction; 
01121     while (Current != NULL)
01122     {   
01123         // Salary check
01124         if (!Current->IsBounded())
01125         {
01126             ERROR3("Current is not a NodeRenderable node");
01127             continue;
01128         }
01129 
01130         // Make a copy of Current 
01131         CALL_WITH_FAIL(Current->NodeCopy(&TheCopy), this, CopiedOK);  
01132         if (!CopiedOK)
01133         {
01134             return FALSE; // No room to take a copy of the node 
01135         }
01136 
01137         // We need to insert the new node into the tree, but we can't use DoInsertNewNode
01138         // as this will insert an unwanted NideNode action
01139         TheCopy->AttachNode(Current, PREV); 
01140         TheCopy->SetSelected(FALSE); 
01141         ((NodeRenderableBounded*)TheCopy)->ValidateBoundingRect();
01142         ((NodeRenderableBounded*)TheCopy)->InvalidateBoundingRect();
01143 
01144         // Hide the copy, creating a ShowNodeAction to show the copy when we undo 
01145         if (!DoHideNode(TheCopy, 
01146                         TRUE        // The hidden node is in the operation history
01147                        )
01148            )
01149         {
01150             return FALSE;   
01151         } 
01152 
01153         // Create a Hide node action to hide the current node when we undo
01154         if ( HideNodeAction::Init(this, 
01155                                   &UndoActions, 
01156                                   Current, 
01157                                   FALSE, 
01158                                   (Action**)(&UndoHideNodeAction))
01159             == AC_FAIL)  
01160         {   
01161             return FALSE;      
01162         };  
01163     
01164         Current = NodeRange.FindNext(Current); 
01165     }
01166     return TRUE; 
01167 } 

BOOL UndoableOperation::DoSelectNode NodeRenderableInk NodeToSelect,
Spread Parent = NULL
 

The function selects NodeToSelect. It also generates an action which will deselect the node when executed.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/10/93
Parameters:
NodeToSelect,: The node that is to be selected [INPUTS]
- [OUTPUTS]
Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)

Errors: -

See also:
UndoableOperation::DoDeselectNode

Definition at line 1416 of file undoop.cpp.

01417 {   
01418     SelectDeselectAction* UndoSelectDeselectAction; 
01419     // Create an action to deselect the NodeToSelect when we undo. 
01420     if ( SelectDeselectAction::Init(this, 
01421                                     &UndoActions, 
01422                                     NodeToSelect,
01423                                     Parent,
01424                                     (Action**)(&UndoSelectDeselectAction))
01425                                     != AC_FAIL)  
01426     {   
01427         // We shall be able to deselect the object if we fail so select it.       
01428         NodeToSelect->Select(FALSE);  
01429         return (TRUE);      
01430     }
01431     else 
01432         return (FALSE); 
01433 } 

BOOL UndoableOperation::DoSmoothNodePath NodePath pThisNode,
double  smoothacc
 

This function will smooth a node path given an accuracy. It will create a new node in the tree after the node specified and hide node passed if all is succesfull.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/11/94
Parameters:
pThisNode - a pointer to a node to smooth. [INPUTS] smoothacc - the smooth accuracy, usually in the range (256^2, 8000^2)
a new tree node will be created as a result [OUTPUTS]
Returns:
TRUE if the operation completed FALSE if the operation failed due to lack of memory. The environment matches that on entry to the function.

Definition at line 2213 of file undoop.cpp.

02214 {
02215 #ifndef STANDALONE
02216 
02217     // Copy the nodepath and all its children, without placing the copy in the tree
02218     Node* pnode;
02219     if (!pThisNode->NodeCopy(&pnode))
02220         return FALSE;
02221     NodePath* pSmoothNode = (NodePath*)pnode;
02222 
02223     // ok, smooth the nodepaths path data
02224     if (!pSmoothNode->InkPath.SmoothRegions(smoothacc, FALSE, TRUE))
02225         goto smoothfailed;
02226 
02227     // update the smoothed paths bounding rectangle
02228     pSmoothNode->InvalidateBoundingRect();
02229 
02230     // Now stick the new path into the tree
02231     if (!DoInsertNewNode(pSmoothNode, pThisNode, NEXT, TRUE))
02232         goto smoothfailed;
02233     
02234     // Now we've formed a smoothed path, let's hide the original
02235     if (!DoHideNode(pThisNode,TRUE))
02236         goto smoothfailed;
02237 
02238 #endif
02239 
02240     // return all is well
02241     return TRUE;
02242 
02243 #ifndef STANDALONE
02244 
02245 // failed to smooth the node so time to tidy up.
02246 smoothfailed:
02247     pSmoothNode->CascadeDelete();
02248     delete pSmoothNode;
02249     return FALSE;
02250 
02251 #endif
02252 }

BOOL UndoableOperation::DoTransformNode NodeRenderableInk NodeToTransform,
TransformBase Trans
 

This high level Do function applies the transform Trans to the NodeToTransform.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
13/9/93
Parameters:
NodeToTransform,: The node to transform [INPUTS] Trans: The transform to apply to the node
- [OUTPUTS]
Returns:
TRUE if successful FALSE if the operation should be aborted (TIDYUP THEN CALL End()!)

Errors: -

See also:
UndoableOperation::DoTransformNodes

Definition at line 1389 of file undoop.cpp.

01391 {
01392     ENSURE((!OpFlags.Failed), "Calling a DO function after operation has failed");
01393 //  RangeControl rc = { TRUE, TRUE, TRUE }; // All nodes in range
01394     Range               range( NodeToTransform, NodeToTransform, RangeControl( TRUE, TRUE, TRUE ) );
01395     return( DoTransformNodes( range, Trans ) ); 
01396 }   

BOOL UndoableOperation::DoTransformNodes Range  NodeRange,
TransformBase Trans
 

This high level Do function applies the transform Trans to each object in the range.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
13/9/93
Parameters:
Range,: The range of nodes to transform [INPUTS] Trans: The transform to apply to every node in the range
- [OUTPUTS]
Returns:
TRUE if successful
FALSE if the operation should be aborted (TIDYUP THEN CALL End()!) The Trans is deleted.

Don't delete the Trans object, it's deleted in TransformNodeAction slaughter method.

Returns:
Errors: -
See also:
UndoableOperation::DoTransformNode

Definition at line 1221 of file undoop.cpp.

01223 {
01224     // If the Trans is invertible then create a Transform node action to undo the transform
01225     // Note at this point Trans is not the inverse Transformation, but it will be soon !!
01226 //  Node * pParent = NULL;
01227 //  Node * pNodeToTransform = NULL;
01228 
01229     // DMc 17/5/99
01230     // include the parent nodes in the range if they wish to be transformed with
01231     // their children by changing the range control flags   
01232     RangeControl rg = NodeRange.GetRangeControlFlags();
01233     rg.PromoteToParent = TRUE;
01234     NodeRange.Range::SetRangeControl(rg);
01235 
01236 //  DoInvalidateNodesRegions(NodeRange, TRUE);
01237     DoInvalidateNodesRegions(NodeRange, TRUE, FALSE, FALSE, FALSE); // Don't forcibly recache (see bHaveTransformedAllCached)
01238 
01239     if (Trans->IsInvertable()) 
01240     {
01241         TransformNodeAction* UndoTransformNodeAction; 
01242 
01243         if ( TransformNodeAction::Init(this, 
01244                                        &UndoActions, 
01245                                        NodeRange, 
01246                                        Trans,
01247                                        NULL,
01248                                        (Action**)(&UndoTransformNodeAction))
01249                                        == AC_FAIL) 
01250          
01251         {   
01252             delete Trans; // for consistency 
01253             return FALSE; // Let's get out while we can        
01254         }; 
01255         
01256         // Scan the range and transform each node 
01257         Node* Current = NodeRange.FindFirst();
01258         Node* Next; 
01259 //      Node* Parent = NULL;
01260 //      BOOL bTransform = FALSE;
01261         while (Current != NULL)
01262         {
01263             Next = NodeRange.FindNext(Current); 
01264 
01265             if (Current->IsNodeRenderableClass())
01266             {
01267                 // Prepare Control and Feedback flags
01268                 Trans->bHaveTransformedCached = TRUE;
01269                 Trans->bHaveTransformedChildren = TRUE;
01270                 Trans->bTransformYourChildren = TRUE;
01271 
01272                 ((NodeRenderable *)Current)->Transform(*Trans);
01273 
01274                 // Compute feedback flags for caller
01275                 Trans->bHaveTransformedAllCached = Trans->bHaveTransformedAllCached && Trans->bHaveTransformedCached;
01276                 Trans->bHaveTransformedAllChildren = Trans->bHaveTransformedAllChildren && Trans->bHaveTransformedChildren;
01277 
01278                 // ----------------------------------------------
01279                 // Now do smart testing to see whether we can retain any cached info the node was holding
01280                 if (Current->IsBounded())
01281                 {
01282                     NodeRenderableBounded* pCurrentBound = (NodeRenderableBounded*) Current;
01283 
01284                     // If we have transformed all cached data successfully
01285                     // And 
01286                     //      We are translating (in which case the cached data will remain usable)
01287                     //      Or
01288                     //      The node was Direct (in which case the cached data comes from outside the tree where it can't have been transformed)
01289                     // Then
01290                     //      Don't force the recacheing of the data for this node, just its parents
01291                     if (Trans->bHaveTransformedCached && (Trans->IsTranslation() || pCurrentBound->HasCachedDirectBitmap()))
01292                         // Yes, we can keep our cached info but we must tell our parents we have changed
01293                         pCurrentBound->ReleaseCached(TRUE, FALSE, FALSE, TRUE); // Parents and derived data only
01294                     else
01295                         // No we can't keep our cached info
01296                         pCurrentBound->ReleaseCached(TRUE, TRUE);
01297                 }
01298                 // ----------------------------------------------
01299             }
01300             
01301             // JCF BODGE
01302         #ifdef _DEBUG
01303             else
01304             {
01305                 TRACE( _T("Warning: UndoableOperation::DoTransformNodes: ")
01306                       _T("Current node %s is not a NodeRenderableInk\n"),
01307                         (LPCTSTR) Current->Name());
01308             }
01309         #endif
01310 
01311             Progress::Update();
01312             Current = Next;  
01313         }
01314 
01315         // Invert the Trans which is in the TransformNodeAction
01316         ((TransInvertable*)Trans)->Invert(); 
01317     }
01318     else // The Trans is not invertable
01319     {
01320         // We will have to go through all node in the range, making a copy and transforming it.
01321         // This used to use DoSaveCopyOfNodes, but this dosen't work as it is not completly undoable
01322         Node* Current = NodeRange.FindFirst();
01323         Node* Next = NULL; 
01324         while (Current != NULL)
01325         {
01326             Next = NodeRange.FindNext(Current);
01327             if (Current->IsNodeRenderableClass())
01328             {
01329                 // Make a copy of Current 
01330                 BOOL CopiedOK = TRUE;
01331                 Node* TheCopy = NULL;
01332                 CALL_WITH_FAIL(Current->NodeCopy(&TheCopy), this, CopiedOK);  
01333                 if (!CopiedOK)
01334                     return FALSE;
01335 
01336                 // transform the copy
01337                 ((NodeRenderable*)TheCopy)->Transform(*Trans);
01338 
01339                 // put the copy into the tree
01340                 if (!DoInsertNewNode((NodeRenderableBounded*)TheCopy, Current, PREV, TRUE, FALSE))
01341                 {
01342                     delete TheCopy;
01343                     return FALSE;
01344                 }
01345 
01346                 // Hide the original
01347                 if (!DoHideNode(Current, FALSE))
01348                     return FALSE;
01349             }
01350 
01351             // JCF BODGE
01352         #ifdef _DEBUG
01353             else
01354             {
01355                 TRACE( _T("Warning: UndoableOperation::DoTransformNodes: ")
01356                       _T("Current node %s is not a NodeRenderableInk\n"),
01357                         (LPCTSTR) Current->Name());
01358             }
01359         #endif
01360 
01361             Progress::Update();
01362             Current = Next;  
01363         }
01364     }
01365     return (TRUE); // Success 
01366 }   

virtual BOOL UndoableOperation::GetStarted  )  const [inline, virtual]
 

Reimplemented in SelOperation.

Definition at line 520 of file undoop.h.

00520 { return FALSE; }

Range * UndoableOperation::IncludeParentTransformNodesInRange Range Rng  )  [private]
 

Transforms the node, checking if any parents need to transform too.

Author:
David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
Date:
15/5/99
Parameters:
- [INPUTS]
A new range (to be deleted outside of this function) [OUTPUTS]
Returns:
-
See also:

Definition at line 4240 of file undoop.cpp.

04241 {
04242     // do this by changing the selection, and then restoring it
04243     // first, save the current selection
04244     List * pSelList = GetApplication()->FindSelection()->MakeListOfNodes(TRUE);
04245     List * pRngList = Rng->MakeListOfNodes(FALSE);
04246 
04247     NodeRenderableInk::DeselectAll();
04248 
04249     NodeListItem * pItem = (NodeListItem *)pRngList->GetHead();
04250     Node * pParent = NULL;
04251 
04252     while (pItem)
04253     {
04254         if (pItem->pNode)
04255         {
04256             if (pItem->pNode->IsRenderable())
04257             {
04258                 pItem->pNode->SetSelected(TRUE);
04259                 
04260                 pParent = pItem->pNode->FindParent();
04261                 
04262                 while (pParent)
04263                 {
04264                     if (pParent->ShouldITransformWithChildren())
04265                     {
04266                         pParent->SetSelected(TRUE);
04267                     }
04268                     
04269                     pParent = pParent->FindParent();
04270                 }
04271             }               
04272         }
04273 
04274         pItem = (NodeListItem *)pRngList->GetNext(pItem);
04275     }
04276 
04277     pRngList->DeleteAll();
04278     delete pRngList;
04279 
04280     // update the selection range and make a copy of it
04281     GetApplication()->UpdateSelection();
04282 
04283     Range * RetnRng = new Range(*(GetApplication()->FindSelection()));
04284 
04285     // restore the selection
04286     NodeRenderableInk::DeselectAll();
04287 
04288     pItem = (NodeListItem *)pSelList->GetHead();
04289 
04290     while (pItem)
04291     {
04292         if (pItem->pNode)
04293         {
04294             pItem->pNode->SetSelected(TRUE);
04295         }
04296 
04297         pItem = (NodeListItem *)pSelList->GetNext(pItem);
04298     }
04299 
04300     // update the selection range and make a copy of it
04301     GetApplication()->UpdateSelection();
04302     
04303     pSelList->DeleteAll();
04304     delete pSelList;
04305 
04306     // set the range control flags
04307     RangeControl rg = RetnRng->GetRangeControlFlags();
04308     rg.PromoteToParent = TRUE;
04309 
04310     RetnRng->SetRangeControl(rg);
04311     
04312     return RetnRng;
04313 }

virtual BOOL UndoableOperation::MayChangeNodeBounds  )  const [inline, virtual]
 

Reimplemented in OpCopy, OpGroup, OpMenuImport, OpDroppedFile, OpLayerGalChange, OpConvertToBitmap, OpMakeStroke, OpMenuLoad, OpApplyNamesToOne, OpRenameAll, OpChangeBarProperty, OpCreateNodeBitmap, OpBreakAtPoints, OpChangeFeatherSize, OpChangeFeatherProfile, OpOverprintLine, OpOverprintFill, OpPrintOnAllPlates, OpBreakShapes, SelOperation, TransOperation, OpPutToBack, OpMoveForwards, OpMoveBackwards, OpMoveToLyrInFront, OpMoveToLyrBehind, OpCombineLayersToFrameLayer, OpChangeBlendSteps, OpApplyClipView, OpRemoveClipView, OpCreateContour, OpRemoveContour, OpChangeContourWidth, OpChangeContourSteps, OpChangeContourColourType, OpChangeContourAttributeProfile, OpChangeContourObjectProfile, OpChangeContourStepDistance, OpConvertPathToShapes, OpToggleContourInsetPath, OpApplyLiveEffect, OpApplyFeatherEffect, OpEditLiveEffect, OpDeleteLiveEffect, OpDeleteAllLiveEffect, OpEffectRes, OpEffectLock, and OpEffectLockAll.

Definition at line 511 of file undoop.h.

00511 { return FALSE; }

void UndoableOperation::MergeWithPrevious  ) 
 

Moves all the actions in this operation to the end of the previous action, then deletes this action.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
10/1/96
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-
See also:
UndoableOperation::PerformMergeProcessing()

Definition at line 4187 of file undoop.cpp.

04188 {
04189     // Obtain a pointer to the operation history for the operation's document
04190     OperationHistory* pOpHist = &GetWorkingDoc()->GetOpHistory();
04191     if (pOpHist == NULL)
04192     {
04193         ERROR3("There's no OpHistory!?");
04194         return;
04195     }
04196 
04197     // Ensure that we are the last operation added to the operation history
04198     if (pOpHist->FindLastOp() != this)
04199     {
04200         ERROR3("Last Op should be this op");
04201         return;
04202     }
04203     
04204     Operation* pPrevOp = pOpHist->FindPrevToLastOp();
04205     if (pPrevOp != NULL)
04206     {   
04207         // Copy all the actions from us to the end of the action list in the previous op.
04208         ActionList* pPrevActions = pPrevOp->GetUndoActionList();
04209         ActionList* pPrevOtherActions = pPrevOp->GetRedoActionList();
04210         if ((pPrevActions == NULL) || (pPrevOtherActions == NULL))
04211         {
04212             ERROR3("Previous actions list pointer was NULL");
04213             return;
04214         }
04215 
04216         // Copy actions across
04217         Action* pCurrentAction = (Action*)UndoActions.RemoveHead();
04218         while (pCurrentAction != NULL)
04219         {
04220             pCurrentAction->TransferToOtherOp(pPrevOp, pPrevActions, pPrevOtherActions);
04221             pCurrentAction = (Action*)UndoActions.RemoveHead();
04222         }
04223     }
04224 
04225     // And remove ourself
04226     pOpHist->DeleteLastOp();
04227 } 

BOOL UndoableOperation::NoStretchUpdateChangedNodes ObjChangeParam pParam,
Document pDoc
[virtual]
 

This is *not* an override of Operation::UpdateChangedNodes(..., Document*), although it performs *almost* exactly the same job. It is provided solely for NameGallery::PostTriggerEdit to call in order to get all affected nodes to update themselves correctly after a stretch. PostTriggerEdit is itself called in response to normal UpdateChangedNodes calls, so this avoids recursion problems.

Author:
Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
Date:
19/01/2000
Parameters:
pParam description of the change. [INPUTS] pDoc pointer to the document.
Causes any nodes marked for updating to update themselves. [OUTPUTS]
Returns:
TRUE if successful, FALSE otherwise.

Errors: We ERROR2 if either of the parameters is NULL. See also: Operation::UpdateChangedNodes(ObjChangeParam*, Document*).

Definition at line 4389 of file undoop.cpp.

04390 {
04391     ERROR2IF(pParam == NULL, FALSE, "pParam == NULL");
04392     ERROR2IF(pDoc   == NULL, FALSE, "pDoc == NULL");
04393 
04394     BOOL ok = TRUE;
04395     Chapter* pChapter = Node::FindFirstChapter(pDoc);
04396     while (pChapter != NULL && ok)
04397     {
04398         // Now find the first child of the Chapter, because this is the level at which Spreads hang out
04399         Node* pNode = pChapter->FindFirstChild();
04400 
04401         // Update changed nodes in each of the chapter's spreads. We *don't* call
04402         // Operation::UpdateChangedNodes(..., Spread*), as that would lead to recursion...
04403         while (pNode != NULL && ok)
04404         {
04405             if (pNode->IsSpread())
04406             {
04407                 Spread* pSpread = (Spread*)pNode;
04408                 ok = UpdateChangedNode(pParam, pSpread->FindFirstChild());
04409             }
04410 
04411             pNode = pNode->FindNext();
04412         }
04413 
04414         pChapter = pChapter->FindNextChapter(); 
04415     }
04416 
04417     return ok;
04418 }

void UndoableOperation::PerformMergeProcessing void   )  [virtual]
 

This function gets called from the Operation::EndOp method after the operation has ended successfuly and been added to the operation history. If the operation could potentially merge itself with the previous operation then perform this merging here.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
04/11/94
Parameters:
[INPUTS] 
- [OUTPUTS]
Returns:
-
Note that this base class function does nothing.

Here are some rules:

1. Note that this function cannot fail - doing so would really be quite scarry. If however you find yourself running out of memory in this function then simply tidyup (leaving things how they were) and then return.

2. After this function has been invoked the operation history size must not be greater than it was prior to the function getting called. It would be quite unimpressive if this was the case anyway.

3. In many cases you will want to delete 'this' operation from this function. so just be careful huh!

The way that you merge the operation is basically up to you, however here are a few pointers.

The first thing you should do on entering this function is to check that the last Operation added to the operation history is this operation. Call OperationHistory::FindLastOp to verify this within an ERROR2 Macro.

Next you will probably want to check if the previous operation performed can be merged with this op. To obtain the previous op call OperationHistory::FindPrevToLastOp. Testing the runtime class of this op is probably enough for you to determine if a merge can take place or not.

Usually you will want to augment the previous operation in some way so that it includes the function which was performed by this operation. This could involve changing an action in the previous operation, adding new actions etc.

Returns:
Errors: -
See also:
OperationHistory::FindLastOp OperationHistory::FindPrevToLastOp OperationHistory::DeleteLastOp ActionList::

Reimplemented in OpApplyAttrInteractive, OpMakeColourLocalToFrame, OpColourChange, OpNudge, OpPathNudge, OpTextKern, and OpDeleteTextStory.

Definition at line 4168 of file undoop.cpp.

04169 {
04170     return; // The base class function does nowt
04171 } 

BOOL UndoableOperation::RegisterOpDescriptor UINT32  toolID,
UINT32  txID,
CCRuntimeClass RuntimeClass,
TCHAR tok,
pfnGetState  gs,
UINT32  helpId = 0,
UINT32  bubbleID = 0,
UINT32  resourceID = 0,
UINT32  controlID = 0,
SystemBarType  GroupBarID = SYSTEMBAR_ILLEGAL,
BOOL  ReceiveMessages = TRUE,
BOOL  Smart = FALSE,
BOOL  Clean = FALSE,
UINT32  OneOpenInstID = 0,
UINT32  AutoStateFlags = 0
[static]
 

This function should be called from the operations Init method. It creates an OpDescriptor for the operation.

static BOOL UndoableOperation::RegisterOpDescriptor( UINT32 toolID, UINT32 txID, CCRuntimeClass* RuntimeClass, TCHAR* tok, pfnGetState gs, UINT32 helpId, UINT32 bubbleID , UINT32 resourceID, UINT32 controlID, SystemBarType GroupBarID, BOOL ReceiveMessages, BOOL Smart, BOOL Clean, UINT32 OneOpenInstID, UINT32 AutoStateFlags)

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/3/94
Parameters:
[INPUTS] toolID : Module Identifier txID : String Resource ID RuntimeClass : The runtime class of the Opdescriptor's operation tok, : pointer to the token string gs, : pointer to the GetState function helpId : help identifier bubbleID : string resource for bubble help bmpID = 0, : bitmap ("icon") resource ID ReceiveMessages : Does the OpDescriptor need to respond to system messages Smart ; A smart duplicate operation ? Clean : Does the operation change the document OneOpenInstID : When not 0 only one live instance of the operation is permitted, and OneOpenInstID is the string resource ID describing why.This will be useful for 1 open instance dialogs. AutoStateFlags : Flags which indicate conditions when the operation should automatically be greyed/ticked etc..(This cuts down the number of tests that need to be made in the GetState function). See Opdesc.h for a description
- [OUTPUTS]
Returns:
TRUE if successful, else ERROR is called and FALSE returned.
See also:
UndoableOpDescriptor::UndoableOpDescriptor

Definition at line 3801 of file undoop.cpp.

03817 {
03818     // tok is going into a string which turns out to be a string 32, so do a sanity check (Neville 26/6/97)
03819     size_t len = camStrclen(tok);
03820     ERROR2IF(len > 32,FALSE,"UndoableOperation::RegisterOpDescriptor token buffer overflow!");
03821 
03822     // Try to create the OpDescriptor
03823     UndoableOpDescriptor* OpDesc = new UndoableOpDescriptor(
03824                                                             toolID,
03825                                                             txID,
03826                                                             RuntimeClass, 
03827                                                             tok,
03828                                                             gs,
03829                                                             helpId,
03830                                                             bubbleID,
03831                                                             resourceID,
03832                                                             controlID,
03833                                                             ReceiveMessages, 
03834                                                             Smart,
03835                                                             Clean,
03836                                                             OneOpenInstID,
03837                                                             AutoStateFlags  
03838                                                            );
03839 
03840     ERRORIF(!OpDesc, _R(IDE_NOMORE_MEMORY), FALSE);
03841     return TRUE; 
03842 }  

BOOL UndoableOperation::UpdateChangedNodes ObjChangeParam pParam,
Spread pSpread = NULL
[virtual]
 

This function overrides its namesake in Operation, calling the base function first and then adding a call to NameGallery::PostTriggerEdit if this Op admits it may change the bounds of nodes within the tree.

Author:
Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
Date:
19/01/2000
Parameters:
pParam describes the way an op has changes the node(s) [INPUTS] pSpread pointer to the spread containing the nodes affected by the Op NULL => use the currently selected spread.
Returns:
TRUE if all affected nodes were able to cope with the Op, FALSE otherwise.

Errors: ERROR2 if pParam is NULL.

See also:
Operation::UpdateChangedNodes(ObjChangeParam*, Spread*)

Reimplemented from Operation.

Definition at line 4338 of file undoop.cpp.

04339 {
04340     ERROR2IF(pParam == NULL, FALSE, "pParam == NULL");
04341     BOOL    ok = Operation::UpdateChangedNodes(pParam, pSpread);
04342     
04344     // Karim MacDonald 19/01/2000.
04345     // If the call to the base class was successful, then we can try to call
04346     // NameGallery::PostTriggerEdit, to allow any nodes marked for stretching to
04347     // change in response to any bounds changes in the tree.
04348     if (ok)
04349     {
04350         // When querying the Op responsible for the change, I've decided to use 'this'.
04351         // Could've asked pParam for the Op's pointer, but 'this' is probably more reliable.
04352         UndoableOperation* pChangeOp = this;// pParam->GetOpPointer();
04353         if (pChangeOp != NULL && pChangeOp->MayChangeNodeBounds() && NameGallery::Instance())
04354         {
04355             NameGallery::Instance()->PostTriggerEdit(pChangeOp, pParam);
04356         }
04357     }
04359 
04360     return ok;
04361 }


Member Data Documentation

BOOL UndoableOperation::MovingNode = FALSE [static]
 

Definition at line 332 of file undoop.h.

BOOL UndoableOperation::WarnInsertObjsOntoLockedLayers [private]
 

Definition at line 524 of file undoop.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 04:02:37 2007 for Camelot by  doxygen 1.4.4