OpBlendNodes Class Reference

#include <blndtool.h>

Inheritance diagram for OpBlendNodes:

SelOperation UndoableOperation Operation MessageHandler ListItem CCObject SimpleCCObject List of all members.

Public Member Functions

 OpBlendNodes ()
 Constructor.
 ~OpBlendNodes ()
 Destructor.
BOOL DoDrag (BlendTool *pBlendTool)
 This starts a drag that may lead to a blend. The DragFinished() method will do the hard work of blending if it can be done.
virtual BOOL SnappingDrag ()
virtual void DragPointerMove (DocCoord PointerPos, ClickModifiers ClickMods, Spread *, BOOL bSolidDrag)
 Pure virtual function which tells the operation that the mouse has moved.
virtual void DragFinished (DocCoord PointerPos, ClickModifiers ClickMods, Spread *, BOOL Success, BOOL bSolidDrag)
 Ends the drag. Either creates a new grid or resizes GridClicked depending on the state of affairs when the drag started.
void RenderMyDragBlobs ()
 Draws an EORed rectangle defined by AnchorPoint and DragPoint.
void RenderDragBlobs (DocRect Rect, Spread *pSpread, BOOL bSolidDrag)
 Draws an EORed rectangle defined by AnchorPoint and DragPoint.
void GetOpName (String_256 *OpName)
 The GetOpName fn is overridden so that we return back a description appropriate to the type of attribute that the operation applies.
virtual BOOL Undo ()
 Gets called whenever this operation is undone.
virtual BOOL Redo ()
 Gets called whenever this operation is Redone.
BOOL RecordBlenderInfo (List &BlenderList, NodeBlend *pNodeBlend)
 This scans the blenders in the given blend node, creating a BlenderInfoItem for each NodeBlender. Each BlenderInfoItem is placed on BlenderList.
void DeinitBlenders (List &BlenderList)
 This scans the blenders, calling the Deinit() method for each of them.
BOOL ReinitBlenders (List &BlenderList)
 This scans the blenders, calling the Reinit() method for each of them. It uses the start and end node pointers gathered by RecordBlenderInfo() when calling Reinit().
BOOL GetNodeClosestToPoint (NodeRenderableInk **ppInk, BOOL StartBlend)
 when blending from two blends, this retrieves the node closest to the actual point where the blend began or ended

Static Public Member Functions

static BOOL Declare ()
 Adds the operation to the list of all known operations.
static OpState GetState (String_256 *Description, OpDescriptor *)
 Find out the state of the operation at the specific time.

Private Member Functions

 CC_DECLARE_DYNCREATE (OpBlendNodes)
BOOL DoBlendObjects ()
 This blends two objects together to form a new blend object in the tree. All the data that's required is stored in pRefStart (for the start object) and pRefEnd (for the end object). It assumes that neither the start or end objects are blends, so no clever merging of blend objects will take place here.
BOOL DoCreateBlender (NodeRenderableInk *pNodeStart, INT32 IndexStart, NodeRenderableInk *pNodeEnd, INT32 IndexEnd, Node *pContextNode, AttachNodeDirection AttachDir)
 This forms a blender object in the tree that can blend pRefStart->pNode to pRefEnd->pNode.
BOOL DoRemapBlend ()
 This tries to remap a blend using the data held in pRefStart && pRefEnd. It asks the pNodeBlend object to try and remap the two paths by rotating the path elements so that the element at Index is the first element in the path.
BOOL DoBlendBlendAndObject ()
 This blends a blend object with another non-blend object. This is like a concatination of the the two nodes, resulting a single blend with an extra blend stage. E.g. blending a blend containing two paths (i.e. a single blend of two objects) with another path. The result will be a single blend object, blending the first path to the second, and the second to the third.
BOOL DoBlendBlendAndBlend ()
 This merges to blend nodes together, so that the last object in the first blend is blended with the first of the second blend.
BOOL DoDeinitBlenders (List &BlenderList)
 This calls DeinitBlenders() on the given list, and creates an action that will call ReinitBlenders() on undo, and DeinitBlenders() on redo.
BOOL DoReinitBlenders (List &BlenderList)
 This calls ReinitBlenders() on the given list, and creates an action that will call DeinitBlenders() on undo, and ReinitBlenders() on redo.
BOOL DeterminBlendObjectsProcessorHit ()
 This function provides a quick (and rough) estimate on the amount of work that will have to be done to create the blend. This estimate is based upon the total length of all paths that exist within the start and end nodes. An attempt is also made at altering the 'threshold' based upon the CPU type.
BOOL RemoveCompoundNodes (CompoundNodeTreeFactoryList *pList)
 Removes all compound nodes.
BOOL RemoveCompoundNodesFromNode (Node *pNode, Node **pRetnNode, CompoundNodeTreeFactoryList *pList)
 Removes all compound nodes from the given node (i.e. unshadows and unbevels nodes).
BOOL DoContourNode (Node *pNode, DocCoord PointerPos, UINT32 Steps)
 Applies a contour to the given node.

Private Attributes

BlendToolRefpRefStart
BlendToolRefpRefEnd
OpBlendOpType OpType
NodeBlendpNodeBlend
NodeBlendpNodeBlendStart
NodeBlendpNodeBlendEnd
BlendToolm_pBlendTool

Detailed Description

Definition at line 475 of file blndtool.h.


Constructor & Destructor Documentation

OpBlendNodes::OpBlendNodes  ) 
 

Constructor.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/10/94

Definition at line 3081 of file blndtool.cpp.

03082 {
03083     pRefStart = NULL;
03084     pRefEnd   = NULL;
03085     OpType    = BLENDOPTYPE_NONE;
03086 
03087     pNodeBlend      = NULL;
03088     pNodeBlendStart = NULL;
03089     pNodeBlendEnd   = NULL;
03090 }

OpBlendNodes::~OpBlendNodes  ) 
 

Destructor.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/10/94

Definition at line 3102 of file blndtool.cpp.

03103 {
03104 }


Member Function Documentation

OpBlendNodes::CC_DECLARE_DYNCREATE OpBlendNodes   )  [private]
 

BOOL OpBlendNodes::Declare  )  [static]
 

Adds the operation to the list of all known operations.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/10/94
Returns:
TRUE if all went OK, FALSE otherwise

Definition at line 4561 of file blndtool.cpp.

04562 {
04563     return (RegisterOpDescriptor(
04564                                 0, 
04565                                 _R(IDS_BLEND_TOOL),
04566                                 CC_RUNTIME_CLASS(OpBlendNodes), 
04567                                 OPTOKEN_BLENDNODES,
04568                                 OpBlendNodes::GetState,
04569                                 0,          /* help ID */
04570                                 _R(IDBBL_NOOP), /* bubble ID */
04571                                 0           /* bitmap ID */
04572                                 ));
04573 }

void OpBlendNodes::DeinitBlenders List BlenderList  ) 
 

This scans the blenders, calling the Deinit() method for each of them.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/11/94
Parameters:
BlenderList = reference to a list of blender info items [INPUTS]
- [OUTPUTS]
Returns:
-

Definition at line 3819 of file blndtool.cpp.

03820 {
03821     BlenderInfoItem* pItem = (BlenderInfoItem*) BlenderList.GetHead();
03822 
03823     while (pItem != NULL)
03824     {
03825         pItem->pNodeBlender->Deinit();
03826         pItem = (BlenderInfoItem*) BlenderList.GetNext(pItem);
03827     }
03828 }

BOOL OpBlendNodes::DeterminBlendObjectsProcessorHit  )  [private]
 

This function provides a quick (and rough) estimate on the amount of work that will have to be done to create the blend. This estimate is based upon the total length of all paths that exist within the start and end nodes. An attempt is also made at altering the 'threshold' based upon the CPU type.

Author:
Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
Date:
6/9/2000
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
TRUE if should continue, FALSE otherwise
This system could probably be enhanced - but for now it seems to work fine.

Definition at line 4338 of file blndtool.cpp.

04339 {
04340     Node* pStart = pRefStart->pNode;
04341     Node* pEnd = pRefEnd->pNode;
04342 
04343     INT32 complexityEstimate1 = pStart->EstimateNodeComplexity (NULL);
04344     INT32 complexityEstimate2 = pEnd->EstimateNodeComplexity (NULL);
04345 
04346     INT32 generatedPathsEstimate = 3*complexityEstimate1 + 2*complexityEstimate2;
04347 
04348     static BOOL foundCPU = FALSE;
04349     static INT32 pathsBeforeAsk = 0;
04350 
04351     if (!foundCPU)
04352     {
04353 /*      SYSTEM_INFO systemInfo;
04354         GetSystemInfo (&systemInfo);
04355 
04356         if (systemInfo.dwProcessorType == PROCESSOR_INTEL_386)
04357         {
04358             pathsBeforeAsk = 6000;
04359         }
04360         else if (systemInfo.dwProcessorType == PROCESSOR_INTEL_486)
04361         {
04362             pathsBeforeAsk = 12000;
04363         }
04364         else if (systemInfo.dwProcessorType == PROCESSOR_INTEL_PENTIUM)
04365         {
04366             pathsBeforeAsk = 20000;
04367         }
04368         else */
04369         {
04370             // assume its faster than a pentium .... (in 2005 this will alwys be the case!)
04371             pathsBeforeAsk = 24000;
04372         }
04373         foundCPU = TRUE;
04374     }
04375 
04376     if (generatedPathsEstimate > pathsBeforeAsk)
04377     {
04378         // Load and build the question text.
04379         String_256 QueryString(_R(IDS_ASKLONGJOB));
04380                         
04381         // The only way of bringing up a box with a string in it
04382         Error::SetError(0, QueryString, 0);
04383         INT32 DlgResult = InformMessage(0, _R(IDS_YES), _R(IDS_NO));
04384         Error::ClearError();
04385 
04386         switch (DlgResult)
04387         {
04388             case 1:     // YES
04389                 return (TRUE);
04390             break;
04391             case 2:     // NO
04392                 return (FALSE);         // break out of this stuff!
04393         }
04394     }
04395 
04396     return (TRUE);
04397 }

BOOL OpBlendNodes::DoBlendBlendAndBlend  )  [private]
 

This merges to blend nodes together, so that the last object in the first blend is blended with the first of the second blend.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/11/94
Parameters:
- (data is taken from pRefStart and pRefEnd member vars) [INPUTS]
- [OUTPUTS]
Returns:
TRUE if all when well, FALSE otherwise

Definition at line 3498 of file blndtool.cpp.

03499 {
03500     // Get ptr to the NodeBlends in question, and put them in the member vars pNodeBlendStart & pNodeBlendEnd
03501     pNodeBlendStart = (NodeBlend*)pRefStart->pNode;
03502     pNodeBlendEnd   = (NodeBlend*)pRefEnd  ->pNode;
03503 
03504     // DY changed to allow for new blending to and from a blend on a path
03505     if (pNodeBlendStart->IsOnACurve() || pNodeBlendEnd->IsOnACurve())
03506     {
03507         OpType = BLENDOPTYPE_BLENDBLENDONPATH;
03508         pNodeBlendStart->SetBlendedOnCurve(TRUE);
03509     }
03510     else
03511         OpType = BLENDOPTYPE_BLENDANDBLEND;
03512 
03513 
03514     if (pNodeBlendStart == NULL || pNodeBlendEnd == NULL || pNodeBlendStart == pNodeBlendEnd) return FALSE;
03515 
03516     ERROR3IF(!IS_A(pNodeBlendStart,NodeBlend) || !IS_A(pNodeBlendEnd,NodeBlend),"Either start or end is not a NodeBlend");
03517     if (!IS_A(pNodeBlendStart,NodeBlend) || !IS_A(pNodeBlendEnd,NodeBlend)) return FALSE;
03518 
03519     // Get a record of all the blenders in the blend nodes
03520     List BlenderListStart,BlenderListEnd;
03521     if (!RecordBlenderInfo(BlenderListStart,pNodeBlendStart) || !RecordBlenderInfo(BlenderListEnd,pNodeBlendEnd))
03522     {
03523         // Tidy up if we fail to get blender info on the two blend nodes
03524         BlenderListStart.DeleteAll();
03525         BlenderListEnd  .DeleteAll();
03526         return FALSE;
03527     }
03528 
03529     //BlenderInfoItem*   pItemStart = (BlenderInfoItem*)BlenderListStart.GetTail();
03530     //BlenderInfoItem*   pItemEnd   = (BlenderInfoItem*)BlenderListEnd  .GetHead();
03531     NodeRenderableInk* pNodeStart = NULL;  //pItemStart->pNodeEnd;
03532     NodeRenderableInk* pNodeEnd   = NULL;  //pItemEnd  ->pNodeStart;
03533 
03534     BOOL ok = GetNodeClosestToPoint(&pNodeStart, TRUE);
03535     if (ok) ok = GetNodeClosestToPoint(&pNodeEnd, FALSE);
03536     ERROR3IF(pNodeStart == NULL,"The start node ptr is NULL");
03537     ERROR3IF(pNodeEnd   == NULL,"The end node ptr is NULL");
03538     if (pNodeStart == NULL || pNodeEnd == NULL) return FALSE;
03539 
03540     BlobManager* pBlobManager = GetApplication()->GetBlobManager();
03541     ENSURE(pBlobManager, "Can't get BlobManager");
03542 
03543     ok = DeterminBlendObjectsProcessorHit ();
03544 
03545     // Now we are ready to do the actual blend
03546 
03547     // Firstly, record the selection state
03548     if (ok) ok = DoStartSelOp(TRUE,TRUE);
03549 
03550     if (ok) ok = (Tool::GetCurrent() != NULL);
03551     if (ok) pBlobManager->RenderToolBlobsOff(Tool::GetCurrent(), pRefStart->pSpread,NULL);
03552     if (ok) NodeRenderableInk::DeselectAll(FALSE);
03553 
03554     // Select the start blend node
03555     if (ok) pNodeBlendStart->SetSelected(TRUE);
03556 
03557     // Deinit all the blenders in the end blend.
03558     if (ok) ok = DoDeinitBlenders(BlenderListEnd);
03559 
03560     // Localise the attributes in the start blend
03561     if (ok) ok = DoLocaliseCommonAttributes(pNodeBlendStart);
03562 
03563     // Localise the attributes in the end blend
03564     if (ok) ok = DoLocaliseCommonAttributes(pNodeBlendEnd);
03565 
03566     // Hide the end blend node
03567     NodeHidden* pNodeHidden;
03568     if (ok) ok = DoHideNode(pNodeBlendEnd,TRUE,&pNodeHidden);
03569 
03570     if (ok)
03571     {
03572         // DY update blendpath indexes in existing blenders before we
03573         // move them
03574         INT32 FirstBlendNumPaths = pNodeBlendStart->GetNumNodeBlendPaths();
03575         NodeBlender* pBlender = pNodeBlendEnd->FindFirstBlender();
03576         while (pBlender != NULL)
03577         {
03578             INT32 CurrentIndex = pBlender->GetNodeBlendPathIndex();
03579             if (CurrentIndex > -1)
03580             {
03581                 ChangeBlenderOpParam Param;
03582                 Param.m_NewNodeBlendPathIndex = (CurrentIndex + FirstBlendNumPaths);
03583                 Param.m_ChangeType = CHANGEBLENDER_NBPINDEX;
03584                 ok = ChangeBlenderAction::Init(this, &UndoActions, pBlender, Param);
03585             }
03586             pBlender =  pNodeBlendEnd->FindNextBlender(pBlender);
03587         }
03588     }
03589 
03590     // Now move all the end blend's children (except hidden nodes) into the start blend.
03591     if (ok)
03592     {
03593         Node* pNode = pNodeBlendEnd->FindFirstChild();
03594         while (pNode != NULL && ok)
03595         {
03596             Node* pNext = pNode->FindNext();
03597             if (!pNode->IS_KIND_OF(NodeHidden))
03598                 ok = DoMoveNode(pNode,pNodeBlendStart,LASTCHILD);
03599             
03600             // DY keep track of which nodeblendpath this is
03601             //if (pNode->IS_KIND_OF(NodeBlendPath))
03602             //  ((NodeBlendPath*)pNode)->SetPathIndex();
03603             pNode = pNext;
03604         }
03605     }
03606 
03607     // Create a blender node to blend the two nodes
03608     if (ok) ok = DoCreateBlender(pNodeStart,-1,pNodeEnd,-1,pNodeStart,NEXT);
03609 
03610     // Reinit the end blenders using the same start and end pointers they were using before the blend
03611     if (ok) ok = DoReinitBlenders(BlenderListEnd);
03612 
03613     // Factor out any common attrs that might have been copied during the blend
03614     if (ok) ok = DoFactorOutCommonChildAttributes(pNodeBlendStart);
03615 
03616     // Invalid the whole of the start blend
03617     if (ok) ok = DoInvalidateNodeRegion(pNodeBlendStart,TRUE);
03618 
03619     // Clear out the lists (we don't want memory leaks, do we).
03620     BlenderListStart.DeleteAll();
03621     BlenderListEnd  .DeleteAll();
03622 
03623     // Throw away the selection cache
03624     GetApplication()->UpdateSelection();
03625 
03626     return (ok);
03627 }

BOOL OpBlendNodes::DoBlendBlendAndObject  )  [private]
 

This blends a blend object with another non-blend object. This is like a concatination of the the two nodes, resulting a single blend with an extra blend stage. E.g. blending a blend containing two paths (i.e. a single blend of two objects) with another path. The result will be a single blend object, blending the first path to the second, and the second to the third.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/11/94
Parameters:
- (data is taken from pRefStart and pRefEnd member vars) [INPUTS]
- [OUTPUTS]
Returns:
TRUE if all when well, FALSE otherwise
The order in which the two objects are concatinated depends on which is is the start of the blend and which is the end.

Definition at line 3649 of file blndtool.cpp.

03650 {
03651     ERROR3IF(!IS_A(pRefStart->pNode,NodeBlend) && !IS_A(pRefEnd->pNode,NodeBlend),"Neither start or end are NodeBlends");
03652     if (!IS_A(pRefStart->pNode,NodeBlend) && !IS_A(pRefEnd->pNode,NodeBlend)) return FALSE;
03653 
03654     OpType = BLENDOPTYPE_BLENDANDOBJECT;
03655     // BlendIsStart == TRUE if the blend node was the start of the blend and not the end
03656     BOOL BlendIsStart = IS_A(pRefStart->pNode,NodeBlend);
03657 
03658     // Get ptr to the NodeBlend in question, and put it in the member var pNodeBlend
03659     pNodeBlend = NULL;
03660     if (BlendIsStart) 
03661         pNodeBlend = (NodeBlend*)pRefStart->pNode; 
03662     else
03663         pNodeBlend = (NodeBlend*)pRefEnd->pNode; 
03664 
03665     if (pNodeBlend == NULL) return FALSE;
03666 
03667     // Get a record of all the blenders in the blend node
03668     List BlenderList;
03669     if (!RecordBlenderInfo(BlenderList,pNodeBlend))
03670         return FALSE;
03671 
03672     NodeRenderableInk* pNodeStart = NULL;
03673     NodeRenderableInk* pNodeEnd = NULL;
03674     Node* pContextNode;
03675     AttachNodeDirection AttachDir;
03676     BOOL ok = FALSE;
03677     if (BlendIsStart)
03678     {
03679 //      BlenderInfoItem* pItem = (BlenderInfoItem*)BlenderList.GetTail();
03680         pNodeBlendStart = pNodeBlend;
03681         ok              = GetNodeClosestToPoint(&pNodeStart, TRUE);
03682         pNodeEnd        = pRefEnd->pNode;
03683         pContextNode    = pNodeEnd;
03684         AttachDir       = PREV;
03685     }
03686     else
03687     {
03688 //      BlenderInfoItem* pItem = (BlenderInfoItem*)BlenderList.GetHead();
03689         pNodeStart      = pRefStart->pNode;
03690         pNodeBlendEnd   = pNodeBlend;
03691         ok              = GetNodeClosestToPoint(&pNodeEnd, FALSE);
03692         pContextNode    = pNodeStart;
03693         AttachDir       = NEXT;
03694     }
03695 
03696     ERROR3IF(pNodeBlend == NULL,"Neither start or end are NodeBlends");
03697     ERROR3IF(pNodeStart == NULL,"The start node ptr is NULL");
03698     ERROR3IF(pNodeEnd   == NULL,"The end node ptr is NULL");
03699     if (pNodeBlend == NULL || pNodeStart == NULL || pNodeEnd == NULL)
03700         return FALSE;
03701 
03702     BlobManager* pBlobManager = GetApplication()->GetBlobManager();
03703     ENSURE(pBlobManager, "Can't get BlobManager");
03704 
03705     ok = DeterminBlendObjectsProcessorHit ();
03706 
03707     // Firstly, record the selection state
03708     if (ok) ok = DoStartSelOp(TRUE,TRUE);
03709 
03710     if (ok) ok = (Tool::GetCurrent() != NULL);
03711     if (ok) pBlobManager->RenderToolBlobsOff(Tool::GetCurrent(), pRefStart->pSpread,NULL);
03712     if (ok) NodeRenderableInk::DeselectAll(FALSE);
03713 
03714     // Select th blend node
03715     if (ok) pNodeBlend->SetSelected(TRUE);
03716 
03717     // Deinit all the blenders in the blend.
03718     if (ok) ok = DoDeinitBlenders(BlenderList);
03719 
03720     // Localise the attributes in the blend before we start moving node around
03721     if (ok) ok = DoLocaliseCommonAttributes(pNodeBlend);
03722 
03723     // If blending to a blend, move the start node, and make sure it's deselected
03724     // Also find the number of paths that will be passed back (for the progress display)
03725     if (ok && !BlendIsStart)    ok = DoMoveNode(pNodeStart,pNodeBlend,FIRSTCHILD);
03726     if (ok && !BlendIsStart)    ok = DoDeselectNode(pNodeStart);
03727 
03728     // If blending from a blend, move the end node, and make sure it's deselected
03729     // Also find the number of paths that will be passed back (for the progress display)
03730     if (ok &&  BlendIsStart)    ok = DoMoveNode(pNodeEnd,pNodeBlend,LASTCHILD);
03731     if (ok &&  BlendIsStart)    ok = DoDeselectNode(pNodeEnd);
03732 
03733     // Create a blender node to blend the two nodes
03734     if (ok) ok = DoCreateBlender(pNodeStart,-1,pNodeEnd,-1,pContextNode,AttachDir);
03735 
03736     // Factor out any common attrs that might have been copied during the blend
03737     if (ok) ok = DoFactorOutCommonChildAttributes(pNodeBlend);
03738 
03739     // Invalidate the whole blend
03740     if (ok) ok = DoInvalidateNodeRegion(pNodeBlend,TRUE);
03741 
03742     // Reinit the blenders using the same start and end pointers they were using before the blend
03743     if (ok) ok = DoReinitBlenders(BlenderList);
03744 
03745     // Clear out the list (we don't want memory leaks, do we).
03746     BlenderList.DeleteAll();
03747 
03748     // Throw away the selection cache
03749     GetApplication()->UpdateSelection();
03750 
03751     return (ok);
03752 }

BOOL OpBlendNodes::DoBlendObjects  )  [private]
 

This blends two objects together to form a new blend object in the tree. All the data that's required is stored in pRefStart (for the start object) and pRefEnd (for the end object). It assumes that neither the start or end objects are blends, so no clever merging of blend objects will take place here.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/10/94
Parameters:
(data is taken from pRefStart and pRefEnd member vars) [INPUTS]
- [OUTPUTS]
Returns:
TRUE if all when well, FALSE otherwise

Definition at line 4230 of file blndtool.cpp.

04231 {
04232     // DMc - are the nodes to be blended shadowed or bevelled ?
04233 //  BOOL bIsShadowed = FALSE;
04234 //  BOOL bIsBevelled = FALSE;
04235 
04236     // What type of blend op are we doing?
04237     OpType = BLENDOPTYPE_NEW;
04238 
04239     // Are we going mad? Better check our onions...
04240     ERROR3IF_PF(pRefStart        == NULL,("pRefStart == NULL"));
04241     ERROR3IF_PF(pRefEnd          == NULL,("pRefEnd == NULL"));
04242     ERROR3IF_PF(pRefStart->pNode == NULL,("pRefStart->pNode == NULL"));
04243     ERROR3IF_PF(pRefEnd  ->pNode == NULL,("pRefEnd->pNode == NULL"));
04244 
04245     BOOL ok = DeterminBlendObjectsProcessorHit ();
04246 
04247     if (!ok)
04248     {
04249         return (FALSE);
04250     }
04251 
04252     ok = DoStartSelOp(TRUE,TRUE);
04253 
04254     CompoundNodeTreeFactoryList CFList;
04255 
04256     RemoveCompoundNodes(&CFList);
04257 
04258     NodeBlend* pNodeBlend;
04259 
04260     // DMc
04261     // move the end nodes upwards to include compound nodes
04262     Node * pParent = pRefStart->pNode;
04263 
04264     while (pParent)
04265     {
04266         if (!pParent->PromoteHitTestOnChildrenToMe() && pParent->IsAnObject())
04267         {
04268             pRefStart->pNode = (NodeRenderableInk *)pParent;
04269         }
04270 
04271         pParent = pParent->FindParent();
04272     }
04273 
04274     pParent = pRefEnd->pNode;
04275 
04276     while (pParent)
04277     {
04278         if (!pParent->PromoteHitTestOnChildrenToMe() && pParent->IsAnObject())
04279         {
04280             pRefEnd->pNode = (NodeRenderableInk *)pParent;
04281         }
04282 
04283         pParent = pParent->FindParent();
04284     }
04285 
04286     BlobManager* pBlobManager = GetApplication()->GetBlobManager();
04287     ENSURE(pBlobManager, "Can't get BlobManager");
04288 
04289     if (ok) ok = (Tool::GetCurrent() != NULL);
04290     if (ok) pBlobManager->RenderToolBlobsOff(Tool::GetCurrent(), pRefStart->pSpread,NULL);
04291     if (ok) NodeRenderableInk::DeselectAll(FALSE,FALSE);
04292 
04293     if (ok) ALLOC_WITH_FAIL(pNodeBlend,new NodeBlend,this);
04294     if (ok) ok = (pNodeBlend != NULL);
04295 
04296     if (ok) pRefStart->pNode->SetSelected(FALSE);
04297     if (ok) pRefEnd  ->pNode->SetSelected(FALSE);
04298 
04299     if (ok) ok = DoInsertNewNode(pNodeBlend,pRefEnd->pNode,NEXT,FALSE,FALSE,FALSE,FALSE);
04300     if (ok) ok = DoMoveNode(pRefStart->pNode,pNodeBlend,LASTCHILD);
04301     if (ok) ok = DoMoveNode(pRefEnd  ->pNode,pNodeBlend,LASTCHILD);
04302     if (ok) ok = DoCreateBlender(pRefStart->pNode,pRefStart->Index,pRefEnd->pNode,pRefEnd->Index,pRefStart->pNode,NEXT);
04303     if (ok) ok = DoInvalidateNodeRegion(pNodeBlend,TRUE);
04304 
04305     // Simon - Factor out the blend's common attributes
04306     if (ok) ok = DoFactorOutCommonChildAttributes(pNodeBlend);
04307 
04308 
04309     if (ok)
04310         pNodeBlend->SetSelected(TRUE);      // Select the new node
04311 
04312     // Throw away the selection cache
04313     GetApplication()->UpdateSelection();
04314 
04315     return (ok);
04316 }

BOOL OpBlendNodes::DoContourNode Node pNode,
DocCoord  PointerPos,
UINT32  Steps
[private]
 

Applies a contour to the given node.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/8/99
Parameters:
Node to contour [INPUTS]
- [OUTPUTS]
Returns:
TRUE if all when well, FALSE otherwise

Definition at line 3342 of file blndtool.cpp.

03343 {
03344     /*
03345     List NodeList;
03346 
03347     // get the bounding rect of the node to be contoured
03348     DocRect br = ((NodeRenderableBounded *)pNode)->GetBoundingRect();
03349 
03350     UINT32 Width = 0;
03351 
03352     INT32 OffsetX = 0;
03353     INT32 OffsetY = 0;
03354 
03355     // try to work out the width of the contour
03356     if (PointerPos.x < br.lo.x && PointerPos.y >= br.lo.y &&
03357         PointerPos.y <= br.hi.y)
03358     {
03359         Width = br.lo.x - PointerPos.x;
03360     }
03361     else if (PointerPos.x > br.hi.x && PointerPos.y >= br.lo.y &&
03362         PointerPos.y <= br.hi.y)
03363     {
03364         Width = PointerPos.x - br.hi.x;
03365     }
03366     else if (PointerPos.x >= br.lo.x && PointerPos.x <= br.hi.x &&
03367         PointerPos.y < br.lo.y)
03368     {
03369         Width = br.lo.y - PointerPos.y;
03370     }
03371     else if (PointerPos.x >= br.lo.x && PointerPos.x <= br.hi.x &&
03372         PointerPos.y > br.hi.y)
03373     {
03374         Width = PointerPos.y - br.hi.y;
03375     }
03376     else if (PointerPos.x < br.lo.x && PointerPos.y < br.lo.y)
03377     {
03378         OffsetX = br.lo.x - PointerPos.x;
03379         OffsetY = br.lo.y - PointerPos.y;
03380 
03381         if (OffsetX > OffsetY)
03382         {
03383             Width = OffsetX;
03384         }
03385         else
03386         {
03387             Width = OffsetY;
03388         }
03389     }
03390     else if (PointerPos.x > br.hi.x && PointerPos.y < br.lo.y)
03391     {
03392         OffsetX = PointerPos.x - br.hi.x ;
03393         OffsetY = br.lo.y - PointerPos.y;
03394 
03395         if (OffsetX > OffsetY)
03396         {
03397             Width = OffsetX;
03398         }
03399         else
03400         {
03401             Width = OffsetY;
03402         }
03403     }
03404     else if (PointerPos.x > br.hi.x && PointerPos.y > br.hi.y)
03405     {
03406         OffsetX = PointerPos.x - br.hi.x ;
03407         OffsetY = PointerPos.y - br.hi.y;
03408 
03409         if (OffsetX > OffsetY)
03410         {
03411             Width = OffsetX;
03412         }
03413         else
03414         {
03415             Width = OffsetY;
03416         }
03417     }
03418     else if (PointerPos.x < br.lo.x && PointerPos.y > br.hi.y)
03419     {
03420         OffsetX = br.lo.x - PointerPos.x ;
03421         OffsetY = PointerPos.y - br.hi.y;
03422 
03423         if (OffsetX > OffsetY)
03424         {
03425             Width = OffsetX;
03426         }
03427         else
03428         {
03429             Width = OffsetY;
03430         }
03431     }
03432 
03433     // find top level of the node to contour
03434     Node * pParent = pNode->FindParent();
03435 
03436     BOOL bContourExists = FALSE;
03437     
03438     while (pParent)
03439     {
03440         if (pParent->IsKindOf(CC_RUNTIME_CLASS(NodeContourController)))
03441         {
03442             pNode = pParent;
03443             bContourExists = TRUE;
03444         }
03445 
03446         pParent = pParent->FindParent();
03447     }
03448 
03449     NodeListItem * pItem = new NodeListItem(pNode);
03450 
03451     NodeList.AddTail(pItem);
03452 
03453     // if a contour exists then change its width
03454     if (!bContourExists)
03455     {
03456         CreateContourParam Param(&NodeList, Steps, Width);
03457 
03458         OpDescriptor * pOpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpCreateContour));
03459 
03460         if (pOpDesc && Width > 0)
03461         {
03462             pOpDesc->Invoke(&Param);
03463         }
03464     }
03465     else
03466     {
03467         ChangeContourWidthParam Param(&NodeList, Width, FALSE);
03468 
03469         OpDescriptor * pOpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpChangeContourWidth));
03470 
03471         if (pOpDesc && Width > 0)
03472         {
03473             pOpDesc->Invoke(&Param);
03474         }
03475     }
03476 
03477     NodeList.DeleteAll();
03478     */
03479     
03480     return TRUE;
03481 
03482 }

BOOL OpBlendNodes::DoCreateBlender NodeRenderableInk pNodeStart,
INT32  PathIndexStart,
NodeRenderableInk pNodeEnd,
INT32  PathIndexEnd,
Node pContextNode,
AttachNodeDirection  AttachDir
[private]
 

This forms a blender object in the tree that can blend pRefStart->pNode to pRefEnd->pNode.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/10/94
Parameters:
pNodeStart = the start node to blend [INPUTS] PathIndexStart = index into start path, if applicable (-1 means not applicable) pNodeEnd = the end node to blend PathIndexEnd = index into end path, if applicable (-1 means not applicable) pContextNode = ptr to context for insertion of the blender AttachDir = how to attach the blender to the tree in relation to pContextNode
- [OUTPUTS]
Returns:
TRUE if all when well, FALSE otherwise

Definition at line 4421 of file blndtool.cpp.

04424 {
04425     ERROR2IF(pNodeStart == NULL,FALSE,"pNodeStart is NULL");
04426     ERROR2IF(pNodeEnd   == NULL,FALSE,"pNodeEnd   is NULL");
04427 
04428     // Work out how many paths will be passed back
04429     // The sum will be used to determine the final count for the progress bar
04430     BecomeA TestStart(BECOMEA_TEST, CC_RUNTIME_CLASS(NodePath));
04431     BecomeA TestEnd(BECOMEA_TEST, CC_RUNTIME_CLASS(NodePath));
04432     TestStart.ResetCount();
04433     TestEnd.ResetCount();
04434     pNodeStart->CanBecomeA(&TestStart);
04435     pNodeEnd  ->CanBecomeA(&TestEnd);
04436 
04437     // Create the hourglass with the correct final count.
04438     Progress Hourglass(_R(IDS_BLENDING), INT32(TestStart.GetCount() + TestEnd.GetCount()) );
04439 
04440     BOOL ok = FALSE;
04441     NodeBlender* pNodeBlender;
04442 
04443     ALLOC_WITH_FAIL(pNodeBlender,new NodeBlender,this);
04444     ok = (pNodeBlender != NULL);
04445 
04446     // If either of the indexes are -ve, make sure both are -ve
04447     if (PathIndexStart < 0 || PathIndexEnd < 0)
04448         PathIndexStart = PathIndexEnd = -1;
04449 
04450     if (ok) ok = DoInsertNewNode(pNodeBlender,pContextNode,AttachDir,FALSE,FALSE,FALSE,FALSE);
04451     if (ok) ok = pNodeBlender->Initialise(pNodeStart,pNodeEnd,PathIndexStart,PathIndexEnd,this,&Hourglass,FALSE);
04452     
04453     pRefStart->pNode = pNodeStart;
04454     pRefEnd->pNode = pNodeEnd;
04455     return (ok);
04456 }

BOOL OpBlendNodes::DoDeinitBlenders List BlenderList  )  [private]
 

This calls DeinitBlenders() on the given list, and creates an action that will call ReinitBlenders() on undo, and DeinitBlenders() on redo.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/11/94
Parameters:
BlenderList = list of blenders to deinit. [INPUTS]
- [OUTPUTS]
Returns:
-

Definition at line 3768 of file blndtool.cpp.

03769 {
03770     InitBlendersAction* pAction;
03771     BOOL ok = (InitBlendersAction::Init(this,&UndoActions,&BlenderList,TRUE,&pAction) != AC_FAIL);
03772 
03773     if (ok) DeinitBlenders(BlenderList);
03774 
03775     return (ok);
03776 }

BOOL OpBlendNodes::DoDrag BlendTool pBlendTool  ) 
 

This starts a drag that may lead to a blend. The DragFinished() method will do the hard work of blending if it can be done.

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

Definition at line 3121 of file blndtool.cpp.

03122 {
03123     // DMc
03124     // find out the active tool for the drag
03125     if (Tool::GetCurrent()->GetID() == TOOLID_BLEND)
03126     {
03127         pRefStart = BlendTool::GetPtrRefStart();
03128         pRefEnd   = BlendTool::GetPtrRefEnd();
03129     }
03130         
03131     ERROR2IF_PF(pRefStart == NULL || pRefEnd == NULL,FALSE,("Blend tool refs are NULL"));
03132 
03133     pRefEnd->PointerPos = pRefStart->PointerPos;
03134     RenderMyDragBlobs();
03135     m_pBlendTool = pBlendTool;
03136 
03137     // Tell the Dragging system that we need drags to happen
03138     StartDrag( DRAGTYPE_AUTOSCROLL );
03139 
03140     return TRUE;
03141 }

BOOL OpBlendNodes::DoReinitBlenders List BlenderList  )  [private]
 

This calls ReinitBlenders() on the given list, and creates an action that will call DeinitBlenders() on undo, and ReinitBlenders() on redo.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/11/94
Parameters:
BlenderList = list of blenders to deinit. [INPUTS]
- [OUTPUTS]
Returns:
-

Definition at line 3792 of file blndtool.cpp.

03793 {
03794     InitBlendersAction* pAction;
03795     BOOL ok = (InitBlendersAction::Init(this,&UndoActions,&BlenderList,FALSE,&pAction) != AC_FAIL);
03796 
03797     if (ok)
03798     {
03799         ok = ReinitBlenders(BlenderList);
03800         if (!ok) FailAndExecuteAllButLast();
03801     }
03802 
03803     return ok;
03804 }

BOOL OpBlendNodes::DoRemapBlend  )  [private]
 

This tries to remap a blend using the data held in pRefStart && pRefEnd. It asks the pNodeBlend object to try and remap the two paths by rotating the path elements so that the element at Index is the first element in the path.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
10/11/94
Parameters:
- (data is taken from pRefStart and pRefEnd member vars) [INPUTS]
- [OUTPUTS]
Returns:
TRUE if all when well, FALSE otherwise

Definition at line 3922 of file blndtool.cpp.

03923 {
03924     // What type of blend op are we doing?
03925     OpType = BLENDOPTYPE_REMAP;
03926 
03927     // Are we going mad? Better check our onions...
03928     ERROR3IF(pRefStart              == NULL,"pRefStart == NULL");
03929     ERROR3IF(pRefEnd                == NULL,"pRefEnd == NULL");
03930     ERROR3IF(pRefStart->pNode       == NULL,"pRefStart->pNode == NULL");
03931     ERROR3IF(pRefEnd  ->pNode       == NULL,"pRefEnd->pNode == NULL");
03932     ERROR3IF(pRefStart->pNodeBlend  == NULL,"pRefStart->pNodeBlend == NULL");
03933     ERROR3IF(pRefEnd  ->pNodeBlend  == NULL,"pRefEnd->pNodeBlend == NULL");
03934     ERROR3IF(pRefStart->pNodeBlend  != pRefEnd->pNodeBlend,"Start and end blend nodes not equal");
03935     ERROR3IF(pRefStart->RemapRef    != pRefEnd->RemapRef,"Start and end remap refs not equal");
03936     ERROR3IF(pRefStart->AStartNode  == pRefEnd->AStartNode,"Start and end AStartNode vals equal");
03937 
03938     BOOL ok = TRUE;
03939     RemapBlendAction* pAction;
03940     NodeBlend*  pNodeBlend  = pRefStart->pNodeBlend;
03941     UINT32      RemapRef    = pRefStart->RemapRef;
03942 
03943     DocCoord    PosStart    = pRefStart->PointerPos;
03944     DocCoord    PosEnd      = pRefEnd  ->PointerPos;
03945 
03946     if (!pRefStart->AStartNode)
03947     {
03948         // Swap the coords around
03949         DocCoord Temp = PosStart;
03950         PosStart = PosEnd;
03951         PosEnd = Temp;
03952     }
03953 
03954     ObjChangeFlags cFlags;
03955     ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,pNodeBlend,this);
03956     ok = pNodeBlend->AllowOp(&ObjChange);
03957 
03958     if (ok) ok = DoInvalidateNodeRegion(pRefStart->pNodeBlend,TRUE);
03959 
03960     if (ok) ok = RemapBlendAction::Init(this,&UndoActions,
03961                                         pNodeBlend,RemapRef,PosStart,PosEnd,
03962                                         &pAction) != AC_FAIL;
03963 
03964     if (ok)
03965     {
03966         ObjChange.Define(OBJCHANGE_FINISHED,cFlags,pNodeBlend,this);
03967         UpdateChangedNodes(&ObjChange);
03968     }
03969 
03970     return (ok);
03971 }

void OpBlendNodes::DragFinished DocCoord  PointerPos,
ClickModifiers  ClickMods,
Spread pSpread,
BOOL  Success,
BOOL  bSolidDrag
[virtual]
 

Ends the drag. Either creates a new grid or resizes GridClicked depending on the state of affairs when the drag started.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/10/94
Parameters:
PointerPos - The position of the mouse at the end of the drag [INPUTS] ClickMods - the key modifiers being pressed pSpread - The spread that the drag finished on Success - TRUE if the drag was terminated properly, FALSE if it was ended with the escape key being pressed
See also:
ClickModifiers

Reimplemented from Operation.

Definition at line 3206 of file blndtool.cpp.

03208 {
03209     ERROR3IF(pRefStart == NULL,"pRefStart is NULL");
03210     ERROR3IF(pRefEnd   == NULL,"pRefEnd is NULL");
03211     if ((pRefStart == NULL) || (pRefEnd == NULL)) return;
03212 
03213     // First Rub out the old box
03214     RenderMyDragBlobs();
03215 
03216     if (Success)
03217     {
03218         // Make sure that start and end refer to the same spread
03219         if (pSpread != pRefStart->pSpread)
03220             PointerPos = MakeRelativeToSpread(pRefStart->pSpread, pSpread, PointerPos);
03221 
03222         if (Tool::GetCurrent()->GetID() == TOOLID_BLEND)
03223         {
03224             BlendTool::UpdateRef(pRefEnd,pRefStart->pSpread,PointerPos);
03225             BlendTool::CheckNodeRemapping(pRefStart,pRefEnd);
03226         }
03227         else
03228         {
03229             FailAndExecute();
03230             EndDrag();
03231             delete this;
03232             return;
03233         }
03234     
03235         String_32 ProgString = _T("Calculating blend, please wait..");
03236         Progress Hourglass(&ProgString, -1, FALSE);
03237         Node* pNodeStart = pRefStart->pNode;
03238         Node* pNodeEnd   = pRefEnd  ->pNode;
03239 
03240         // make the start & end nodes point to any 'needs parent' compounds
03241         while (pNodeStart)
03242         {
03243             if (!pNodeStart->PromoteHitTestOnChildrenToMe() && pNodeStart->IsAnObject())
03244             {
03245                 pRefStart->pNode = (NodeRenderableInk *)pNodeStart;
03246             }
03247 
03248             pNodeStart = pNodeStart->FindParent();
03249         }
03250 
03251         while (pNodeEnd)
03252         {
03253             if (!pNodeEnd->PromoteHitTestOnChildrenToMe() && pNodeEnd->IsAnObject())
03254             {
03255                 pRefEnd->pNode = (NodeRenderableInk *)pNodeEnd;
03256             }
03257 
03258             pNodeEnd = pNodeEnd->FindParent();
03259         }
03260 
03261 
03262         BOOL ok = FALSE;
03263 
03264         if (pRefStart->pNode == NULL || pRefEnd->pNode == NULL)
03265         {
03266             // can't blend so exit
03267             FailAndExecute();
03268             EndDrag();
03269             delete this;
03270             return;
03271         }
03272         else if (pRefStart->pNode == pRefEnd->pNode)
03273         {
03274             if (pRefStart->RemapRef == pRefEnd->RemapRef && pRefStart->RemapRef > 0)
03275             {
03276                 // User's tried to remap two blend blobs
03277 
03278                 if (pRefStart->AStartNode != pRefEnd->AStartNode)
03279                     // The blobs lie on opposite ends of a blend
03280                     ok = DoRemapBlend();
03281             }
03282             else
03283             {
03284                 // can't blend so exit
03285                 FailAndExecute();
03286                 EndDrag();
03287                 delete this;
03288                 return;
03289             }
03290         }
03291         else if (IS_A(pRefStart->pNode,NodeBlend) &&
03292                  IS_A(pRefEnd  ->pNode,NodeBlend))
03293         {
03294             // Blending a blend to a blend
03295             ok = DoBlendBlendAndBlend();
03296         }
03297         else if (IS_A(pRefStart->pNode,NodeBlend) ||
03298                  IS_A(pRefEnd  ->pNode,NodeBlend))
03299         {
03300             // Blending an object to a blend, or a blend to an object
03301             ok = DoBlendBlendAndObject();
03302         }
03303         else
03304         {
03305             ok = DoBlendObjects();
03306         }
03307 
03308         if (!ok) 
03309             FailAndExecute();
03310 
03311         // Do this at the end so that the status bar text doesn't get wiped before the op begins
03312         if (Tool::GetCurrent()->GetID() == TOOLID_BLEND)
03313         {
03314             BlendTool::UpdateCursorAndStatus();
03315         }
03316         else
03317         {
03318             
03319         }
03320     }
03321     else
03322         FailAndExecute();
03323 
03324 
03325     // End the drag and the op
03326     EndDrag();
03327     End();
03328 }

void OpBlendNodes::DragPointerMove DocCoord  PointerPos,
ClickModifiers  ClickMods,
Spread pSpread,
BOOL  bSolidDrag
[virtual]
 

Pure virtual function which tells the operation that the mouse has moved.

virtual void Operation::DragPointerMove( DocCoord PointerPos, ClickModifiers ClickMods, Spread *pSpread, BOOL bSolidDrag)

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
5/7/93
Parameters:
PointerPos,: Position of the mouse pointer [INPUTS] ClickMods: Click modifiers
- [OUTPUTS]
Returns:
-

Errors: -

See also:
ClickModifiers

Reimplemented from Operation.

Definition at line 3161 of file blndtool.cpp.

03163 {
03164     // First Rub out the old box
03165     RenderMyDragBlobs();
03166 
03167     // Make sure that start and end refer to the same spread
03168     if (pSpread != pRefStart->pSpread)
03169         PointerPos = MakeRelativeToSpread(pRefStart->pSpread, pSpread, PointerPos);
03170 
03171     // DMc
03172     // find out the active tool for the drag
03173     if (Tool::GetCurrent()->GetID() == TOOLID_BLEND)
03174     {
03175         BlendTool::UpdateRef(pRefEnd,pRefStart->pSpread,PointerPos,FALSE);
03176         BlendTool::CheckNodeRemapping(pRefStart,pRefEnd);
03177         BlendTool::UpdateCursorAndStatus();
03178     }
03179     
03180     // Render the new drag box
03181     RenderMyDragBlobs();
03182 }

BOOL OpBlendNodes::GetNodeClosestToPoint NodeRenderableInk **  ppInk,
BOOL  StartBlend
 

when blending from two blends, this retrieves the node closest to the actual point where the blend began or ended

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
27/9/99
Parameters:
- [INPUTS] Outputs; ppInk, the starting node of the blend StartBlend - do we wish to find the start or end
Returns:
TRUE if successful , FALSE otherwise, or if we are not blending two blends.

Definition at line 4783 of file blndtool.cpp.

04784 {
04785 //  ERROR3IF_PF(pNodeBlendStart == NULL; "Nodeblend start is NULL");
04786 //  ERROR3IF_PF(pNodeBlendEnd == NULL; "Nodeblend end is NULL");
04787 
04788     DocCoord Point;
04789 //  Node* pStart = NULL;
04790 //  Node* pEnd = NULL;
04791 //  BOOL ok = FALSE;
04792     NodeBlend* pBlend = NULL;
04793     
04794     if (StartBlend)
04795     {
04796         Point = pRefStart->PointerPos;
04797         //ok = pNodeBlendStart->GetStartAndEndNodes(&pStart, &pEnd);
04798         pBlend = pNodeBlendStart;
04799     }
04800     else
04801     {
04802         Point = pRefEnd->PointerPos;
04803         //ok = pNodeBlendEnd->GetStartAndEndNodes(&pStart, &pEnd);
04804         pBlend = pNodeBlendEnd;
04805     }
04806     
04807     
04808     double ClosestDistance = 9999999999999.9;
04809     Node* pClosestNode = NULL;
04810     Node* pNode = pBlend->FindFirstChild();
04811     while (pNode != NULL)
04812     {
04813         // we are looking for inks but don't want blenders or nodeblendpaths
04814         // could do with some virtual functions here
04815         if (pNode->IS_KIND_OF(NodeRenderableInk) && 
04816             (!pNode->IS_KIND_OF(NodeBlender)) && 
04817             (!pNode->IS_KIND_OF(NodeBlendPath)))
04818         {
04819             DocRect Rect = ((NodeRenderableInk*)pNode)->GetBoundingRect();
04820             Coord Centre = (Coord)(Rect.Centre());
04821             double Distance = Point.Distance(Centre);
04822         
04823             if (Distance < ClosestDistance)
04824             {
04825                 pClosestNode = pNode;
04826                 ClosestDistance = Distance;
04827             }
04828         }
04829         pNode = pNode->FindNext();
04830     }
04831     if (pClosestNode != NULL)
04832     {
04833         *ppInk = (NodeRenderableInk*)pClosestNode;
04834         return TRUE;
04835     }
04836     else
04837     {
04838         ERROR3("Couldn't find a node close to point");
04839         return FALSE;
04840     }
04841 }

void OpBlendNodes::GetOpName String_256 OpName  )  [virtual]
 

The GetOpName fn is overridden so that we return back a description appropriate to the type of attribute that the operation applies.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/10/94
Parameters:
OpName = ptr to str to place op name in [INPUTS]
The undo string for the operation [OUTPUTS]
Returns:

Errors: -

See also:
-

Reimplemented from Operation.

Definition at line 4613 of file blndtool.cpp.

04614 { 
04615     switch (OpType)
04616     {
04617         case BLENDOPTYPE_NEW:
04618         case BLENDOPTYPE_BLENDANDOBJECT:
04619         case BLENDOPTYPE_BLENDANDBLEND:
04620             *OpName = String_256(_R(IDS_BLEND_UNDO));
04621             break;
04622 
04623         case BLENDOPTYPE_REMAP:
04624             *OpName = String_256(_R(IDS_REMAP_UNDO));
04625             break;
04626 
04627         default:
04628             break;
04629     }
04630 }  

OpState OpBlendNodes::GetState String_256 Description,
OpDescriptor
[static]
 

Find out the state of the operation at the specific time.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/10/94
Parameters:
Description - GetState fills this string with an approriate description [OUTPUTS] of the current state of the push tool
Returns:
The state of the operation, so that menu items (ticks and greying can be done properly

Definition at line 4590 of file blndtool.cpp.

04591 {
04592     OpState State;
04593     
04594     return State;
04595 }

BOOL OpBlendNodes::RecordBlenderInfo List BlenderList,
NodeBlend pNodeBlend
 

This scans the blenders in the given blend node, creating a BlenderInfoItem for each NodeBlender. Each BlenderInfoItem is placed on BlenderList.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/11/94
Parameters:
BlenderList = reference to a list to put all the blender info items on [INPUTS] pNodeBlend = the blend containing the blenders of interested
- [OUTPUTS]
Returns:
TRUE if all when well, FALSE otherwise

Definition at line 3874 of file blndtool.cpp.

03875 {
03876     ERROR3IF(pNodeBlend == NULL,"pNodeBlend == NULL");
03877     if (pNodeBlend == NULL) return FALSE;
03878 
03879     BOOL ok = TRUE;
03880 
03881     Node* pNode = pNodeBlend->FindFirstChild();
03882     while (pNode != NULL && ok)
03883     {
03884         if (IS_A(pNode,NodeBlender))
03885         {
03886             NodeBlender* pNodeBlender = (NodeBlender*)pNode;
03887             BlenderInfoItem* pItem = new BlenderInfoItem;
03888             ok = (pItem != NULL);
03889 
03890             if (ok)
03891             {
03892                 pItem->pNodeBlender = pNodeBlender;
03893                 pItem->pNodeStart   = pNodeBlender->GetNodeStart();
03894                 pItem->pNodeEnd     = pNodeBlender->GetNodeEnd();
03895 
03896                 ok = (pItem->pNodeStart != NULL && pItem->pNodeEnd != NULL);
03897             }
03898 
03899             if (ok) BlenderList.AddTail(pItem);
03900         }
03901         pNode = pNode->FindNext();
03902     }
03903 
03904     return ok;
03905 }

BOOL OpBlendNodes::Redo  )  [virtual]
 

Gets called whenever this operation is Redone.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
15/11/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
TRUE if all OK, FALSE otherwise

Errors: -

See also:
-

Reimplemented from Operation.

Definition at line 4715 of file blndtool.cpp.

04716 {
04717     // Pre-Redo stuff
04718     switch (OpType)
04719     {
04720         case BLENDOPTYPE_NEW:
04721         case BLENDOPTYPE_BLENDANDBLEND:
04722         case BLENDOPTYPE_REMAP:
04723         case BLENDOPTYPE_BLENDANDOBJECT:
04724         case BLENDOPTYPE_BLENDBLENDONPATH:
04725             break;
04726         default:
04727             ERROR3_PF(("Unknown blend OpType (%d)",OpType));
04728             break;
04729     }
04730     SelRange* pSel = GetApplication()->FindSelection();
04731     /*Node* pNode =*/ pSel->FindFirst();
04732 
04733     // Do the Redo
04734     SelOperation::Redo();
04735 
04736     // Post-Redo stuff
04737     switch (OpType)
04738     {
04739         case BLENDOPTYPE_NEW:
04740         case BLENDOPTYPE_REMAP:
04741             break;
04742 
04743         case BLENDOPTYPE_BLENDANDBLEND:
04744         /*
04745             // Check that we have a blend object
04746             ERROR3IF(pNodeBlendStart==NULL,"pNodeBlendStart == NULL");
04747             if (pNodeBlendStart == NULL) return TRUE;
04748             DeinitAndReinitBlend(pNodeBlendStart);
04749         */
04750             break;
04751 
04752         case BLENDOPTYPE_BLENDANDOBJECT:
04753         /*
04754             // Check that we have a blend object
04755             ERROR3IF(pNodeBlend==NULL,"pNodeBlend == NULL");
04756             if (pNodeBlend == NULL) return TRUE;
04757             DeinitAndReinitBlend(pNodeBlend);
04758         */
04759             break;
04760 
04761         default:
04762             break;
04763     }
04764 
04765     return TRUE;
04766 }

BOOL OpBlendNodes::ReinitBlenders List BlenderList  ) 
 

This scans the blenders, calling the Reinit() method for each of them. It uses the start and end node pointers gathered by RecordBlenderInfo() when calling Reinit().

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/11/94
Parameters:
BlenderList = reference to a list of blender info items [INPUTS]
- [OUTPUTS]
Returns:
TRUE if all when well, FALSE otherwise

Definition at line 3845 of file blndtool.cpp.

03846 {
03847     BOOL ok = TRUE;
03848     BlenderInfoItem* pItem = (BlenderInfoItem*) BlenderList.GetHead();
03849 
03850     while (pItem != NULL && ok)
03851     {
03852         ok = pItem->pNodeBlender->Reinit(pItem->pNodeStart,pItem->pNodeEnd);
03853         pItem = (BlenderInfoItem*) BlenderList.GetNext(pItem);
03854     }
03855 
03856     return (ok);
03857 }

BOOL OpBlendNodes::RemoveCompoundNodes CompoundNodeTreeFactoryList pList  )  [private]
 

Removes all compound nodes.

Author:
David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
Date:
4/8/99
Parameters:
The list to return the class factories necessary to regenerate any [INPUTS] compound nodes which have been removed
TRUE if all when well, FALSE otherwise [OUTPUTS]

Definition at line 3985 of file blndtool.cpp.

03986 {
03987 /*  Node * pNewStartNode = NULL;
03988     Node * pNewEndNode = NULL;
03989     
03990     if (!RemoveCompoundNodesFromNode(pRefStart->pNode, &pNewStartNode, NULL))
03991     {
03992     ERROR3("OpBlendNodes::RemoveCompoundNodes - Removal of compound nodes\n\
03993         from start node has failed");
03994     }
03995     
03996     if (!RemoveCompoundNodesFromNode(pRefEnd->pNode, &pNewEndNode, pList))
03997     {
03998     ERROR3("OpBlendNodes::RemoveCompoundNodes - Removal of compound nodes\n\
03999         from end node has failed");
04000     }
04001 
04002     pRefStart->pNode = (NodeRenderableInk *)pNewStartNode;
04003     pRefEnd->pNode   = (NodeRenderableInk *)pNewEndNode;
04004 
04005     GetApplication()->UpdateSelection();*/
04006     
04007     
04008     return TRUE;
04009 }

BOOL OpBlendNodes::RemoveCompoundNodesFromNode Node pNode,
Node **  pRetnNode,
CompoundNodeTreeFactoryList pList
[private]
 

Removes all compound nodes from the given node (i.e. unshadows and unbevels nodes).

Author:
David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
Date:
4/8/99
Parameters:
The node to remove all compound nodes from, and the return node to be [INPUTS] used in the blend as well as the list of compound node factories needed to regenerate the compounds nodes removed
The return node to use in the blend [OUTPUTS]
Returns:
TRUE if all when well, FALSE otherwise

Definition at line 4027 of file blndtool.cpp.

04029 {
04030     /*if (!pNode)
04031         return FALSE;
04032 
04033     if (!pRetnNode)
04034         return FALSE;
04035 
04036     // first, get the first parent in the hierarchy which has a PromoteHitTestOnChildrenToMe() set
04037     Node * pParent = pNode->FindParent();
04038 
04039     Node * pPromoteParent = NULL;
04040 
04041     *pRetnNode = pNode;
04042 
04043     while (pParent)
04044     {
04045         if (!pParent->PromoteHitTestOnChildrenToMe())
04046         {
04047             pPromoteParent = pParent;
04048         }
04049 
04050         pParent = pParent->FindParent();
04051     }
04052 
04053     // if we haven't found one - this means that there is one under me
04054     if (!pPromoteParent)
04055     {
04056         pPromoteParent = pNode;
04057     }
04058 
04059     List CompoundNodeList;
04060 
04061     // get the compound node list for the whole subtree
04062     BevelTools::GetAllNodesUnderNode(pPromoteParent, &CompoundNodeList, CC_RUNTIME_CLASS(NodeCompound));
04063 
04064     NodeListItem * pNodeToGroupItem = (NodeListItem *)CompoundNodeList.GetHead();
04065     Node         * pChildNode       = NULL;
04066     Node         * pNextChildNode   = NULL;
04067     NodeHidden   * pHidden          = NULL;
04068     Node * pChildNode2 = NULL;
04069 
04070     BOOL ok = TRUE;
04071 
04072     // first, invalidate all the compound node's regions
04073     while (pNodeToGroupItem && ok)
04074     {
04075         if (ok)
04076             ok = DoInvalidateNodeRegion((NodeRenderableBounded *)pNodeToGroupItem->pNode, TRUE);                
04077 
04078         pNodeToGroupItem = (NodeListItem *)CompoundNodeList.GetNext(pNodeToGroupItem);
04079     }           
04080 
04081     // now, run through all the compound nodes turning them into groups
04082     pNodeToGroupItem = (NodeListItem *)CompoundNodeList.GetHead();
04083 
04084     while (pNodeToGroupItem && ok)
04085     {
04086         if (pNodeToGroupItem->pNode->ShouldITransformWithChildren())
04087         {
04088             
04089             // find out how many children we have -
04090             // if there are more than 1 that don't need their parents then we need to group them
04091             // otherwise, just promote them
04092             INT32 NumChildren = 0;
04093 
04094             pChildNode2 = pNodeToGroupItem->pNode->FindFirstChild();
04095 
04096             while (pChildNode2)
04097             {
04098                 if (!pChildNode2->NeedsParent(pNodeToGroupItem->pNode) &&
04099                     !pChildNode2->IsAnAttribute()                      &&
04100                     !pChildNode2->IsNodeHidden()                       &&
04101                     pChildNode2->IsAnObject())
04102                 {
04103                     NumChildren ++;
04104                 }
04105 
04106                 pChildNode2 = pChildNode2->FindNext();
04107             }
04108 
04109             // localise the common attributes underneath the compound node
04110             if (ok)
04111                 ok = DoLocaliseCommonAttributes((NodeRenderableInk *)pNodeToGroupItem->pNode,
04112                 TRUE);              
04113             
04114             if (NumChildren > 1)
04115             {
04116                 // make a new group node and transfer all child nodes which don't need their
04117                 // parents into this group node
04118                 NodeGroup * pGroup = NULL;
04119                 ALLOC_WITH_FAIL(pGroup, new NodeGroup, this);
04120                 
04121                 *pRetnNode = pGroup;
04122                 
04123                 // get the first child
04124                 pChildNode = pNodeToGroupItem->pNode->FindFirstChild();
04125                 
04126                 while (pChildNode && ok)
04127                 {
04128                     pNextChildNode = pChildNode->FindNext();
04129                     
04130                     if (!pChildNode->NeedsParent(pNodeToGroupItem->pNode) &&
04131                         pChildNode->IsAnObject() && !pChildNode->IsNodeHidden())
04132                     {
04133                         if (ok) 
04134                             ok = DoMoveNode(pChildNode, pGroup, LASTCHILD);
04135                     }
04136                     // continuity check
04137                     else if (pChildNode->ShouldITransformWithChildren())
04138                     {
04139                         ERROR3("Found a child node which is a compound node !");
04140                     }
04141                     
04142                     pChildNode = pNextChildNode;
04143                 }
04144                 
04145                 // insert the group node into the tree, and hide the original node
04146                 
04147                 if (ok)
04148                 {
04149                     ok = DoInsertNewNode(   pGroup,
04150                         pNodeToGroupItem->pNode,
04151                         NEXT,
04152                         FALSE);
04153                 }
04154             }
04155             else
04156             {
04157                 // if there's only one node, then move it
04158                 // find the first node that NeedParent returns FALSE
04159                 pChildNode = pNodeToGroupItem->pNode->FindFirstChild();
04160 
04161                 while (pChildNode->NeedsParent(pNodeToGroupItem->pNode)  ||
04162                        pChildNode->IsAnAttribute()                       ||
04163                        pChildNode->IsNodeHidden()                        ||
04164                        !pChildNode->IsAnObject()
04165                        )
04166                 {
04167                     pChildNode = pChildNode->FindNext();
04168                 }
04169 
04170                 // ok, move the node & set the passback variable
04171                 if (ok)
04172                 {
04173                     ok = DoMoveNode(pChildNode, pNodeToGroupItem->pNode, NEXT);
04174 
04175                     *pRetnNode = pChildNode;
04176                 }
04177             }
04178 
04179             // before we hide the original, add its class factory to the list
04180             if (pList)
04181             {
04182                 CompoundNodeTreeFactory * pFactory = NULL;
04183                 
04184                 ((NodeCompound *)pNodeToGroupItem->pNode)->CreateCompoundNodeTreeFactory(&pFactory);
04185                 
04186                 if (pFactory)
04187                 {
04188                     pList->AddItem(pFactory);
04189                 }
04190             }
04191                 
04192             // hide the original
04193             if (ok)
04194             {
04195                 ok = DoHideNode ( pNodeToGroupItem->pNode,
04196                                   TRUE,
04197                                   &pHidden,
04198                                   TRUE);
04199             }
04200         }
04201 
04202         pNodeToGroupItem = (NodeListItem *)CompoundNodeList.GetNext(pNodeToGroupItem);
04203     }
04204 
04205     CompoundNodeList.DeleteAll();
04206     */
04207 
04208     return TRUE;
04209 }

void OpBlendNodes::RenderDragBlobs DocRect  Rect,
Spread pSpread,
BOOL  bSolidDrag
[virtual]
 

Draws an EORed rectangle defined by AnchorPoint and DragPoint.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/10/94
Parameters:
Rect - The region that needs the blobs to be drawn [INPUTS] pSpread - The spread that the drawing will happen on

Reimplemented from Operation.

Definition at line 4500 of file blndtool.cpp.

04501 {
04502     if (pRefStart->PointerPos == pRefEnd->PointerPos)
04503         return;
04504 
04505     // Get the scaled pixel size for the view.
04506     FIXED16 ScaledPixelWidth,
04507             ScaledPixelHeight;
04508     GetWorkingView()->GetScaledPixelSize(&ScaledPixelWidth, &ScaledPixelHeight);
04509 
04510     MILLIPOINT LineWidth = ScaledPixelWidth.MakeLong()*2;
04511     StockColour Colour = COLOUR_BLACK;
04512 
04513     if (pRefStart->RemapRef == pRefEnd->RemapRef && pRefStart->RemapRef > 0 &&
04514         pRefStart->AStartNode != pRefEnd->AStartNode)
04515     {
04516         Colour = COLOUR_RED;
04517         LineWidth += LineWidth;
04518     }
04519     else if ((pRefStart->pNode != NULL) &&
04520              (pRefEnd  ->pNode != NULL) &&
04521              (pRefStart->pNode != pRefEnd->pNode) &&
04522              (pRefStart->Index >= 0) &&
04523              (pRefEnd  ->Index >= 0))
04524     {
04525         Colour = COLOUR_RED;
04526         LineWidth += LineWidth;
04527     }
04528 
04529     // Inflate for the width of the line
04530     Rect.Inflate(LineWidth);
04531 
04532     RenderRegion* pRegion = DocView::RenderOnTop( &Rect, pSpread, UnclippedEOR );
04533 
04534     while ( pRegion != NULL )
04535     {
04536         // Set the line colour and Draw the rect
04537         pRegion->SetLineColour(Colour);
04538 
04539         // Draw the line
04540         pRegion->SetLineWidth(LineWidth);
04541         pRegion->DrawLine(pRefStart->PointerPos,pRefEnd->PointerPos);
04542 
04543         // Get the Next render region
04544         pRegion = DocView::GetNextOnTop( &Rect );
04545     }
04546 }

void OpBlendNodes::RenderMyDragBlobs  ) 
 

Draws an EORed rectangle defined by AnchorPoint and DragPoint.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/10/94
Parameters:
Rect - The region that needs the blobs to be drawn [INPUTS] pSpread - The spread that the drawing will happen on

Definition at line 4474 of file blndtool.cpp.

04475 {
04476     INT32 x0 = pRefStart->PointerPos.x;
04477     INT32 y0 = pRefStart->PointerPos.y;
04478     INT32 x1 = pRefEnd  ->PointerPos.x;
04479     INT32 y1 = pRefEnd  ->PointerPos.y;
04480 
04481     DocRect Rect = DocRect( min(x0,x1),min(y0,y1),max(x0,x1),max(y0,y1));
04482 
04483     RenderDragBlobs(Rect, pRefStart->pSpread, FALSE);
04484 }

virtual BOOL OpBlendNodes::SnappingDrag  )  [inline, virtual]
 

Reimplemented from Operation.

Definition at line 486 of file blndtool.h.

00486 { return FALSE; }

BOOL OpBlendNodes::Undo  )  [virtual]
 

Gets called whenever this operation is undone.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
Date:
15/11/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
TRUE if all OK, FALSE otherwise

Errors: -

See also:
-

Reimplemented from Operation.

Definition at line 4647 of file blndtool.cpp.

04648 {
04649     // Pre-undo stuff
04650     switch (OpType)
04651     {
04652         case BLENDOPTYPE_NEW:
04653         case BLENDOPTYPE_BLENDANDBLEND:
04654         case BLENDOPTYPE_REMAP:
04655         case BLENDOPTYPE_BLENDANDOBJECT:
04656         case BLENDOPTYPE_BLENDBLENDONPATH:
04657             break;
04658         default:
04659             ERROR3_PF(("Unknown blend OpType (%d)",OpType));
04660             break;
04661     }
04662 
04663     // Do the Undo
04664     SelOperation::Undo();
04665 
04666     // Post-undo stuff
04667     switch (OpType)
04668     {
04669         case BLENDOPTYPE_NEW:
04670         case BLENDOPTYPE_REMAP:
04671             break;
04672 
04673         case BLENDOPTYPE_BLENDANDBLEND:
04674         /*
04675             // Check that we have a blend object
04676             ERROR3IF(pNodeBlendStart==NULL,"pNodeBlendStart == NULL");
04677             ERROR3IF(pNodeBlendEnd  ==NULL,"pNodeBlendEnd == NULL");
04678             if (pNodeBlendStart == NULL || pNodeBlendEnd == NULL) return TRUE;
04679             DeinitAndReinitBlend(pNodeBlendStart);
04680             DeinitAndReinitBlend(pNodeBlendEnd);
04681         */
04682             break;
04683 
04684         case BLENDOPTYPE_BLENDANDOBJECT:
04685         /*
04686             // Check that we have a blend object
04687             ERROR3IF(pNodeBlend==NULL,"pNodeBlend == NULL");
04688             if (pNodeBlend == NULL) return TRUE;
04689             DeinitAndReinitBlend(pNodeBlend);
04690         */
04691             break;
04692 
04693         default:
04694             break;
04695     }
04696 
04697     return TRUE;
04698 }


Member Data Documentation

BlendTool* OpBlendNodes::m_pBlendTool [private]
 

Definition at line 543 of file blndtool.h.

OpBlendOpType OpBlendNodes::OpType [private]
 

Definition at line 536 of file blndtool.h.

NodeBlend* OpBlendNodes::pNodeBlend [private]
 

Definition at line 539 of file blndtool.h.

NodeBlend* OpBlendNodes::pNodeBlendEnd [private]
 

Definition at line 541 of file blndtool.h.

NodeBlend* OpBlendNodes::pNodeBlendStart [private]
 

Definition at line 540 of file blndtool.h.

BlendToolRef* OpBlendNodes::pRefEnd [private]
 

Definition at line 534 of file blndtool.h.

BlendToolRef* OpBlendNodes::pRefStart [private]
 

Definition at line 533 of file blndtool.h.


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