CarbonCopyOp Class Reference

This class allows OpClone and OpDuplicate to share common code. Both are derived from it. More...

#include <cutop.h>

Inheritance diagram for CarbonCopyOp:

SelOperation UndoableOperation Operation MessageHandler ListItem CCObject SimpleCCObject OpBarCreation OpClone OpCopyAndTransform OpDelBar OpDuplicate OpDuplicateBar OpShortenBar List of all members.

Public Member Functions

 CarbonCopyOp ()
 CarbonCopyOp constructor - does nothing itself, just calls the parent constructor.
BOOL DoProcessing (Trans2DMatrix Transformer, BOOL SelectCopy)
 Performs the common processing of the Clone, Duplicate and CopyAndTransform operations. Clones are not offset from the original, whilst Duplicated objects are offset by the amount in the parameter matrix. CopyAndTransform creates a copy transformed by the specified matrix.

Static Public Member Functions

static OpState GetState (String_256 *, OpDescriptor *)
 For finding the operations state.

Detailed Description

This class allows OpClone and OpDuplicate to share common code. Both are derived from it.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/11/94
See also:
OpDuplicate, OpClone

Definition at line 304 of file cutop.h.


Constructor & Destructor Documentation

CarbonCopyOp::CarbonCopyOp  ) 
 

CarbonCopyOp constructor - does nothing itself, just calls the parent constructor.

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

Errors: -

See also:
OpDuplicate, OpClone

Definition at line 1776 of file cutop.cpp.

01776                           : SelOperation()                              
01777 {                              
01778 }


Member Function Documentation

BOOL CarbonCopyOp::DoProcessing Trans2DMatrix  Transformer,
BOOL  SelectCopy = TRUE
 

Performs the common processing of the Clone, Duplicate and CopyAndTransform operations. Clones are not offset from the original, whilst Duplicated objects are offset by the amount in the parameter matrix. CopyAndTransform creates a copy transformed by the specified matrix.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> (from Simon M code). Altered by Graham 25/6/96.
Date:
18/11/94
Parameters:
A Trans2DMatrix (Graham 25/6/96) giving details of how the copy [INPUTS] should be transformed/translated.
SelectCopy: TRUE if the original is to be deselected and the copy selected (as in Clone and Duplicate)

FALSE if the original is to remain selected and the copy unselected (as in dropping copies with CopyAndTransform)

Parameters:
- [OUTPUTS]
Returns:
TRUE if the operation completed OK, FALSE otherwise

Errors: ERROR2IF's to check there is no selection, Selection is not an ink object, or Selection is not bounded.

See also:
-

Definition at line 1832 of file cutop.cpp.

01833 {   
01834     //Help the user with their selection...
01835     Range* Selection = GetApplication()->FindSelection();
01836     RangeControl TransFlags = Selection->GetRangeControlFlags();
01837     TransFlags.IgnoreNoneRenderable=TRUE;
01838     TransFlags.IgnoreInvisibleLayers = TRUE;
01839     Selection->SetRangeControl(TransFlags);
01840     SliceHelper::ModifySelectionToContainWholeButtonElements();
01841 
01842     // Obtain the current selections 
01843     NodeListItem * pItem = NULL;
01844 
01845     // DMc - build a list of the original selection, so we can reselect them later
01846     Range Sel(*(GetApplication()->FindSelection()));
01847 
01848     List * pSelList = Sel.MakeListOfNodes(FALSE);
01849     
01850     RangeControl rg = Sel.GetRangeControlFlags();
01851     rg.PromoteToParent = TRUE;
01852     Sel.Range::SetRangeControl(rg);
01853 
01854     ObjChangeFlags cFlags;
01855     ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
01856 
01857     if (!Sel.AllowOp(&ObjChange))
01858     {
01859         SliceHelper::RestoreSelection();
01860         return FALSE;
01861     }
01862 
01863 
01864     // Find the first node which is selected 
01865     Node* FirstSelectedNode = Sel.FindFirst();
01866 
01867     Node* Current; 
01868 
01869 //      RangeControl LyrCntrl = { TRUE, FALSE, FALSE };  // Selected + don't cross layers  
01870     Range LayerRange; 
01871 
01872     Node* FirstNodeToCopyOnLyr;
01873     Node* LastNodeToCopyOnLyr;
01874     Node* Tail; 
01875 
01876     ERROR2IF(FirstSelectedNode == NULL, FALSE, "Called CarbonCopy operation with no nodes selected"); 
01877 
01878     // init the vars needed for the mesh layers bit later on
01879     Node * pFirstNodeOfImportedLayer[5];
01880     String_256  StateLayerNames[5];
01881     Node * pLayer = NULL;
01882 
01883     StateLayerNames[0].Load(_R(IDS_ROLLOVER_DEFAULT)); // = "Default";
01884     StateLayerNames[1].Load(_R(IDS_ROLLOVER_MOUSE)); // = "Mouse";
01885     StateLayerNames[2].Load(_R(IDS_ROLLOVER_CLICKED)); // = "Clicked";
01886     StateLayerNames[3].Load(_R(IDS_ROLLOVER_SELECTED)); // = "Selected";
01887     StateLayerNames[4].Load(_R(IDS_BACK_BAR)); // = "BackBar";
01888 
01889     INT32 i;
01890     for (i = 0; i < 5; i++)
01891         pFirstNodeOfImportedLayer[i] = NULL;
01892 
01893     //Graham 30/9/96: Tell the current drag operation to clear its list
01894     //of nodes to select at the end of the drag.
01895     TransOperation* pTransOperation=(TransOperation*) GetCurrentDragOp();
01896 
01897     if(pTransOperation)
01898         pTransOperation->ClearNodesToSelect();
01899     
01900     if (!DoStartSelOp(FALSE,TRUE))  // Try to record the selection state
01901     {
01902         goto EndOperation;
01903     }
01904 
01905 // The following is error checking to make sure the copy doesn't go off the edge of the
01906 // pasteboard.
01907 
01908     // Is the transform matrix going to move or transform the copy?
01909     if (Transformer.GetMatrix().Type!=TRANS_IDENTITY)
01910     {
01911         //Yes. So check the copy will not spill off the pasteboard.
01912 
01913         // Find the bounding rectangle of the selection
01914         DocRect CurrentBounds = Sel.GetBoundingRect();
01915         
01916         //And the bounding rectangle of the selection once transformed
01917         DocRect NewBounds=CurrentBounds;
01918         Transformer.GetMatrix().TransformBounds(&NewBounds);
01919         
01920         //And the current spread if there is one
01921         Spread* pSpread = pOurDoc->GetSelectedSpread();
01922         
01923         //Is there a spread currently selected?
01924         if (pSpread!=NULL)
01925         {
01926             //Yes. Will its pasteboard expand to include the bounds of the transformed selection?
01927             //(Note: ExpandPasteboardToInclude doesn't actually expand the pasteboard
01928             //currently. It just checks whether NewBounds fits within the pasteboard area.)
01929             if(!pSpread->ExpandPasteboardToInclude(NewBounds))
01930             {
01931                 //No, the transformed copy will not fit in the pasteboard.
01932                 //Is the transform a translation?
01933                 if(Transformer.GetMatrix().IsTranslation())
01934                 {
01935                     //Yes. So restrict the translation so it fits within the
01936                     //pasteboard.
01937                     
01938                     //First get the translation in "INT32" form
01939                     INT32 XOffset;
01940                     INT32 YOffset;
01941 
01942                     Transformer.GetMatrix().GetTranslation(XOffset, YOffset);
01943 
01944                     DocRect PasteRect = pSpread->GetPasteboardRect();
01945                     pSpread->DocCoordToSpreadCoord(&PasteRect);
01946                     
01947                     // Find out how far we can move
01948                     INT32 MaxX = 0;
01949                     INT32 MaxY = 0;
01950 
01951                     // First the X direction
01952                     if (XOffset<0)
01953                     {
01954                         // The offset is negative, so work out the maximum negative offset allowed
01955                         MaxX = PasteRect.lo.x - CurrentBounds.lo.x;
01956                         if (XOffset<MaxX) XOffset = MaxX;
01957                     }
01958                     else
01959                     {
01960                         MaxX = PasteRect.hi.x - CurrentBounds.hi.x;
01961                         if (XOffset>MaxX)
01962                         XOffset = MaxX;
01963                     }
01964 
01965                     // and then the Y direction
01966                     if (YOffset<0)
01967                     {   
01968                         // The offset is negative, so work out the maximum negative offset allowed
01969                         MaxY = PasteRect.lo.y - CurrentBounds.lo.y;
01970                         if (YOffset<MaxY) YOffset = MaxY;
01971                     }
01972                     else
01973                     {
01974                         MaxY = PasteRect.hi.y - CurrentBounds.hi.y;
01975                         if (YOffset>MaxY)
01976                         YOffset = MaxY;
01977                     }
01978                     
01979                     //And put the translations back into the Transformer matrix
01980                     Matrix TranslateMatrix=Transformer.GetMatrix();
01981                     TranslateMatrix.SetTranslation(XOffset, YOffset);
01982 
01983                     Transformer=Trans2DMatrix(TranslateMatrix);
01984                 }
01985                 else
01986                 {
01987                     //No, this is not a translation.
01988                     //End the operation without copying the selection.
01989                     //This should not be confusing to the user, because the user can see
01990                     //he has dragged the selection over the edge of the pasteboard.
01991                     //So he should not be surprised that the operation does nothing.
01992 
01993                     goto EndOperation;
01994                 }
01995             }
01996         }
01997         else
01998         {
01999         //No, there is no spread selected.
02000         //We do not want to risk creating a copy outside the current bounds
02001         //of the object. So we set the Transformer matrix to the identity, which simply
02002         //clones the object
02003         Transformer=Trans2DMatrix();
02004         }
02005     }
02006         
02007     // Now start the copying procedure, which we do one layer at a time
02008 
02009         //The first node to copy on the first layer is the first selected node
02010         FirstNodeToCopyOnLyr = FirstSelectedNode;
02011 
02012         // When there are no more objects to copy, FirstNodeToCopyOnLyr will be NULL
02013         while (FirstNodeToCopyOnLyr != NULL)
02014         {
02015 
02016             // Tail is the position to insert the new Duplicate nodes                                                       
02017             Tail = FirstNodeToCopyOnLyr->FindParent()->FindLastChild(TRUE); // Excludes InsertionNode
02018 
02019             // Create a range of selected nodes on this layer
02020 //          LayerRange = Range(FirstNodeToCopyOnLyr, NULL, RangeControl(TRUE,FALSE,FALSE,FALSE,
02021 //              FALSE,FALSE,FALSE,TRUE) );
02022             Range temp(FirstNodeToCopyOnLyr, NULL, RangeControl(TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,TRUE));
02023             LayerRange = temp;
02024 
02025             //When we enter the loop, Current should signify the last copied node on this layer.
02026             //Set to null to signify we need to copy the first node on this layer.
02027             Current=NULL;
02028             LastNodeToCopyOnLyr = LayerRange.FindLast();
02029 
02030             Node * pFirstNewNodeInLayer = NULL;
02031 
02032             // Loop for each node on this layer
02033             do
02034             {
02035                 //Get the next node in the layer to copy. If Current is NULL, this
02036                 //is the first node in the layer to be copied.
02037 
02038                 if(Current==NULL)
02039                     Current=FirstNodeToCopyOnLyr;
02040                 else
02041                     Current = LayerRange.FindNext(Current);
02042 
02043                 // Make a copy of the current node
02044                 Node* TheCopy;
02045                 BOOL CopiedOK; 
02046 
02047                 CALL_WITH_FAIL(Current->NodeCopy(&TheCopy), this, CopiedOK);
02048                 if (!CopiedOK)
02049                 {
02050                     goto EndOperation;
02051                 }
02052 
02053                 // store this to tidy up later in meshing layers
02054                 if (!pFirstNewNodeInLayer)
02055                     pFirstNewNodeInLayer = TheCopy;
02056 
02057                 // make sure that it is bounded
02058                 ERROR2IF(!TheCopy->IsBounded(), FALSE, "Object being pasted is not a NodeRenderableBounded"); 
02059                 NodeRenderableBounded* BoundCopy = (NodeRenderableBounded*)TheCopy;
02060 
02061                 // Insert the copied node at the tail position
02062                 if (!DoInsertNewNode(BoundCopy, Tail, NEXT,
02063                                      FALSE,     // Don't Invalidate region 
02064                                      FALSE))    // Don't Clear the selections
02065                 {
02066                     // Failed, so tidy up before returning
02067                     TheCopy->CascadeDelete(); 
02068                     delete TheCopy; 
02069                     goto EndOperation;
02070                 } 
02071 
02072                 // DMc - to fix bug with r-hand clicks on drags
02073                 BoundCopy->SetSelected(TRUE);
02074                 BoundCopy->SetRender(TRUE, TRUE);
02075 
02076                 //If we need to Transform the copy, do so
02077                 if (Transformer.GetMatrix().Type!=TRANS_IDENTITY)
02078                 {
02079                     BoundCopy->Transform(Transformer);
02080                 }
02081 
02082                 ERROR2IF(!Current->IsAnObject(), FALSE, "Current should be an ink node");
02083 
02084                 // Call PostDuplicate on the copied node and all it's children
02085                 BOOL ok = TRUE;
02086                 Node* pCurrent = BoundCopy->FindFirstDepthFirst();
02087                 while (pCurrent!=NULL && ok)
02088                 {
02089                     ok = pCurrent->PostDuplicate(this);
02090                     pCurrent = pCurrent->FindNextDepthFirst(BoundCopy);
02091                 }
02092                 if (!ok) goto EndOperation; 
02093 
02094                 
02095                 //Now we need to select the copy and deselect the original.
02096 
02097                 //This code isn't too elegant, because it's four days until deadline
02098                 //and I want to get this "bug" fixed. So...
02099 
02100                 //Is there a transform drag going on?
02101                 Operation* pDragOp=GetCurrentDragOp();
02102                 TransOperation* pTransDragOp=(TransOperation*) pDragOp;
02103 
02104                 if (!pTransDragOp)
02105                 {
02106                     //No. So we can deselect the original now.
02107                     //((NodeRenderableInk*)Current)->DeSelect(TRUE); 
02108                 }
02109                 else
02110                 {
02111                     //Yes, there's a transform drag going on.
02112                     //Transform drags start acting strangely if you
02113                     //change the selection halfway through.
02114                     //So first we need to deselect the copy, to ensure
02115                     //we haven't changed the selection.
02116                     //((NodeRenderableInk*)BoundCopy)->DeSelect(TRUE);
02117 
02118                     //And tell the drag to select the copy after the
02119                     //drag has finished.
02120                     pTransDragOp->SelectNodeAfterDrag(BoundCopy);
02121                 }
02122             
02123                 // We also need to invalidate the region of the node now that it has been transformed
02124                 BoundCopy->ReleaseCached(TRUE, FALSE, FALSE, FALSE);                // Release Parents because of change
02125                 if (!DoInvalidateNodeRegion(BoundCopy, TRUE, FALSE, FALSE, FALSE))  // Don't recache everything
02126                 {
02127                     // Tidyup
02128                     TheCopy->CascadeDelete(); 
02129                     delete TheCopy; 
02130                     goto EndOperation;
02131                 }
02132 
02133                 // We also need to invalidate the region of the node now that it has been transformed
02134                 BoundCopy->ReleaseCached(TRUE, FALSE, FALSE, FALSE);                // Release Parents because of change
02135                 DoInvalidateNodeRegion((NodeRenderableBounded*) Current, TRUE, FALSE, FALSE, FALSE);    // Don't recache everything
02136                 
02137     
02138                 //New insertion position is after the last copied node
02139                 Tail = BoundCopy;
02140 
02141             } while (Current != LastNodeToCopyOnLyr);
02142 
02143 
02144             // is this a rollover layer?
02145             pLayer = pFirstNewNodeInLayer->FindParent();
02146             if (pLayer->IsLayer())
02147                 for (i = 0; i < 5; i++)
02148                 {
02149                     if (pFirstNodeOfImportedLayer[i] == NULL 
02150                         && StateLayerNames[i].CompareTo(((Layer *)pLayer)->GetLayerID() ) == 0)
02151                         pFirstNodeOfImportedLayer[i] = pFirstNewNodeInLayer;
02152                 }
02153 
02154 
02155             //And get the first node on the next layer to copy
02156             FirstNodeToCopyOnLyr = Sel.FindNext(Tail);
02157         }
02158     
02159     // Mesh the buttons duplicated onto the layers
02160     // if we have any of these special layers
02161     if (pFirstNodeOfImportedLayer[0] || pFirstNodeOfImportedLayer[1] || pFirstNodeOfImportedLayer[2] || pFirstNodeOfImportedLayer[3])
02162         SliceHelper::MeshImportedLayersWithExistingButtonBars(pFirstNodeOfImportedLayer, this, FALSE);
02163 
02164     // DMc - deselect the original selection
02165     if (pSelList)
02166     {
02167         pItem = (NodeListItem *)pSelList->GetHead();
02168         
02169         while (pItem)
02170         {
02171             if (pItem->pNode)
02172             {
02173                 pItem->pNode->SetSelected(FALSE);
02174             }
02175             
02176             pItem = (NodeListItem *)pSelList->GetNext(pItem);
02177         }
02178         
02179         pSelList->DeleteAll();
02180         delete pSelList;
02181     }
02182         
02183     //Just incase we helped the user with their selection - restore it back again
02184     TRACEUSER( "Matt", _T("Changing Selection in CarbonCopyOp::DoProcessing()\n"));
02185     SliceHelper::RestoreSelection();
02186 
02187     ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this);
02188     UpdateChangedNodes(&ObjChange);
02189 
02190     End();
02191 
02192     return TRUE;
02193 
02194     EndOperation:
02195 
02196     if (pSelList)
02197     {
02198         pSelList->DeleteAll();
02199         delete pSelList;
02200     }
02201 
02202     //Just incase we helped the user with their selection - restore it back again
02203     TRACEUSER( "Matt", _T("Restoring Selection in CarbonCopyOp::DoProcessing()\n"));
02204     SliceHelper::RestoreSelection();
02205 
02206     End();
02207     return FALSE;
02208 }

OpState CarbonCopyOp::GetState String_256 UIDescription,
OpDescriptor Bob
[static]
 

For finding the operations state.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/11/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
The state of the CarbonCopyOp or any operations derived from it that dosen't overide this function.

Errors: -

See also:
-

Reimplemented in OpDuplicate, OpClone, OpCopyAndTransform, OpBarCreation, OpDuplicateBar, OpShortenBar, and OpDelBar.

Definition at line 1797 of file cutop.cpp.

01798 {
01799     OpState OpSt;
01800 
01801     return(OpSt);   
01802 }


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