OpLiveEffect Class Reference

Base class for all LiveEffect ops See also:. More...

#include <opliveeffects.h>

Inheritance diagram for OpLiveEffect:

SelOperation UndoableOperation Operation MessageHandler ListItem CCObject SimpleCCObject OpApplyFeatherEffect OpApplyLiveEffect OpDeleteAllLiveEffect OpDeleteLiveEffect OpEditLiveEffect OpEffectLock OpEffectRes OpEffectLockAll List of all members.

Public Member Functions

 OpLiveEffect ()
 Constructor.
 ~OpLiveEffect ()
 Destructor.
virtual void Do (OpDescriptor *pOpDesc)
virtual void DoWithParam (OpDescriptor *pOpDesc, OpParam *pOpParam)
ListRangeGetLiveEffectList ()
virtual void DoEndEdit (BOOL bChangingSelection=FALSE, BOOL bBroadcast=TRUE, BOOL bCancelled=FALSE, BOOL bEmpty=FALSE)
BOOL GetPreviewQuality () const
void SetPreviewQuality (BOOL bNew)

Protected Member Functions

ListRangeDoApplyLiveEffect (Range *pSel, String_256 strEffectID, String_64 strDisplayName, double dResolution, IXMLDOMDocumentPtr pEditsList=NULL, BOOL bMakeLocked=FALSE, BOOL bDetectDirectBitmaps=FALSE)
virtual ListRangeDoApplyLockedEffect (Range *pSel, String_256 strEffectID, String_64 strDisplayName, double dResolution, IXMLDOMDocumentPtr pEditsList=NULL, BOOL bDetectDirectBitmaps=FALSE)
BOOL EnsureLiveEffectOriginalBitmaps ()
 Ensure that all NodeBitmapEffects in the current selection have original bitmaps ready and wait for us to pick up.
BOOL GenerateBitmap (NodeBitmapEffect *pBitmapEffect, double dResolution, LPBITMAPINFO *ppInfo, LPBYTE *ppBits, DocRect *prectBounds)
BOOL SetChanged (BOOL bNewState)
BOOL HasChanged ()
 Detect whether any of the LiveEffect nodes created/edited by this operation have actually been changed/do anything useful...
BOOL IsTopOfStack (EffectsStack *pPPStack, INT32 iStackPos)
virtual BOOL DoEffectOp (ListRange *pLevelRange, OpLiveEffectParam *pLEOpParam)
virtual BOOL AllowEmptySelection () const
virtual BOOL CheckEffectOpParam (OpLiveEffectParam *pLEOpParam)
virtual BOOL DoEffectRangeOp (UINT32 idsProgress, Range *pLevel, OpLiveEffectParam *pParam)
virtual BOOL DoEffectNodeOp (NodeEffect *pEffect, OpLiveEffectParam *pParam, NodeBitmapEffect **ppNewEffect)

Protected Attributes

ListRangem_pLERange
BOOL m_bAppliedNewEffects
String_256 m_strEffectID
INT32 m_iStackPos
BOOL m_bPreviewQuality

Private Member Functions

 CC_DECLARE_DYNCREATE (OpLiveEffect)

Static Private Member Functions

static BOOL Init ()
static BOOL UpdateCurrentEditor ()
 Reset the current Op to refer to the new PPStack and tell the running XPE edit that things are changing.
static BOOL DoCopyPPStackToSelection (UndoableOperation *pOp, EffectsStack *pPPStack, Document *pSrcDoc, Document *pDestDoc)
 Copy the specified LiveEffect stack onto the selection Used by Paste Attributes.
static BOOL DoLocaliseLiveEffects (UndoableOperation *pOp, Node *pNode)
 Copy the specified LiveEffect stack onto the selection Used by Paste Attributes.
static BOOL DoLocaliseEffectAttrs (UndoableOperation *pOp, Node *pNode)
 Copy the Effect attributes from the specified node down to lower nodes, remaining effect attrs where possible but becoming normal attrs if that's not possible Used by ungroup.
static BOOL DoCopyEffectAttr (UndoableOperation *pOp, NodeAttribute *pAttr, Node *pNode)
 Copy the Effect attributes from the specified node down to lower nodes, remaining effect attrs where possible but becoming normal attrs if that's not possible Used by ungroup.
static NodeDoDeleteAllPostProcessors (UndoableOperation *pOp, NodeRenderableInk *pNode, BOOL bDeleteOldControllers=FALSE, BOOL bDeleteBelowLocked=FALSE)
static BOOL DoDeletePostProcessor (UndoableOperation *pOp, Range *pRange)
static BOOL DoDeletePostProcessor (UndoableOperation *pOp, NodeEffect *pLE, BOOL bMoveEffectAttrs=FALSE)
static ListRangeDoApplyFeatherEffect (UndoableOperation *pOp, Range *pSel, String_256 strEffectID, String_64 strDisplayName, MILLIPOINT FeatherSize, CProfileBiasGain Profile)
static NodeFeatherEffectDoApplyFeatherEffectNode (UndoableOperation *pOp, Node *pSel, String_256 strEffectID, String_64 strDisplayName, MILLIPOINT FeatherSize, CProfileBiasGain Profile)
static BOOL DoCopyEffectsStack (UndoableOperation *pOp, Node *pDestNode, ListRange *pEffectsStack, Document *pSrcDoc, Document *pDestDoc)
 Copy the specified LiveEffect stack onto the selection Used by Paste Attributes and OpCombineShapes.
static NodeBitmapEffectDoApplyLiveEffect (UndoableOperation *pOp, Node *pNode, String_256 strEffectID, String_64 strDisplayName, double dResolution, IXMLDOMDocumentPtr pEditsList=NULL, BOOL bMakeLocked=FALSE)
static BOOL DoCopyAttributes (UndoableOperation *pOp, Node *pSrcNode, Node *pDestNode, BOOL bEffectsOnly, Document *pSrcDoc, Document *pDestDoc)
 Copy the specified LiveEffect stack onto the selection Used by Paste Attributes Assumes that only simple attributes will be copied in simple situations I.e. attrs that aren't optimsed so much.

Detailed Description

Base class for all LiveEffect ops See also:.

Author:
Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
Date:
13/09/2004

Definition at line 229 of file opliveeffects.h.


Constructor & Destructor Documentation

OpLiveEffect::OpLiveEffect  ) 
 

Constructor.

Author:
Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
Date:
07/09/2004
Returns:
Errors: See also:

Definition at line 168 of file opliveeffects.cpp.

00169 {
00170     m_pLERange=NULL;
00171     m_bAppliedNewEffects = FALSE;
00172     m_iStackPos = 0;
00173     m_bPreviewQuality = FALSE;
00174 }

OpLiveEffect::~OpLiveEffect  ) 
 

Destructor.

Author:
Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
Date:
07/09/2004
Returns:
Errors: See also:

Definition at line 189 of file opliveeffects.cpp.

00190 {
00191     if (m_pLERange)
00192     {
00193         delete m_pLERange;
00194         m_pLERange = NULL;
00195     }
00196 }


Member Function Documentation

virtual BOOL OpLiveEffect::AllowEmptySelection  )  const [inline, protected, virtual]
 

Reimplemented in OpEditLiveEffect.

Definition at line 307 of file opliveeffects.h.

00307 { return FALSE; }

OpLiveEffect::CC_DECLARE_DYNCREATE OpLiveEffect   )  [private]
 

BOOL OpLiveEffect::CheckEffectOpParam OpLiveEffectParam pLEOpParam  )  [protected, virtual]
 

Author:
Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
Date:
08/06/2005
Parameters:
pLEopParam - pointer to parameter object to check [INPUTS]
- [OUTPUTS]
Returns:
TRUE if Op can continue FALSE otherwise

Reimplemented in OpDeleteAllLiveEffect, and OpEffectLockAll.

Definition at line 2615 of file opliveeffects.cpp.

02616 {
02617     if (pLEOpParam->StackPosition==-1)
02618     {
02619         ERROR3("OpLiveEffect must be given a valid position in the LiveEffects Stack");
02620         return FALSE;
02621     }
02622 
02623 //  ERROR3IF(pLEOpParam->pPPStack==NULL, "Can't find EffectsStack");
02624     if (pLEOpParam->pPPStack==NULL)
02625         return FALSE;
02626 
02627     return TRUE;
02628 }

void OpLiveEffect::Do OpDescriptor pOpDesc  )  [virtual]
 

Author:
Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
Date:
08/06/2005
Parameters:
[INPUTS] 
[OUTPUTS] 
Returns:

Errors: See also:

Reimplemented from Operation.

Definition at line 2464 of file opliveeffects.cpp.

02465 {
02466 //  ERROR3("Why are you doing this? You need params, boy, params!");
02467     DoWithParam(pOpDesc, NULL);
02468 }

ListRange * OpLiveEffect::DoApplyFeatherEffect UndoableOperation pOp,
Range pSel,
String_256  strEffectID,
String_64  strDisplayName,
MILLIPOINT  FeatherSize,
CProfileBiasGain  Profile
[static, private]
 

Definition at line 585 of file opliveeffects.cpp.

00591 {
00592     ENSURE(pSel, "DoApplyFeatherEffect not given a useful range");
00593     ENSURE(strEffectID!=String(""), "DoApplyFeatherEffect given blank effect name string");
00594 
00595     ListRange* pLERange = new ListRange();
00596     ENSURE(pLERange, "DoApplyEffect can't create a ListRange");
00597     if (pLERange==NULL)
00598         return NULL;
00599 
00600     Node* pNode = pSel->FindFirst();
00601     BOOL bOK = TRUE;
00602     while (pNode && bOK)
00603     {
00604         NodeFeatherEffect* pEffect = DoApplyFeatherEffectNode(pOp, pNode, strEffectID, strDisplayName, FeatherSize, Profile);
00605         if (pEffect)
00606         {
00607             pLERange->AddNode(pEffect);
00608 
00609             // Make sure the attributes are optimised correctly
00610             bOK = pOp->DoFactorOutCommonChildAttributes(pEffect);
00611         }
00612         else
00613             bOK = FALSE;
00614 
00615         pNode = pSel->FindNext(pNode);
00616     }
00617 
00618     if (pLERange->FindFirst()==NULL || bOK==FALSE)
00619     {
00620         // Don't let an empty list of LiveEffect nodes hang around
00621         delete pLERange;
00622         pLERange = NULL;
00623     }
00624 
00625     return pLERange;
00626 }

NodeFeatherEffect * OpLiveEffect::DoApplyFeatherEffectNode UndoableOperation pOp,
Node pSel,
String_256  strEffectID,
String_64  strDisplayName,
MILLIPOINT  FeatherSize,
CProfileBiasGain  Profile
[static, private]
 

Definition at line 650 of file opliveeffects.cpp.

00656 {
00657     ENSURE(pNode, "DoApplyFeatherEffectNode not given a useful node");
00658     ENSURE(strEffectID!=String(""), "DoApplyFeatherEffectNode given blank effect name string");
00659 
00660     BOOL bSelectInside = pNode->IsSelected() || pNode->IsParentOfSelected();
00661 
00662     // create a new NodeLiveEffect, which we will shortly insert into the tree;
00663     // note that ALLOC_WITH_FAIL automatically calls FailAndExecute() if things go wrong.
00664     NodeFeatherEffect* pBmpFXNode = NULL;
00665     ALLOC_WITH_FAIL(pBmpFXNode, new NodeFeatherEffect, pOp);
00666     if (pBmpFXNode == NULL)
00667         return NULL;
00668 
00669     // put an action to hide the NodeClipViewController onto the undo action-list,
00670     // so that if the user presses undo then it will be hidden.
00671     pBmpFXNode->SetPostProcessorID(strEffectID);
00672     pBmpFXNode->SetDisplayName(strDisplayName);
00673     pBmpFXNode->m_FeatherSize = FeatherSize;
00674     pBmpFXNode->m_Profile = Profile;
00675 
00676     HideNodeAction* pUndoHideNodeAction = NULL;
00677     ActionCode ac = HideNodeAction::Init(pOp,
00678                                         pOp->GetUndoActions(),
00679                                         pBmpFXNode,
00680                                         FALSE,      // don't include subtree size
00681                                         (Action**)&pUndoHideNodeAction,
00682                                         FALSE);     // don't tell subtree when undone
00683     if (ac == AC_FAIL)
00684     {
00685         delete pBmpFXNode;
00686         return NULL;
00687     }
00688 
00689     // right! we've got our node, we've got our action - lets stick it in the tree
00690     // (at a position just next to the last node which will go in the group).
00691     pBmpFXNode->AttachNode(pNode, NEXT);
00692 
00693     // Move the node below the newly inserted LiveEffect
00694     BOOL bOK = pOp->DoMoveNode(pNode, pBmpFXNode, FIRSTCHILD);
00695     if (!bOK)
00696         return NULL;
00697 
00698     // Deselect the node and select the live effect instead
00699     ((NodeRenderable*)pNode)->DeSelect(FALSE);
00700     pBmpFXNode->Select(FALSE);
00701 
00702 // Set the OpPersmission flags in the newly inserted node
00703 // Otherwise the tree scanner in UpdateChangedNodes won't go below this node
00704 ObjChangeFlags cFlags(NULL, TRUE, NULL, NULL, NULL, NULL, NULL, TRUE);  // ReplaceNode & RegenerateNode
00705 ObjChangeParam ObjChange(OBJCHANGE_STARTING, cFlags, NULL, pOp);
00706 pBmpFXNode->AllowOp(&ObjChange);
00707 
00708     return pBmpFXNode;
00709 }

ListRange * OpLiveEffect::DoApplyLiveEffect Range pSel,
String_256  strEffectID,
String_64  strDisplayName,
double  dResolution,
IXMLDOMDocumentPtr  pEditsList = NULL,
BOOL  bMakeLocked = FALSE,
BOOL  bDetectDirectBitmaps = FALSE
[protected]
 

Author:
Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/09/2004
Parameters:
pSel - pointer to range of nodes to insert LiveEffects above [INPUTS] strDispayName - The display name of the effect we're going to apply
pNewSel - pointer to new range of LiveEffect nodes [OUTPUTS]
  • NULL if no new live effects added
Returns:

Errors: See also:

Definition at line 365 of file opliveeffects.cpp.

00366 {
00367     ENSURE(pSel, "DoApplyLiveEffect not given a useful range");
00368     ENSURE(strEffectID!=String(""), "DoApplyLiveEffect given blank effect name string");
00369 
00370     ListRange* pLERange = new ListRange();
00371     ENSURE(pLERange, "DoApplyEffect can't create a ListRange");
00372     if (pLERange==NULL)
00373         return NULL;
00374 
00375     Node* pNode = pSel->FindFirst();
00376     while (pNode)
00377     {
00378         // create a new NodeLiveEffect, which we will shortly insert into the tree;
00379         // note that ALLOC_WITH_FAIL automatically calls FailAndExecute() if things go wrong.
00380         NodeBitmapEffect* pBmpFXNode = NULL;
00381         pBmpFXNode = DoApplyLiveEffect(this, pNode, strEffectID, strDisplayName, dResolution, pEditsList, bMakeLocked);
00382 
00383         if (pBmpFXNode)
00384         {
00385             // If the node we're applying to can supply DirectBitmaps and we can accept them
00386             // Then change res to be "automatic"
00387             if (bDetectDirectBitmaps &&
00388                 pNode->IsAnObject() &&
00389                 ((NodeRenderableInk*)pNode)->CanSupplyDirectBitmap() &&
00390                 dResolution != 0
00391                 )
00392             {
00393                 // Child node can supply a DirectBitmap so it would be better if we were in
00394                 // "Automatic" mode.
00395                 pBmpFXNode->SetPixelsPerInch(0);            // Set "Automatic"
00396 
00397                 // We can only test EnableDirectCapture after we have set the res to automatic
00398                 // Otherwise it may return FALSE because the stored res (dResolution) may not match that
00399                 // of the DirectBitmap child.
00400                 // If it fails, then reset resolution back to what was specified.
00401                 if (!pBmpFXNode->EnableDirectCapture())
00402                     pBmpFXNode->SetPixelsPerInch(dResolution);
00403             }
00404 
00405             // Deselect the node and select the live effect instead
00406             // TODO: Really?
00407             ((NodeRenderable*)pNode)->DeSelect(FALSE);
00408             pBmpFXNode->Select(FALSE);
00409 
00410             pLERange->AddNode(pBmpFXNode);
00411 
00412             // Make sure the attributes are optimised correctly
00413             BOOL ok = DoFactorOutCommonChildAttributes(pBmpFXNode);
00414             if (!ok)
00415                 pBmpFXNode = NULL;
00416         }
00417 
00418         if (!pBmpFXNode)
00419         {
00420             if (pLERange->FindFirst()==NULL)
00421             {
00422                 // Don't let an empty list of LiveEffect nodes hang around
00423                 delete pLERange;
00424                 pLERange = NULL;
00425             }
00426             return pLERange;
00427         }
00428 
00429         pNode = pSel->FindNext(pNode);
00430     }
00431 
00432     if (pLERange->FindFirst()==NULL)
00433     {
00434         // Don't let an empty list of LiveEffect nodes hang around
00435         delete pLERange;
00436         pLERange = NULL;
00437     }
00438 
00439     return pLERange;
00440 }

NodeBitmapEffect * OpLiveEffect::DoApplyLiveEffect UndoableOperation pOp,
Node pNode,
String_256  strEffectID,
String_64  strDisplayName,
double  dResolution,
IXMLDOMDocumentPtr  pEditsList = NULL,
BOOL  bMakeLocked = FALSE
[static, private]
 

Author:
Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
Date:
07/02/2005
Parameters:
pOp - Op to add undo info to [INPUTS] pNode - pointer to node to insert LiveEffects above strEffectID - Unique identifier for Op strDispayName - The display name of the effect we're going to apply pEditsList - pointer to optional list of edit params for this effect
- [OUTPUTS]
Returns:
TRUE if worked OK

Errors: See also:

Definition at line 469 of file opliveeffects.cpp.

00476 {
00477     ERROR2IF(pOp==NULL, NULL, "Missing Op pointer");
00478     ERROR2IF(pNode==NULL, NULL, "Missing Node pointer");
00479     ERROR2IF(strEffectID==String(""), NULL, "DoApplyLiveEffect given blank effect name string");
00480     ERROR2IF(strDisplayName==String(""), NULL, "DoApplyLiveEffect given blank display name string");
00481 
00482     BOOL bSelectInside = pNode->IsSelected() || pNode->IsParentOfSelected();
00483 
00484     // Possible solution to issue of Bitmap with Feather attr under DirectBitmap effects
00485     // Detect that state, delete the feather attr, apply a feather effect with the same values
00486     //pNode = ApplyDirectFeatherBodge(pNode);
00487 
00488     // create a new NodeLiveEffect, which we will shortly insert into the tree;
00489     // note that ALLOC_WITH_FAIL automatically calls FailAndExecute() if things go wrong.
00490     NodeBitmapEffect* pBmpFXNode = NULL;
00491     if (bMakeLocked)
00492     {
00493         ALLOC_WITH_FAIL(pBmpFXNode, new NodeLockedEffect, pOp);
00494     }
00495     else
00496     {
00497         ALLOC_WITH_FAIL(pBmpFXNode, new NodeLiveEffect, pOp);
00498     }
00499     if (pBmpFXNode==NULL)
00500         return NULL;
00501 
00502     // Get details from XPE so that displayname gets translated into
00503     // locale language if not already
00504     BOOL bDestructive = FALSE;
00505     XPEHost::GetEffectDetails(strEffectID, &strDisplayName, &bDestructive);
00506     ERROR3IF(bDestructive, "DoApplyLiveEffect asked to apply destructive effect!!!");
00507     if (bDestructive)
00508         return NULL;
00509 
00510     // Set effect params
00511     pBmpFXNode->SetPostProcessorID(strEffectID);
00512     pBmpFXNode->SetDisplayName(strDisplayName);
00513     pBmpFXNode->SetPixelsPerInch(dResolution);
00514     if (pEditsList)
00515     {
00516         pBmpFXNode->SetEditList(pEditsList);
00517     }
00518     else if (!pBmpFXNode->SetDefaultEditList())
00519     {
00520         return NULL;
00521     }
00522 
00523     if (pBmpFXNode->IsLockedEffect())
00524         ((NodeLockedEffect*)pBmpFXNode)->SetLockPermanence(bDestructive);
00525 
00526     // put an action to hide the NodeLiveEffect onto the undo action-list,
00527     // so that if the user presses undo then it will be hidden.
00528     HideNodeAction* pUndoHideNodeAction = NULL;
00529     ActionCode ac = HideNodeAction::Init(pOp,
00530                                         pOp->GetUndoActionList(),
00531                                         pBmpFXNode,
00532                                         FALSE,      // don't include subtree size
00533                                         (Action**)&pUndoHideNodeAction,
00534                                         FALSE);     // don't tell subtree when undone
00535     if (ac == AC_FAIL)
00536         return NULL;
00537 
00538     // right! we've got our node, we've got our action - lets stick it in the tree
00539     // (at a position just next to the last node which will go in the group).
00540     pBmpFXNode->AttachNode(pNode, NEXT);
00541 
00542     // Move the node below the newly inserted LiveEffect
00543     BOOL ok = pOp->DoMoveNode(pNode, pBmpFXNode, FIRSTCHILD);
00544     if (!ok)
00545         return NULL;
00546 
00547 // Set the OpPersmission flags in the newly inserted node
00548 // Otherwise the tree scanner in UpdateChangedNodes won't go below this node
00549 ObjChangeFlags cFlags(NULL, TRUE, NULL, NULL, NULL, NULL, NULL, TRUE);  // ReplaceNode & RegenerateNode
00550 ObjChangeParam ObjChange(OBJCHANGE_STARTING, cFlags, NULL, pOp);
00551 pBmpFXNode->AllowOp(&ObjChange);
00552 
00553     // Deselect the node and select the live effect instead
00554     // TODO: Really?
00555 //  ((NodeRenderable*)pNode)->DeSelect(FALSE);
00556 //  pBmpFXNode->Select(FALSE);
00557 
00558     return pBmpFXNode;
00559 }

ListRange * OpLiveEffect::DoApplyLockedEffect Range pSel,
String_256  strEffectID,
String_64  strDisplayName,
double  dResolution,
IXMLDOMDocumentPtr  pEditsList = NULL,
BOOL  bDetectDirectBitmaps = FALSE
[protected, virtual]
 

Author:
Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/09/2004
Parameters:
pSel - pointer to range of nodes to insert LiveEffects above [INPUTS] strDispayName - The display name of the effect we're going to apply
pNewSel - pointer to new range of LiveEffect nodes [OUTPUTS]
  • NULL if no new live effects added
Returns:

Errors: See also:

Definition at line 737 of file opliveeffects.cpp.

00743 {
00744     ENSURE(pSel, "DoApplyLockedEffect not given a useful range");
00745     ENSURE(strEffectID!=String(""), "DoApplyLockedEffect given blank effect name string");
00746 
00747     ListRange* pLERange = new ListRange();
00748     ENSURE(pLERange, "DoApplyEffect can't create a ListRange");
00749     if (pLERange==NULL)
00750         return NULL;
00751 
00752     // we need to insert the controller node at the position of the highest
00753     // selected node in the z-order, ie last in the selection, so find it.
00754     Node* pFirstNode = pSel->FindFirst();
00755     Node* pNode = pFirstNode;
00756     Node* pLastNode = NULL;
00757     while (pNode != NULL)
00758     {
00759         pLastNode = pNode;
00760         pNode = pSel->FindNext(pLastNode);
00761     }   // loop terminates with pNode == NULL, pLastNode == last-node-in-sel.
00762 
00763     // create a new NodeClipViewController, which we will shortly insert into the tree;
00764     // note that ALLOC_WITH_FAIL automatically calls FailAndExecute() if things go wrong.
00765     NodeLockedEffect* pBmpFXNode = NULL;
00766     ALLOC_WITH_FAIL(pBmpFXNode, new NodeLockedEffect, this);
00767     BOOL ok = (pBmpFXNode != NULL);
00768 
00769     if (ok)
00770     {
00771         // Get details from XPE so that displayname gets translated into
00772         // locale language if not already and destructive state is updated
00773         // for the current machine (shouldn't really change, though)
00774         BOOL bDestructive = TRUE;
00775         XPEHost::GetEffectDetails(strEffectID, &strDisplayName, &bDestructive);
00776 
00777         pBmpFXNode->SetPostProcessorID(strEffectID);
00778         pBmpFXNode->SetDisplayName(strDisplayName);
00779         pBmpFXNode->SetPixelsPerInch(dResolution);
00780         if (pEditsList)
00781         {
00782             pBmpFXNode->SetEditList(pEditsList);
00783         }
00784         else if (!pBmpFXNode->SetDefaultEditList())
00785         {
00786             delete pBmpFXNode;
00787 
00788             // Don't let an empty list of LiveEffect nodes hang around
00789             delete pLERange;
00790             pLERange = NULL;
00791             return pLERange;
00792         }
00793         pBmpFXNode->SetLockPermanence(bDestructive);
00794 
00795         // put an action to hide the NodeClipViewController onto the undo action-list,
00796         // so that if the user presses undo then it will be hidden.
00797         HideNodeAction* pUndoHideNodeAction = NULL;
00798         ActionCode ac = HideNodeAction::Init(this,
00799                                             &UndoActions,
00800                                             pBmpFXNode,
00801                                             FALSE,      // don't include subtree size
00802                                             (Action**)&pUndoHideNodeAction,
00803                                             FALSE);     // don't tell subtree when undone
00804         if (ac == AC_FAIL)
00805         {
00806             delete pBmpFXNode;
00807 
00808             // Don't let an empty list of LiveEffect nodes hang around
00809             delete pLERange;
00810             pLERange = NULL;
00811             return pLERange;
00812         }
00813         else
00814         {
00815             // right! we've got our node, we've got our action - lets stick it in the tree
00816             // (at a position just next to the last node which will go in the group).
00817             pBmpFXNode->AttachNode(pLastNode, NEXT);
00818             pLERange->AddNode(pBmpFXNode);
00819         }
00820     }
00821 
00822     // move each item from the selection into our ClipView group,
00823     // remembering to deselect them as we go.
00824     // TODO:
00825     //  sneaky suspicion I should be putting this in a Do fn in UndoableOperation...
00826     if (ok)
00827     {
00828         pNode = pSel->FindNext(pFirstNode);             // the node we're moving now.
00829 
00830 //      if (pFirstNode->IsAnObject())
00831 //          ok = DoLocaliseCommonAttributes((NodeRenderableInk*)pFirstNode);
00832 
00833         ok = DoMoveNode(pFirstNode, pBmpFXNode, FIRSTCHILD);
00834         if (ok)
00835             ((NodeRenderable*)pFirstNode)->DeSelect(FALSE, TRUE);
00836     }
00837 
00838     Node* pNextNode     = NULL;                         // the next node to move.
00839     Node* pAnchorNode   = pFirstNode;                   // the node we've just moved.
00840     while (ok && pNode != NULL)
00841     {
00842         // get the next node to move.
00843         pNextNode = pSel->FindNext(pNode);
00844 
00845         // now move the current node next to the anchor and deselect it.
00846 //      if (pNode->IsAnObject())
00847 //          ok = DoLocaliseCommonAttributes((NodeRenderableInk*)pNode);
00848 
00849         ok = DoMoveNode(pNode, pAnchorNode, NEXT);
00850         if (ok)
00851             ((NodeRenderable*)pNode)->DeSelect(FALSE, TRUE);
00852 
00853         // get the new anchor node and the next node to move.
00854         pAnchorNode = pNode;
00855         pNode = pNextNode;
00856     }
00857 
00858     // If we're applied to a single node and that node can supply DirectBitmaps and we can accept them
00859     // Then change res to be same as child node
00860     NodeRenderableInk* pInkNode = pBmpFXNode->GetInkNodeFromController();
00861     if (bDetectDirectBitmaps &&
00862         pInkNode &&
00863         pInkNode->CanSupplyDirectBitmap()
00864         )
00865     {
00866         // Child node can supply a DirectBitmap so it would be better if we had same resolution
00867         // as the child node...
00868         double dDirectRes = 0;
00869         pInkNode->GetDirectBitmap(NULL, NULL, NULL, NULL, NULL, &dDirectRes);
00870         if (dDirectRes!=0)
00871         {
00872             pBmpFXNode->SetPixelsPerInch(dDirectRes);           // Set res
00873 
00874             // We can only test EnableDirectCapture after we have set the res correctly
00875             // Otherwise it may return FALSE because the stored res (dResolution) may not match that
00876             // of the DirectBitmap child.
00877             // If it fails, then reset resolution back to what was specified.
00878             if (!pBmpFXNode->EnableDirectCapture())
00879                 pBmpFXNode->SetPixelsPerInch(dResolution);
00880         }
00881     }
00882 
00883     if (ok)
00884     {
00885         // select the new destructive effect, but don't draw any blobs yet.
00886         pBmpFXNode->Select(FALSE);
00887 
00888         // factor out any common attributes.
00889         DoFactorOutCommonChildAttributes(pBmpFXNode);
00890 
00891 // Set the OpPersmission flags in the newly inserted node
00892 // Otherwise the tree scanner in UpdateChangedNodes won't go below this node
00893 ObjChangeFlags cFlags(NULL, TRUE, NULL, NULL, NULL, NULL, NULL, TRUE);  // ReplaceNode & RegenerateNode
00894 ObjChangeParam ObjChange(OBJCHANGE_STARTING, cFlags, NULL, this);
00895 pBmpFXNode->AllowOp(&ObjChange);
00896     }
00897 
00898     if (pLERange->FindFirst()==NULL)
00899     {
00900         // Don't let an empty list of LiveEffect nodes hang around
00901         delete pLERange;
00902         pLERange = NULL;
00903     }
00904 
00905     return pLERange;
00906 }

BOOL OpLiveEffect::DoCopyAttributes UndoableOperation pOp,
Node pSrcNode,
Node pDestNode,
BOOL  bEffectsOnly,
Document pSrcDoc,
Document pDestDoc
[static, private]
 

Copy the specified LiveEffect stack onto the selection Used by Paste Attributes Assumes that only simple attributes will be copied in simple situations I.e. attrs that aren't optimsed so much.

Author:
Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/03/2005
Parameters:
pOp - POinter to Op to add undo records to [INPUTS] pSrcNode - Node containing attrs to copy pDestNode - Node to copy attrs into bEffectsOnly - TRUE if should only copy Effect Attrs Doc ptrs to allow component data to be copied
[OUTPUTS] 
Returns:

Errors: See also:

Definition at line 1692 of file opliveeffects.cpp.

01693 {
01694     if (!pDestNode->IsBounded() || !pSrcNode->IsBounded())
01695         return TRUE;
01696 
01697     ((NodeRenderableBounded*)pDestNode)->InvalidateBoundingRect();
01698     DocRect NodeBounds = ((NodeRenderableBounded*)pDestNode)->GetBoundingRect(TRUE);
01699     Node* pNode = pSrcNode->FindFirstChild();
01700     while (pNode)
01701     {
01702         if (pNode->IsAnAttribute())
01703         {
01704             NodeAttribute* pAttr = (NodeAttribute*)pNode;
01705             if (!bEffectsOnly || pAttr->IsEffectAttribute())
01706             {
01707                 if (pAttr->CanBeAppliedToObject())
01708                 {
01709                     NodeAttribute* pAttrCopy = NULL;
01710                     pAttr->NodeCopy((Node **)(&pAttrCopy));
01711 
01712                     if (pAttrCopy->IsAFillAttr())
01713                     {
01714                         // Set the bounds of the attribute. (Why is this wrong here?)
01715                         ((AttrFillGeometry*)pAttrCopy)->SetBoundingRect(((NodeRenderableBounded*)pSrcNode)->GetBoundingRect());
01716 
01717                         // I'm not sure if this is neccessary but Will does it when making an attribute
01718                         // current.
01719                         if (pAttrCopy->IsAFractalFill())
01720                         {
01721                             // The attr, should always use the default DPI for fractals.
01722                             ((AttrFillGeometry*)pAttrCopy)->SetFractalDPI(AttrFillGeometry::FractalDPI);
01723                         }
01724                     }
01725 
01726                     pAttrCopy->TransformToNewBounds(NodeBounds); 
01727                     pAttrCopy->AttachNode(pDestNode, LASTCHILD);
01728                     pAttrCopy->LinkToGeometry(pDestNode);
01729 
01730                     if (pAttrCopy->IsAFillAttr())
01731                     {
01732                         // Now the Attribute is in the tree, we need to tell the fill
01733                         // attribute to check that it's control points are valid.
01734                         // Unless the fill we transformed above, this will usually 
01735                         // involve the fill 'centring' itself within the bounds of its
01736                         // parent.
01737                         ((AttrFillGeometry*)pAttrCopy)->AttributeChanged();
01738                     }
01739 
01740                     // Inform all DocComponents in the destination doc that a copy is about to take place
01741                     BOOL ok;
01742                     CALL_WITH_FAIL((pDestDoc->StartComponentCopy()), pOp, ok)
01743                     if (ok)
01744                     {
01745                         if (!pAttrCopy->CopyComponentData(pSrcDoc, pDestDoc))
01746                         {
01747                             pDestDoc->AbortComponentCopy(); // Cancel all data which has been copied
01748                             ok = FALSE; // stop what were doing
01749                         }
01750 
01751                         if (ok)
01752                             ok = pDestDoc->EndComponentCopy();
01753                     }
01754 
01755                     // Remove similar nodes in this level
01756                     Node* pCurrent = pDestNode->FindFirstChild();
01757                     Node* pNext;
01758                     CCRuntimeClass* pAttrType = pAttrCopy->GetAttributeType();
01759                     while (pCurrent)
01760                     {
01761                         pNext =  pCurrent->FindNext();
01762                         // Determine if the Current node is to be hidden
01763                         if (pCurrent!=pAttrCopy && pCurrent->IsKindOf(CC_RUNTIME_CLASS(NodeAttribute)))
01764                         {
01765                             { 
01766                                 if (((NodeAttribute*)pCurrent)->GetAttributeType() == pAttrType)
01767                                 {
01768                                     pCurrent->CascadeDelete();
01769                                     delete pCurrent;
01770                                 }
01771                             }
01772                         }
01773                         pCurrent = pNext;
01774                     }
01775                 }
01776             }
01777         }
01778 
01779         pNode = pNode->FindNext();
01780     }
01781 
01782     return TRUE;
01783 }

BOOL OpLiveEffect::DoCopyEffectAttr UndoableOperation pOp,
NodeAttribute pAttr,
Node pNode
[static, private]
 

Copy the Effect attributes from the specified node down to lower nodes, remaining effect attrs where possible but becoming normal attrs if that's not possible Used by ungroup.

Author:
Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
Date:
07/03/2005
Parameters:
pOp - pointer to op [INPUTS] pAttr - pointer to effect attribute to copy pNode - pointer to node whose children should get copies of the attribute
[OUTPUTS] 
Returns:
TRUE if it worked

Errors: See also:

Definition at line 1969 of file opliveeffects.cpp.

01970 {
01971     Node* pChildNode = pNode->FindFirstChild();
01972     while (pChildNode)
01973     {
01974         if (pChildNode->IsAnObject())
01975         {
01976             NodeRenderableInk* pInkNode = (NodeRenderableInk*)pChildNode;
01977             if (pInkNode->IsValidEffectAttr(pAttr))
01978             {
01979                 NodeAttribute* pExistingAttr = pInkNode->FindAppliedAttribute(pAttr->GetRuntimeClass());
01980                 if (pExistingAttr==NULL || pExistingAttr->FindParent()!=pInkNode)
01981                 {
01982                     // We can copy our effect attr to pInkNode as an effect attr
01983                     // Make a copy of this LiveEffect
01984                     NodeAttribute* pCopyAttr = NULL;
01985                     BOOL bOK = FALSE;
01986                     CALL_WITH_FAIL(pCopyAttr = (NodeAttribute*)pAttr->SimpleCopy(), pOp, bOK);  
01987                     if (!bOK) return FALSE; // No room to take a copy of the node
01988 
01989 //                  pOp->DoInsertNewNode(pCopyAttr, pInkNode, LASTCHILD, FALSE, FALSE, FALSE, FALSE);
01990 
01991                     // Create a hide node action to hide the node when we undo 
01992                     pCopyAttr->AttachNode(pInkNode, LASTCHILD);
01993                     HideNodeAction* UndoHideNodeAction;
01994                     if (HideNodeAction::Init(pOp, pOp->GetUndoActions(), pCopyAttr, TRUE, (Action**)(&UndoHideNodeAction))
01995                             == AC_FAIL)
01996                     {
01997                         pCopyAttr->CascadeDelete();
01998                         delete pCopyAttr;
01999                         return FALSE;
02000                     }
02001                 }
02002             }
02003             else
02004             {
02005                 NodeAttribute* pExistingAttr = pInkNode->FindAppliedAttribute(pAttr->GetRuntimeClass());
02006                 if (pExistingAttr==NULL || pExistingAttr->FindParent()!=pInkNode)
02007                 {
02008                     // We can copy our effect attrs to pInkNode as a normal attr
02009                     NodeAttribute* pCopyAttr = NULL;
02010                     BOOL bOK = FALSE;
02011                     CALL_WITH_FAIL(pCopyAttr = (NodeAttribute*)pAttr->SimpleCopy(), pOp, bOK);  
02012                     if (!bOK) return FALSE; // No room to take a copy of the node
02013 
02014 //                  pOp->DoInsertNewNode(pCopyAttr, pInkNode, FIRSTCHILD, FALSE, FALSE, FALSE, FALSE);
02015 
02016                     // Create a hide node action to hide the node when we undo 
02017                     pCopyAttr->AttachNode(pInkNode, FIRSTCHILD);
02018                     HideNodeAction* UndoHideNodeAction;
02019                     if (HideNodeAction::Init(pOp, pOp->GetUndoActions(), pCopyAttr, TRUE, (Action**)(&UndoHideNodeAction))
02020                             == AC_FAIL)
02021                     {
02022                         pCopyAttr->CascadeDelete();
02023                         delete pCopyAttr;
02024                         return FALSE;
02025                     }
02026 
02027 //                  if (UndoHideNodeAction)
02028 //                      UndoHideNodeAction->DontPanic();
02029 
02030                     // Remove any deeper attributes of the same type to make a consistent structure
02031                     pOp->DoRemoveAttrTypeFromSubtree(pInkNode, pAttr->GetRuntimeClass(), pCopyAttr);
02032                 }
02033             }
02034         }
02035 
02036         pChildNode = pChildNode->FindNext();
02037     }
02038 
02039     return TRUE;
02040 }

BOOL OpLiveEffect::DoCopyEffectsStack UndoableOperation pOp,
Node pDestNode,
ListRange pEffectsStack,
Document pSrcDoc,
Document pDestDoc
[static, private]
 

Copy the specified LiveEffect stack onto the selection Used by Paste Attributes and OpCombineShapes.

Author:
Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
Date:
07/02/2005
Parameters:
pOp - pointer to Op [INPUTS] pPPStack - pointer to EffectsStack to copy
[OUTPUTS] 
Returns:

Errors: See also:

Definition at line 1530 of file opliveeffects.cpp.

01531 {
01532     ERROR2IF(pOp==NULL, FALSE, "No Op given to DoCopyEffectsStack\n");
01533     ERROR2IF(pEffectsStack==NULL || pEffectsStack->IsEmpty(), FALSE, "No stack/empty stack given to DoCopyEffectsStack\n");
01534     ERROR2IF(pDestNode==NULL, FALSE, "No destination node given to DoCopyEffectsStack\n");
01535 
01536     //-----------------------------------------------------------------------------
01537     // Remove all current LiveEffects on the selection
01538     //
01539     if (pDestNode->IsAnObject() && !pDestNode->NeedsParent(pDestNode->FindParent()))
01540         pDestNode = DoDeleteAllPostProcessors(pOp, (NodeRenderableInk*)pDestNode, FALSE, TRUE); // TRUE means delete all effects in stack, even those below pDestNode
01541 
01542     //-----------------------------------------------------------------------------
01543     // Apply new LiveEffects from the specified stack
01544     //
01545     BOOL bWasSelected = pDestNode->IsSelected() || pDestNode->IsParentOfSelected();
01546     Node* pSelectNode = pDestNode;
01547     if (pDestNode->IsNodeRenderableClass())
01548         ((NodeRenderable*)pDestNode)->DeSelect(FALSE, TRUE);
01549 
01550     Node* pTopNode = pDestNode;
01551 
01552     NodeEffect* pEffect = (NodeEffect*)pEffectsStack->FindFirst();
01553     while (pEffect)
01554     {
01555         // Test for legacy effect special cases first
01556         // Shadow -------------------------------------------------------------
01557         if (pEffect->IsAShadowController())
01558         {
01559             if (pTopNode->NeedsParent(pTopNode->FindParent()))
01560             {
01561                 if (pTopNode->IsAShadow())
01562                 {
01563                     // TODO: Copy shadow properties here?
01564                 }
01565             }
01566             else
01567             {
01568                 NodeShadowController* pController = (NodeShadowController*)pEffect;
01569 
01570                 NodeShadowParam param(pController->GetShadowType(),
01571                                         pController->GetFloorShadowAngle(),
01572                                         pController->GetFloorShadowHeight(),
01573                                         pController->GetOffsetX(),
01574                                         pController->GetOffsetY(),
01575                                         pController->GetPenumbraWidth(),
01576                                         pController->GetShadow()->GetDarkness(),
01577                                         pController->GetWallShadowScale(),
01578                                         pController->GetGlowWidth(),
01579                                         pController->GetShadow()->GetBiasGain(),
01580                                         TRUE);
01581                 param.strOpUnique = pEffect->GetPostProcessorID();
01582                 param.StackPosition = STACKPOS_INSERT_TOP;
01583                 pTopNode = OpApplyShadow::DoApplyShadow(pOp, pTopNode, &param, FALSE);
01584     //          BOOL ok = pOp->DoFactorOutCommonChildAttributes(pShadControl);
01585                 if (pTopNode == NULL)
01586                 {
01587                     pOp->FailAndExecute();
01588                     return FALSE;
01589                 }
01590 
01591                 // Copy attributes applied to Shadow node
01592                 NodeShadow* pShadow = pController->GetShadow();
01593                 NodeShadow* pNewShadow = NULL;
01594                 if (pTopNode->IsAShadowController())
01595                     pNewShadow = ((NodeShadowController*)pTopNode)->GetShadow();
01596