OpGroup Class Reference

This class represents the Group operation. More...

#include <groupops.h>

Inheritance diagram for OpGroup:

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

Public Member Functions

 OpGroup ()
 OpGroup constructor.
void Do (OpDescriptor *)
 Performs the Group operation.
virtual BOOL MayChangeNodeBounds () const

Static Public Member Functions

static BOOL Init ()
 OpGroup initialiser method.
static OpState GetState (String_256 *, OpDescriptor *)
 For finding the OpGroup's state.

Private Member Functions

BOOL NeedToInvalidateGroup ()
 This function determines if the selected objects will need to be invalidated if they are to be made into a group.

Static Private Attributes

static BOOL bAskBeforeFactoringEffects
static BOOL bLocaliseEffects

Friends

class OpUngroup

Detailed Description

This class represents the Group operation.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
9/7/93
See also:
OpUnGroup Documentation: specs.doc

Definition at line 128 of file groupops.h.


Constructor & Destructor Documentation

OpGroup::OpGroup  ) 
 

OpGroup constructor.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/9/93

Definition at line 172 of file groupops.cpp.

00172                 : SelOperation()                                
00173 {                              
00174 }


Member Function Documentation

void OpGroup::Do OpDescriptor  )  [virtual]
 

Performs the Group operation.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/8/93
Parameters:
OpDescriptor (unused) [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
-

Reimplemented from Operation.

Definition at line 361 of file groupops.cpp.

00362 {   
00363     // Obtain the current selections 
00364     Range Sel(*(GetApplication()->FindSelection()));
00365     RangeControl rg = Sel.GetRangeControlFlags();
00366     rg.PromoteToParent = TRUE;
00367     Sel.Range::SetRangeControl(rg);
00368 
00369     // Find the first node which is selected 
00370     Node* FirstSelectedNode = Sel.FindFirst(); 
00371     
00372     ENSURE(FirstSelectedNode != NULL, "Called group operation with no nodes selected"); 
00373     
00374     HideNodeAction* UndoHideNodeAction; 
00375 
00376     // In the retail build it is best to do nothing if we find there are no selected nodes 
00377     if (FirstSelectedNode != NULL) // No nodes selected so End
00378     {   
00379         // Get the current tool
00380         Tool* pTool = Tool::GetCurrent();
00381         Spread* pSelSpread = Document::GetSelectedSpread();
00382 
00383         // Get the tool to remove all its blobs before we deselect the nodes.
00384         // Only do this if the current tool dosent update itself on sel changed messages
00385         if (pSelSpread!=NULL && pTool!=NULL && !pTool->AreToolBlobsRenderedOnSelection())
00386             pTool->RenderToolBlobs(pSelSpread,NULL);
00387 
00388         // Determine if it will be neccessary to invalidate the groups bounds
00389         BOOL InvalidateBounds = TRUE; 
00390         BOOL IfBgRedraw = !NeedToInvalidateGroup();
00391 
00392         // Draw blobs if we are not invalidating the object bounds
00393         if (!DoStartSelOp(IfBgRedraw,IfBgRedraw)) 
00394         {
00395             End();
00396             return;
00397         }
00398         
00399         if (InvalidateBounds)
00400         {
00401             // We need to invalidate the region
00402             if (!DoInvalidateNodesRegions(Sel, TRUE, FALSE, IfBgRedraw))
00403             {
00404                 End();
00405                 return;
00406             } 
00407         }
00408 
00409         // Go and find the spread that the selected objects are on
00410 #ifdef _DEBUG
00411         Spread* pSpread = FirstSelectedNode->FindParentSpread();
00412         ENSURE(pSpread != NULL, "A selected nodes spread is NULL"); 
00413 #endif
00414 
00415         // Find the selected node with the highest z-order position, as we will need to insert 
00416         // the group node here
00417         Node* FinalNode = NULL; 
00418 
00419         for(Node* n = Sel.FindFirst(); n != NULL; n = Sel.FindNext(n))
00420         {   
00421             FinalNode = n; 
00422         }
00423 
00424         ENSURE(FinalNode != NULL, "The final selected node is NULL ?"); 
00425                                         
00426         // Create a group node and attach it as a next sibling of the final selected node    
00427         NodeGroup* Group; 
00428         ALLOC_WITH_FAIL(Group, (new NodeGroup(FinalNode, NEXT)), this);
00429         // If the allocation fails the FailAndExecute will have been called 
00430         if (Group != NULL)                 
00431         {    
00432             // Create an action to hide the group when we undo 
00433             if ( HideNodeAction::Init(this, 
00434                  &UndoActions, 
00435                  Group, 
00436                  FALSE, // Don't include subtree size
00437                  (Action**)(&UndoHideNodeAction),
00438                  FALSE) // Don't tell subtree when undone
00439                  == AC_FAIL)  
00440             {
00441                 Group->UnlinkNodeFromTree();
00442                 delete (Group); 
00443 
00444                 End();
00445                 return;
00446             };
00447                
00448             // Take each node in the range and attach it to the NodeGroup
00449             Node* n = Sel.FindFirst(); // Get first node to be added to group   
00450     
00451             // Loop until all nodes in range have been added to the group   
00452             Node* NxtInRange; 
00453             
00454             Node* LastObjectMoved = NULL;   
00455               
00456             DocRect GroupBounds; // bounding rectangle of the group  
00457             while (n != NULL) // Stop when there are no more selected nodes. 
00458             {                                                     
00459                 // Ensure that the selected node is a NodeRenderableInk
00460                 ENSURE(n->IsAnObject(), 
00461                        "Selected node is not a NodeRenderableInk");    
00462                 NxtInRange = Sel.FindNext(n); // Neccessary because n is 
00463                                               // just about to be moved
00464                 // Attach n to NodeGroup 
00465                 if (LastObjectMoved == NULL)
00466                 {
00467                     if (!DoMoveNode((NodeRenderableInk*)n, Group, LASTCHILD)) 
00468                     {
00469                         End();
00470                         return;
00471                     }
00472                 }
00473                 else
00474                 {
00475                     // We can do it quicker
00476                     if (!DoMoveNode((NodeRenderableInk*)n, LastObjectMoved, NEXT)) 
00477                     {
00478                         End();
00479                         return;
00480                     }
00481                 }
00482 
00483                 // Deselect the object
00484                 // Botch - until selstate restores child states
00485                 //if (!DoDeselectNode(((NodeRenderableInk*)n)))
00486                 //{
00487                 //  goto EndOperation;
00488                 //}
00489                 ((NodeRenderableInk*)n)->DeSelect(FALSE, TRUE); 
00490 
00491                 GroupBounds = 
00492                     GroupBounds.Union( ((NodeRenderableBounded*)n)->GetBoundingRect());
00493                 
00494                 
00495                 LastObjectMoved = n; 
00496 
00497                 n = NxtInRange;                 // Get the next node in the range   
00498             } 
00499             
00500                  
00501             // Set the group's bounding rectangle 
00502             Group->InvalidateBoundingRect();
00503 
00504             // Select the group and draw its blobs   
00505             ((NodeRenderable*)Group)->Select(FALSE);
00506             
00507             if (InvalidateBounds)
00508             {
00509                 if (!DoInvalidateNodesRegions(*(GetApplication()->FindSelection()), TRUE, FALSE, IfBgRedraw))
00510                 {
00511                     // We need to invalidate the region
00512                     End();
00513                     return;
00514                 }
00515             }
00516 
00517             // Now factor out all common attributes
00518             // bodge 
00519             if (!DoFactorOutCommonChildAttributes(Group))
00520             {
00521                 End();
00522                 return;
00523             }
00524         }
00525 
00526         // Get the tool to remove all its blobs before we deselect the nodes.
00527         // Only do this if the current tool dosent update itself on sel changed messages
00528         if (pSelSpread!=NULL && pTool!=NULL && !pTool->AreToolBlobsRenderedOnSelection())
00529             pTool->RenderToolBlobs(pSelSpread,NULL);
00530     }                   
00531     End(); 
00532 }           

OpState OpGroup::GetState String_256 UIDescription,
OpDescriptor
[static]
 

For finding the OpGroup's state.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/9/93
Returns:
The state of the OpGroup

Definition at line 227 of file groupops.cpp.

00228 {
00229     OpState OpSt;
00230     String_256 DisableReason; 
00231 
00232     // Obtain the current selections 
00233     Range Sel(*(GetApplication()->FindSelection()));
00234     RangeControl rg = Sel.GetRangeControlFlags();
00235     rg.PromoteToParent = TRUE;
00236     Sel.Range::SetRangeControl(rg);
00237       
00238     // This operation is disabled if there are no nodes selected, or if the only selected node
00239     // is a node group.                           
00240     Node* FirstSelected = Sel.FindFirst();  
00241     
00242     OpSt.Greyed = FALSE; 
00243     if (IS_A(FirstSelected,NodeGroup) 
00244          && (Sel.FindNext(FirstSelected) == NULL) )      // Only a NodeGroup selected
00245     {  
00246         OpSt.Greyed = TRUE; 
00247         // Load reason why operation is disabled
00248         // Grouping only a single group is pointless
00249         DisableReason = String_256(_R(IDS_ILLEGAL_TO_GROUP_SINGLE_GROUP));
00250         *UIDescription = DisableReason;          
00251     }
00252         
00253     return(OpSt);   
00254 }

BOOL OpGroup::Init void   )  [static]
 

OpGroup initialiser method.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/9/93
Returns:
TRUE if the operation could be successfully initialised FALSE if no more memory could be allocated

Errors: ERROR will be called if there was insufficient memory to allocate the operation.

Reimplemented from SimpleCCObject.

Definition at line 190 of file groupops.cpp.

00191 {
00192     return (RegisterOpDescriptor(0,
00193                             _R(IDS_GROUPOP),
00194                             CC_RUNTIME_CLASS(OpGroup),
00195                             OPTOKEN_GROUP,
00196                             OpGroup::GetState,
00197                             0,  /* help ID */
00198                             _R(IDBBL_GROUPOP),
00199                             0,  /* bitmap ID */
00200                             0,
00201                             SYSTEMBAR_ILLEGAL,          // For now !
00202                             TRUE,                       // Receive messages
00203                             FALSE,
00204                             FALSE,
00205                             0,
00206                             (GREY_WHEN_NO_CURRENT_DOC | GREY_WHEN_NO_SELECTION)
00207 
00208                             )); 
00209 
00210     if (Camelot.DeclareSection(_T("Groups"), 2))
00211     {
00212         Camelot.DeclarePref(_T("Groups"), _T("AskUngroupEffects"), &bAskBeforeFactoringEffects, FALSE, TRUE);
00213         Camelot.DeclarePref(_T("Groups"), _T("UngroupLocaliseEffects"), &bLocaliseEffects, FALSE, TRUE);
00214     }
00215 }               

virtual BOOL OpGroup::MayChangeNodeBounds  )  const [inline, virtual]
 

Reimplemented from SelOperation.

Definition at line 141 of file groupops.h.

00141 { return FALSE; }

BOOL OpGroup::NeedToInvalidateGroup  )  [private]
 

This function determines if the selected objects will need to be invalidated if they are to be made into a group.

Author:
Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/7/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
TRUE if we need to invalidate

Errors: - Scope: private

See also:
-

Definition at line 277 of file groupops.cpp.

00278 {
00279 //  if (TRUE /*GetApplication()->IsBkRendering()*/)
00280 //      return TRUE;        // Always invalidate if Background Redraw is occuring
00281 
00282     // If all selected objects are contiguous then there will be no need to invalidate
00283     // the group's bounds.
00284 
00285     // Obtain the current selection
00286     SelRange Sel(*(GetApplication()->FindSelection()));
00287     RangeControl rg = Sel.GetRangeControlFlags();
00288     rg.PromoteToParent = TRUE;
00289     Sel.Range::SetRangeControl(rg);
00290     
00291     Node* Current = Sel.FindFirst(); 
00292     
00293     ERROR2IF(Current == NULL, TRUE, "There are no selected objects"); 
00294 
00295     // Create a range of all objects starting with the first selected object
00296         
00297 //  RangeControl rc = { TRUE, TRUE, TRUE }; // selected + unselected nodes, cross layer
00298 
00299     Range ObjectRange(Current, NULL, RangeControl(TRUE,TRUE,TRUE,TRUE));
00300 
00301     BOOL Contiguous = TRUE; // Until we know better
00302     DocRect SelBounds;
00303 
00304     Node* SelObject = Current; 
00305     Node* Object = Current;
00306     
00307     // Traverse both ranges simultaneously
00308     while (SelObject != NULL)
00309     {
00310         if (SelObject != Object)
00311         {
00312             // All selected objects are not contiguous
00313             if (Contiguous)
00314             {
00315                 // We will need to calculate the bounds of the selection for what comes next
00316                 SelBounds = Sel.GetBoundingRect();
00317                 Contiguous = FALSE; // So we don't calculate the bounds again
00318             }
00319         
00320             // Check if the uncontiguous object intersects with the bounds of the selection
00321         
00322             if (Object->IsAnObject())
00323             { 
00324 
00325                 if ( ((NodeRenderableInk*)Object)->GetBoundingRect().IsIntersectedWith(SelBounds))
00326                 {
00327                     return TRUE; // An unselected object intersects with a selected object
00328                 }
00329             }
00330             // Objects don't intersect so it doesn't matter
00331             Object = ObjectRange.FindNext(Object);
00332             ERROR3IF(Object == NULL, "Reached end of object list"); 
00333         }
00334         else
00335         {
00336             // Get next items in both ranges
00337             SelObject = Sel.FindNext(SelObject); 
00338             Object = ObjectRange.FindNext(Object);
00339         }
00340     }
00341     return FALSE; // No need to invalidate
00342 
00343 }


Friends And Related Function Documentation

friend class OpUngroup [friend]
 

Definition at line 130 of file groupops.h.


Member Data Documentation

BOOL OpGroup::bAskBeforeFactoringEffects [static, private]
 

Definition at line 147 of file groupops.h.

BOOL OpGroup::bLocaliseEffects [static, private]
 

Definition at line 148 of file groupops.h.


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