#include <opbreak.h>
Inheritance diagram for OpBreakAtPoints:
Public Member Functions | |
OpBreakAtPoints () | |
void | GetOpName (String_256 *OpName) |
The GetOpName fn is overridden so that we return back a description appropriate to the type of attribute that the operation applies. | |
void | Do (OpDescriptor *) |
This operation works on the selected objects in the current document. It will scan through all path objects in the selection and if any contain selected points, break the path at those points, producing a number of output paths. These paths will be connected on the next sibling to the original. All attributes will be distributed to the output siblings. | |
virtual BOOL | MayChangeNodeBounds () const |
Static Public Member Functions | |
static BOOL | Init () |
OpDeletePoints initialiser method. | |
static OpState | GetState (String_256 *, OpDescriptor *) |
For finding the OpBreakAtPoints's state. |
Definition at line 124 of file opbreak.h.
|
|
|
This operation works on the selected objects in the current document. It will scan through all path objects in the selection and if any contain selected points, break the path at those points, producing a number of output paths. These paths will be connected on the next sibling to the original. All attributes will be distributed to the output siblings.
Reimplemented from Operation. Definition at line 319 of file opbreak.cpp. 00320 { 00321 00322 // Obtain the current selections 00323 SelRange* Selected = GetApplication()->FindSelection(); 00324 NodePath* pSplitNode; 00325 00326 // Now, because we're going to be doing mad things to the selection, we have to make a list 00327 // of all the selected nodes, so that adding nodes into the tree won't confuse us 00328 00329 List* NodeList = Selected->MakeListOfNodes(); 00330 NodeListItem* CurItem = (NodeListItem*)(NodeList->GetHead()); 00331 00332 if (!CurItem) 00333 goto FailAndDeleteList; 00334 00335 if (!DoStartSelOp(TRUE,TRUE)) 00336 goto FailAndDeleteList; 00337 00338 while (CurItem) 00339 { 00340 // get a pointer to the NodePath 00341 NodePath* pThisNode = (NodePath*)(CurItem->pNode); 00342 00343 // Only interested in NodePaths that have a sub selection, and that will allow the op to happen 00344 if ((IS_A(pThisNode,NodePath) || IS_A(pThisNode,NodeBlendPath)) && pThisNode->InkPath.IsSubSelection()) 00345 { 00346 // Find out how many nodes this op will reproduce 00347 INT32 NumSplinters = pThisNode->InkPath.NumSplinters(); 00348 BOOL DoThisNode = FALSE; 00349 00350 if (NumSplinters > 0) 00351 { 00352 // We need to ask the effected nodes if they (and their parents) can handle this node being replaced 00353 ObjChangeFlags cFlags; 00354 00355 if (NumSplinters > 1) 00356 cFlags.MultiReplaceNode = TRUE; // Node will be replaced with more than one node. 00357 else 00358 cFlags.ReplaceNode = TRUE; // Node will be replaced with one node only. 00359 00360 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this); 00361 DoThisNode = pThisNode->AllowOp(&ObjChange); 00362 } 00363 00364 if (DoThisNode) 00365 { 00366 00367 BOOL ok; 00368 Node* pnode; 00369 00370 // Copy the nodepath and all its children, without placing the copy in the tree 00371 CALL_WITH_FAIL(pThisNode->NodeCopy(&pnode), this, ok); 00372 if (!ok) goto DeleteList; 00373 pSplitNode = (NodePath*)pnode; 00374 00375 // remove the fill from this path as we're about to open it 00376 pSplitNode->InkPath.IsFilled = FALSE; 00377 00378 // Now stick the new path into the tree 00379 CALL_WITH_FAIL 00380 ( 00381 DoInsertNewNode(pSplitNode, pThisNode, NEXT, TRUE, FALSE), 00382 this,ok 00383 ); 00384 00385 if (!ok) 00386 goto DeleteListAndPath; 00387 00388 // Now breakup this copy of the path where necessary 00389 Path* pChildPath; 00390 INT32 split; 00391 00392 do 00393 { 00394 // Create a new path, ready for split 00395 ALLOC_WITH_FAIL(pChildPath, new Path, this); 00396 if (!pChildPath) 00397 goto DeleteList; 00398 00399 // Now split the path, possibly into two pieces. 00400 split = pSplitNode->InkPath.BreakInTwo(pChildPath); 00401 00402 if (split==-1) 00403 { 00404 InformError(_R(IDS_OUT_OF_MEMORY), _R(IDS_OK)); 00405 delete pChildPath; 00406 goto FailAndDeleteList; 00407 } 00408 00409 /* Karim 05/12/2000 00410 No longer required - see code addition at the bottom of this loop. 00411 00412 if (split==1) 00413 { 00414 delete pChildPath; 00415 continue; 00416 } 00417 00418 */ 00419 00420 if (split>1) 00421 { 00422 00423 // update the split paths bounding rectangle 00424 pSplitNode->InvalidateBoundingRect(); 00425 00426 // Create a new nodepath. 00427 NodePath* pChildNode; 00428 ALLOC_WITH_FAIL(pChildNode, new NodePath(), this); 00429 if (!pChildNode) 00430 { 00431 delete pChildPath; 00432 goto DeleteList; 00433 } 00434 00435 // make room for the new path in the node path. 00436 CALL_WITH_FAIL 00437 ( 00438 pChildNode->SetUpPath(pChildPath->GetNumCoords(),12), 00439 this,ok 00440 ); 00441 00442 if (!ok) 00443 { 00444 delete pChildNode; 00445 delete pChildPath; 00446 goto DeleteList; 00447 } 00448 00449 // now copy the path data in there. 00450 pChildNode->InkPath.CopyPathDataFrom(pChildPath); 00451 delete pChildPath; 00452 00453 // Clear the selection flag from the first element in both the split 00454 // and child paths. All others apart from the last will be unselected 00455 // by definition. Also select the last element in the child 00456 (pSplitNode->InkPath.GetFlagArray())[0].IsSelected = FALSE; 00457 (pChildNode->InkPath.GetFlagArray())[0].IsSelected = FALSE; 00458 (pChildNode->InkPath.GetFlagArray())[(pChildNode->InkPath.GetNumCoords()-1)].IsSelected = TRUE; 00459 pChildNode->InkPath.IsFilled = FALSE; 00460 00461 // now, copy all attributes from the parent split to the child split 00462 Node* pAttr = pSplitNode->FindFirstChild(); 00463 while (pAttr != NULL) 00464 { 00465 if (pAttr->IsKindOf(CC_RUNTIME_CLASS(NodeAttribute))) 00466 { 00467 Node* pAttrCopy; 00468 CALL_WITH_FAIL(pAttr->NodeCopy(&pAttrCopy), this,ok); 00469 if (!ok) 00470 { 00471 pChildNode->CascadeDelete(); 00472 delete pChildNode; 00473 goto DeleteList; 00474 } 00475 pAttrCopy->AttachNode(pChildNode, FIRSTCHILD); 00476 } 00477 pAttr = pAttr->FindNext(); 00478 } 00479 00480 for (INT32 loop = 0; loop < pChildNode->InkPath.GetNumCoords(); loop ++) 00481 { 00482 pChildNode->InkPath.GetVerbArray()[loop] = pChildNode->InkPath.GetVerbArray()[loop] & ~PT_CLOSEFIGURE; 00483 } 00484 00485 // Now stick the new path into the tree 00486 CALL_WITH_FAIL 00487 ( 00488 DoInsertNewNode(pChildNode, pSplitNode, NEXT, TRUE, FALSE), 00489 this,ok 00490 ); 00491 00492 if (!ok) 00493 { 00494 pChildNode->CascadeDelete(); 00495 delete pChildNode; 00496 goto DeleteList; 00497 } 00498 00499 pSplitNode = pChildNode; 00500 } 00501 00502 // Karim 05/12/2000 00503 // Fix for memory leak. 00504 else 00505 { 00506 delete pChildPath; 00507 } 00508 } 00509 while (split); 00510 00511 // Clear out any remaining closefigures on the last bit of the path 00512 for (INT32 loop = 0; loop < pSplitNode->InkPath.GetNumCoords(); loop ++) 00513 { 00514 pSplitNode->InkPath.GetVerbArray()[loop] = pSplitNode->InkPath.GetVerbArray()[loop] & ~PT_CLOSEFIGURE; 00515 } 00516 00517 // Now we've broken up this path, let's hide it 00518 CALL_WITH_FAIL(DoHideNode(pThisNode,TRUE), this, ok) 00519 if (!ok) goto DeleteList; 00520 } 00521 } 00522 CurItem = (NodeListItem*)(NodeList->GetNext(CurItem)); 00523 } 00524 00525 // Update all the parents of this node 00526 { 00527 ObjChangeFlags cFlags; 00528 ObjChangeParam ObjChange(OBJCHANGE_FINISHED,cFlags,NULL,this); 00529 if (!UpdateChangedNodes(&ObjChange)) 00530 goto FailAndDeleteList; 00531 } 00532 00533 End(); 00534 00535 // delete the nodelist (and all the list items) 00536 while (!NodeList->IsEmpty()) 00537 delete (NodeListItem*)(NodeList->RemoveHead()); 00538 delete NodeList; 00539 return; 00540 00541 00542 FailAndDeleteList: 00543 while (!NodeList->IsEmpty()) 00544 delete (NodeListItem*)(NodeList->RemoveHead()); 00545 delete NodeList; 00546 FailAndExecute(); 00547 End(); 00548 return; 00549 00550 DeleteListAndPath: 00551 pSplitNode->CascadeDelete(); 00552 delete pSplitNode; 00553 00554 DeleteList: 00555 while (!NodeList->IsEmpty()) 00556 delete (NodeListItem*)(NodeList->RemoveHead()); 00557 delete NodeList; 00558 End(); 00559 return; 00560 00561 }
|
|
The GetOpName fn is overridden so that we return back a description appropriate to the type of attribute that the operation applies.
Reimplemented from Operation. Definition at line 289 of file opbreak.cpp. 00290 { 00291 *OpName = String_256(_R(IDS_UNDO_BREAKATPOINTSOP)); 00292 }
|
|
For finding the OpBreakAtPoints's state.
Definition at line 214 of file opbreak.cpp. 00215 { 00216 00217 OpState OpSt; 00218 String_256 DisableReason; 00219 00220 OpSt.Greyed = FALSE; 00221 BOOL FoundSelected = FALSE; 00222 00223 // Go through the selection until we find a selected point 00224 00225 SelRange* Selected = GetApplication()->FindSelection(); 00226 Node* pNode = Selected->FindFirst(); 00227 00228 while (pNode) 00229 { 00230 if (IS_A(pNode,NodePath) || IS_A(pNode,NodeBlendPath)) 00231 { 00232 NodePath* pNodePath = (NodePath*)pNode; 00233 INT32 NumSplinters = pNodePath->InkPath.NumSplinters(); 00234 00235 if (NumSplinters > 0) 00236 { 00237 // We need to ask the effected nodes if they (and their parents) can handle this node being replaced 00238 ObjChangeFlags cFlags; 00239 00240 if (NumSplinters > 1) 00241 cFlags.MultiReplaceNode = TRUE; // Node will be replaced with more than one node. 00242 else 00243 cFlags.ReplaceNode = TRUE; // Node will be replaced with one node only. 00244 00245 String_32 optokenstring(OPTOKEN_BREAKATPOINTS); 00246 ObjChangeParamWithToken ObjChange(OBJCHANGE_STARTING,cFlags,pNodePath,NULL,&optokenstring); 00247 00248 // Will the node allow this op to happen? 00249 if (pNodePath->AllowOp(&ObjChange,FALSE)) 00250 { 00251 FoundSelected = TRUE; 00252 break; 00253 } 00254 } 00255 } 00256 pNode = Selected->FindNext(pNode); 00257 } 00258 00259 // The operation is disabled if there are no complex paths selected 00260 00261 if (!FoundSelected) 00262 { 00263 OpSt.Greyed = TRUE; 00264 DisableReason = String_256(_R(IDS_NEEDS_SELECTED_POINT)); 00265 *UIDescription = DisableReason; 00266 } 00267 00268 return(OpSt); 00269 }
|
|
OpDeletePoints initialiser method.
Reimplemented from SimpleCCObject. Definition at line 175 of file opbreak.cpp. 00176 { 00177 return (RegisterOpDescriptor(0, // tool ID 00178 _R(IDS_BREAKATPOINTSOP), // string resource ID 00179 CC_RUNTIME_CLASS(OpBreakAtPoints), // runtime class for Op 00180 OPTOKEN_BREAKATPOINTS, // Ptr to token string 00181 OpBreakAtPoints::GetState, // GetState function 00182 0, // help ID 00183 _R(IDBBL_BREAKATPOINTSOP), // bubble help ID 00184 _R(IDD_BARCONTROLSTORE), // resource ID 00185 _R(IDC_BTN_BREAKATPOINTSOP), // control ID 00186 SYSTEMBAR_EDIT, // Group bar ID 00187 TRUE, // Receive messages 00188 FALSE, // Smart 00189 FALSE, // Clean 00190 0, // One open Instance ID 00191 0 00192 00193 )); 00194 00195 }
|
|
Reimplemented from SelOperation. Definition at line 137 of file opbreak.h. 00137 { return FALSE; }
|