#include <groupops.h>
Inheritance diagram for OpGroup:
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 |
Definition at line 128 of file groupops.h.
|
OpGroup constructor.
Definition at line 172 of file groupops.cpp. 00172 : SelOperation() 00173 { 00174 }
|
|
Performs the Group operation.
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 }
|
|
For finding the OpGroup's state.
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 }
|
|
OpGroup initialiser method.
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 }
|
|
Reimplemented from SelOperation. Definition at line 141 of file groupops.h. 00141 { return FALSE; }
|
|
This function determines if the selected objects will need to be invalidated if they are to be made into a group.
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 }
|
|
Definition at line 130 of file groupops.h. |
|
Definition at line 147 of file groupops.h. |
|
Definition at line 148 of file groupops.h. |