Range Class Reference

#include <range.h>

Inheritance diagram for Range:

CCObject SimpleCCObject ListRange SelRange List of all members.

Public Types

enum  CommonAttribResult { ATTR_COMMON, ATTR_NONE, ATTR_MANY }

Public Member Functions

 Range ()
 Creates an uninitialised range.
virtual ~Range ()
 Range (Node *First, Node *Last, RangeControl RangeControlFlgs)
 The purpose of this function is to create a node range.
 Range (Range &Range)
 Range copy constructor.
Rangeoperator= (Range &Range)
 Range = operator.
BOOL operator== (const Range &) const
 Test for equality of two ranges. Ranges are considered equal if they have the same flags and the same first & last nodes. SeeAlso Range::operator!=.
BOOL operator!= (const Range &) const
 Test for non-equality of two ranges. Ranges are considered equal if they have the same flags and the same first & last nodes. SeeAlso Range::operator==.
void SetRangeControl (RangeControl RangeControlFlgs)
 To set the range control for the range.
virtual NodeFindFirst (BOOL AndChildren=FALSE)
 The purpose of this function is to find the first node in a range.
virtual NodeFindLast ()
 The purpose of this function is to find the last node in a range. If the range was constructed with a NULL last node specifier then the range is scanned until the last node is found. If a non NULL last node was specified however the value of last is simply returned. It's existance is not verified !.
virtual NodeFindNext (Node *Previous, BOOL AndChildren=FALSE)
virtual NodeFindPrev (Node *pNode, BOOL AndChildren=FALSE)
virtual void Update (BOOL TellWorld=FALSE)
 To inform the SelRange that the selection has changed This invalidates the SelRange's selection-info cache so it will be recached when info is next requested.
virtual void FreshenCache ()
RangeControl GetRangeControlFlags () const
BOOL ForceRenderEORAll () const
UINT32 Count ()
BOOL Contains (Node *pNode, BOOL bAndChildren=FALSE)
 To determin whether a particular node is actually in the range list.
BOOL ContainsSelectInside ()
BOOL ConsistsOf (CCRuntimeClass *pccrtSearch, BOOL fIncludeDerivedClasses=TRUE)
 Determines whether the range consists entirely of the given class of object - or of derived classes of the given sort of object.
BOOL IsEmpty ()
 Determines whether the range is empty.
ListMakeListOfNodes (BOOL AndChildren=FALSE)
 This function will create and return a pointer to a list representing the objects in the range. It will return NULL if it couldn't create the list due to lack of memory. WARNING! This function creates objects which must be deleted by the calling routine. The last thing we need right now is another bunch of listitems appearing on shutdown.
void UpdateParentBoundsOfSelection (BOOL AndChildren=FALSE)
 This function updates the parent bounds of all selected objects. It is a lot more efficient than calling ChangeBounds on every node in the selection (cos it uses an algorithm!).
BOOL MakeAttributeComplete (BOOL CheckForDuplicates=TRUE, BOOL AndChildren=FALSE, BOOL IgnoreComplex=FALSE)
 This function calls NodeRenderableInk::MakeAttributeComplete on every Object in the selection. If we run out of memory then all changes are undone.
void NormaliseAttributes (BOOL AndChildren=FALSE, BOOL IgnoreComplex=FALSE)
 This function calls NodeRenderableInk::NormaliseAttributes on every Object in the selection.
BOOL CopyComponentDataToDoc (BaseDocument *pSrcDoc, BaseDocument *pDestDoc, BOOL AndChildren=FALSE)
 Asks all objects in the range (including their children) to copy across their component data to the specified destination document. The range must be in the destination doc.
void ResetXOROutlineRenderer (BOOL FlushTheCache=TRUE)
void RenderXOROutlinesOn (DocRect *ClipRect, Spread *pSpread, Matrix *Transform, Node *ClickedObject=NULL)
 Shared code used by the rotate, select, and scale tools to XOR the object(s) being dragged on/off screen. This function will do background rendering to XOR outlines onto screen (Successive calls will render more of the selection until it has all been rendered - it must therefore be called during mouse idle events to complete redraws).
void RenderXOROutlinesOff (DocRect *ClipRect, Spread *pSpread, Matrix *Transform)
 Shared code used by the rotate, select, and scale tools to XOR the object(s) being dragged onto screen. This function is used to remove XORed object outline blobs from the screen (obviously they will only be truly removed if you call it with the screen in the correct state). After the outlines have been rendered, the XOROutline renderer state is reset, so it is ready to begin a fresh pass of rendering blobs back on to the screen.
void RenderXOROutlinesToCatchUp (DocRect *ClipRect, Spread *pSpread, Matrix *Transform)
 Shared code used by the rotate, select, and scale tools to XOR the object(s) being dragged onto screen. This function is used when an area is redrawn during a drag (e.g. scrolling the window forces a redraw) to 'catch up' to the XOR outlines already present in other areas of the screen (i.e. it redraws everything that should already be on screen in unchanged areas into the invalidated area, so that XOR dragging can continue without leaving mess behind.
virtual DocRect GetBoundingRect ()
 To determine the bounds of all objects in the range.
virtual DocRect GetBoundingRectForEorDragging ()
 Same as for GetBoundingRect() but calls GetDragEorBoundingRect for all nodes.
virtual BOOL AllowOp (ObjChangeParam *pParam, BOOL SetOpPermissionState=TRUE, BOOL DoPreTriggerEdit=TRUE)
 Calls AllowOp() on all nodes in the range. If SetOpPermissionState is TRUE, the op permission state of all nodes in the range, plus all parents of these nodes, will have their op permission state changed.
BOOL GetCompoundObjectSet (ObjectSet *pCompoundObjectSet, BOOL ExcludeTextObjects=FALSE)
 This function traverses the range, and whenever it finds an object which is the child of a compound node it adds the compound node to the set.
BOOL AddTextStoryCompoundsForDel (ObjectSet *pCompoundObjectSet)
 This function is really a BODGE. When we are deleting a range which contains text chars, the deletion code may/may-not hide unselected TextLines as well. If this occurs then we will not be able to globally localise/factor out attributes on these TextLines.
Range::CommonAttribResult FindCommonAttribute (CCRuntimeClass *AttribClass, NodeAttribute **pAttribute, BOOL bRangeIsEffectsLevel=FALSE)
 To determine if all objects in the range share an attribute with the same value. You should only use this function if you need to find a common attribute value for a single attribute type. If you need to find common values for many types then FindCommonAttributes is much more efficient.
BOOL FindCommonAttributes (CommonAttrSet *CommonAttributeSet, BOOL CompoundAccuracy=FALSE)
 Finds all attributes which are common to the objects in the selection. There is a CommonAttributeItem for every attribute type (common or not). The Status field in this structure specifies if the attribute is common.
Range::CommonAttribResult FindCommonAttributeType (CCRuntimeClass *AttribType, CCRuntimeClass **pCommonType, BOOL ForceAttribType=FALSE, BOOL bRangeIsEffectsLevel=FALSE)
 To determine if all objects in the selection share attributes with the same type.
Range::CommonAttribResult FindCommonNonOptimisingAttr (CCRuntimeClass *pAttribClass, NodeAttribute **ppAttr)
 Do a search on the range, for non-optimising attrs. Because they are not optimised, we don't need to search up and down the tree for these attributes - we just look at the children of each node in the range.
BOOL FindBitmap (KernelBitmap **ppFoundBitmap=NULL, KernelBitmapRef **ppFoundBitmapRef=NULL, NodeBitmap **ppFoundNode=NULL, AttrFillGeometry **ppFoundFillAttribute=NULL)
 Find out if there is a valid bitmap in the selection and return useful information to the caller.
virtual void AttrsHaveChanged ()
 This function gets called to inform the range that attributes applied to its objects have, or may have changed. It deletes the Common attribute cache if one exists.
virtual void SetRenderable (BOOL bNewVis=FALSE)
virtual RangeCloneNodes (UINT32 timeLimit, BOOL bCloneOnTop=FALSE, BOOL bLightweight=FALSE, Layer *pDestLayer=NULL)
virtual void DeleteNodes ()
virtual void ForceRedrawView (DocView *pDocView, BOOL bReleaseCache=FALSE, BOOL bUseBlobRects=FALSE, BOOL bReleaseParentsOnly=FALSE)
virtual BOOL TransformNodes (TransformBase *Trans)
virtual void SetDraggedNodes (BOOL bNewState=FALSE)
virtual void CopyNodesContents (Range *pDestRange, BOOL bSetDragged=FALSE, BOOL bSetRenderable=FALSE)
virtual BOOL SetPromoteToParent (BOOL bNewValue)

Public Attributes

NodeNodeToRender

Protected Member Functions

CommonAttrSetGetCommonAttrCache ()
 This fn should be called to get a pointer to the range's common attribute cache. If the cache does not exist in the range then one is first created. Scope: private.
BOOL FindNextXOROutlineNode (Node **OriginalNode, DocRect *pClipRect)
 Shared code used by the rotate, select, and scale tools to XOR the object(s) being dragged on/off screen. This function is used to calculate the next object to be drawn; it attempts to draw the most significant objects first, so that minute detail is only drawn if there is enough time spare. This significantly enhances interactiveness of dragging.
BOOL CacheXOROutlineInfo (Spread *pSpread, Node *ClickedObject=NULL)
 This function is called before starting to XOR the objects onto screen to precalculate information pertaining to object significance (the order in which objects are drawn).
virtual NodeSmartFindNext (Node *pContext, BOOL AndChildren=FALSE, BOOL FindFirst=FALSE) const
virtual BOOL InRange (Node *pNode, BOOL AndChildren) const
 Private helper function for SmartFindNext. Tests whether the presented node is in the range according to the RangeControlFlags and two other locally presented flags.

Protected Attributes

CommonAttrSetpCommonAttribCache
RangeControl RangeControlFlags
NodeFirstNode
NodeLastNode
INT32 NumObjectsDrawn
INT32 RenderingPass
XOROutlineInfoStr XORInfo

Detailed Description

Definition at line 311 of file range.h.


Member Enumeration Documentation

enum Range::CommonAttribResult
 

Enumerator:
ATTR_COMMON 
ATTR_NONE 
ATTR_MANY 

Definition at line 387 of file range.h.


Constructor & Destructor Documentation

Range::Range  ) 
 

Creates an uninitialised range.

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

Errors: -

See also:
-

Definition at line 314 of file range.cpp.

00315 {
00316     FirstNode = LastNode = NULL;
00317     pCommonAttribCache = NULL;             // The common attribute cache only comes into
00318                                            // existance if the FindCommonAttribute functions
00319 }

Range::~Range  )  [virtual]
 

Definition at line 324 of file range.cpp.

00325 {
00326     // Destroy the CommonAttribSet if one exists
00327     if (pCommonAttribCache)
00328     {
00329         delete pCommonAttribCache; 
00330     }
00331 }

Range::Range Node First,
Node Last,
RangeControl  RangeControlFlgs
 

The purpose of this function is to create a node range.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/6/93
Parameters:
RangeControlFlags,: Specifies the selected status of the nodes to be included [INPUTS] in the range.
If RangeControlFlgs.Selected = TRUE All nodes with a selected status are included as members of the range.

If RangeControlFlgs.Unselected = TRUE All nodes with an unselected status are included as members in the range.

If both these flags are TRUE then all nodes from First to Last are included in the range.

If RangeControlFlgs.CrossLayer = TRUE The range may cross several layers; when the end of a layer is reached, the search will continue at the start of the following layer.

If RangeControlFlgs.IgnoreLockedLayers = TRUE locked layers are included in the search. Defaults to FALSE so locked layers ignored.

If RangeControlFlgs.IgnoreNoneRenderable = TRUE non-renderable nodes are included in the search. Defaults to FALSE so non-redenderable nodes ignored.

If RangeControlFlgs.IgnoreInvisibleLayers = TRUE Invisable layers are included in the search. Defaults to FALSE so invisible layers ignored.

First: The node from which to commence searching for members of a range. Last: The final node to search (must be a right sibling of First, or NULL). NULL specifies that all nodes from First to the end of First's sibling list (or end of the tree, if CrossLayer is TRUE) are to be searched for members of the range.

Parameters:
- [OUTPUTS]
Returns:
-

Errors: -

Definition at line 268 of file range.cpp.

00269 {
00270     // When the First node in a range is NULL the range is assumed to lie directly under
00271     // the surface of layers...
00272 /*
00273     if (First!=NULL)
00274     {
00275         ERROR3IF( RangeControlFlgs.Unselected
00276                     && !First->FindParent()->IsLayer()
00277                     && First != Last,
00278                     "Attempt to create an illegal range!"
00279                  );
00280     }
00281 */
00282 
00283     RangeControlFlags = RangeControlFlgs; 
00284     FirstNode = First; 
00285     LastNode = Last;
00286     pCommonAttribCache = NULL;             // The common attribute cache only comes into
00287                                            // existance if the FindCommonAttribute functions
00288                                            // are called on the range.
00289  
00290     // Initialise the XOR rendering stuff
00291     NodeToRender = NULL;
00292     ResetXOROutlineRenderer(TRUE);
00293 } 

Range::Range Range Rng  ) 
 

Range copy constructor.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
2/3/94
Parameters:
Rng,: The Range to copy [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
-

Definition at line 351 of file range.cpp.

00352 {
00353     // If the range is a sel range we must be sure that the range has been cached 
00354     Rng.FreshenCache();
00355 
00356     RangeControlFlags = Rng.RangeControlFlags;  
00357     FirstNode = Rng.FirstNode; 
00358     LastNode = Rng.LastNode;
00359     pCommonAttribCache = NULL;      
00360 }      


Member Function Documentation

BOOL Range::AddTextStoryCompoundsForDel ObjectSet pCompoundObjectSet  ) 
 

This function is really a BODGE. When we are deleting a range which contains text chars, the deletion code may/may-not hide unselected TextLines as well. If this occurs then we will not be able to globally localise/factor out attributes on these TextLines.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
6/6/95
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-
So what this function does is to add all parent TextStory compounds of any selected TextChars to the set, so that we can factor out on these.

Really any deletion of this sort should occur after the operation ends similar to group deletion in the no children case.But we have got to ship this product some time.

Returns:
Errors: -
See also:
-

Definition at line 3371 of file range.cpp.

03372 {
03373     Node* pCurrent = FindFirst();
03374     Node* pParent;
03375     while (pCurrent)
03376     {
03377         pParent = pCurrent->FindParent();
03378         ERROR3IF(!pParent, "object in range has no parent"); 
03379         if (pParent)
03380         { 
03381             if (IS_A(pParent, TextLine))
03382             {
03383                 pParent = pParent->FindParent(); 
03384                 ERROR3IF(!pParent, "parent of object in range has no parent"); 
03385                 ERROR3IF(!(IS_A(pParent, TextStory)), "Parent of TextLine is not a TextStory");
03386                 if (IS_A(pParent, TextStory))
03387                 {
03388                     // Add the story to the set
03389                     if (!(pCompoundObjectSet->AddToSet((NodeRenderableInk*)pParent)))
03390                         return FALSE;  
03391                 }
03392             }
03393         }
03394         pCurrent = pCurrent->FindNext(); 
03395     }
03396     return TRUE; 
03397 } 

BOOL Range::AllowOp ObjChangeParam pParam,
BOOL  SetOpPermissionState = TRUE,
BOOL  DoPreTriggerEdit = TRUE
[virtual]
 

Calls AllowOp() on all nodes in the range. If SetOpPermissionState is TRUE, the op permission state of all nodes in the range, plus all parents of these nodes, will have their op permission state changed.

Author:
Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 19/01/2000
Date:
6/02/95
Parameters:
pParam = describes the way an op wants to change the node [INPUTS] SetOpPermissionState = if TRUE the Op permission state of this node (and its parents) will be set according to the outcome of the call DoPreTriggerEdit = if TRUE then calls NameGallery::PreTriggerEdit. Must* be TRUE if the calling Op may make any nodes change their bounds, eg move, line width, cut. Use TRUE if unsure.
- [OUTPUTS]
Returns:
TRUE if one or more of the nodes in the range will allow the op to happen, FALSE otherwise
See also:
Node::AllowOp(),Node::GetOpPermission(),Node::SetOpPermission()

Definition at line 2349 of file range.cpp.

02350 {
02351     Node* pNode = FindFirst();
02352     BOOL result = FALSE,allowed;
02353 
02354     // we call AllowOp on all Nodes in the range, but never ask for a PreTriggerEdit on
02355     // each one, as if it is necessary then we deal with them en masse next.
02356     while (pNode != NULL)
02357     {
02358         Node* pNextNode = FindNext(pNode);
02359         allowed = pNode->AllowOp(pParam, SetOpPermissionState, FALSE);
02360         result  = result || allowed;
02361         pNode = pNextNode;
02362     }
02363 
02364     // if we're ok so far and were asked to do a PreTriggerEdit, then
02365     // determine whether the Op may change the bounds of some nodes.
02366     // If it may, then call NameGallery::PreTriggerEdit.
02367     if (result && DoPreTriggerEdit)
02368     {
02369         // if the Op is non-NULL then query its MayChangeNodeBounds() method.
02370         UndoableOperation* pChangeOp = pParam->GetOpPointer();
02371         if (pChangeOp != NULL && pChangeOp->MayChangeNodeBounds() && NameGallery::Instance())
02372         {
02373             result = NameGallery::Instance()->PreTriggerEdit(pChangeOp, pParam, this);
02374         }
02375     }
02376 
02377     return result;
02378 }

void Range::AttrsHaveChanged  )  [virtual]
 

This function gets called to inform the range that attributes applied to its objects have, or may have changed. It deletes the Common attribute cache if one exists.

void Range::AttrsHaveChanged()

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/12/94
See also:
SelRange::AttrsHaveChanged

Reimplemented in SelRange.

Definition at line 3412 of file range.cpp.

03413 {
03414     // if we are currently caching current attrs delete them 
03415     if (pCommonAttribCache)
03416     {
03417         delete pCommonAttribCache;
03418         pCommonAttribCache = NULL;
03419     }
03420 }

BOOL Range::CacheXOROutlineInfo Spread pSpread,
Node ClickedObject = NULL
[protected]
 

This function is called before starting to XOR the objects onto screen to precalculate information pertaining to object significance (the order in which objects are drawn).

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/2/94
Parameters:
Spread - The spread in which the drag is occurring [INPUTS] ClickedNode - The renderable node which the user clicked on to start the drag. (This object will always be drawn first. You may pass in NULL, but this will reduce the interactiveness of the dragging system)
Notes: See the selector and rotate tools for example code using this system.

Scope: private

See also:
SelRange::RenderXOROutlinesOn; SelRange::RenderXOROutlinesOff; SelRange::RenderXOROutlinesToCatchUp

Definition at line 1678 of file range.cpp.

01683 {
01684 
01685 #if !defined(EXCLUDE_FROM_RALPH)
01686 
01687     if (XORInfo.Cached)     // Have already cached the info
01688         return TRUE;
01689 
01690     BOOL bPromote = RangeControlFlags.PromoteToParent;
01691     RangeControlFlags.PromoteToParent = TRUE;
01692 
01693     ERROR2IF(pSpread == NULL,FALSE, "NULL Spread pointer passed to SelRange::CacheXOROutlineInfo");
01694     ERROR2IF(DocView::GetSelected() == NULL,FALSE, "DocView::GetSelected is NULL in SelRange::CacheXOROutlineInfo");
01695 
01696     DocView *pDocView = DocView::GetSelected();
01697     if (pDocView == NULL)
01698     {
01699         RangeControlFlags.PromoteToParent = bPromote;
01700         return FALSE;
01701     }
01702 
01703     XORInfo.SigRegion = pDocView->GetDocViewRect(pSpread);
01704     
01705     // Take screenrect or source bounding rect, whichever is smaller
01706     // (if the source rect passed in was NULL, just use screen coords)
01707     DocRect SourceRegion = GetBoundingRectForEorDragging();
01708     if (Count() > 0 &&
01709         XORInfo.SigRegion.Width() + XORInfo.SigRegion.Height() >
01710         SourceRegion.Width() + SourceRegion.Height())
01711     {
01712         XORInfo.SigRegion = SourceRegion;
01713         XORInfo.SigRegionIsScreen = FALSE;
01714     }
01715     else
01716     {
01717         // Convert SigRgn from Document to Spread coords
01718         pSpread->DocCoordToSpreadCoord(&XORInfo.SigRegion);
01719         XORInfo.SigRegionIsScreen = TRUE;
01720     }
01721 
01722 
01723     XORInfo.PrimeObject = NULL;
01724     if (ClickedObject != NULL)
01725     {
01726         // And remember which object must always be drawn first (the prime object)
01727         //  --but only if it's a renderable object that is part of the selection!
01728         BOOL Selected = ClickedObject->IsSelected();
01729 
01730         if (ClickedObject->ShouldITransformWithChildren())
01731         {
01732             Selected = TRUE;
01733         }
01734 
01735         if (!Selected)
01736         {
01737             // The object isn't selected, but perhaps it is in a selected group.
01738             // Search up through all parent nodes until we have determined if it
01739             // really is selected.
01740 
01741             Node *TheNode = (Node *) ClickedObject;
01742             do
01743             {
01744                 Selected = (TheNode->IsSelected());
01745                 TheNode = TheNode->FindParent();
01746             }
01747             while (!Selected && TheNode != NULL);
01748         }
01749     
01750         if (Selected && ClickedObject->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)))
01751             XORInfo.PrimeObject = ClickedObject;
01752     }
01753     else
01754     {
01755         
01756     }
01757 
01758     XORInfo.Cached = TRUE;
01759 
01760     RangeControlFlags.PromoteToParent = bPromote;
01761 
01762     return TRUE;
01763 #else
01764     return FALSE;
01765 #endif
01766 }

Range * Range::CloneNodes UINT32  timeLimit,
BOOL  bCloneOnTop = FALSE,
BOOL  bLightweight = FALSE,
Layer pDestLayer = NULL
[virtual]
 

Definition at line 3556 of file range.cpp.

03557 {
03558     Node* pNode;
03559     ListRange* pCloneRange = new ListRange();
03560     MonotonicTime timeClone;
03561 
03562     pNode = FindFirst();
03563     while (pNode && !timeClone.Elapsed(timeLimit))
03564     {
03565         // Make a copy of the current node
03566         Node* pCopy = NULL;
03567         BOOL bOK = FALSE;
03568 
03569 //      bOK = pNode->CloneNode(&pCopy, bLightweight);
03570         bOK = pNode->NodeCopy(&pCopy);
03571         if (!bOK)
03572             goto CloneError;
03573 
03574         // make sure that it is bounded
03575         ERROR2IF(!pCopy->IsBounded(), FALSE, "Object being pasted is not a NodeRenderableBounded"); 
03576 //      NodeRenderableBounded* BoundCopy = (NodeRenderableBounded*)pCopy;
03577 
03578         // Make sure the copy is not selected
03579         pCopy->SetSelected(FALSE);
03580 
03581         if (pDestLayer==NULL)
03582         {
03583             if (!bCloneOnTop)
03584             {
03585                 // Insert the copied node right alongside the original
03586                 pCopy->AttachNode(pNode, NEXT, FALSE, FALSE);
03587             }
03588             else
03589             {
03590                 Node* pTail = pNode->FindParent(CC_RUNTIME_CLASS(Layer))->FindLastChild(TRUE);
03591                 pCopy->AttachNode(pTail, NEXT, FALSE, FALSE);
03592             }
03593         }
03594         else
03595         {
03596             // Copy the node into a new target spread...
03597             Node* pTail = pDestLayer->FindLastChild(TRUE);
03598             if (pTail)
03599                 pCopy->AttachNode(pTail, NEXT, FALSE, FALSE);
03600             else
03601                 pCopy->AttachNode(pDestLayer, FIRSTCHILD, FALSE, FALSE);
03602         }
03603 
03604         // Add the copied node to the output ListRange
03605         pCloneRange->AddNode(pCopy);
03606 
03607         pNode = FindNext(pNode);
03608     }
03609 
03610 //  If we ran through all the nodes we needed to then pNode will be NULL and we can exit normally
03611     if (pNode==NULL)
03612         return pCloneRange;
03613 //  Else we aborted early and we must fall through to the tidy up routine and return NULL
03614 
03615 CloneError:
03616     pNode = pCloneRange->FindLast();
03617     while (pNode)
03618     {
03619         pNode->CascadeDelete();
03620         delete pNode;
03621 
03622         pNode = pCloneRange->FindPrev(pNode);
03623     }
03624 
03625     delete pCloneRange;
03626 
03627     return NULL;
03628 }

BOOL Range::ConsistsOf CCRuntimeClass pccrtSearch,
BOOL  fIncludeDerivedClasses = TRUE
 

Determines whether the range consists entirely of the given class of object - or of derived classes of the given sort of object.

BOOL Range::ConsistsOf(CCRuntimeClass* pccrtSearch, BOOL fIncludeDerivedClasses=TRUE)

Author:
Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/3/97
Parameters:
pccrtSearch The type of object to search for [INPUTS] fIncludeDerivedClasses If FALSE, the region must consist only of objects of class pccrtSearch.
If TRUE, the region must consist only of objects of pccrtSearch and derived classes.

This is used by the WebAddressDlg, which needs to know whether the selection consists entirely of text.

See also:
Range::FindFirst, Range::FindNext, SelRange::FindFirst, Range::FindNext

Definition at line 3448 of file range.cpp.

03449 {
03450     //Find the first node in the range, not including children
03451     Node* pThisNode=FindFirst(FALSE);
03452 
03453     //Now scan until we get to the end of the range
03454     while (pThisNode!=NULL)
03455     {
03456         BOOL ok=TRUE;
03457 
03458         //Is the object allowed to be a derived class of pccrtSearch?
03459         if (fIncludeDerivedClasses)
03460             //Yes. So test to see whether the node is a derived class of pccrtSearch
03461             ok=pThisNode->IsKindOf(pccrtSearch);
03462         else
03463             //No. So test whether the node is exactly the same class as pccrtSearch
03464             ok=(pThisNode->GetRuntimeClass()==pccrtSearch);
03465 
03466         //If the node wasn't of the appropriate class, return FALSE now.
03467         if (!ok)
03468             return FALSE;
03469 
03470         //Get the next object to test
03471         pThisNode=FindNext(pThisNode, FALSE);
03472     }
03473 
03474     //We've reached the end of the range and all the nodes were of the class we wanted.
03475     //So return TRUE
03476     return TRUE;
03477 
03478 }

BOOL Range::Contains Node pLookFor,
BOOL  bAndChildren = FALSE
 

To determin whether a particular node is actually in the range list.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
3/5/95
Parameters:
pLookFor = a pointer to a node to look for. [INPUTS] bAndChildren - Test for node being in subtree of member of range
- [OUTPUTS]
Returns:
TRUE if the range contains this particular node FALSE if the node is not held within this range

Errors: -

Definition at line 731 of file range.cpp.

00732 {
00733     Node* pNode=FindFirst();
00734     while (pNode)
00735     {
00736         if (pNode==pLookFor)
00737             return TRUE;
00738 
00739         if (bAndChildren && pNode->IsNodeInSubtree(pLookFor))
00740             return TRUE;
00741 
00742         pNode=FindNext(pNode);
00743     }
00744     return FALSE;
00745 }

BOOL Range::ContainsSelectInside  ) 
 

Definition at line 765 of file range.cpp.

00766 {
00767 #if !defined(EXCLUDE_FROM_RALPH)
00768     // Preconditions
00769     ERROR2IF(this==NULL,FALSE,"ContainsSelectInside called on NULL pointer");
00770 
00771     // Implementation
00772     Node* pNodeInRange = FindFirst();
00773     Node* pParent;
00774     while (pNodeInRange)                                // While there's a node in the range
00775     {
00776         pParent = pNodeInRange->FindParent();           // Look at it's parent node
00777         
00778         // DMc - added promotehittestonchildrentome test to eliminate the 'inside' setting
00779         // for nodes should as shadows, contours, bevels etc
00780         while (pParent)
00781         {
00782             if (pParent->IsAnObject() && pParent->IsParentOfSelected() &&
00783                 pParent->PromoteHitTestOnChildrenToMe())    // If that's marked parent of sel
00784                 return TRUE;                                // Then this node is "inside" so return TRUE
00785 
00786             pParent = pParent->FindParent();
00787         }
00788 
00789         pNodeInRange = FindNext(pNodeInRange);          // Else, keep scanning members of range
00790     }
00791 #endif
00792     return FALSE;                                       // If no more in range, none were "inside"
00793 }

BOOL Range::CopyComponentDataToDoc BaseDocument pSrcDoc,
BaseDocument pDestDoc,
BOOL  AndChildren = FALSE
 

Asks all objects in the range (including their children) to copy across their component data to the specified destination document. The range must be in the destination doc.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
9/9/94
Parameters:
pSrcDoc,: the document from where all nodes in the range were copied [INPUTS] pDestDoc - where to copy all the nodes to.
Returns:
FALSE if we are unable to copy the data accross. In this situation AbortComponentCopy is called on the CurrentDocument.

Errors: -

See also:
-

Definition at line 1443 of file range.cpp.

01446 {
01447     // Scan all nodes in the range
01448     Node* Scan = FindFirst(AndChildren);
01449     while (Scan != NULL)
01450     {
01451         Node* Root = Scan;
01452         Node* Current = Root->FindFirstDepthFirst();
01453         // This depth first search was written BEFORE the AndChildren flag was passed in.
01454         // It could probably be removed now...
01455         while (Current != NULL)
01456         {
01457             // Ask the current node if it would copy it's data to the relevant DocComponents
01458             if (Current->IsKindOf(CC_RUNTIME_CLASS(NodeRenderable)))
01459             {
01460                 if (!((NodeRenderable*)Current)->CopyComponentData(pSrcDoc, pDestDoc))
01461                 {
01462                     // No luck
01463                     pDestDoc->AbortComponentCopy(); // Cancel all data which has been copied
01464                     return FALSE; 
01465                 }
01466             }
01467 
01468             Current = Current->FindNextDepthFirst(Root); 
01469         }
01470         Scan = FindNext(Scan, AndChildren);
01471     }
01472     return TRUE; // Success         
01473 } 

void Range::CopyNodesContents Range pDestRange,
BOOL  bSetDragged = FALSE,
BOOL  bSetRenderable = FALSE
[virtual]
 

Definition at line 3790 of file range.cpp.

03791 {
03792     Node* pSrcNode;
03793     Node* pDestNode;
03794     NodeRenderable* pSrcRendNode;
03795     NodeRenderable* pDestRendNode;
03796 
03797 //  ENSURE(GetCount()==pDestRange->GetCount(), "Ranges differ too much");
03798 
03799     pSrcNode = FindFirst(FALSE);
03800     pDestNode = pDestRange->FindFirst(FALSE);
03801     while (pSrcNode && pDestNode)
03802     {
03803         ENSURE(pSrcNode->GetRuntimeClass() == pDestNode->GetRuntimeClass(), "Ranges differ unexpectedly");
03804         if (pSrcNode->IsBounded() && pSrcNode->GetRuntimeClass() == pDestNode->GetRuntimeClass())
03805         {
03806             pSrcRendNode = (NodeRenderable*)pSrcNode;
03807             pDestRendNode = (NodeRenderable*)pDestNode;
03808 
03809             // Do the children because PolyCopyNodeContents can't sensibly be recursive
03810             Node* pSrcSubNode = pSrcRendNode->FindFirstDepthFirst();
03811             while (pSrcSubNode && (pSrcSubNode->IsNodeHidden() || pSrcSubNode->IsDragged()))                    // URGH
03812                 pSrcSubNode = pSrcSubNode->FindNextDepthFirst(pSrcRendNode);    // URGH
03813 
03814             Node* pDestSubNode = pDestRendNode->FindFirstDepthFirst();
03815             while (pDestSubNode && (pDestSubNode->IsNodeHidden() || !pDestSubNode->IsDragged()))                // URGH
03816                 pDestSubNode = pDestSubNode->FindNextDepthFirst(pDestRendNode); // URGH
03817 
03818             while (pSrcSubNode && pDestSubNode)
03819             {
03820                 if (pSrcSubNode->IsNodeRenderableClass()
03821                     && pDestSubNode->IsNodeRenderableClass())
03822                 {
03823                     ENSURE(pSrcSubNode->GetRuntimeClass() == pDestSubNode->GetRuntimeClass(), "Ranges differ unexpectedly");
03824                     ((NodeRenderable*)pSrcSubNode)->PolyCopyNodeContents((NodeRenderable*)pDestSubNode);
03825                     pDestSubNode->SetSelected(FALSE);
03826                     pDestSubNode->SetParentOfSelected(FALSE);
03827                 }
03828 
03829                 pSrcSubNode = pSrcSubNode->FindNextDepthFirst(pSrcRendNode);
03830                 while (pSrcSubNode && (pSrcSubNode->IsNodeHidden() || pDestSubNode->IsDragged()))                   // URGH
03831                     pSrcSubNode = pSrcSubNode->FindNextDepthFirst(pSrcRendNode);    // URGH
03832 
03833                 pDestSubNode = pDestSubNode->FindNextDepthFirst(pDestRendNode);
03834                 while (pDestSubNode && (pDestSubNode->IsNodeHidden() || !pDestSubNode->IsDragged()))                // URGH
03835                     pDestSubNode = pDestSubNode->FindNextDepthFirst(pDestRendNode); // URGH
03836             }
03837 
03838 //          if (bSetDragged && pDestRendNode->IsBounded())
03839 //              ((NodeRenderableBounded*)pDestRendNode)->SetDraggedState(TRUE, TRUE);
03840             if (bSetDragged)
03841                 pDestRendNode->SetDraggedState(TRUE, TRUE);
03842             if (bSetRenderable)
03843                 pDestRendNode->SetRender(TRUE, TRUE);
03844 
03845         }
03846 
03847         pSrcNode = FindNext(pSrcNode, FALSE);
03848         pDestNode = pDestRange->FindNext(pDestNode, FALSE);
03849     }
03850 }

UINT32 Range::Count  ) 
 

Reimplemented in SelRange.

Definition at line 699 of file range.cpp.

00700 {
00701     UINT32 count = 0;
00702     Node* pNode;
00703 
00704     pNode = FindFirst();
00705     while (pNode)
00706     {
00707         count++;
00708         pNode = FindNext(pNode);
00709     }
00710 
00711     return(count); 
00712 }

void Range::DeleteNodes  )  [virtual]
 

Definition at line 3648 of file range.cpp.

03649 {
03650     Node* pNode;
03651     Node* pNext;
03652 
03653     pNode = FindFirst();
03654     while (pNode)
03655     {
03656         pNext = FindNext(pNode);
03657 
03658         pNode->CascadeDelete();
03659         delete pNode;
03660 
03661         pNode = pNext;
03662     }
03663 }

BOOL Range::FindBitmap KernelBitmap **  ppFoundBitmap = NULL,
KernelBitmapRef **  ppFoundBitmapRef = NULL,
NodeBitmap **  ppFoundNode = NULL,
AttrFillGeometry **  ppFoundFillAttribute = NULL
 

Find out if there is a valid bitmap in the selection and return useful information to the caller.

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/1/97 Changed: Phil, 20/01/2004: Moved from PlugInUndoOp static to be member function of range !!!!!!!!!
Parameters:
None [INPUTS]
if supplied, it will return a pointer to the bitmap that is in the selection [OUTPUTS] if supplied, it will return a pointer to the bitmap ref that is in the selection if supplied, it will return a pointer to the node bitmap that is in the selection if supplied, it will return a pointer to the fill geometry that is in the selection
Returns:
TRUE if succeeded in finding a bitmap, FALSE if not
See also:
-

Definition at line 7229 of file range.cpp.

07233 {
07234     KernelBitmap * pBitmap = NULL;
07235     KernelBitmapRef* pBitmapRef = NULL;
07236 
07237     // Assume nothing found
07238     if (ppFoundBitmap)          *ppFoundBitmap = NULL;
07239     if (ppFoundBitmapRef)       *ppFoundBitmapRef = NULL;
07240     if (ppFoundNode)            *ppFoundNode = NULL;
07241     if (ppFoundFillAttribute)   *ppFoundFillAttribute = NULL;
07242 
07243     Node* pCurrentNode = FindFirst(); 
07244 
07245     if (pCurrentNode != NULL) // No nodes selected so End
07246     {
07247         // Do all bitmaps. OK this should pick up the fill as well. Never mind
07248         while (pCurrentNode != NULL)
07249         {
07250             if  (pCurrentNode->IsABitmap())
07251             {
07252                 NodeBitmap* pNodeBmp = (NodeBitmap*)pCurrentNode;
07253                 pBitmap = pNodeBmp->GetBitmap();
07254                 pBitmapRef = pNodeBmp->GetBitmapRef();
07255                 // If the caller wanted it, return the found bitmap to them
07256                 if (ppFoundBitmap)
07257                     *ppFoundBitmap = pBitmap;
07258                 // ditto found bitmap ref
07259                 if (ppFoundBitmapRef)
07260                     *ppFoundBitmapRef = pBitmapRef;
07261                 // ditto found node
07262                 if (ppFoundNode)
07263                     *ppFoundNode = pNodeBmp;
07264                 // ditto found fill attribute
07265                 if (ppFoundFillAttribute)
07266                     *ppFoundFillAttribute = NULL;
07267 
07268                 return TRUE;
07269             }
07270 
07271             pCurrentNode = FindNext(pCurrentNode);
07272         }
07273 
07274     } 
07275 
07276     if (ppFoundFillAttribute)
07277     {
07278         // Find the first Fill Attribute in the selection
07279         AttrFillGeometry* pAttrNode = AttrFillGeometry::FindFirstSelectedAttr();
07280 
07281         while (pAttrNode != NULL)
07282         {
07283             if (pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrBitmapColourFill)))
07284             {
07285                 pBitmap = pAttrNode->GetBitmap();
07286                 pBitmapRef = pAttrNode->GetBitmapRef();
07287                 // If the caller wanted it, return the found bitmap to them
07288                 if (ppFoundBitmap)
07289                     *ppFoundBitmap = pBitmap;
07290                 // ditto found bitmap ref
07291                 if (ppFoundBitmapRef)
07292                     *ppFoundBitmapRef = pBitmapRef;
07293                 // ditto found node
07294                 if (ppFoundNode)
07295                     *ppFoundNode = NULL;
07296                 // ditto found fill attribute
07297                 if (ppFoundFillAttribute)
07298                     *ppFoundFillAttribute = pAttrNode;
07299 
07300                 return TRUE;
07301             }
07302 
07303             // Check the next fill
07304             pAttrNode = AttrFillGeometry::FindNextSelectedAttr();
07305         }
07306     }
07307 
07308     return FALSE;
07309 }

Range::CommonAttribResult Range::FindCommonAttribute CCRuntimeClass AttribType,
NodeAttribute **  pAttribute,
BOOL  bRangeIsEffectsLevel = FALSE
 

To determine if all objects in the range share an attribute with the same value. You should only use this function if you need to find a common attribute value for a single attribute type. If you need to find common values for many types then FindCommonAttributes is much more efficient.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/6/94
Parameters:
AttribType,: The Type of attribute to find - defined in the virtual [INPUTS] GetAttributeType method of NodeAttribute
pAttribute,: Depends on the return value, see below [OUTPUTS]
Returns:
ATTR_COMMON:There is a common attribute pAttribute will point to an instance of it
ATTR_NONE: There is no selection, or none of the selected objects require the attribute. If there is a document pAttribute will point to the current attribute for the selected tool, this will be the value which is usually displayed in this situation. else pAttribute will be NULL No value will usually be displayed in this situation

ATTR_MANY: There is no common attribute, pAttribute will be NULL

Returns:
Errors: - Scope: private
See also:
Range::FindCommonAttributes

Definition at line 2787 of file range.cpp.

02790 {
02791 #if !defined(EXCLUDE_FROM_RALPH)
02792     CommonAttribResult Result;
02793     *pAttribute = NULL;
02794 
02795     // Before we go away and do any hard work, let's see if the value that the user
02796     // is after is already cached.
02797     CommonAttrSet* pCommonAttrCache = GetCommonAttrCache(); 
02798     if (pCommonAttrCache)
02799     {
02800         // are the AttrTypes common details cached 
02801         CommonAttributeItem* pAttrItem = pCommonAttrCache->FindAttrItem(AttribType);
02802         if (pAttrItem)
02803         {
02804             // Aren't we lucky
02805             *pAttribute = pAttrItem->pAttr;
02806             return (pAttrItem->Status);
02807         }   
02808     }
02809     // else the cache could not be created. We shall just have to work without one 
02810 
02811     // Scan each selected node until we get a result
02812     NodeRenderableInk* n = NULL;
02813     NodeRenderableInk* pn = (NodeRenderableInk*)FindFirst(); 
02814     
02815     NodeAttribute* AppliedAttr; // The attribute applied and used by n.
02816 
02817     while (pn != NULL)
02818     {
02819         n = pn;
02820         if (bRangeIsEffectsLevel)
02821             n = pn->GetObjectToApplyTo(AttribType);
02822 
02823         AppliedAttr = NULL;
02824         if (n->IsCompound())
02825         {
02826             // Determine if all objects within the  compound object share a common attribute
02827             
02828             ERROR3IF(!n->IsAnObject(), "Item in range is not a NodeRenderableInk"); 
02829 
02830             // We may sometime later decide that this attribute is not applied to the 
02831             // compound.
02832             AppliedAttr = ((NodeRenderableInk*)n)->FindAppliedAttribute(AttribType);
02833 
02834             if (AppliedAttr->IsADefaultAttr() && !((NodeRenderableInk*)n)->IsValidEffectAttr(AppliedAttr))   // else AppliedAttr will be correct
02835             {
02836                 // This can mean one of three things
02837                 // a. All nodes in the compound which require the attribute share the default 
02838                 //    attribute
02839                 // b. Nodes requiring attribute have more than one attribute value. i.e. 
02840                 //    the default attribute is not a common attribute.
02841                 // c. No nodes in the group require the attribute
02842 
02843                 // Flag which is set to TRUE when we know that AttribType is required by the 
02844                 // the compound
02845                 BOOL AttribRequiredInCompound = FALSE; 
02846 
02847                 // Scan the compound depth first
02848                 Node* Current = n->FindFirstDepthFirst();
02849                                     
02850                 while(Current != n)  // Stop when we hit the compound (used to be NULL, this was a bug)
02851                 {
02852                     if (!AttribRequiredInCompound)
02853                     {
02854                         // Determine if the attribute is required by the current node
02855                         if (Current->IsAnObject())
02856                         {
02857                             AttribRequiredInCompound = ((NodeRenderableInk*)Current)
02858                                 ->RequiresAttrib(AttribType);   
02859                         }
02860                     }
02861                     if (Current->IsAnAttribute())
02862                     {
02863                         if (((NodeAttribute*)Current)->GetAttributeType() == AttribType)
02864                         {
02865                             // This means that the compound must have more than one
02866                             // attribute value, because if this attribute was common to
02867                             // all objects requiring the attribute in the compound then
02868                             // it would have been found in the child attribute block !
02869                             (*pAttribute) = NULL; // Nothing useful to return here
02870                             Result = ATTR_MANY;
02871                             goto End;        
02872                         }
02873                     }
02874                     Current = Current->FindNextDepthFirst(n);       
02875                 }
02876                 if (!AttribRequiredInCompound)
02877                 {
02878                     AppliedAttr = NULL; // Compound has no applied attribute !
02879                 }
02880                 // else attribute not required in compound so ignore it. 
02881             }
02882         }
02883         else
02884         {
02885             // Does n require attribute AttribType to render itself ?
02886             if (n->RequiresAttrib(AttribType))
02887             {
02888                 // n needs to have attribute AttribType defined so that it can render properly
02889                 // scan from the last child of n, up the tree in reverse render order until we 
02890                 // find an instance of an AttribType attribute.
02891                 AppliedAttr = n->FindAppliedAttribute(AttribType);
02892                 
02893             }
02894             // else n does not require the attribute so it is ignored
02895         }
02896         
02897         // Determine if the attribute is common
02898 
02899         if (AppliedAttr != NULL)
02900         {
02901 
02902             if ((*pAttribute) == NULL) // This is the first instance of the attribute found
02903             {
02904                 (*pAttribute) = AppliedAttr;    
02905             }
02906             else
02907             {
02908                 // If the attribute found is not the same as all others found then 
02909                 // we know that there is no common attribute, so there is no point in
02910                 // searching any further
02911             
02912                 if (!((**pAttribute) == (*AppliedAttr)))
02913                 {
02914                     (*pAttribute) = NULL; // Nothing useful to return here
02915                     Result = ATTR_MANY;
02916                     goto End;
02917                 }
02918                 // else the Applied attribute is the same as all others found so carry
02919                 // on searching.
02920             }
02921         }
02922          
02923         pn = (NodeRenderableInk*)FindNext(pn); // Obtain the next selected object
02924     }
02925 
02926     // Ok weve finished the scan, so either no objects require the attribute, or there
02927     // is a common attribute value shared by all objects that do require the attribute
02928     if ((*pAttribute) != NULL)
02929     {
02930         Result = ATTR_COMMON;
02931         // pAttribute will point to an instance of the common attribute
02932     }
02933     else
02934     {
02935         Result = ATTR_NONE;
02936 
02937         Document* SelectedDoc = Document::GetSelected();
02938     
02939         // If there is a selected document then pAttribute is set to the current attribute
02940         // for the selected tool.
02941         if (SelectedDoc != NULL)
02942         {
02943             (*pAttribute) = SelectedDoc->GetAttributeMgr().GetSelToolCurrentAttribute(AttribType);
02944         }
02945         // else pAttribute will be NULL 
02946     }
02947 
02948     End:
02949 
02950     // Add the result to the Common attribute cache
02951     if (pCommonAttrCache)
02952     {
02953         CommonAttributeItem* pNewAttrItem = new CommonAttributeItem(AttribType);
02954         if (pNewAttrItem)
02955         {
02956             // Add the attribute type results to the cache, taking a copy of the attribute
02957             if (!(pNewAttrItem->InitSafeAttrItem(AttribType, *pAttribute, Result)))
02958                 delete pNewAttrItem;
02959             else
02960                 pCommonAttrCache->AddTail(pNewAttrItem); // Add to the cache    
02961         } // else we failed to allocate memory for the item, we can live with this.
02962     }
02963     // If we have a Common
02964     return Result;
02965 #else
02966     return ATTR_NONE;
02967 #endif
02968 }

BOOL Range::FindCommonAttributes CommonAttrSet CommonAttributeSet,
BOOL  CompoundAccuracy = FALSE
 

Finds all attributes which are common to the objects in the selection. There is a CommonAttributeItem for every attribute type (common or not). The Status field in this structure specifies if the attribute is common.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
3/8/94
Parameters:
CommonAttributeSet:An OPTIONAL subset of attribute types to find common attributes [INPUTS] for. Use the CommonAttrSet::AddTypeToSet fn to build up a subset of attribute types. If this set is empty on entry then the function will find common attributes for ALL attribute types.
Handy hint: If you repeatedly need to find common attribute values for a specific set of attribute types eg. for a tool's InfoBar, then you only need to create the CommmonAttributeSet once (during initialisation).

CompoundAccuracy: TRUE => Accurate results with compound objects. This requires more work. This is important in some cases eg. PasteAttributes.

Parameters:
The CommonAttributeSet containing a CommonAttributeItem for each attribute Type [OUTPUTS] (or a subset of attribute types - see above). These define the status of each attribute type (see below). Use CommonAttrSet::FindAttrItem to locate a particular attribute type in this set; the order of the items in the set will have changed.
Returns:
TRUE if successful, FALSE otherwise (out of memory)
Status field values

ATTR_COMMON:There is a common attribute pAttr will point to an instance of it

ATTR_NONE: There is no selection, or none of the selected objects require the attribute. If there is a document pAttr will point to the current attribute for the selected tool, this will be the value which is usually displayed in this situation. else pAttr will be NULL No value will usually be displayed in this situation

ATTR_MANY: There is no common attribute. In this situation 'Many' will usually be displayed in this situation.

Returns:
Errors: - Scope: private
See also:
Range::FindCommonAttribute

InternalClipboard::GetCommonAttributes

CommonAttrSet

CommonAttrSet::FindAttrItem

Definition at line 2499 of file range.cpp.

02501 {
02502 #if !defined(EXCLUDE_FROM_RALPH)
02503 
02504     ERROR3IF(!CommonAttributeSet, "Common Attribute Set is NULL"); 
02505     
02506     BOOL DelCommonAttrSet = FALSE; // If we run out of memory whilst processing then 
02507                                    // we want to leave the CommonAttributeSet with 
02508                                    // the same number of items it entered with.
02509               
02510     // Has the user specified a subset of attributes ?
02511     if (CommonAttributeSet->IsEmpty())
02512     {
02513         // Place all attributes in the CommonAttributeSet
02514         if (!(CommonAttributeSet->AddAllTypesToSet()))
02515         {
02516             return FALSE; // ERROR already called 
02517         }
02518         DelCommonAttrSet = TRUE; // Delete all items in set if we fail
02519     }
02520 
02521     // Initialise all CommonAttributeItems. Remember this function has been written so that 
02522     // the CommonAttributeSet can be reused. So the Status and pAttr fields may contain
02523     // garbage on entry to the function.
02524     CommonAttributeSet->ClearResults();
02525     
02526     INT32 NumValuesToFind; // The number of attribute types we need to find values for.
02527                          // This value will decrease as more values are found.
02528     INT32 NumNewValues;
02529      
02530     // One, Many, or all common attribute values may already be cached
02531     CommonAttrSet* pCommonAttrCache = GetCommonAttrCache(); 
02532 
02533     if (pCommonAttrCache)
02534     {
02535         // We only need to consider the first NumValuesToFind attributes in the list
02536         NumValuesToFind = CommonAttributeSet->UpdateKnownValues(pCommonAttrCache);
02537     }
02538     else
02539     {
02540         // We need to find all values
02541         NumValuesToFind = CommonAttributeSet->GetCount();
02542     }
02543 
02544     NumNewValues = NumValuesToFind;
02545 
02546     if (!NumValuesToFind)
02547         return TRUE; 
02548 
02549     // This is a recent optimisation. We create a map of Attribute types to applied attrs. This 
02550     // allows us to scan up the tree looking for attributes applied to each object once only.
02551     CCAttrMap* pAttrMap = new CCAttrMap;  // Create it dynamically as it could be quite big
02552     if (!pAttrMap)
02553     {
02554         if (DelCommonAttrSet) CommonAttributeSet->DeleteAll(); 
02555         return FALSE; // out of memory
02556     }
02557 
02558     // A special type of attribute map which is used for Compound objects only. It only gets 
02559     // built if and when we need it. When we find a default attribute applied to a compound
02560     // object, we only know that this attribute is a common attribute if at least one object
02561     // in the compound requires the attribute AND the attribute does not make an appearance 
02562     // anywhere as a child of the compound. The attrmap maps an attribute type which is known
02563     // to be a default onto an ObjectAttrUsage value.
02564     BOOL CompoundAttrMapBuilt;  
02565     CMapPtrToWord* pCompoundAttrMap = new CMapPtrToWord;
02566     if (!pCompoundAttrMap)
02567     {
02568         delete pAttrMap;
02569         if (DelCommonAttrSet) CommonAttributeSet->DeleteAll(); 
02570         return FALSE;   // out of memory 
02571     }
02572     
02573     // Scan all objects in the range,
02574     Node* pNode = NULL;
02575     NodeRenderableInk* CurrentObject;
02576 
02577     pNode = FindFirst(); 
02578     // Stop when we have found all attribute values (all ATTR_MANY), or there are no more objects
02579     // to process.
02580     while ((pNode != NULL) && (NumValuesToFind))
02581     {
02582         if (pNode->IsAnObject())
02583         {
02584             CurrentObject = (NodeRenderableInk*)pNode;
02585 
02586             pAttrMap->RemoveAll();          // Remove any items that may have been in the map
02587             pCompoundAttrMap->clear();  // Ditto
02588             CompoundAttrMapBuilt = FALSE;   // Cos we only build this when it becomes required
02589 
02590             // Find all attributes applied to CurrentObject, let's worry about compounds a bit later 
02591             CurrentObject->FindAppliedAttributes(pAttrMap); 
02592 
02593             // Scan attributes in the CommonAttributeSet
02594             CommonAttributeItem* CommonAttrItem;
02595             CommonAttributeItem* NxtCommonAttrItem;
02596 
02597             INT32 NumValuesToProcess = NumValuesToFind;
02598             
02599             CommonAttrItem = (CommonAttributeItem*)CommonAttributeSet->GetHead();
02600             while (NumValuesToProcess)
02601             {
02602                 ERROR3IF(CommonAttrItem==NULL || CommonAttrItem->CheckMemory(FALSE)==FALSE, "CommonAttrItem should not be NULL"); 
02603                 // Hand over hand, as the item will be moved to the tail of the list if 
02604                 // it's value becomes known
02605                 NxtCommonAttrItem = (CommonAttributeItem*)CommonAttributeSet->GetNext(CommonAttrItem); 
02606                 if (CurrentObject->RequiresAttrib(CommonAttrItem->AttrType, CompoundAccuracy)) 
02607                 {
02608                     // Find the attribute which is applied to the CurrentObject
02609                     void* vpAttr=NULL;
02610                     NodeAttribute* pAttrNode;
02611                     pAttrMap->Lookup(CommonAttrItem->AttrType, vpAttr);
02612                     pAttrNode = (NodeAttribute*)vpAttr;
02613                     ERROR3IF(pAttrNode == NULL, "Could not find attribute of type AttrType"); 
02614                     if (pAttrNode != NULL)  // For safety
02615                     {
02616                         BOOL AttrCommonInCompound = TRUE;
02617                         BOOL AttrReqd = TRUE;
02618                         // Special Compound object processing
02619                         if (CurrentObject->IsCompound())
02620                         {
02621                             // In this situation pAttrNode will be a common attribute if it is 
02622                             // not a default attribute. i.e. if it's parent is not a NodeDocument
02623                             if (pAttrNode->IsADefaultAttr())
02624                             {
02625                                 // ok we are messing with a default attribute here.
02626                                 if (!CompoundAttrMapBuilt)
02627                                 {
02628                                     // If we haven't already got ourselves a CompoundAttrMap
02629                                     // construct one, adding all attribute types that are
02630                                     // known to be defaults.
02631                                     if (!CommonAttributeSet->BuildAttrDetailsMap(CurrentObject, 
02632                                                                             NumValuesToFind,
02633                                                                             pAttrMap, 
02634                                                                             pCompoundAttrMap))
02635                                     {
02636                                         if (DelCommonAttrSet) CommonAttributeSet->DeleteAll();
02637                                         delete pAttrMap; delete pCompoundAttrMap; 
02638                                         return FALSE; 
02639                                     }
02640                                     CompoundAttrMapBuilt = TRUE;
02641                                 }
02642 //                              WORD wCompoundAttrUsage;
02643 //                              pCompoundAttrMap->Lookup(CommonAttrItem->AttrType, wCompoundAttrUsage);
02644                                 CMapPtrToWord::iterator iter = pCompoundAttrMap->find(CommonAttrItem->AttrType);
02645                                 if (pCompoundAttrMap->end() != iter)
02646                                 {
02647                                     CommonAttrSet::ObjectAttrUsage CompoundAttrUsage = 
02648                                         (CommonAttrSet::ObjectAttrUsage)iter->second;
02649                                     // if the attribute type has been found as a child of the compound then we know
02650                                     // it's not a common attribute of the compound, and so the Selection.
02651                                     if (CompoundAttrUsage == CommonAttrSet::FOUND)
02652                                         AttrCommonInCompound = FALSE;
02653                                     else if (CompoundAttrUsage == CommonAttrSet::NOT_REQUIRED)
02654                                         AttrReqd = FALSE;
02655                                     // else CompoundAttrUsage == REQUIRED (attr is common so continue)
02656                                 }
02657                             }
02658                         }
02659                         if (AttrReqd)  
02660                         {
02661                             // Ok it has an attribute of this type
02662                             if (CommonAttrItem->pAttr == NULL)
02663                             {
02664                                 // The attribute becomes a common attribute
02665                                 CommonAttrItem->Status = Range::ATTR_COMMON;  // up to this point anyway
02666                                 CommonAttrItem->pAttr = pAttrNode;
02667                             }                       
02668                             // not an else (need to catch Compound case
02669                             if (!AttrCommonInCompound || (!((*pAttrNode)==(*(CommonAttrItem->pAttr)))) )
02670                             {
02671                                 // Attributes have different values. 
02672                                 CommonAttrItem->Status = Range::ATTR_MANY;
02673                                 CommonAttrItem->pAttr = NULL;
02674                                 // This item's value has been found it will not cahnge so move it to the
02675                                 // end of the list. 
02676                                 CommonAttributeSet->RemoveItem(CommonAttrItem); 
02677                                 CommonAttributeSet->AddTail(CommonAttrItem);
02678                                 NumValuesToFind--; // One less to find for the next object
02679                             }
02680                         }
02681                     } // if
02682                 } // if
02683                 NumValuesToProcess--;
02684                 CommonAttrItem = NxtCommonAttrItem;
02685             } // Attribute scan
02686         }
02687         // Get the next object
02688         pNode = FindNext(pNode);
02689     } // Range scan
02690 
02691 
02692     // Post processing: For every new value found 
02693     //      Each ATTR_NONE item should point at the current attribute associated with the selected tool
02694     //      The new value should be added to the cache
02695     Document* SelectedDoc = Document::GetSelected();
02696 
02697     CommonAttributeItem* CommonAttrItem;
02698 
02699     AttributeManager& pAttrMgr = SelectedDoc->GetAttributeMgr();
02700     INT32 Count;
02701     for (CommonAttrItem = (CommonAttributeItem*)CommonAttributeSet->GetHead(), Count = 0;
02702          Count != NumNewValues;
02703          CommonAttrItem = (CommonAttributeItem*)CommonAttributeSet->GetNext(CommonAttrItem), Count++)
02704     {
02705         ERROR3IF(!CommonAttrItem, "CommonAttrItem should not be NULL"); 
02706         if (SelectedDoc && CommonAttrItem->Status == Range::ATTR_NONE)
02707         {
02708             CommonAttrItem->pAttr = pAttrMgr.GetSelToolCurrentAttribute(CommonAttrItem->AttrType);
02709         }
02710         // Add the item to the cache.
02711         if (pCommonAttrCache)
02712         {
02713             CommonAttributeItem* pNewAttrItem = new CommonAttributeItem(CommonAttrItem->AttrType);
02714             if (pNewAttrItem)
02715             {
02716                 // Add the attribute type results to the cache, taking a copy of the attribute
02717                 if (!(pNewAttrItem->InitSafeAttrItem(CommonAttrItem->AttrType, 
02718                                                      CommonAttrItem->pAttr, 
02719                                                      CommonAttrItem->Status)))
02720                 {
02721                     delete pNewAttrItem;
02722                 }
02723                 else
02724                 {
02725                     pCommonAttrCache->AddTail(pNewAttrItem); // Add to the cache    
02726                 }
02727             } // else we failed to allocate memory for the item, we can live with this.
02728         }
02729     }
02730 
02731     // else pAttr will be NULL for all items
02732 
02733     delete pAttrMap;
02734     delete pCompoundAttrMap; 
02735 
02736     return TRUE; // Job done
02737 #else
02738     return FALSE;
02739 #endif
02740 }

Range::CommonAttribResult Range::FindCommonAttributeType CCRuntimeClass AttribType,
CCRuntimeClass **  pCommonType,
BOOL  ForceAttribType = FALSE,
BOOL  bRangeIsEffectsLevel = FALSE
 

To determine if all objects in the selection share attributes with the same type.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
15/8/94
Parameters:
AttribType,: The Type of attribute to find - defined in the virtual [INPUTS] GetAttributeType method of NodeAttribute
pCommonType,: Depends on the return value, see below [OUTPUTS]
Returns:
ATTR_COMMON:There is a common attribute type pCommonType will point to its runtime class
ATTR_NONE: There is no selection, or none of the selected objects require the attribute. If there is a document pCommonType will point to the type of thecurrent attribute for the selected tool, this will be the value which is usually displayed in this situation. else pCommonType will be NULL No value will usually be displayed in this situation

ATTR_MANY: There is no common attribute type, pCommonType will be NULL

Returns:
Errors: - Scope: private
See also:
-

Definition at line 3014 of file range.cpp.

03018 {
03019 #if !defined(EXCLUDE_FROM_RALPH)
03020     CommonAttribResult Result;
03021     NodeAttribute *pAttribute = NULL;
03022     *pCommonType = NULL;
03023 
03024     // Scan each selected node until we get a result
03025     NodeRenderableInk* n = NULL;
03026     NodeRenderableInk* pn = (NodeRenderableInk*)FindFirst(); 
03027     
03028     NodeAttribute* AppliedAttr; // The attribute applied to n
03029 
03030     while (pn != NULL)
03031     {
03032         n = pn;
03033         if (bRangeIsEffectsLevel)
03034             n = pn->GetObjectToApplyTo(AttribType);
03035 
03036         AppliedAttr = NULL;
03037         if (n->IsCompound())        // TODO: Don't do this clause if n would allow effect attrs of the given type???
03038         {
03039             // Determine if all objects within the  compound object share a common attribute
03040             
03041             // (Check the child attribute block)
03042             // If we find the attribute defined as a left child of the compound object (before 
03043             // other, non attribute nodes) then we can be sure that this attribute is 
03044             // shared by all objects requiring the attribute within the compound.
03045 
03046             ERROR3IF(!n->IsAnObject(), "Item in range is not a NodeRenderableInk"); 
03047 
03048             AppliedAttr = ((NodeRenderableInk*)n)->GetChildAttrOfType(AttribType);
03049             
03050             if (!AppliedAttr)
03051             {
03052                 // This can mean one of three things
03053                 // a. All nodes in the compound which require the attribute share the default 
03054                 //    attribute
03055                 // b. Nodes requiring attribute have more than one attribute value
03056                 // c. No nodes in the group require the attribute
03057 
03058                 // Flag which is set to TRUE when we know that AttribType is required by the 
03059                 // the compound
03060                 BOOL AttribRequiredInCompound = FALSE; 
03061 
03062                 // Scan the compound depth first
03063                 Node* Current = n->FindFirstDepthFirst();
03064                 
03065                 while (Current != NULL)
03066                 {
03067                     if (!AttribRequiredInCompound)
03068                     {
03069                         // Determine if the attribute is required by the current node
03070                         if (Current->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)))
03071                         {
03072                             AttribRequiredInCompound = ((NodeRenderableInk*)Current)
03073                                 ->RequiresAttrib(AttribType);   
03074                         }
03075                     }
03076                     if (Current->IsAnAttribute())
03077                     {
03078                         if (((NodeAttribute*)Current)->GetAttributeType() == AttribType)
03079                         {
03080                             // This means that the compound must have more than one
03081                             // attribute value, because if this attribute was common to
03082                             // all objects requiring the attribute in the compound then
03083                             // it would have been found in the child attribute block !
03084                             
03085                             if (!ForceAttribType)
03086                             {
03087                                 (*pCommonType) = NULL; // Nothing useful to return here
03088                                 return ATTR_MANY;         //                        *RETURN
03089                             }
03090                             else        // we want to try and force a common attribute ....
03091                                         // e.g.  if we have two shapes with a different linear
03092                                         // fill each and then group these, it is desirable to
03093                                         // still show these to the user as linear, and NOT change
03094                                         // (by default) to showing many ....
03095                             {
03096                                 AppliedAttr = (NodeAttribute*)Current;
03097                                 
03098                                 if ((pAttribute) == NULL) // This is the first instance of the attribute found
03099                                 {
03100                                     (pAttribute) = AppliedAttr; 
03101                                 }
03102                                 else
03103                                 {
03104                                     // If the attribute found is not the same as all others found then 
03105                                     // we know that there is no common attribute, so there is no point in
03106                                     // searching any further
03107             
03108                                     if (! ((pAttribute->GetRuntimeClass()) == (AppliedAttr->GetRuntimeClass())) )
03109                                     {
03110                                         (*pCommonType) = NULL; // Nothing useful to return here
03111                                         return ATTR_MANY;         //                                    *RETURN
03112                                     }
03113     
03114                                     // Complicated by this special case.
03115                                     // If it's a Radial Fill Geometry, then we need to see if it's
03116                                     // circular or elliptical
03117 
03118                                     if ( pAttribute->IsKindOf(CC_RUNTIME_CLASS(AttrRadialFill)) )
03119                                     {
03120                                         if (! (((AttrRadialFill*)pAttribute)->IsElliptical()) == 
03121                                             (((AttrRadialFill*)AppliedAttr)->IsElliptical()) )
03122                                         {
03123                                             (*pCommonType) = NULL; // Nothing useful to return here
03124                                             return ATTR_MANY;      //                                   *RETURN
03125                                         }
03126                                     }
03127 
03128                                     // else the Applied attribute is the same as all others found so carry
03129                                     // on searching.
03130                                 }
03131                             }
03132                         }
03133                     }
03134                     Current = Current->FindNextDepthFirst(n);       
03135                 }
03136                 if ((AttribRequiredInCompound) && (!ForceAttribType))
03137                 {
03138                     // The group uses an attribute further up the tree
03139                     // scan left then up the tree in reverse render order until we 
03140                     // find an instance of an AttribClass attribute.
03141                     AppliedAttr = n->FindAppliedAttribute(AttribType, TRUE);    // bExcludeChildAttrs
03142                 }
03143                 // else attribute not required in compound so ignore it. 
03144             }
03145         }
03146         else
03147         {
03148             // Does n require attribute AttribType to render itself ?
03149             if (n->RequiresAttrib(AttribType))
03150             {
03151                 // n needs to have attribute AttribType defined so that it can render properly
03152                 // scan from the last child of n, up the tree in reverse render order until we 
03153                 // find an instance of an AttribType attribute.
03154                 AppliedAttr = n->FindAppliedAttribute(AttribType);
03155                 
03156             }
03157             // else n does not require the attribute so it is ignored
03158         }
03159         
03160         // Determine if the attribute is common
03161 
03162         if (AppliedAttr != NULL)
03163         {
03164 
03165             if ((pAttribute) == NULL) // This is the first instance of the attribute found
03166             {
03167                 (pAttribute) = AppliedAttr; 
03168             }
03169             else
03170             {
03171                 // If the attribute found is not the same as all others found then 
03172                 // we know that there is no common attribute, so there is no point in
03173                 // searching any further
03174             
03175                 if (! ((pAttribute->GetRuntimeClass()) == (AppliedAttr->GetRuntimeClass())) )
03176                 {
03177                     (*pCommonType) = NULL; // Nothing useful to return here
03178                     return ATTR_MANY;         //                                    *RETURN
03179                 }
03180     
03181                 // Complicated by this special case.
03182                 // If it's a Radial Fill Geometry, then we need to see if it's
03183                 // circular or elliptical
03184 
03185                 if ( pAttribute->IsKindOf(CC_RUNTIME_CLASS(AttrRadialFill)) )
03186                 {
03187                     if (! (((AttrRadialFill*)pAttribute)->IsElliptical()) == 
03188                             (((AttrRadialFill*)AppliedAttr)->IsElliptical()) )
03189                     {
03190                         (*pCommonType) = NULL; // Nothing useful to return here
03191                         return ATTR_MANY;      //                                   *RETURN
03192                     }
03193                 }
03194 
03195                 // else the Applied attribute is the same as all others found so carry
03196                 // on searching.
03197             }
03198         }
03199          
03200         pn = (NodeRenderableInk*)FindNext(pn); // Obtain the next selected object
03201     }
03202 
03203     // Ok weve finished the scan, so either no objects require the attribute, or there
03204     // is a common attribute value shared by all objects that do require the attribute
03205     if ((pAttribute) != NULL)
03206     {
03207         *pCommonType = pAttribute->GetRuntimeClass();
03208 
03209         // If it's one of these silly circle things then
03210         // we'll have to return this 'virtual' class type.
03211         if ( pAttribute->IsKindOf(CC_RUNTIME_CLASS(AttrRadialColourFill)) )
03212         {
03213             if ( ((AttrRadialColourFill*)pAttribute)->IsCircular() )
03214                 *pCommonType = CC_RUNTIME_CLASS(AttrCircularColourFill);
03215         }
03216         else if ( pAttribute->IsKindOf(CC_RUNTIME_CLASS(AttrRadialTranspFill)) )
03217         {
03218             if ( ((AttrRadialTranspFill*)pAttribute)->IsCircular() )
03219                 *pCommonType = CC_RUNTIME_CLASS(AttrCircularTranspFill);
03220         }
03221 
03222         Result = ATTR_COMMON;
03223         // pAttribute will point to an instance of the common attribute
03224     }
03225     else
03226     {
03227         Result = ATTR_NONE;
03228 
03229         Document* SelectedDoc = Document::GetSelected();
03230     
03231         // If there is a selected document then pAttribute is set to the current attribute
03232         // for the selected tool.
03233         if (SelectedDoc != NULL)
03234         {
03235             *pCommonType = (SelectedDoc->GetAttributeMgr().GetSelToolCurrentAttribute(AttribType))->GetRuntimeClass();
03236         }
03237         // else pAttribute will be NULL 
03238     }
03239     return Result;
03240 #else
03241     return ATTR_NONE;
03242 #endif
03243 }

Range::CommonAttribResult Range::FindCommonNonOptimisingAttr CCRuntimeClass pAttribClass,
NodeAttribute **  ppAttr
 

Do a search on the range, for non-optimising attrs. Because they are not optimised, we don't need to search up and down the tree for these attributes - we just look at the children of each node in the range.

Parameters:
If returning ATTR_COMMON, then ppAttr is filled with a ptr to one of the [OUTPUTS] common attributes, so that its values may be read by whoever called us.
Returns:
ATTR_MANY if we find more than one attribute of the given class, and they are different. ATTR_COMMON if we find one or more attributes, and they are the same. ATTR_NONE if we find no attributes of the given class.
Notes: This method *does* search all children of a node, so that it will detect multiple different attributes of the same type attached to one node.

Returns:
Errors: ERROR2 with ATTR_NONE if either parameter is NULL. See also: FindCommonAttribute().

Definition at line 3301 of file range.cpp.

03303 {
03304     ERROR2IF(ppAttr == NULL || pAttribClass == NULL, ATTR_NONE,
03305             "Range::FindCommonNonOptimisingAttr; NULL input parameter!");
03306 
03307     NodeAttribute* pAttr    = NULL;
03308     NodeAttribute* pFirstAttr   = NULL;
03309 
03310     Node* pNode = FindFirst();
03311     while (pNode != NULL)
03312     {
03313         if (pNode->IsAnObject())    // sanity check.
03314         {
03315             pAttr = (NodeAttribute*)pNode->FindFirstChild(pAttribClass);
03316             while (pAttr != NULL)
03317             {
03318                 // remember the first match we have, so we can check for differences.
03319                 if (pFirstAttr == NULL)
03320                     pFirstAttr = pAttr;
03321 
03322                 // if we have multiple matches, then check each one for differences.
03323                 else if (pAttr->IsDifferent(pFirstAttr))
03324                     return ATTR_MANY;
03325 
03326                 pAttr = (NodeAttribute*)pAttr->FindNext(pAttribClass);
03327             }
03328         }
03329 
03330         pNode = FindNext(pNode);
03331     }
03332 
03333     if (pFirstAttr != NULL)
03334     {
03335         *ppAttr = pFirstAttr;
03336         return ATTR_COMMON;
03337     }
03338     else
03339     {
03340         return ATTR_NONE;
03341     }
03342 }

Node * Range::FindFirst BOOL  AndChildren = FALSE  )  [virtual]
 

The purpose of this function is to find the first node in a range.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> (Changed by Phil, 30/11/94)
Date:
25/6/93
Returns:
If the range contains any members then A pointer to the first node in the range is returned Else NULL is returned
See also:
Range::FindNext
Returns:
Errors: An assertion failure will occur if:
There are no more nodes to search and the last node to search was not found.

Reimplemented in SelRange, and ListRange.

Definition at line 442 of file range.cpp.

00443 {
00444     // Preconditions...
00445     ERROR2IF(this==NULL,NULL,"FindFirst called on NULL range");
00446 
00447     // Locals...
00448     Node* pNode = FirstNode;
00449 
00450 
00451 // **** !!!! BODGE - Traps bug in message broadcast from document.cpp to try to
00452 // keep the program stable.
00453     if (Document::GetSelectedSpread() != NULL)
00454     {
00455         if (!Document::SpreadBelongsToDoc(Document::GetSelected(),
00456                                             Document::GetSelectedSpread()))
00457         {
00458             TRACE( _T("SelRange: Selected Spread is NOT in the Selected Document!\n"));
00459             return(NULL);
00460         }
00461     }
00462 // **** !!!! BODGE
00463 
00464     // Implementation...
00465     // If First is NULL then the caller expects to get a range of nodes
00466     // in the child lists of layers. So find the first layer on the
00467     // current spread.
00468     if (pNode == NULL)
00469     {
00470         Spread* pSelectedSpread = Document::GetSelectedSpread();
00471         if (pSelectedSpread==NULL)
00472         {
00473             // The range does not have a FirstNode. Normally it would find one
00474             // automatically based on the SelectedSpread but there is no SelectedSpread
00475             // so we have no choice but to return an empty range to the caller...
00476             TRACEUSER( "Phil", _T("Warning! Range is NULL because there's no selected spread\n"));
00477             return NULL;
00478         }
00479         
00480         // Oh well, we will use the first layer instead
00481         pNode = pSelectedSpread->FindFirstLayer();
00482 
00483         // If there is no layer, then give up and return NULL
00484         if (pNode==NULL)
00485             return NULL;
00486     }
00487 
00488     // The first node might be a valid member of the range so test for that...
00489     // (Set the special FirstNode flag TRUE so that the logic treats this node is
00490     //  if it hasn't yet been met in the scan.)
00491     pNode = SmartFindNext(pNode, AndChildren, TRUE);
00492     return pNode;
00493 }                       

Node * Range::FindLast  )  [virtual]
 

The purpose of this function is to find the last node in a range. If the range was constructed with a NULL last node specifier then the range is scanned until the last node is found. If a non NULL last node was specified however the value of last is simply returned. It's existance is not verified !.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
25/6/93
Returns:
If the range contains any members then A pointer to the last node in the range is returned Else NULL is returned
See also:
Range::FindFirst Range::FindNext
Returns:
Errors: An assertion failure will occur if:
There are no more nodes to search and the last node to search was not found.

Reimplemented in SelRange, and ListRange.

Definition at line 609 of file range.cpp.

00610 {
00611     if (LastNode == NULL)
00612     {
00613         // We need to search for the last node in the range
00614         Node* Scout = FindFirst();
00615         Node* n = NULL; 
00616         while (Scout != NULL)
00617         {
00618             n = Scout;
00619             Scout = FindNext(Scout); // Get the next value in the range
00620         }
00621         return n; // If the range is empty NULL will be returned
00622     }
00623     else
00624     {
00625         // get the parent of the last node (if necessary to promote)
00626         Node * pContext = LastNode;
00627 
00628         if (pContext != NULL)
00629         {
00630             Node *pParent = pContext->FindParent();
00631         
00632             if (RangeControlFlags.PromoteToParent)
00633             {
00634                 while (pParent)
00635                 {
00636                     if (pParent->ShouldITransformWithChildren())
00637                     {
00638                         pContext = pParent;
00639                     }
00640                 
00641                     pParent = pParent->FindParent();
00642                 }
00643             }
00644         }
00645 
00646         return pContext; 
00647     }
00648 }

Node * Range::FindNext Node Previous,
BOOL  AndChildren = FALSE
[virtual]
 

Reimplemented in SelRange, and ListRange.

Definition at line 517 of file range.cpp.

00518 {
00519     // Preconditions
00520     // No need to check that "this" is NULL because that's already been done
00521     // in FindFirst.
00522     ERROR2IF(pPrevious == NULL, NULL, "NULL pointer passed to Range::FindNext");
00523 
00524     Node* pNode = SmartFindNext(pPrevious, AndChildren);
00525 
00526     // DMc
00527     // if the output is the same as the input, and promote to parent is set,
00528     // the this should never happen !
00529     if (pNode == pPrevious && RangeControlFlags.PromoteToParent)
00530     {
00531         return NULL;
00532     }
00533         
00534     return pNode;
00535 }

BOOL Range::FindNextXOROutlineNode Node **  OriginalNode,
DocRect pClipRect
[protected]
 

Shared code used by the rotate, select, and scale tools to XOR the object(s) being dragged on/off screen. This function is used to calculate the next object to be drawn; it attempts to draw the most significant objects first, so that minute detail is only drawn if there is enough time spare. This significantly enhances interactiveness of dragging.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/2/94
Parameters:
OriginalNode - A handle on the current Node. Will be filled in with NULL or a [INPUTS] pointer to the next node to be drawn, or NULL if there is nothing more to draw
pClipRect - The current rendering clip rectangle - nodes outside this area will not be considered for redrawing.

Notes: See the selector and rotate tools for example code using this system.

Scope: private

See also:
SelRange::RenderXOROutlinesOn; SelRange::RenderXOROutlinesOff; SelRange::RenderXOROutlinesToCatchUp

Definition at line 1796 of file range.cpp.

01798                                                                             :
01799 //  1) Prime object (the object on whic the user clicked to start the drag)
01800 //  2) High priority object(s) - any:   screen/2 < object_size < screen
01801 //  3) Medium priority -                screen/6 < object_size < screen/2
01802 //  4) Low priority - anything left over (<screen/6 or >screen)
01803 //
01804 // If the selection was larger than the screen, the significance of each object
01805 // which was initially visible on screen is promoted (by doubling it) to increase
01806 // the chance of visible things being drawn before offscreen things.
01807 {
01808 #if !defined(EXCLUDE_FROM_RALPH)
01809     BOOL bPromote = RangeControlFlags.PromoteToParent;
01810     RangeControlFlags.PromoteToParent = FALSE;
01811 
01812     Node * pParent = NULL;
01813 
01814     BOOL DoRender = FALSE;
01815     const INT32 MaxSignificance = XORInfo.SigRegion.Width() + XORInfo.SigRegion.Height();
01816     const INT32 MediumSignificance  = MaxSignificance / 6;
01817     const INT32 HighSignificance        = MaxSignificance / 2;
01818 
01819     NodeRenderable *PrimeObject = (NodeRenderableInk *)XORInfo.PrimeObject;
01820 
01821     ERROR2IF(OriginalNode == NULL,FALSE, "Range::FindNextXOROutlineNode - NULL parameter is illegal");
01822     NodeRenderableBounded *CurrentNode = (NodeRenderableBounded *) *OriginalNode;
01823 
01824     if (CurrentNode == NULL)            // Can't continue from here, so start fresh
01825         RenderingPass = RENDER_START;
01826 
01827     if (CurrentNode == PrimeObject)
01828         CurrentNode = NULL;             // Start at beginning of selectn for next pass
01829     else
01830     {
01831         if (RenderingPass == RENDER_START && PrimeObject != NULL)
01832         {
01833             SubtreeRenderState state = PrimeObject->RenderSubtree(NULL);
01834             if (state==SUBTREE_ROOTONLY || state==SUBTREE_ROOTANDCHILDREN)
01835             {
01836                 *OriginalNode = (Node *) PrimeObject;   // Just starting, so
01837                 RangeControlFlags.PromoteToParent = bPromote;
01838                 return TRUE;                            // render prime object now
01839             }
01840         }
01841     }
01842 
01843     do
01844     {
01845         do      // Search for next renderable object
01846         {
01847             if (CurrentNode == NULL)
01848             {
01849                 // Have run out of objects to draw - Start again on the next pass
01850                 if (++RenderingPass >= RENDER_END)
01851                 {
01852                     *OriginalNode = NULL;
01853                     return TRUE;            // Everything drawn (all passes done)
01854                 }
01855 
01856                 CurrentNode = (NodeRenderableBounded *) FindFirst(TRUE);
01857 
01858                 // now, see if this node has a PromoteToParent node
01859                 if (CurrentNode)
01860                 {
01861                     pParent = CurrentNode->FindParent();
01862                 }
01863                 else
01864                 {
01865                     pParent = NULL;
01866                 }
01867                 
01868                 // DMc insertion - to cope with compound nodes
01869                 // in the cases they take care of their own blob rendering
01870                 if (pParent && pParent->IsAnObject())
01871                 {
01872                     if (((NodeRenderableInk *)pParent)->ChildrenAreEorDragRenderedByMe())
01873                     {
01874                         CurrentNode = (NodeRenderableBounded *)pParent;
01875                     }
01876 
01877                     pParent = pParent->FindParent();
01878                 }
01879             }
01880             else
01881             {
01882                 // DMc insertion - to cope with compound nodes
01883                 // in the cases they take care of their own blob rendering
01884                 CurrentNode = (NodeRenderableBounded *) FindNext(CurrentNode, TRUE);
01885 
01886                 // now, see if this node has a PromoteToParent node
01887                 if (CurrentNode)
01888                 {
01889                     pParent = CurrentNode->FindParent();
01890                 }
01891                 else
01892                 {
01893                     pParent = NULL;
01894                 }
01895                 
01896                 while (pParent && pParent->IsBounded())
01897                 {
01898                     if (pParent->IsAnObject())
01899                     {
01900                         if (((NodeRenderableInk *)pParent)->ChildrenAreEorDragRenderedByMe())
01901                         {
01902                             CurrentNode = (NodeRenderableBounded *)pParent;
01903                         }
01904                     }
01905 
01906                     pParent = pParent->FindParent();
01907                 }               
01908             }
01909                 
01910 //              CurrentNode = (NodeRenderableBounded *) FindNextAndChild(CurrentNode);
01911 
01912         } while (CurrentNode == NULL            ||
01913                     CurrentNode == PrimeObject  ||
01914                     !CurrentNode->IsBounded() );
01915                     
01916         // Now, determine priority, and return this object if priority is right
01917         DocRect BBox = CurrentNode->GetBoundingRect();
01918         INT32 Significance = BBox.Width() + BBox.Height();
01919 
01920         if (XORInfo.SigRegionIsScreen &&
01921             Significance < HighSignificance &&
01922             XORInfo.SigRegion.ContainsRect(BBox))
01923         {
01924             // If selection is larger than the screen, and this is not
01925             // large enough to be a high-significance object, but it was 
01926             // visible on-screen at the start of the drag, promote its
01927             // significance so it has a greater chance of being drawn soon.
01928             Significance *= 2;
01929         }
01930 
01931         switch(RenderingPass)
01932         {
01933             case RENDER_HIGH:           // High significance - draw ASAP
01934                 DoRender = Significance >= HighSignificance &&
01935                             Significance < MaxSignificance;
01936                 break;
01937 
01938             case RENDER_MEDIUM:         // Medium Significance - draw second
01939                 DoRender = Significance >= MediumSignificance &&
01940                             Significance < HighSignificance;
01941                 break;
01942     
01943             case RENDER_LOW:            // Low significance - draw last
01944                 DoRender = (Significance >= MaxSignificance) ||
01945                             (Significance < MediumSignificance);
01946                 break;
01947 
01948             default:
01949                 ERROR3_PF( ("** FindNextDragBlobNode - Illegal rendering pass %d. Tell Jason", RenderingPass) );
01950                 break;
01951         }
01952     } while (!DoRender);    
01953 
01954     *OriginalNode = (Node *) CurrentNode;
01955 
01956     RangeControlFlags.PromoteToParent = bPromote;
01957 
01958     return TRUE;
01959 #else
01960     return FALSE;
01961 #endif
01962 }

Node * Range::FindPrev Node pNode,
BOOL  AndChildren = FALSE
[virtual]
 

Reimplemented in ListRange.

Definition at line 559 of file range.cpp.

00560 {
00561     // Preconditions
00562     // No need to check that "this" is NULL because that's already been done
00563     // in FindFirst.
00564     ERROR2IF(pNode == NULL, NULL, "NULL pointer passed to Range::FindNext");
00565 
00566     Node* pPrev = NULL;
00567     Node* pCurrent = FindFirst(AndChildren);
00568     while (pCurrent)                                // While there's a node to check
00569     {
00570         if (pCurrent == pNode)                      // See if it's the one we're looking for
00571             return pPrev;                           // If it is return the previous node!
00572 
00573         pPrev = pCurrent;                           // Else, remember this node
00574         pCurrent = FindNext(pCurrent, AndChildren); // and find the next one in the range
00575     }
00576 
00577     return NULL;
00578 }

void Range::ForceRedrawView DocView pDocView,
BOOL  bReleaseCache = FALSE,
BOOL  bUseBlobRects = FALSE,
BOOL  bReleaseParentsOnly = FALSE
[virtual]
 

Definition at line 7175 of file range.cpp.

07176 {
07177     BOOL bOldPromote = SetPromoteToParent(TRUE);
07178 
07179     NodeRenderableBounded* CurrentNode = (NodeRenderableBounded*)FindFirst(); 
07180 
07181     if (CurrentNode != NULL && pDocView!=NULL)
07182     {
07183         Spread* pSpread = (Spread*)CurrentNode->FindParent(CC_RUNTIME_CLASS(Spread));
07184         Node* pBackmost = CurrentNode;
07185         DocRect Bounds(0,0,0,0);
07186 
07187         while (CurrentNode)
07188         {
07189             if (bReleaseCache && CurrentNode->IsAnObject()) ((NodeRenderableInk*)CurrentNode)->ReleaseCached(TRUE, !bReleaseParentsOnly, !bReleaseParentsOnly, !bReleaseParentsOnly);
07190             if (CurrentNode->IsBounded()) Bounds = Bounds.Union( ((NodeRenderableBounded*)CurrentNode)->GetBoundingRect() );
07191             if (CurrentNode->IsBounded() && bUseBlobRects) Bounds = Bounds.Union( ((NodeRenderableBounded*)CurrentNode)->GetBlobBoundingRect() );
07192             if (CurrentNode->IsUnder(pBackmost)) pBackmost = CurrentNode;
07193 
07194             CurrentNode = (NodeRenderableBounded*)FindNext(CurrentNode);
07195         }
07196 
07197         pDocView->ForceRedraw(pSpread, Bounds, TRUE, pBackmost);
07198     }
07199 
07200     SetPromoteToParent(bOldPromote);
07201 }

BOOL Range::ForceRenderEORAll  )  const [inline]
 

Definition at line 334 of file range.h.

00334 { return TRUE; }

virtual void Range::FreshenCache  )  [inline, virtual]
 

Reimplemented in SelRange.

Definition at line 330 of file range.h.

00330 {};

DocRect Range::GetBoundingRect  )  [virtual]
 

To determine the bounds of all objects in the range.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/9/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
The bounding rectangle of all objects in the range

Errors: -

See also:
-

Definition at line 1493 of file range.cpp.

01494 {
01495     DocRect Bounds; 
01496     // Calculate the union of all bounded nodes within the range 
01497     Node* pNode = FindFirst(FALSE);
01498     while (pNode != NULL)
01499     {
01500         if (pNode->IsBounded())
01501             Bounds = Bounds.Union(((NodeRenderableBounded*)pNode)->GetBoundingRect());
01502 
01503         pNode = FindNext(pNode, FALSE);
01504     } 
01505     return Bounds; 
01506 
01507 }

DocRect Range::GetBoundingRectForEorDragging  )  [virtual]
 

Same as for GetBoundingRect() but calls GetDragEorBoundingRect for all nodes.

Author:
David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/1/2000
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
The bounding rectangle of all objects in the range

Errors: -

See also:
-

Definition at line 1525 of file range.cpp.

01526 {
01527     DocRect Bounds; 
01528     // Calculate the union of all nodes within the range 
01529     NodeRenderableBounded* pNode = (NodeRenderableBounded*) FindFirst(FALSE);
01530     while (pNode != NULL)
01531     {
01532         Bounds = Bounds.Union(pNode->GetEorDragBoundingRect()); 
01533         pNode =(NodeRenderableBounded*)FindNext(pNode, FALSE);
01534     } 
01535     return Bounds; 
01536 
01537 }

CommonAttrSet * Range::GetCommonAttrCache  )  [protected]
 

This fn should be called to get a pointer to the range's common attribute cache. If the cache does not exist in the range then one is first created. Scope: private.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
13/9/95
Returns:
A pointer to the common attribute cache. NULL is returned if one could not be created because we ran out of memory.

Definition at line 3259 of file range.cpp.

03260 {
03261     FreshenCache();            // Cache may not be valid
03262     if (!pCommonAttribCache)
03263     {
03264         // Let's try and create one
03265         pCommonAttribCache = new CommonAttrSet(); 
03266     }
03267     FreshenCache();            // Could delete the pCommonAttribCache if not cached
03268     return pCommonAttribCache; // Will be NULL if we ran out of memory
03269 } 

BOOL Range::GetCompoundObjectSet ObjectSet pCompoundObjectSet,
BOOL  ExcludeTextObjects = FALSE
 

This function traverses the range, and whenever it finds an object which is the child of a compound node it adds the compound node to the set.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
5/6/95
Parameters:
- [INPUTS]
pCompoundObjectSet,: A set of all the parent compound nodes of the items in the [OUTPUTS] range. This set can already contain items on entry to this function, and these items will not be deleted.
ExcludeTextObjects: When TRUE TextStory compound objects will be excluded from the set.

Returns:
TRUE if successful FALSE if we run out of memory. In this situation we do NOT delete any items already added to the set.
This is useful if you want to process the compound parents of the range after they have been hidden, eg. when we need to factor out attributes after a complex deletion.

Returns:
Errors: -
See also:
-

Definition at line 2412 of file range.cpp.

02413 {
02414     Node *pParent;
02415 
02416     // Scan the range
02417     Node* pCurrent = FindFirst();
02418     while (pCurrent)
02419     {
02420         pParent = pCurrent->FindParent();
02421         ERROR3IF(!pParent, "Object in range has no parent !"); 
02422         if (pParent && (pParent->IsCompound()))
02423         {
02424             if (!(ExcludeTextObjects && ((IS_A(pParent, TextLine)) || (IS_A(pParent, TextStory)))) )
02425             {
02426 
02427                 // A compound parent has been found, add it to the set
02428                 if (!(pCompoundObjectSet->AddToSet(((NodeRenderableInk*)pParent))))
02429                 {
02430                     return FALSE;
02431                 }
02432             }
02433         }
02434 
02435         pCurrent = pCurrent->FindNext(); 
02436     }
02437     return TRUE;
02438 }

RangeControl Range::GetRangeControlFlags  )  const [inline]
 

Definition at line 332 of file range.h.

00332 { return RangeControlFlags; }

BOOL Range::InRange Node pNode,
BOOL  AndChildren
const [protected, virtual]
 

Private helper function for SmartFindNext. Tests whether the presented node is in the range according to the RangeControlFlags and two other locally presented flags.

Author:
Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/11/94 Rewritten: 08/12/2004
Parameters:
pNode Pointer to node to test for inclusion in the range [INPUTS] AndChildren Children of the primary range are allowed to be returned
- [OUTPUTS]
Returns:
TRUE if node is in this range (ignoring CrossLayer flag) FALSE if not
Version 2, 08/12/2004 Simplified and adjusted to deal with selection inside Compound Parents Controllers and PostProcessors

This function should ONLY be called on nodes that /could/ be members of Range Not Layers or Paper nodes!

Scope: Protected

See also:
Range::SmartFindNext
Returns:
Errors: When attempting to return children and finds no parent link.

Reimplemented in ListRange.

Definition at line 1061 of file range.cpp.

01062 {
01063     // Preconditions
01064     ERROR2IF(this==NULL, FALSE, "InRange called on NULL range");
01065     ERROR2IF(pNode==NULL, FALSE, "InRange given a NULL node");
01066     ERROR2IF(pNode->IsPaper(), FALSE, "InRange asked to decide on Paper");
01067     ERROR2IF(pNode->IsLayer(), FALSE, "InRange asked to decide on Layer");
01068     ERROR2IF(RangeControlFlags.Unselected && !RangeControlFlags.Selected && FirstNode==NULL, FALSE, "InRange can't detect unselected nodes without a FirstNode");
01069 
01070     //------------------------------------------------------------------------------------
01071     // Test for Primary members of the range...
01072     //
01073     // If an op has asked this node for permission to apply the op to it, and the node said no, return.
01074     if (pNode->GetOpPermission() == PERMISSION_DENIED)
01075         return FALSE;
01076 
01077     // if trying to ignore none renderable nodes then check the node
01078     SubtreeRenderState state = pNode->RenderSubtree(NULL);
01079     if (RangeControlFlags.IgnoreNoneRenderable && !(state==SUBTREE_ROOTONLY || state==SUBTREE_ROOTANDCHILDREN))
01080         return FALSE;
01081 
01082     // If looking for selected nodes and node is selected, OK
01083     if (RangeControlFlags.Selected && pNode->IsSelected())
01084         return TRUE;
01085 
01086 // If we're not promoting to parents but we seem to have found one such parent
01087 // Then deny this node
01088 if (!AndChildren && !RangeControlFlags.PromoteToParent && pNode->ShouldITransformWithChildren())
01089     return FALSE;
01090 
01091     // If looking for all nodes but not going into child subtrees, OK whether node is selected or not
01092     if (!AndChildren && RangeControlFlags.Selected && RangeControlFlags.Unselected)
01093         return TRUE;
01094 
01095     // If node isn't paper then it ought to have a parent node which we will need later...
01096     Node* pParent = pNode->FindParent();
01097     ERROR2IF_PF(pParent==NULL, FALSE, ("OOER! Range found an ink node %lx without any parents!",pNode));
01098 
01099     Node* pFirstParent = NULL;
01100     if (FirstNode)
01101         pFirstParent = FirstNode->FindParent();
01102 
01103     // If looking for immediate siblings only then check that this ndoe has the same parent as
01104     // the first node (we've already checked pParent to be non-NULL)
01105     if (RangeControlFlags.SiblingsOnly)
01106     {
01107         if (pFirstParent!=pParent)
01108             return FALSE;
01109     }
01110     
01111     // If looking for unselected nodes then we need to check whether this node is unselected
01112     // and in the same level of the tree as the first node...
01113     while (!pNode->IsSelected() && RangeControlFlags.Unselected && pFirstParent && pParent)
01114     {
01115         if (pFirstParent == pParent)
01116             return TRUE;
01117 
01118         pFirstParent = pFirstParent->FindParent();
01119         pParent = pParent->FindParent();
01120     }
01121 
01122     //------------------------------------------------------------------------------------
01123     // Test for Secondary members of the range by recursion...
01124     //
01125     // If looking for children of nodes in the primary range specification
01126     // or looking for selected nodes (which may be "selected-inside")
01127     // Then we must check that our parent is in the range. If he is then we are!
01128     if (AndChildren && !pParent->IsLayer() && !pParent->IsPaper())
01129         return InRange(pParent, AndChildren);
01130 
01131     return FALSE;
01132 }

BOOL Range::IsEmpty  ) 
 

Determines whether the range is empty.

BOOL Range::IsEmpty()

Author:
Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/3/97
Parameters:
- [INPUTS]
Returns:
TRUE if the range is empty
See also:
-

Definition at line 3496 of file range.cpp.

03497 {
03498     return (FindFirst()==NULL);
03499 }

BOOL Range::MakeAttributeComplete BOOL  CheckForDuplicates = TRUE,
BOOL  AndChildren = FALSE,
BOOL  IgnoreComplex = FALSE
 

This function calls NodeRenderableInk::MakeAttributeComplete on every Object in the selection. If we run out of memory then all changes are undone.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
7/2/94
Parameters:
CheckForDuplicates,: When TRUE a check is made to ensure that duplicate [INPUTS] attribiutes are not added to the subtree AndChildren: IgnoreComplex: When TRUE do not make attributes complete on complexcopy nodes.
- [OUTPUTS]
Returns:
TRUE if successful FALSE if we run out of memory, the children of the node will remain unchanged
See also:
NodeRenderableInk::MakeAttributeComplete

Range::NormaliseAttributes

Definition at line 1312 of file range.cpp.

01315 {
01316     BOOL MakeComplete;
01317     Node* Current = FindFirst(AndChildren); // First item in range
01318     while (Current != NULL)
01319     {
01320         if (Current->IsAnObject())
01321         {
01322             NodeRenderableInk* pInkObj = (NodeRenderableInk*)Current;
01323             MakeComplete = TRUE;
01324 
01325             if (IgnoreComplex)
01326                 if ((pInkObj->GetCopyType()) == COMPLEXCOPY)
01327                     MakeComplete=FALSE;
01328 
01329             // complete the attributes on this node if necessary
01330             if (MakeComplete)
01331             {
01332                 if (!(pInkObj->MakeAttributeComplete(NULL, CheckForDuplicates)))
01333                 {
01334                     // Note that at this point Current's children have not been changed
01335                     goto Abort; 
01336                 }
01337             }
01338         }
01339         Current = FindNext(Current, AndChildren); 
01340     }
01341     return TRUE; // Success
01342     
01343     Abort:
01344     // We need to tidyup any changes that have been made
01345     BOOL Normalise;
01346     Node* Sentinal = Current; 
01347     Current = FindFirst(AndChildren); 
01348     while (Current != Sentinal )
01349     {
01350         ERROR3IF(Current == NULL, "Could not find sentinal"); 
01351         if (Current->IsAnObject())
01352         {
01353             NodeRenderableInk* pInkObj = (NodeRenderableInk*)Current;
01354             Normalise = TRUE;
01355 
01356             if (IgnoreComplex)
01357                 if ((pInkObj->GetCopyType()) == COMPLEXCOPY)
01358                     Normalise=FALSE;
01359 
01360             // complete the attributes on this node if necessary
01361             if (Normalise)
01362                 pInkObj->NormaliseAttributes();         
01363         }
01364 
01365         Current = FindNext(Current, AndChildren);
01366     }
01367     return FALSE; 
01368 }

List * Range::MakeListOfNodes BOOL  AndChildren = FALSE  ) 
 

This function will create and return a pointer to a list representing the objects in the range. It will return NULL if it couldn't create the list due to lack of memory. WARNING! This function creates objects which must be deleted by the calling routine. The last thing we need right now is another bunch of listitems appearing on shutdown.

/

/*!

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/7/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
Pointer to a list of NodeListItems representing the current range

Errors: -

See also:
-

Definition at line 1163 of file range.cpp.

01164 {
01165     // Create the list object first
01166     List* RangeList = new List;
01167     
01168     // only build the list if we found enough memory
01169     if (RangeList)
01170     {
01171         // Get the first object in the range to start the loop
01172         Node* pNode = FindFirst(AndChildren);
01173         BOOL Failed = FALSE;            // Will be TRUE if we ran out of memory
01174 
01175         // loop round all the objects in the range
01176         while (pNode)
01177         {
01178             if (!pNode->IsNodeHidden()) // DON'T record hidden nodes because they might be deleted!
01179             {
01180                 // Mark Howitt 13/12/00 - This is a bodge fix for the release version. As the ClipViewAttribute is
01181                 // only used by the new bevel code, it`s safe (Bodge) to make it not includable in any selections.
01182                 // This will need to be fix for future versions if we decide to start using the attribute correctly!
01183                 if(!pNode->IsAClipViewAttr())
01184                 {
01185                     NodeListItem* pItem;
01186                     if ((pItem = new NodeListItem(pNode))!=NULL)
01187                     {
01188                         // Creation successful, so add it to the list
01189                         RangeList->AddTail(pItem);
01190                     }
01191                     else
01192                     {
01193                         // Creation failed, so flag an error and break the loop
01194                         Failed = TRUE;
01195                         break;
01196                     }
01197                 }
01198             }
01199 
01200             // Go to the next node in the range
01201             pNode = FindNext(pNode, AndChildren);
01202         }
01203         // Handle an error if it occurred
01204         if (Failed)
01205         {
01206             while (!RangeList->IsEmpty())
01207             {
01208                 NodeListItem* pItem = (NodeListItem*)(RangeList->RemoveHead());
01209                 delete pItem;
01210             }
01211             delete RangeList;
01212             return NULL;
01213         }
01214 
01215     }
01216     return RangeList;
01217 }

void Range::NormaliseAttributes BOOL  AndChildren = FALSE,
BOOL  IgnoreComplex = FALSE
 

This function calls NodeRenderableInk::NormaliseAttributes on every Object in the selection.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
7/2/94 Inputs AndChildren: Normalise the attributes on children as well IgnoreComplex: When TRUE do not make attributes complete on complexcopy nodes.
Parameters:
- [OUTPUTS]
Returns:
-
See also:
NodeRenderableInk::NormaliseAttributes

Range::MakeAttributeComplete

Definition at line 1394 of file range.cpp.

01396 {
01397     BOOL Normalise;
01398     Node* Current = FindFirst(AndChildren); // First item in range
01399     while (Current != NULL)
01400     {
01401         if (Current->IsAnObject())
01402         {
01403             NodeRenderableInk* pInkObj = (NodeRenderableInk*)Current;
01404             Normalise = TRUE;
01405 
01406             if (IgnoreComplex)
01407                 if ((pInkObj->GetCopyType()) == COMPLEXCOPY)
01408                     Normalise=FALSE;
01409 
01410             // complete the attributes on this node if necessary
01411             if (Normalise)
01412                 pInkObj->NormaliseAttributes();         
01413 
01414         }
01415         Current = FindNext(Current, AndChildren);
01416     }
01417 }

BOOL Range::operator!= const Range R  )  const
 

Test for non-equality of two ranges. Ranges are considered equal if they have the same flags and the same first & last nodes. SeeAlso Range::operator==.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/1/96
Parameters:
R - the range to compare against. [INPUTS]
- [OUTPUTS]
Returns:
TRUE if R dosen't describe the same range as this range.

Errors: None.

Definition at line 6628 of file range.cpp.

06629 {
06630     return !(*this==R);
06631 }

Range & Range::operator= Range Rng  ) 
 

Range = operator.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
2/3/94
Parameters:
Range,: The range to copy [INPUTS]
[OUTPUTS] 
Returns:
The Range

Errors: -

See also:
-

Definition at line 380 of file range.cpp.

00381 {
00382     // If the range is a sel range we must be sure that the range has been cached 
00383     Rng.FreshenCache(); 
00384 
00385     RangeControlFlags = Rng.RangeControlFlags;  
00386     FirstNode = Rng.FirstNode; 
00387     LastNode = Rng.LastNode; 
00388     pCommonAttribCache = NULL;      
00389     return *this;       
00390 }

BOOL Range::operator== const Range R  )  const
 

Test for equality of two ranges. Ranges are considered equal if they have the same flags and the same first & last nodes. SeeAlso Range::operator!=.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/1/96
Parameters:
R - the range to compare against. [INPUTS]
- [OUTPUTS]
Returns:
TRUE if R describes the same range as this range.

Errors: None.

Definition at line 6601 of file range.cpp.

void Range::RenderXOROutlinesOff DocRect ClipRect,
Spread pSpread,
Matrix Transform
 

Shared code used by the rotate, select, and scale tools to XOR the object(s) being dragged onto screen. This function is used to remove XORed object outline blobs from the screen (obviously they will only be truly removed if you call it with the screen in the correct state). After the outlines have been rendered, the XOROutline renderer state is reset, so it is ready to begin a fresh pass of rendering blobs back on to the screen.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
04/03/94
Parameters:
ClipRect - NULL to just clip to the spread/window bounds, or a pointer to [INPUTS] a clipping rectangle into which the xored stuff will be clipped. Spread - The spread in which the drag is occurring Transform - A transformation matrix indicating how the blobs should be rendered - this allows use of this one routine for translation, scaling, and rotation operations.
Notes: See the selector and rotate tools for example code using this system.

See also:
SelRange::RenderXOROutlinesOn; SelRange::RenderXOROutlinesToCatcvhUp

Definition at line 2110 of file range.cpp.

02111 {
02112 #if !defined(EXCLUDE_FROM_RALPH)
02113     // If called in the correct state, the following will un-XOR the existing drag blobs
02114     // and then reset the rendering state (as we should now have a 'blank' screen, so 
02115     // there is no way we should try to un-XOR this stuff again)
02116     RenderXOROutlinesToCatchUp(ClipRect, pSpread, Transform);
02117     ResetXOROutlineRenderer(FALSE);     // Reset, but don't discard cached info
02118 #endif
02119 }

void Range::RenderXOROutlinesOn DocRect ClipRect,
Spread pSpread,
Matrix Transform,
Node ClickedObject = NULL
 

Shared code used by the rotate, select, and scale tools to XOR the object(s) being dragged on/off screen. This function will do background rendering to XOR outlines onto screen (Successive calls will render more of the selection until it has all been rendered - it must therefore be called during mouse idle events to complete redraws).

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> (moved here by Jason) (recoded by Jason)
Date:
27/10/93
Parameters:
ClipRect - NULL to just clip to the spread/window bounds, or a pointer to [INPUTS] a clipping rectangle into which the xored stuff will be clipped. Spread - The spread in which the drag is occurring Transform - A transformation matrix indicating how the blobs should be rendered - this allows use of this one routine for translation, scaling, and rotation operations. ClickedObject - NULL, or a pointer to the node object which needs to be redrawn first (the prime object). This allows super-interactive dragging, by always redrawing the object which the user clicked upon to start the drag first, so a specific thing can be easily positioned without waiting hours for redraw. Note that the 'ClickedObject' is cached during the first call, so it need only be passed in the first time you call this function.
Notes: See the selector and rotate tools for example code using this system.

See also:
SelRange::RenderXOROutlinesOff; SelRange::RenderXOROutlinesToCatcvhUp

Definition at line 2155 of file range.cpp.

02157 {
02158     // DMc
02159     // promote the clicked object to any parents which take care of their own eor drag
02160     // rendering
02161     if (ClickedObject)
02162     {
02163         Node * pLastParent = ClickedObject;
02164         Node * pParent = ClickedObject->FindParent();
02165         
02166         while (pParent)
02167         {
02168             if (pParent->IsAnObject())
02169             {
02170                 if (((NodeRenderableInk *)pParent)->ChildrenAreEorDragRenderedByMe())
02171                 {
02172                     pLastParent = pParent;
02173                 }
02174             }
02175             
02176             pParent = pParent->FindParent();
02177         }
02178         
02179         ClickedObject = pLastParent;
02180     }
02181 
02182     BOOL bPromote = RangeControlFlags.PromoteToParent;
02183     RangeControlFlags.PromoteToParent = TRUE;
02184 
02185 #if !defined(EXCLUDE_FROM_RALPH)
02186     CacheXOROutlineInfo(pSpread, ClickedObject);
02187 
02188         // If we have drawn nothing so far, find the first object
02189     if (NumObjectsDrawn == 0)
02190         NodeToRender = NULL;
02191     else
02192     {
02193         if (RenderingPass == RENDER_END)
02194         {
02195             RangeControlFlags.PromoteToParent = bPromote;
02196             return; // No more to be drawn
02197         }
02198     
02199         if (NodeToRender == NULL)       // If starting fresh redraw, ensure counter zeroed
02200             NumObjectsDrawn = 0;
02201     }
02202 
02203 #if ENABLE_FAST_XOR
02204     // The following significantly speeds up XOR redrawing
02205     // The problem is that we want to multitask while drawing blobs on, so
02206     // we must draw each object into ALL render regions. The code below works,
02207     // but has to create a new render region for each invalid region for each
02208     // node, so is *very* slow.
02209     // However, in the case where there is only one render region (often the case
02210     // when dragging in a topped window, and apparently also the case under Windows,
02211     // which gives you an all-encompassing rectangle and does the clipping to the
02212     // arbitrary invalid region itself), we can just select that region, draw
02213     // all the objects we can, and then deselect the region. Much faster
02214 
02215     // First, count the number of render regions with a dummy rendering loop...
02216     INT32 RegionCount = 0;
02217     RenderRegion* pRegion = DocView::RenderOnTop( ClipRect, pSpread, ClippedEOR );
02218     while ( pRegion )
02219     {
02220         RegionCount++;
02221         pRegion = DocView::GetNextOnTop( ClipRect );
02222     }
02223 
02224     if (RegionCount == 1)       // There is ony one render region, so we can draw much faster
02225     {
02226         MonotonicTime RenderClock;
02227         RenderRegion* pRegion = DocView::RenderOnTop( ClipRect, pSpread, ClippedEOR );
02228 
02229         // Need to tell the render region to transform the objects a bit first.
02230         Matrix OldRenderMatrix = pRegion->ConcatenateMatrix( *Transform );
02231 
02232         // Draw the original bounding box in it's rotated/translated position, but only
02233         // on the first pass - we don't want the box flashing on and off!
02234         if (NumObjectsDrawn == 0)
02235         {
02236             DocRect Bounds = GetBoundingRectForEorDragging();
02237 
02238             DrawXORBoundingRect(pRegion, Bounds);
02239         }
02240         
02241         // Set the line colour and fill colour
02242         pRegion -> SetFillColour( COLOUR_TRANS );
02243         pRegion -> SetLineColour( COLOUR_XORDRAG );
02244 
02245         while (!RenderClock.Elapsed( 90 ))
02246         {
02247             FindNextXOROutlineNode(&NodeToRender, ClipRect);
02248 
02249             if (NodeToRender == NULL)
02250                 break;      // Nothing more to render - exit
02251 
02252             // Render the next node that needs rendering
02253             if (NodeToRender->IsRenderable() || ForceRenderEORAll()) ((NodeRenderableInk*)NodeToRender) -> RenderEorDrag( pRegion );
02254 
02255             // Keep the count of what we have drawn
02256             NumObjectsDrawn++;
02257         }
02258 
02259         // OK, we have finished with this render region, so set the matrix
02260         // back to how we found it and get the next one
02261         pRegion -> SetMatrix( OldRenderMatrix );
02262         pRegion = DocView::GetNextOnTop( ClipRect );
02263 
02264         ERROR3IF(pRegion != NULL, "FastXor drawing failed - There is another render region!");
02265 
02266         RangeControlFlags.PromoteToParent = bPromote;
02267         return;
02268     }
02269     
02270     //... else drop through to the normal slow rendering loop
02271 
02272 #endif
02273 
02274 
02275     // Start a clock to tell us how long we have been rendering
02276     MonotonicTime RenderClock;
02277     while ( !RenderClock.Elapsed( 90 ) )
02278     {
02279         FindNextXOROutlineNode(&NodeToRender, ClipRect);
02280         if (NodeToRender == NULL)
02281         {
02282             RangeControlFlags.PromoteToParent = bPromote;
02283             return;             // Nothing else to draw, may as well stop
02284         }
02285 
02286         // Start up a bit of a RenderOnTop loop type of thing to do all the rendering
02287         RenderRegion* pRegion = DocView::RenderOnTop( ClipRect, pSpread, ClippedEOR );
02288         while ( pRegion )
02289         {
02290             // Need to tell the render region to transform the objects a bit first.
02291             Matrix OldRenderMatrix = pRegion->ConcatenateMatrix( *Transform );
02292 
02293             // Draw the original bounding box in it's rotated/translated position, but only
02294             // on the first pass - we don't want the box flashing on and off!
02295             if (NumObjectsDrawn == 0)
02296             {
02297                 DocRect Bounds = GetBoundingRectForEorDragging();
02298                 DrawXORBoundingRect(pRegion, Bounds);
02299             }
02300             
02301             // Set the line colour and fill colour
02302             pRegion -> SetFillColour( COLOUR_TRANS );
02303             pRegion -> SetLineColour( COLOUR_XORDRAG );
02304 
02305             // Render the next node that needs rendering
02306             if (NodeToRender->IsRenderable() || ForceRenderEORAll()) ((NodeRenderableInk*)NodeToRender) -> RenderEorDrag( pRegion );
02307 
02308             // OK, we have finished with this render region, so set the matrix
02309             // back to how we found it and get the next one
02310             pRegion -> SetMatrix( OldRenderMatrix );
02311             pRegion = DocView::GetNextOnTop( ClipRect );
02312         }
02313         
02314         // Keep the count of what we have drawn
02315         NumObjectsDrawn++;
02316     }
02317 #endif
02318 
02319     RangeControlFlags.PromoteToParent = bPromote;
02320 
02321 }

void Range::RenderXOROutlinesToCatchUp DocRect ClipRect,
Spread pSpread,
Matrix Transform
 

Shared code used by the rotate, select, and scale tools to XOR the object(s) being dragged onto screen. This function is used when an area is redrawn during a drag (e.g. scrolling the window forces a redraw) to 'catch up' to the XOR outlines already present in other areas of the screen (i.e. it redraws everything that should already be on screen in unchanged areas into the invalidated area, so that XOR dragging can continue without leaving mess behind.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> (moved here by Jason) (recoded and renamed by Jason)
Date:
27/10/93 (new lease of life 04/03/94)
Parameters:
ClipRect - NULL to just clip to the spread/window bounds, or a pointer to [INPUTS] a clipping rectangle into which the xored stuff will be clipped. Spread - The spread in which the drag is occurring Transform - A transformation matrix indicating how the blobs should be rendered - this allows use of this one routine for translation, scaling, and rotation operations.
Notes: See the selector and rotate tools for example code using this system. This function is identical to RenderXOROutlinesOff, only it preserves the current state of background redraw, so that XOR state will not be corrupted.

See also:
SelRange::RenderXOROutlinesOn; SelRange::RenderXOROutlinesOff

Definition at line 2032 of file range.cpp.

02033 {
02034 #if !defined(EXCLUDE_FROM_RALPH)
02035     BOOL bPromote = RangeControlFlags.PromoteToParent;
02036     RangeControlFlags.PromoteToParent = TRUE;
02037 
02038     INT32 OldRenderingPass = RenderingPass; // Preserve previous rendering pass
02039 
02040     // Start up a bit of a RenderOnTop loop type of thing to do all the rendering
02041     RenderRegion* pRegion = DocView::RenderOnTop( ClipRect, pSpread, ClippedEOR );
02042     while ( pRegion )
02043     {
02044         // Need to tell the render region to transform the objects a bit first.
02045         Matrix OldRenderMatrix = pRegion->ConcatenateMatrix( *Transform );
02046 
02047         DocRect Bounds = GetBoundingRectForEorDragging();
02048         DrawXORBoundingRect(pRegion, Bounds);
02049 
02050         // Set the line colour and fill colour
02051         pRegion -> SetFillColour( COLOUR_TRANS );
02052         pRegion -> SetLineColour( COLOUR_XORDRAG );
02053 
02054         // Render the first NumObjectsDrawn objects
02055         Node *CurrentNode = NULL;
02056         RenderingPass = RENDER_START;
02057 
02058         for (INT32 i=0; i<NumObjectsDrawn; i++)
02059         {
02060             // Find and draw the next object
02061             FindNextXOROutlineNode(&CurrentNode, ClipRect);
02062             if (CurrentNode == NULL)
02063                 break;              // Shouldn't happen, but best to be safe
02064 
02065             if (CurrentNode->IsRenderable() || ForceRenderEORAll()) ((NodeRenderableInk*)CurrentNode)->RenderEorDrag(pRegion);
02066         }
02067 
02068         // OK, we have finished with this render region, so set the matrix
02069         // back to how we found it and get the next one
02070         pRegion -> SetMatrix( OldRenderMatrix );
02071         pRegion = DocView::GetNextOnTop( ClipRect );
02072     }
02073 
02074     RenderingPass = OldRenderingPass;   // Restore previous rendering pass info
02075 
02076     RangeControlFlags.PromoteToParent = bPromote;
02077 
02078 #endif
02079 }

void Range::ResetXOROutlineRenderer BOOL  FlushTheCache = TRUE  ) 
 

Definition at line 1636 of file range.cpp.

01637 {
01638     NumObjectsDrawn = 0;
01639     RenderingPass   = RENDER_START;
01640 
01641     if (FlushTheCache)          // Ensure info cache is cleared     
01642     {
01643         XORInfo.PrimeObject = NULL;
01644         XORInfo.SigRegion.MakeEmpty();
01645         XORInfo.SigRegionIsScreen = TRUE;
01646         XORInfo.Cached = FALSE;
01647     }
01648 
01649     
01650 }

void Range::SetDraggedNodes BOOL  bNewState = FALSE  )  [virtual]
 

Definition at line 3756 of file range.cpp.

03757 {
03758     Node* pNode;
03759 
03760     pNode = FindFirst();
03761     while (pNode)
03762     {
03763 //      if (pNode->IsBounded())
03764 //          ((NodeRenderableBounded*)pNode)->SetDraggedState(bNewState, TRUE);
03765         if (pNode->IsNodeRenderableClass())
03766             ((NodeRenderable*)pNode)->SetDraggedState(bNewState, TRUE);
03767 
03768         pNode = FindNext(pNode);
03769     }
03770 }

virtual BOOL Range::SetPromoteToParent BOOL  bNewValue  )  [inline, virtual]
 

Definition at line 422 of file range.h.

void Range::SetRangeControl RangeControl  RangeControlFlgs  ) 
 

To set the range control for the range.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/6/93
Parameters:
RangeControlFlags,: Specifies the selected status of the nodes to be included [INPUTS] in the range.
- [OUTPUTS]
Returns:
-

Errors: -

See also:
-

Reimplemented in SelRange.

Definition at line 412 of file range.cpp.

00413 {
00414     RangeControlFlags = RangeControlFlgs;
00415 }   

void Range::SetRenderable BOOL  bNewVis = FALSE  )  [virtual]
 

Definition at line 3519 of file range.cpp.

03520 {
03521     Node* pNode;
03522 
03523     pNode = FindFirst();
03524     while (pNode)
03525     {
03526         pNode->SetRender(bNewVis, TRUE);
03527 //      if (pNode->IsAnObject()) ((NodeRenderableInk*)pNode)->ReleaseCached();
03528 
03529         pNode = FindNext(pNode);
03530     }
03531 }

Node * Range::SmartFindNext Node pContext,
BOOL  AndChildren = FALSE,
BOOL  FindFirst = FALSE
const [protected, virtual]
 

Definition at line 838 of file range.cpp.

00839 {
00840     // Preconditions
00841     ERROR2IF(this==NULL,NULL,"SmartFindNext called on NULL range");
00842     ERROR2IF(pContext==NULL,NULL,"SmartFindNext not given a context node to start from");
00843     ERROR2IF(RangeControlFlags.Unselected && AndChildren,NULL,"Range can't cope with unsel and children");
00844     ERROR2IF(pContext->IsPaper() && !pContext->IsLayer(),NULL,"SmartFindNext called above layers surface");
00845 
00846     // If the PromoteToParent flag is set then the context node might be a "promoted parent"
00847     if (RangeControlFlags.PromoteToParent && !FirstCall && !AndChildren)
00848     {
00849         // Using PromoteToParent, it is possible for the context node to jump *above* the
00850         // last node in the Range, causing us to iterate outside of it. We must therefore
00851         // check whether the context node is a parent of the last node, in which case
00852         // we have finished iteration.
00853         if (pContext->IsNodeInSubtree(LastNode))
00854             return NULL;
00855 
00856         // If the context node's parents wish to do so, then switch them in instead of it.
00857         // Go up the tree until this is no longer the case.
00858         Node* pParent = pContext->FindParent();
00859         while (pParent != NULL && pParent->ShouldITransformWithChildren())
00860         {
00861             pContext = pParent;
00862             pParent = pContext->FindParent();
00863         }
00864     }
00865 
00866     // Implementation
00867     // Loop, looking for suitable nodes and testing whether they're in the range or not.
00868     // Traverses the tree in basically depth-first order...
00869     do
00870     {
00871         // If context node from previous findnext was last node then there can be no more...
00872         if (!FirstCall && LastNode!=NULL && pContext==LastNode) return NULL;
00873 
00874         // Do the normal depth-first thing; assume subtree we're given has already been
00875         // met and so try to find lowest leaf of next subtree...
00876         // (If this is the first call, from FindFirst, then treat the node we've got
00877         //  as if it hasn't been scanned yet. 'Cos it hasn't!)
00878         if (pContext->FindNext() || FirstCall)
00879         {
00880             // Here, either have a sibling or FirstCall is TRUE
00881             // So, if firstcall is NOT TRUE, must be here due to sibling...
00882             if (!FirstCall)
00883                 pContext = pContext->FindNext();                    // Find top of next subtree
00884             FirstCall = FALSE;
00885 
00886             // In a normal depth-first traversal of the tree we would find the deepest first child
00887             // in the subtree. However, by choosing not to go down certain child links
00888             // we can omit whole subtrees from the scan.
00889             // The following tests optimise away much of the work of a true depth-first
00890             // search by pruning subtrees that don't need to be traversed.
00891 
00892             //---------------------------------------------------------------------------//
00893             // If above layers, skip on down towards one...
00894             while (pContext->FindFirstChild() && !pContext->IsLayer() && pContext->IsPaper())
00895                 pContext = pContext->FindFirstChild();
00896             // If we've not made it to a layer and we're still in paper then prune whatever
00897             // subtree we have because this routine is interested in children of layers and
00898             // their subtrees.
00899             if (pContext->IsPaper() && !pContext->IsLayer())
00900                 goto PruneSubtree;
00901 
00902             //---------------------------------------------------------------------------//
00903             // We know now we're either at a layer node or underneath one...
00904             // If this layer has children go down to that level because that surface has
00905             // a special meaning to this routine. Most ranges are found in the child lists
00906             // of Layers.
00907             if (pContext->IsLayer())
00908             {
00909                 // Don't allow Ranges into invisible layers at all!
00910                 // New range control flag allows this to be overriden, defaults to FALSE
00911                 if ( !RangeControlFlags.IgnoreInvisibleLayers && !((Layer*)pContext)->IsVisible() )
00912                     goto PruneSubtree;
00913 
00914                 // Don't allow SelRanges into locked layers at all!
00915                 // New range control flag allows this to be overriden, defaults to FALSE
00916                 if ( RangeControlFlags.IgnoreLockedLayers && ((Layer*)pContext)->IsLocked() )
00917                     goto PruneSubtree;
00918 
00919                 // If layer has children go find first child and continue pruning tests
00920                 if (pContext->FindFirstChild())
00921                     pContext = pContext->FindFirstChild();
00922                 // Otherwise don't try to process empty layers at all!
00923                 else
00924                     goto PruneSubtree;
00925             }
00926 
00927             //---------------------------------------------------------------------------//
00928             // Descend subtree further if we come across select-inside (flagged by ParentOfSelected)
00929             // If looking for selected nodes (and not unselected nodes - Ed 1/5/95)
00930             // AND this node is the parent of selected nodes
00931             // Then go down this subtree as far as the parent of selected
00932             // flags last out...
00933             if (pContext->IsParentOfSelected() && RangeControlFlags.Selected && !RangeControlFlags.Unselected)
00934             {
00935                 while (pContext->IsParentOfSelected() && pContext->FindFirstChild())
00936                 {
00937                     pContext = pContext->FindFirstChild();
00938                 }
00939                 ERROR3IF(pContext->IsParentOfSelected(),"Parent of selected has no children!");
00940             }
00941 
00942 // Logically, if promotetoparent is not set we shouldn't return any node which would
00943 // be the target of promotetoparent activities...
00944 if (!RangeControlFlags.PromoteToParent && RangeControlFlags.Selected && RangeControlFlags.Unselected)
00945 {
00946     while (pContext->ShouldITransformWithChildren() && pContext->FindFirstChild())
00947     {
00948         pContext = pContext->FindFirstChild();
00949     }
00950     ERROR3IF(pContext->ShouldITransformWithChildren(), "Parent of selected has no children!");
00951 }
00952 
00953             //---------------------------------------------------------------------------//
00954             // Finally, there's no choice any more, we've got to descend into the subtree IF
00955             // the AndChildren flag is set and the node is a Primary member of the range
00956             // Then we are either already scanning a subtree and so we must continue
00957             // or else we're starting to scan a subtree because it meets the range
00958             // criteria and the range specifies that all child nodes of primary nodes
00959             // should be returned.
00960             // So, look for lowest leaf of subtree...
00961             if (!RangeControlFlags.SiblingsOnly && AndChildren)
00962             {
00963                 Node* pChild = pContext->FindFirstChild();
00964                 while (pChild)
00965                 {
00966                     if (InRange(pChild, AndChildren))
00967                     {
00968                         pContext=pChild;
00969                         pChild=pChild->FindFirstChild();
00970                     }
00971                     else
00972                         pChild=pChild->FindNext();
00973                 }
00974             }
00975 
00976             //---------------------------------------------------------------------------//
00977             // If control gets here then the root of the "next" subtree is being returned for
00978             // consideration because we have judged that its subtree doesn't need scanning!
00979 PruneSubtree:;
00980 
00981         }
00982         else
00983         {
00984             // No next subtree, so go up to parent...
00985             // If no parent then we must have scanned the entire tree (by definition of
00986             // depth-first traversal) so return NULL to caller.
00987             pContext = pContext->FindParent();
00988 
00989             // If we're not promoting to parent and we find our parent is the type of object we would normally
00990             // promote to, DON'T return it, keep going up!
00991             // (It doesn't make sense to return a node and it's parent controller)
00992             // This change made so that a shadowed node on the clipboard will return a set of sensible
00993             // common attributes when FindCommonAttributes is called on the clipboard range.
00994             // Test by using Paste Attributes
00995 // NOPE, THIS DOESN'T WORK!
00996 //          while (pContext && !AndChildren && !RangeControlFlags.PromoteToParent && pContext->ShouldITransformWithChildren())
00997 //          {
00998 //              pContext = pContext->FindParent();
00999 //          }
01000 
01001             if (pContext==NULL)
01002                 return NULL;
01003 
01004             // Ranges cannot exist across spreads so if we reach a Spread node we can stop...
01005             if (pContext->IsSpread())
01006                 return NULL;
01007 
01008             if (pContext->IsLayer() && !RangeControlFlags.CrossLayer)
01009                 // Can't cross layers so signal end of Range...
01010                 return NULL;
01011         }
01012     }
01013     while (pContext!=NULL && (pContext->IsLayer() || pContext->IsPaper() || !InRange(pContext, AndChildren)));
01014 
01015     // Finally, check for parents wanting to be included instead of the children
01016     if (pContext != NULL && RangeControlFlags.PromoteToParent && !AndChildren)
01017     {
01018         Node *pParent = pContext->FindParent();
01019         while (pParent != NULL && pParent->ShouldITransformWithChildren())
01020         {
01021             pContext = pParent;
01022             pParent = pContext->FindParent();
01023         }
01024     }
01025 
01026     return pContext;
01027 }

BOOL Range::TransformNodes TransformBase Trans  )  [virtual]
 

Definition at line 3684 of file range.cpp.

03685 {
03686     // If the Trans is invertible then create a Transform node action to undo the transform
03687     // Note at this point Trans is not the inverse Transformation, but it will be soon !!
03688 //  Node* pParent = NULL;
03689 //  Node* pNodeToTransform = NULL;
03690 
03691     // Assume that the transformation is invertible
03692     // If we test for it below, the test explodes when the matrix scale factor is zero.
03693 //  if (Trans->IsInvertable()) 
03694     {
03695         // Scan the range and transform each node 
03696         Node* Current = FindFirst();
03697         Node* Next; 
03698 //      Node* Parent = NULL;
03699 //      BOOL bTransform = FALSE;
03700         while (Current != NULL)
03701         {
03702             Next = FindNext(Current); 
03703 
03704             if (Current->IsNodeRenderableClass())
03705             {
03706                 Trans->bHaveTransformedCached = TRUE;
03707                 Trans->bHaveTransformedChildren = TRUE;
03708 
03709                 ((NodeRenderable*)Current)->Transform(*Trans);
03710 
03711                 ERROR3IF(!Trans->bHaveTransformedCached && !Trans->bHaveTransformedChildren,
03712                          "Node::Transform has failed to either transform its children or transform its cached data"
03713                         );
03714 
03715                 ERROR3IF(Trans->bTransformYourChildren && !Trans->bHaveTransformedChildren,
03716                          "Node::Transform was told to transform its children but says it hasn't done so"
03717                         );
03718 
03719                 Trans->bHaveTransformedAllCached = Trans->bHaveTransformedAllCached && Trans->bHaveTransformedCached;
03720                 Trans->bHaveTransformedAllChildren = Trans->bHaveTransformedAllChildren && Trans->bHaveTransformedChildren;
03721 
03722             }
03723             
03724             Current = Next;  
03725         }
03726 
03727     }
03728 //  else // The Trans is not invertable
03729 //  {
03730 //      ERROR2(FALSE, "Range::TransformNodes can't do non-invertible transforms yet");
03731 //  }
03732 
03733     return (TRUE); // Success 
03734 }   

void Range::Update BOOL  TellWorld = FALSE  )  [virtual]
 

To inform the SelRange that the selection has changed This invalidates the SelRange's selection-info cache so it will be recached when info is next requested.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
03/10/94 (Was an inline function prior to this)
Parameters:
BOOL TellWorld: When TRUE the function will inform the world that the [INPUTS] selection has changed. Normally the selection is changed in an operation and it is unneccesary to broadcast a SelChangingMsg at this point because this will occur at the end of the operation. However If the selection is changed outside of an operation then the flag should be set to TRUE.
- [OUTPUTS]
Returns:
-

Definition at line 674 of file range.cpp.

00675 {
00676     Camelot.FindSelection()->Update(TellWorld);     
00677 }   

void Range::UpdateParentBoundsOfSelection BOOL  AndChildren = FALSE  ) 
 

This function updates the parent bounds of all selected objects. It is a lot more efficient than calling ChangeBounds on every node in the selection (cos it uses an algorithm!).

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
15/7/94
See also:
NodeRenderableBounded::ChangeBounds

Definition at line 1233 of file range.cpp.

01234 {
01235     // Find the first node in the selection
01236     Node* pNode = FindFirst(AndChildren);
01237     
01238     // loop through the selection, invalidating all the bounding rects
01239     while (pNode!=NULL)
01240     {
01241         // If the node was bounded, then invalidate its bounding rect
01242         if (pNode->IsBounded())
01243             ((NodeRenderableBounded*)pNode)->InvalidateBoundingRect();
01244 
01245         // Get the next node in the selection
01246         pNode = FindNext(pNode, AndChildren);
01247     }
01248 
01249 // Below is the old version of this function, that used to use change bounds
01250 // Since this no longer exists, a new bit of code has been created
01251 #if 0
01252     Node* Current = FindFirst(); 
01253     Node* UpdatedDaddy = NULL;
01254     Node* CurrentDaddy;
01255 
01256     NodeRenderableBounded* CurrentBound; 
01257 
01258     // For each selected node
01259     while(Current != NULL)
01260     {
01261         if (Current->IsAnObject())
01262         {
01263             // Find out Current's dad
01264             CurrentDaddy = Current->FindParent(); 
01265         
01266             CurrentBound = (NodeRenderableBounded*)Current;
01267 
01268             if (UpdatedDaddy != CurrentDaddy)
01269             {
01270                 // We need to update CurrentDaddy
01271                 CurrentBound->InvalidateBoundingRect();
01272 
01273                 // Remember that CurrentDaddy has been updated
01274                 UpdatedDaddy = CurrentDaddy;    
01275             }
01276         }
01277         Current = FindNext(Current);        
01278     }
01279 #endif
01280 } 


Member Data Documentation

Node* Range::FirstNode [protected]
 

Definition at line 441 of file range.h.

Node* Range::LastNode [protected]
 

Definition at line 442 of file range.h.

Node* Range::NodeToRender
 

Definition at line 369 of file range.h.

INT32 Range::NumObjectsDrawn [protected]
 

Definition at line 447 of file range.h.

CommonAttrSet* Range::pCommonAttribCache [protected]
 

Definition at line 432 of file range.h.

RangeControl Range::RangeControlFlags [protected]
 

Definition at line 439 of file range.h.

INT32 Range::RenderingPass [protected]
 

Definition at line 448 of file range.h.

XOROutlineInfoStr Range::XORInfo [protected]
 

Definition at line 451 of file range.h.


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