#include <range.h>
Inheritance diagram for Range:
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. | |
Range & | operator= (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 Node * | FindFirst (BOOL AndChildren=FALSE) |
The purpose of this function is to find the first node in a range. | |
virtual Node * | FindLast () |
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 Node * | FindNext (Node *Previous, BOOL AndChildren=FALSE) |
virtual Node * | FindPrev (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. | |
List * | 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. | |
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 Range * | CloneNodes (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 | |
Node * | NodeToRender |
Protected Member Functions | |
CommonAttrSet * | GetCommonAttrCache () |
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 Node * | SmartFindNext (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 | |
CommonAttrSet * | pCommonAttribCache |
RangeControl | RangeControlFlags |
Node * | FirstNode |
Node * | LastNode |
INT32 | NumObjectsDrawn |
INT32 | RenderingPass |
XOROutlineInfoStr | XORInfo |
Definition at line 311 of file range.h.
|
Definition at line 387 of file range.h. 00387 { ATTR_COMMON, ATTR_NONE, ATTR_MANY };
|
|
Creates an uninitialised range.
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 }
|
|
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 }
|
|
The purpose of this function is to create a node 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.
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 copy constructor.
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 }
|
|
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.
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.
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 }
|
|
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.
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 }
|
|
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()
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 }
|
|
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).
Scope: private
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 }
|
|
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 }
|
|
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)
This is used by the WebAddressDlg, which needs to know whether the selection consists entirely of text.
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 }
|
|
To determin whether a particular node is actually in the range list.
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 }
|
|
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 }
|
|
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.
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 }
|
|
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 }
|
|
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 }
|
|
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 }
|
|
Find out if there is a valid bitmap in the selection and return useful information to the caller.
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 }
|
|
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.
ATTR_MANY: There is no common attribute, pAttribute will be NULL
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 }
|
|
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.
CompoundAccuracy: TRUE => Accurate results with compound objects. This requires more work. This is important in some cases eg. PasteAttributes.
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.
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 }
|
|
To determine if all objects in the selection share attributes with the same type.
ATTR_MANY: There is no common attribute type, pCommonType will be NULL
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 }
|
|
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.
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 }
|
|
The purpose of this function is to find the first node in a range.
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 }
|
|
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 !.
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 }
|
|
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 }
|
|
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.
Notes: See the selector and rotate tools for example code using this system. Scope: private
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 }
|
|
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 }
|
|
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 }
|
|
Definition at line 334 of file range.h. 00334 { return TRUE; }
|
|
Reimplemented in SelRange. Definition at line 330 of file range.h.
|
|
To determine the bounds of all objects in the range.
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 }
|
|
Same as for GetBoundingRect() but calls GetDragEorBoundingRect for all nodes.
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 }
|
|
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.
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 }
|
|
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.
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 }
|
|
Definition at line 332 of file range.h. 00332 { return RangeControlFlags; }
|
|
Private helper function for SmartFindNext. Tests whether the presented node is in the range according to the RangeControlFlags and two other locally presented flags.
This function should ONLY be called on nodes that /could/ be members of Range Not Layers or Paper nodes! Scope: Protected
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 }
|
|
Determines whether the range is empty. BOOL Range::IsEmpty()
Definition at line 3496 of file range.cpp.
|
|
This function calls NodeRenderableInk::MakeAttributeComplete on every Object in the selection. If we run out of memory then all changes are undone.
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 }
|
|
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. / /*!
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 }
|
|
This function calls NodeRenderableInk::NormaliseAttributes on every Object in the selection.
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 }
|
|
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==.
Definition at line 6628 of file range.cpp.
|
|
Range = operator.
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 }
|
|
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!=.
Definition at line 6601 of file range.cpp. 06602 { 06603 return (R.RangeControlFlags.Selected == RangeControlFlags.Selected && 06604 R.RangeControlFlags.Unselected == RangeControlFlags.Unselected && 06605 R.RangeControlFlags.CrossLayer == RangeControlFlags.CrossLayer && 06606 R.RangeControlFlags.IgnoreLockedLayers == RangeControlFlags.IgnoreLockedLayers && 06607 R.RangeControlFlags.IgnoreNoneRenderable == RangeControlFlags.IgnoreNoneRenderable && 06608 R.RangeControlFlags.IgnoreInvisibleLayers == RangeControlFlags.IgnoreInvisibleLayers && 06609 R.FirstNode == FirstNode && 06610 R.LastNode == LastNode); 06611 }
|
|
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.
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 }
|
|
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).
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 }
|
|
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.
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 }
|
|
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 }
|
|
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 }
|
|
Definition at line 422 of file range.h. 00422 {BOOL b = RangeControlFlags.PromoteToParent; RangeControlFlags.PromoteToParent = bNewValue; return b;}
|
|
To set the range control for the range.
Reimplemented in SelRange. Definition at line 412 of file range.cpp. 00413 { 00414 RangeControlFlags = RangeControlFlgs; 00415 }
|
|
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 }
|
|
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 }
|
|
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 }
|
|
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.
Definition at line 674 of file range.cpp. 00675 { 00676 Camelot.FindSelection()->Update(TellWorld); 00677 }
|
|
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!).
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 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|