00001 // $Id: opbezier.cpp 1282 2006-06-09 09:46:49Z alex $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 // Implementation of the Line tool operations 00099 00100 /* 00101 */ 00102 00103 #include "camtypes.h" 00104 #include "opbezier.h" 00105 00106 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00107 #include "beztool.h" 00108 #include "blobs.h" 00109 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00110 //#include "jim.h" 00111 #include "nodepath.h" 00112 #include "progress.h" 00113 //#include "rik.h" 00114 #include "bubbleid.h" 00115 00116 DECLARE_SOURCE( "$Revision: 1282 $" ); 00117 00118 CC_IMPLEMENT_DYNCREATE(OpSelectPathPoints, UndoableOperation) 00119 CC_IMPLEMENT_DYNCREATE(OpInsertFloater, UndoableOperation) 00120 CC_IMPLEMENT_DYNCREATE(OpRemoveFloater, UndoableOperation) 00121 CC_IMPLEMENT_DYNCREATE(RemoveFloaterAction, Action) 00122 CC_IMPLEMENT_DYNCREATE(InsertFloaterAction, Action) 00123 CC_IMPLEMENT_MEMDUMP(InsertFloaterParam, OpParam) 00124 00125 00126 // Must come after the last CC_IMPLEMENT.. macro 00127 #define new CAM_DEBUG_NEW 00128 00129 00131 // The OpSelectPathPoints Operation 00132 00133 BOOL OpSelectPathPoints::DragUnderway = FALSE; 00134 00135 /******************************************************************************************** 00136 00137 > OpSelectPathPoints::OpSelectPathPoints() 00138 00139 Author: Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com> 00140 Created: 29/6/94 00141 Purpose: Constructor. This simply sets a few of the operation flags. 00142 00143 ********************************************************************************************/ 00144 00145 OpSelectPathPoints::OpSelectPathPoints() 00146 { 00147 } 00148 00149 /******************************************************************************************** 00150 00151 > BOOL OpSelectPathPoints::Init() 00152 00153 Author: Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com> 00154 Created: 22/7/94 00155 Returns: TRUE if all went OK, False otherwise 00156 Purpose: Adds the operation to the list of all known operations 00157 00158 ********************************************************************************************/ 00159 00160 BOOL OpSelectPathPoints::Init() 00161 { 00162 return (RegisterOpDescriptor( 0, 00163 _R(IDS_NODEPATH_EDIT), 00164 CC_RUNTIME_CLASS(OpSelectPathPoints), 00165 OPTOKEN_NODEPATH, 00166 OpSelectPathPoints::GetState, 00167 0, /* help ID */ 00168 _R(IDBBL_NODEPATHOP), 00169 0 /* bitmap ID */)); 00170 } 00171 00172 00173 00174 /******************************************************************************************** 00175 00176 > static BOOL OpSelectPathPoints::DragInProgress() 00177 00178 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00179 Created: 21/10/94 00180 Inputs: - 00181 Returns: TRUE if a drag is underway, otherwise FALSE. 00182 Purpose: To find out if there is a select points operation in progress. 00183 00184 ********************************************************************************************/ 00185 00186 BOOL OpSelectPathPoints::DragInProgress() 00187 { 00188 return DragUnderway; 00189 } 00190 00191 00192 00193 /******************************************************************************************** 00194 00195 > void OpSelectPathPoints::DoDrag( DocCoord Anchor, Spread *pSpread, BOOL isAdjust, 00196 BezierTool* tptr, 00197 ClickModifiers ClickMods) 00198 00199 Author: Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com> - Modified by Peter 00200 Created: 29/6/94 00201 Inputs: Anchor - The position of the mouse at the start of the Drag 00202 pSpread - The spread that the drag started on 00203 isAdjust - lets the operation remember if the drag is adjust or not 00204 tptr points at the calling tool, so that we can call it back if this 00205 drag happened to really insert a floating endpoint 00206 ClickMods are the modifiers so that we know if adjust was down 00207 Purpose: Starts dragging a rectangle, and when the drag finishes, any points inside 00208 the rectangle will be selected. If isAdjust, points inside the rectangle will 00209 be toggled. 00210 00211 If the drag finishes where it started, we assume that actually the user wanted 00212 to insert a floating endpoint at the click position, so we have to call back to 00213 the bezier tool to tell it where to put the endpoint. 00214 00215 On the drag start all control point blobs are removed, also if the drag is 00216 a select drag (as opposed to an adjust drag) the selected endpoints blobs 00217 are replaced with unselected blobs. 00218 00219 ********************************************************************************************/ 00220 00221 void OpSelectPathPoints::DoDrag(DocCoord Anchor, 00222 Spread *pSpread, 00223 BOOL isAdjust, 00224 BezierTool* tptr, 00225 ClickModifiers ClickMods ) 00226 { 00227 // Make a mental note of the start point 00228 StartPoint = Anchor; 00229 StartSpread = pSpread; 00230 PreviousPoint = Anchor; 00231 AdjustDrag = isAdjust; 00232 BezToolPtr = tptr; 00233 Mods = ClickMods; 00234 00235 // Go through all the selected NodePaths and remove all the 00236 // control point blobs 00237 SelRange* Selection = GetApplication()->FindSelection(); 00238 Node* pNode = Selection->FindFirst(); 00239 NodePath* pSelected = NULL; 00240 00241 while (pNode != NULL) 00242 { 00243 if (pNode->IsNodePath()) 00244 pSelected = (NodePath*)pNode; 00245 else 00246 pSelected = (NodePath*) (pNode->HasEditableChild(CC_RUNTIME_CLASS(NodePath), NULL)); 00247 00248 if (pSelected) 00249 { 00250 Path* ThisPath = &(pSelected->InkPath); 00251 Spread* pSpread = pNode->FindParentSpread(); 00252 00253 // Dereference the pointers 00254 DocCoord* Coords = ThisPath->GetCoordArray(); 00255 PathFlags* Flags = ThisPath->GetFlagArray(); 00256 PathVerb* Verbs = ThisPath->GetVerbArray(); 00257 INT32 UsedSlots = ThisPath->GetNumCoords(); 00258 00259 DocCoord StartCoord = Coords[0]; 00260 00261 // Go into a RenderOnTop loop 00262 RenderRegion* pRender = DocView::RenderOnTop(NULL, pSpread, ClippedEOR); 00263 while (pRender!=NULL) 00264 { 00265 // loop through the path and count the selected blobs 00266 INT32 endcount = 0; // Count the number of selected endpoints 00267 INT32 EndPtIndex = 0; // Index of only selected endpoint 00268 for (INT32 i=0; i<UsedSlots; i++) 00269 { 00270 if (Flags[i].IsEndPoint && Flags[i].IsSelected) 00271 { 00272 if (!(Verbs[i] & PT_CLOSEFIGURE)) 00273 { 00274 EndPtIndex = i; 00275 endcount++; 00276 if (!AdjustDrag) 00277 { 00278 // If in select mode then remove the selection blob 00279 ThisPath->DrawBlob(pRender, Coords[i], TRUE); 00280 ThisPath->DrawBlob(pRender, Coords[i], FALSE); 00281 } 00282 } 00283 } 00284 } 00285 if (endcount == 1) 00286 { 00287 // Remove the control points and lines 00288 ThisPath->RenderPathControlBlobs(pSpread,EndPtIndex); 00289 } 00290 pRender = DocView::GetNextOnTop(NULL); 00291 } // while the render region 00292 } // if its a node path 00293 pNode = Selection->FindNext(pNode); 00294 } // while there are selected nodes 00295 00296 // And tell the Dragging system that we need drags to happen 00297 StartDrag( DRAGTYPE_AUTOSCROLL ); 00298 00299 DragUnderway = TRUE; 00300 } 00301 00302 00303 00304 00305 /******************************************************************************************** 00306 00307 > void OpSelectPathPoints::DragPointerMove( DocCoord PointerPos, ClickModifiers ClickMods, 00308 Spread *pSpread, BOOL bSolidDrag) 00309 00310 Author: Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com> 00311 Created: 29/6/94 00312 Inputs: PointerPos - The current position of the mouse in Doc Coords 00313 ClickMods - Which key modifiers are being pressed 00314 pSpread - The spread that the mouse is moving over 00315 Purpose: Handles the event of the mouse moving during a drag 00316 SeeAlso: ClickModifiers 00317 00318 ********************************************************************************************/ 00319 00320 void OpSelectPathPoints::DragPointerMove( DocCoord PointerPos, ClickModifiers ClickMods, 00321 Spread *pSpread, BOOL bSolidDrag) 00322 { 00323 // If drag has moved onto a different spread, convert the coord to be relative to the 00324 // original spread. 00325 if (pSpread != StartSpread) 00326 PointerPos = MakeRelativeToSpread(StartSpread, pSpread, PointerPos); 00327 00328 // Remove old rubber rectangle 00329 DocRect OldOutline(StartPoint, StartPoint); 00330 OldOutline.IncludePoint(PreviousPoint); 00331 RenderRubberRect(&OldOutline); 00332 00333 // Change the variable that remembers the other corner of the rectangle 00334 PreviousPoint = PointerPos; 00335 00336 // And render the rubber rect in its new position 00337 DocRect NewOutline(StartPoint, StartPoint); 00338 NewOutline.IncludePoint(PreviousPoint); 00339 RenderRubberRect(&NewOutline); 00340 00341 // Now we need to render selection status of newly entered/exited endpoints 00342 // Go through all the endpoints on selected NodePaths. 00343 SelRange* Selection = GetApplication()->FindSelection(); 00344 Node* pNode = Selection->FindFirst(); 00345 NodePath* pSelected = NULL; 00346 00347 while (pNode != NULL) 00348 { 00349 if (pNode->IsNodePath()) 00350 pSelected = (NodePath*)pNode; 00351 else 00352 pSelected = (NodePath*) (pNode->HasEditableChild(CC_RUNTIME_CLASS(NodePath), NULL)); 00353 00354 if (pSelected) 00355 { 00356 Path* ThisPath = &(pSelected->InkPath); 00357 Spread* pSpread = pNode->FindParentSpread(); 00358 00359 // Dereference the pointers 00360 DocCoord* Coords = ThisPath->GetCoordArray(); 00361 PathFlags* Flags = ThisPath->GetFlagArray(); 00362 PathVerb* Verbs = ThisPath->GetVerbArray(); 00363 INT32 UsedSlots = ThisPath->GetNumCoords(); 00364 00365 // Go into a RenderOnTop loop 00366 RenderRegion* pRender = DocView::RenderOnTop(NULL, pSpread, ClippedEOR); 00367 while (pRender!=NULL) 00368 { 00369 // loop through the path, processing every endpoint 00370 for (INT32 i=0; i<UsedSlots; i++) 00371 { 00372 if (Flags[i].IsEndPoint && !(Verbs[i] & PT_CLOSEFIGURE) ) 00373 { 00374 BOOL First = TRUE; // Default selection status/es/i/whatever 00375 BOOL Second = FALSE; // This means we can skip doing thigs 00376 BOOL Render = FALSE; 00377 if (!(AdjustDrag && Flags[i].IsSelected)) 00378 { 00379 if (NewOutline.ContainsCoord(Coords[i]) && 00380 !OldOutline.ContainsCoord(Coords[i]) ) 00381 { 00382 // Point has just entered the selection rect 00383 First = FALSE; 00384 Second = TRUE; 00385 Render = TRUE; 00386 } 00387 if (!NewOutline.ContainsCoord(Coords[i]) 00388 && OldOutline.ContainsCoord(Coords[i]) ) 00389 { 00390 // Point has just left the selection rect 00391 Render = TRUE; 00392 } 00393 } 00394 if (Render) 00395 { 00396 ThisPath->DrawBlob(pRender, Coords[i], First); 00397 ThisPath->DrawBlob(pRender, Coords[i], Second); 00398 } 00399 } 00400 } 00401 pRender = DocView::GetNextOnTop(NULL); 00402 } // while the render region 00403 } // if its a node path 00404 pNode = Selection->FindNext(pNode); 00405 } // while there are selected nodes 00406 } 00407 00408 00409 00410 /******************************************************************************************** 00411 00412 > void OpSelectPathPoints::DragFinished( DocCoord PointerPos, ClickModifiers ClickMods, 00413 Spread *pSpread, BOOL Success, BOOL bSolidDrag) 00414 00415 Author: Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com> 00416 Created: 29/6/94 00417 Inputs: PointerPos - The position of the mouse at the end of the drag 00418 ClickMods - the key modifiers being pressed 00419 pSpread - The spread that the drag finished on 00420 Success - TRUE if the drag was terminated properly, FALSE if it 00421 was ended with the escape key being pressed 00422 Purpose: Handles the drag finishing by rubbing out an EOR on the screen and 00423 selecting any points which fall within the rectangle dragged out 00424 SeeAlso: ClickModifiers 00425 00426 ********************************************************************************************/ 00427 00428 void OpSelectPathPoints::DragFinished( DocCoord PointerPos, ClickModifiers ClickMods, 00429 Spread *pSpread, BOOL Success, BOOL bSolidDrag) 00430 { 00431 00432 DocRect RubberRect(StartPoint, StartPoint); 00433 RubberRect.IncludePoint(PreviousPoint); 00434 RenderRubberRect(&RubberRect); 00435 00436 DragUnderway = FALSE; 00437 00438 BeginSlowJob(); 00439 // End the Drag 00440 if ( !EndDrag() ) 00441 { 00442 FailAndExecute(); 00443 End(); 00444 } 00445 00446 // select any points within the rectangle if the drag completed properly 00447 // If the rectangle is tiny, we're not selecting points, we're inserting a new 00448 // path at the click position 00449 00450 if ( Success ) 00451 { 00452 DocRect temp; 00453 GetApplication()->GetBlobManager()->GetBlobRect(StartPoint,&temp); 00454 if (!temp.ContainsCoord(PreviousPoint)) 00455 { 00456 // Must be selecting points 00457 // Get all selected points, and remove any selected EORing, replacing it with 00458 // normal EORing 00459 00460 SelRange* Selected = GetApplication()->FindSelection(); 00461 Node* pNode = Selected->FindFirst(); 00462 NodePath* pSelected = NULL; 00463 00464 while (pNode) 00465 { 00466 if (pNode->IsNodePath()) 00467 pSelected = (NodePath*)pNode; 00468 else 00469 pSelected = (NodePath*) (pNode->HasEditableChild(CC_RUNTIME_CLASS(NodePath), NULL)); 00470 00471 if ((pSelected) && (pSelected->FindParentSpread() == StartSpread)) 00472 { 00473 // Go through the points in this path. 00474 // Select any unselected points that fall in the rectangle. 00475 // If Adjust, deselected any selected points that fall in the rectangle. 00476 // If not Adjust, deselect any selected points that fall outside. 00477 00478 DocCoord testcoord; 00479 Path* ThisPath = &(pSelected->InkPath); 00480 DocCoord* Coords = ThisPath->GetCoordArray(); 00481 PathFlags* Flags = ThisPath->GetFlagArray(); 00482 PathVerb* Verbs = ThisPath->GetVerbArray(); 00483 INT32 UsedSlots = ThisPath->GetNumCoords(); 00484 INT32 SelectedEndPoints = 0; 00485 INT32 EndPtIndex = 0; 00486 00487 for (INT32 i=0; i<UsedSlots; i++) 00488 { 00489 if (Flags[i].IsEndPoint) 00490 { 00491 // Selected points change depending on Adjust and whether they are 00492 // within the rectangle. 00493 if (Flags[i].IsSelected) 00494 { 00495 if (!AdjustDrag && !RubberRect.ContainsCoord(Coords[i])) 00496 { 00497 Flags[i].IsSelected = FALSE; 00498 } 00499 else 00500 { 00501 if (!(Verbs[i] & PT_CLOSEFIGURE)) 00502 { 00503 SelectedEndPoints++; 00504 EndPtIndex = i; 00505 } 00506 } 00507 } 00508 else 00509 { 00510 // unselected points inside rect are selected 00511 if (RubberRect.ContainsCoord(Coords[i])) 00512 { 00513 Flags[i].IsSelected = TRUE; 00514 if (!(Verbs[i] & PT_CLOSEFIGURE)) 00515 { 00516 SelectedEndPoints++; 00517 EndPtIndex = i; 00518 } 00519 } 00520 } 00521 } 00522 } 00523 ThisPath->EnsureSelection(TRUE); 00524 // Now render on the control points if there was just one selected endpoint 00525 if (SelectedEndPoints == 1) 00526 { 00527 ThisPath->RenderPathControlBlobs(pSpread,EndPtIndex); 00528 } 00529 } 00530 pNode = Selected->FindNext(pNode); 00531 } // while 00532 00533 } 00534 else 00535 { 00536 // Must have been a single click. If Adjust was down, clear all selected points 00537 // if not, still clear all selected points, but tell the bezier tool that 00538 // the user wants to start a new path at this point 00539 // Get all selected points, and remove any selected EORing, replacing it with 00540 // normal EORing 00541 RemoveDragBlobs(FALSE, TRUE); 00542 00543 // Now we've cleared the selection, check Adjust. If adjust is not set 00544 // we have to put in a floating endpoint 00545 if (!Mods.Adjust) 00546 { 00547 DocView::SnapCurrent(pSpread, &StartPoint); 00548 BezToolPtr->SetMoveTo(StartPoint, pSpread, GetWorkingDoc()); 00549 00550 if (!RemoveFloaterAction::DoRemove(this, &UndoActions, BezToolPtr)) 00551 { 00552 FailAndExecute(); 00553 End(); 00554 return; 00555 } 00556 } 00557 } 00558 } 00559 else 00560 { 00561 // Escape was pressed, we just have to restore the blob state to the previous 00562 RemoveDragBlobs(TRUE, FALSE); 00563 } 00564 GetApplication()->UpdateSelection(); 00565 End(); 00566 } 00567 00568 00569 00570 /******************************************************************************************** 00571 00572 > virtual void OpSelectPathPoints::RenderDragBlobs( DocRect Rect, Spread* pSpread, BOOL bSolidDrag ) 00573 00574 Author: Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com> 00575 Created: 29/6/94 00576 Inputs: Rect - The Rectangle that needs to be re-rendered 00577 pSpread - The spread on which the rendering is to take place 00578 Purpose: EORs the rectangle onto the screen 00579 SeeAlso: OpBezier::RenderLineSegment() 00580 00581 ********************************************************************************************/ 00582 00583 void OpSelectPathPoints::RenderDragBlobs( DocRect Rect, Spread* pSpread, BOOL bSolidDrag) 00584 { 00585 // If being called from DocView::RenderView, then the spread could be wrong - so 00586 // convert the rectangle if necessary. 00587 if (pSpread != StartSpread) 00588 { 00589 Rect.lo = MakeRelativeToSpread(StartSpread, pSpread, Rect.lo); 00590 Rect.hi = MakeRelativeToSpread(StartSpread, pSpread, Rect.hi); 00591 } 00592 00593 RenderRubberRect(&Rect); 00594 RenderRegion* pRegion = DocView::RenderOnTop(&Rect, StartSpread, UnclippedEOR); 00595 00596 while (pRegion) 00597 { 00598 if (DragUnderway) 00599 RenderRubberSelection(pRegion); 00600 00601 // Get the Next render region 00602 pRegion = DocView::GetNextOnTop(&Rect); 00603 } 00604 } 00605 00606 00607 00608 /******************************************************************************************** 00609 00610 > void OpSelectPathPoints::RenderRubberRect(DocRect* Rect) 00611 00612 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00613 Created: 26/10/94 00614 Inputs: Rect - pointer to the bounding box of the render region. NOT the rubber 00615 rectangle. 00616 Returns: - 00617 Purpose: EORs the selection rectangle onto the screen. The rectangle is rendered 00618 using the coordinates StartPoint to PreviousPoint. 00619 SeeAlso: OpSelectPathPoints::RenderRubberSelection(), OpSelectPathPoints::RenderDragBlobs() 00620 00621 ********************************************************************************************/ 00622 void OpSelectPathPoints::RenderRubberRect(DocRect* Rect) 00623 { 00624 RenderRegion* pRegion = DocView::RenderOnTop(Rect, StartSpread, UnclippedEOR); 00625 while (pRegion) 00626 { 00627 // Set the line colour 00628 pRegion -> SetLineColour(COLOUR_XORNEW); 00629 pRegion -> SetFillColour(COLOUR_NONE); 00630 00631 // And Draw the rect 00632 DocRect RubberBox(StartPoint, StartPoint); 00633 RubberBox.IncludePoint(PreviousPoint); 00634 00635 // Draw the rectangle 00636 pRegion->DrawDragRect(&RubberBox); 00637 00638 // Get the Next render region 00639 pRegion = DocView::GetNextOnTop(Rect); 00640 } 00641 } 00642 00643 00644 00645 /******************************************************************************************** 00646 00647 > void OpSelectPathPoints::RenderRubberSelection(RenderRegion* pRegion) 00648 00649 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00650 Created: 26/10/94 00651 Inputs: pRegion - pointer to the render region to draw into. 00652 Returns: - 00653 Purpose: EORs the blobs on the selected paths onto the screen. This is is needed to 00654 solve quite an ugly situation. If the path(s) are scrolled then their blobs 00655 will be redrawn as per their document status. We need to go through 00656 all the paths rendering their selection status as we want them to be. 00657 SeeAlso: OpSelectPathPoints::RenderRubberRect(), OpSelectPathPoints::RenderDragBlobs() 00658 00659 ********************************************************************************************/ 00660 00661 void OpSelectPathPoints::RenderRubberSelection(RenderRegion* pRegion) 00662 { 00663 ERROR3IF (pRegion == NULL, "Pointer to RenderRegion was NULL"); 00664 ERROR3IF (!DragUnderway, "RenderRubberSelection called when no drag was underway"); 00665 00666 SelRange* Selection = GetApplication()->FindSelection(); 00667 Node* pNode = Selection->FindFirst(); 00668 00669 DocRect RubberBox(StartPoint, StartPoint); 00670 RubberBox.IncludePoint(PreviousPoint); 00671 NodePath* pSelected = NULL; 00672 00673 while (pNode) 00674 { 00675 if (pNode->IsNodePath()) 00676 pSelected = (NodePath*)pNode; 00677 else 00678 pSelected = (NodePath*) (pNode->HasEditableChild(CC_RUNTIME_CLASS(NodePath), NULL)); 00679 00680 if ((pSelected) && (pSelected->FindParentSpread() == StartSpread)) 00681 { 00682 Path* ThisPath = &(pSelected->InkPath); 00683 INT32 UsedSlots = ThisPath->GetNumCoords(); 00684 DocCoord* Coords = ThisPath->GetCoordArray(); 00685 PathFlags* Flags = ThisPath->GetFlagArray(); 00686 PathVerb* Verbs = ThisPath->GetVerbArray(); 00687 INT32 EndPtIndex =0; 00688 INT32 endcount = 0; 00689 00690 for (INT32 i=0; i<UsedSlots; i++) 00691 { 00692 if (Flags[i].IsEndPoint && !(Verbs[i] & PT_CLOSEFIGURE)) 00693 { 00694 // Now we need to render on the selection blob status 00695 BOOL First = TRUE; // By default deselect a selected blob 00696 BOOL Second = FALSE; 00697 BOOL Render = FALSE; 00698 00699 if (Flags[i].IsSelected) 00700 { 00701 EndPtIndex = i; 00702 endcount++; 00703 Render = TRUE; 00704 } 00705 00706 if (AdjustDrag) 00707 Render = FALSE; 00708 00709 if (RubberBox.ContainsCoord(Coords[i]) && !Flags[i].IsSelected) 00710 { 00711 // Render an unselected blob as selected 00712 Render = TRUE; 00713 First = FALSE; 00714 Second = TRUE; 00715 } 00716 00717 if (Render) 00718 { 00719 ThisPath->DrawBlob(pRegion, Coords[i], First); 00720 ThisPath->DrawBlob(pRegion, Coords[i], Second); 00721 } 00722 } 00723 } 00724 if (endcount == 1) 00725 { 00726 // Remove the control points and lines 00727 ThisPath->RenderPathControlBlobs(StartSpread,EndPtIndex); 00728 } 00729 } 00730 pNode = Selection->FindNext(pNode); 00731 } 00732 } 00733 00734 00735 00736 /******************************************************************************************** 00737 00738 > BOOL OpSelectPathPoints::Declare() 00739 00740 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00741 Created: 5/7/93 00742 Returns: TRUE if all went OK, False otherwise 00743 Purpose: Adds the operation to the list of all known operations 00744 00745 ********************************************************************************************/ 00746 00747 BOOL OpSelectPathPoints::Declare() 00748 { 00749 return (RegisterOpDescriptor( 00750 0, 00751 _R(IDS_SELECTPATHPOINTS), 00752 CC_RUNTIME_CLASS(OpSelectPathPoints), 00753 OPTOKEN_BEZTOOL, 00754 OpSelectPathPoints::GetState, 00755 0, /* help ID */ 00756 _R(IDBBL_FREEHANDTOOLOP), 00757 0 /* bitmap ID */)); 00758 } 00759 00760 00761 00762 /******************************************************************************************** 00763 00764 > void OpSelectPathPoints::RemoveDragBlobs(BOOL RenderControlBlobs, BOOL Deselect) 00765 00766 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00767 Created: 21/10/94 00768 Inputs: RenderContolBlobs - TRUE if the control blobs should be rendered 00769 Deselect - TRUE if all endpoints should be deslected 00770 Returns: - 00771 Purpose: Implement a common bit of code shared by two bits at the end of DragFinished. 00772 Both want to go through all selected paths although they do different things 00773 with them. 00774 SeeAlso: OpSelectPathPoints::DragFinished() 00775 00776 ********************************************************************************************/ 00777 00778 void OpSelectPathPoints::RemoveDragBlobs(BOOL RenderControlBlobs, BOOL Deselect) 00779 { 00780 DocRect RubberRect(StartPoint, StartPoint); 00781 RubberRect.IncludePoint(PreviousPoint); 00782 00783 SelRange* Selected = GetApplication()->FindSelection(); 00784 Node* pNode = Selected->FindFirst(); 00785 NodePath* pSelected = NULL; 00786 00787 while (pNode) 00788 { 00789 if (pNode->IsNodePath()) 00790 pSelected = (NodePath*)pNode; 00791 else 00792 pSelected = (NodePath*) (pNode->HasEditableChild(CC_RUNTIME_CLASS(NodePath), NULL)); 00793 00794 if ((pSelected) && (pSelected->FindParentSpread() == StartSpread)) 00795 { 00796 Path* ThisPath = &(pSelected->InkPath); 00797 INT32 UsedSlots = ThisPath->GetNumCoords(); 00798 DocCoord* Coords = ThisPath->GetCoordArray(); 00799 PathFlags* Flags = ThisPath->GetFlagArray(); 00800 PathVerb* Verbs = ThisPath->GetVerbArray(); 00801 00802 RenderRegion* pRender = DocView::RenderOnTop(NULL, StartSpread, ClippedEOR); 00803 while (pRender!=NULL) 00804 { 00805 INT32 SelectedEndPoints = 0; 00806 INT32 EndPtIndex = 0; 00807 DocCoord EndPtCoord; 00808 for (INT32 i=0; i<UsedSlots; i++) 00809 { 00810 if (Flags[i].IsEndPoint) 00811 { 00812 if ( ((AdjustDrag && Flags[i].IsSelected) || 00813 RubberRect.ContainsCoord(Coords[i])) 00814 && !(Verbs[i] & PT_CLOSEFIGURE) ) 00815 { 00816 // Remove the selection blobs 00817 ThisPath->DrawBlob(pRender, Coords[i], TRUE); 00818 ThisPath->DrawBlob(pRender, Coords[i], FALSE); 00819 } 00820 if (Flags[i].IsSelected) 00821 { 00822 SelectedEndPoints ++; 00823 EndPtIndex = i; 00824 EndPtCoord = Coords[i]; 00825 } 00826 } 00827 if (Deselect) 00828 { 00829 Flags[i].IsSelected = FALSE; 00830 } 00831 } 00832 if ((SelectedEndPoints == 1) && (RenderControlBlobs)) 00833 { 00834 ThisPath->RenderPathControlBlobs(StartSpread,EndPtIndex); 00835 if (!(AdjustDrag && RubberRect.ContainsCoord(EndPtCoord))) 00836 { 00837 ThisPath->DrawBlob(pRender, EndPtCoord, FALSE); 00838 ThisPath->DrawBlob(pRender, EndPtCoord, TRUE); 00839 } 00840 } 00841 pRender = DocView::GetNextOnTop(NULL); 00842 } 00843 } 00844 pNode = Selected->FindNext(pNode); 00845 } 00846 } 00847 00848 00849 00850 00851 /******************************************************************************************** 00852 00853 > OpState OpSelectPathPoints::GetState(String_256* Description, OpDescriptor*) 00854 00855 Author: Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com> 00856 Created: 29/6/94 00857 Outputs: Description - GetState fills this string with an approriate description 00858 of the current state of the push tool 00859 Returns: The state of the operation, so that menu items (ticks and greying can be 00860 done properly 00861 Purpose: Find out the state of the operation at the specific time 00862 00863 ********************************************************************************************/ 00864 00865 OpState OpSelectPathPoints::GetState(String_256* Description, OpDescriptor*) 00866 { 00867 OpState Blobby; 00868 00869 return Blobby; 00870 } 00871 00872 00873 00875 // OpInsertFloater // 00877 00878 00879 /******************************************************************************************** 00880 00881 > OpInsertFloater::OpInsertFloater() 00882 00883 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00884 Created: 06/12/94 00885 Purpose: Constructor. Currently does nothing. 00886 00887 ********************************************************************************************/ 00888 00889 OpInsertFloater::OpInsertFloater() 00890 { 00891 } 00892 00893 00894 00895 /******************************************************************************************** 00896 00897 > OpState OpInsertFloater::GetState(String_256* Description, OpDescriptor*) 00898 00899 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00900 Created: 06/12/94 00901 Outputs: - 00902 Returns: - 00903 Purpose: Find out the state of the operation at the specific time 00904 00905 ********************************************************************************************/ 00906 00907 OpState OpInsertFloater::GetState(String_256* Description, OpDescriptor*) 00908 { 00909 OpState Blobby; 00910 00911 return Blobby; 00912 } 00913 00914 00915 00916 /******************************************************************************************** 00917 00918 > BOOL OpInsertFloater::Declare() 00919 00920 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00921 Created: 06/12/94 00922 Returns: TRUE if all went OK, False otherwise 00923 Purpose: Adds the operation to the list of all known operations 00924 00925 ********************************************************************************************/ 00926 00927 BOOL OpInsertFloater::Declare() 00928 { 00929 return (RegisterOpDescriptor( 0, 00930 _R(IDS_NODEPATH_EDIT), 00931 CC_RUNTIME_CLASS(OpInsertFloater), 00932 OPTOKEN_INSERTFLOATER, 00933 OpInsertFloater::GetState)); 00934 } 00935 00936 00937 00938 /******************************************************************************************** 00939 00940 > void OpInsertFloater::DoWithParam(OpDescriptor* pOpDesc, OpParam* pOpParam) 00941 00942 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00943 Created: 06/12/94 00944 Inputs: pOpDesc - pointer to the OpDescriptor for the operation 00945 pOpParam - pointer to the operations parameter object 00946 Returns: - 00947 Purpose: Performs the insertion of the floating endpoint into the Line tool, creating 00948 undo actions. 00949 00950 ********************************************************************************************/ 00951 00952 void OpInsertFloater::DoWithParam(OpDescriptor* pOpDesc, OpParam* pOpParam) 00953 { 00954 InsertFloaterParam* Params = (InsertFloaterParam*)pOpParam; 00955 00956 if (Params->pOpWorkingDocument != NULL) 00957 { 00958 pOurDoc = Params->pOpWorkingDocument; 00959 pOurView = NULL; 00960 } 00961 00962 if (!InsertFloaterAction::DoInsert(this, &UndoActions, Params->pTool, 00963 &Params->InsertPos, Params->InsertSpread)) 00964 { 00965 FailAndExecute(); 00966 } 00967 00968 End(); 00969 } 00970 00971 00972 00973 /******************************************************************************************** 00974 00975 > void InsertFloaterParam::InsertFloaterParam(DocCoord* pInsertPos, 00976 Spread* pInsertSpread, 00977 BezierTool* pLineTool, 00978 Document* pWorkDoc) 00979 00980 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00981 Created: 06/12/94 00982 Inputs: pInsertPos - pointer to a coordinate to insert the floating endpoint. 00983 pInsertSpread - pointer to a spread to insert the floating endpoint onto. 00984 pLineTool - pointer to the Line Tool (which contains the floating endpoint) 00985 pWorkDoc - points to the document to invoke this operation into 00986 Outputs: - 00987 Returns: - 00988 Purpose: Constructs the InsertFloaterParam object ready for passing to OpInsertFloater 00989 00990 ********************************************************************************************/ 00991 InsertFloaterParam::InsertFloaterParam(DocCoord* pInsertPos, Spread* pInsertSpread, 00992 BezierTool* pLineTool, Document* pWorkDoc) 00993 { 00994 ERROR3IF(pInsertPos == NULL, "pInsertPos was NULL"); 00995 ERROR3IF(pInsertSpread == NULL, "pInsertSpread was NULL"); 00996 ERROR3IF(pLineTool == NULL, "pTool was NULL"); 00997 00998 InsertPos = *pInsertPos; 00999 InsertSpread = pInsertSpread; 01000 pTool = pLineTool; 01001 pOpWorkingDocument = pWorkDoc; 01002 } 01003 01004 01005 01007 // OpRemoveFloater // 01009 01010 01011 /******************************************************************************************** 01012 01013 > OpRemoveFloater::OpRemoveFloater() 01014 01015 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01016 Created: 06/12/94 01017 Purpose: Constructor. Currently does nothing. 01018 01019 ********************************************************************************************/ 01020 01021 OpRemoveFloater::OpRemoveFloater() 01022 { 01023 } 01024 01025 01026 01027 /******************************************************************************************** 01028 01029 > OpState OpRemoveFloater::GetState(String_256* Description, OpDescriptor*) 01030 01031 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01032 Created: 06/12/94 01033 Outputs: - 01034 Returns: - 01035 Purpose: Find out the state of the operation at the specific time 01036 01037 ********************************************************************************************/ 01038 01039 OpState OpRemoveFloater::GetState(String_256* Description, OpDescriptor*) 01040 { 01041 OpState Blobby; 01042 01043 return Blobby; 01044 } 01045 01046 01047 01048 /******************************************************************************************** 01049 01050 > BOOL OpRemoveFloater::Declare() 01051 01052 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01053 Created: 06/12/94 01054 Returns: TRUE if all went OK, False otherwise 01055 Purpose: Adds the operation to the list of all known operations 01056 01057 ********************************************************************************************/ 01058 01059 BOOL OpRemoveFloater::Declare() 01060 { 01061 return (RegisterOpDescriptor( 0, 01062 _R(IDS_NODEPATH_EDIT), 01063 CC_RUNTIME_CLASS(OpRemoveFloater), 01064 OPTOKEN_REMOVEFLOATER, 01065 OpRemoveFloater::GetState)); 01066 } 01067 01068 01069 01070 /******************************************************************************************** 01071 01072 > void OpRemoveFloater::DoWithParam(OpDescriptor* pOpDesc, OpParam* pOpParam) 01073 01074 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01075 Created: 06/12/94 01076 Inputs: pOpDesc - pointer to the OpDescriptor for the operation 01077 pOpParam - pointer to the operations parameter object 01078 Returns: - 01079 Purpose: Performs the removal of the floating endpoint from the Line tool, creating 01080 undo actions. 01081 01082 ********************************************************************************************/ 01083 01084 void OpRemoveFloater::DoWithParam(OpDescriptor* pOpDesc, OpParam* pOpParam) 01085 { 01086 InsertFloaterParam* Params = (InsertFloaterParam*)pOpParam; 01087 01088 if (Params->pOpWorkingDocument != NULL) 01089 { 01090 pOurDoc = Params->pOpWorkingDocument; 01091 pOurView = NULL; 01092 } 01093 01094 // Create an undo action for this operation 01095 DocCoord OldPos; 01096 Spread* OldpSpread; 01097 Document* OldpDoc; 01098 01099 if (Params->pTool->GetMoveTo(&OldpSpread, &OldPos, &OldpDoc)) 01100 { 01101 if (!InsertFloaterAction::DoInsert(this, &UndoActions, Params->pTool, &OldPos, OldpSpread)) 01102 { 01103 FailAndExecute(); 01104 } 01105 } 01106 01107 // and now perform the operation 01108 Params->pTool->ClearMoveTo(); 01109 01110 End(); 01111 } 01112 01113 01114 01116 // The InsertFloaterAction class // 01118 01119 /******************************************************************************************** 01120 01121 > InsertFloaterAction::InsertFloaterAction() 01122 01123 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01124 Created: 05/12/94 01125 Inputs: - 01126 Outputs: - 01127 Returns: - 01128 Purpose: Constructor for the action to insert a floating endpoint. 01129 Errors: - 01130 SeeAlso: - 01131 01132 ********************************************************************************************/ 01133 InsertFloaterAction::InsertFloaterAction() 01134 { 01135 pLineTool = NULL; 01136 } 01137 01138 01139 /******************************************************************************************** 01140 01141 > ActionCode InsertFloaterAction::Init( Operation* pOp, 01142 ActionList* pActionList, 01143 BezierTool* pTool, 01144 Action** NewAction) 01145 01146 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01147 Created: 05/12/94 01148 Inputs: pOp is the pointer to the operation to which this action belongs 01149 pTool is a pointer to the Line tool so the action can access the SetLineTo 01150 and ClearLineTo functions 01151 pActionList is the action list to which this action should be added 01152 Outputs: NewAction is a pointer to a pointer to an action, allowing the function to 01153 return a pointer to the created action 01154 Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL 01155 Purpose: This is the function which creates an instance of this action. If there is no 01156 room in the undo buffer (which is determined by the base class Init function 01157 called within) the function will either return AC_NO_RECORD which means the 01158 operation can continue, but no undo information needs to be stored, or AC_OK 01159 which means the operation should continue AND record undo information. If 01160 the function returns AC_FAIL, there was not enough memory to record the undo 01161 information, and the user has decided not to continue with the operation. 01162 Errors: - 01163 SeeAlso: Action::Init() 01164 01165 ********************************************************************************************/ 01166 ActionCode InsertFloaterAction::Init( Operation* pOp, 01167 ActionList* pActionList, 01168 Action** NewAction) 01169 { 01170 UINT32 ActSize = sizeof(InsertFloaterAction); 01171 01172 ActionCode Ac = Action::Init( pOp, pActionList, ActSize, CC_RUNTIME_CLASS(InsertFloaterAction), NewAction); 01173 return Ac; 01174 } 01175 01176 01177 01178 /******************************************************************************************** 01179 01180 > ActionCode InsertFloaterAction::DoInsert(Operation* pOp, 01181 ActionList* pActionList, 01182 BezierTool* pTool) 01183 01184 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01185 Created: 05/12/94 01186 Inputs: pOp is the currently running operation 01187 pActionList is a pointer ot the action list to which the action should be appended 01188 pTool is a pointer to the Line tool. 01189 Outputs: - 01190 Returns: Action code which indicates success or failure to create the action 01191 Purpose: This static function makes it a little easier to use this action. It creates an instance 01192 of this action and appends it to the action list. 01193 Errors: - 01194 SeeAlso: RemoveFloaterAction::DoRemove 01195 01196 ********************************************************************************************/ 01197 01198 ActionCode InsertFloaterAction::DoInsert(Operation* pOp, 01199 ActionList* pActionList, 01200 BezierTool* pTool, 01201 DocCoord* pPoint, 01202 Spread* pSpread) 01203 { 01204 InsertFloaterAction* RecAction = NULL; 01205 ActionCode Act = InsertFloaterAction::Init(pOp, pActionList, (Action**)&RecAction); 01206 if ( (Act == AC_OK) && (RecAction != NULL) ) 01207 { 01208 RecAction->pLineTool = pTool; 01209 RecAction->pSpread = pSpread; 01210 RecAction->Point = *pPoint; 01211 } 01212 return Act; 01213 } 01214 01215 01216 01217 /******************************************************************************************** 01218 01219 > ActionCode InsertFloaterAction::Execute() 01220 01221 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01222 Created: 05/12/94 01223 Inputs: - 01224 Outputs: - 01225 Returns: ActionCode, either AC_OK, AC_NORECORD or AC_FAIL 01226 Purpose: Inserts the floating endpoint into the Line Tool, creating an undo action to 01227 remove the endpoint. 01228 Errors: - 01229 SeeAlso: RemoveFloaterAction::Execute 01230 01231 ********************************************************************************************/ 01232 ActionCode InsertFloaterAction::Execute() 01233 { 01234 ERROR3IF(pLineTool == NULL, "Pointer to line tool was NULL"); 01235 01236 RemoveFloaterAction* ReAction = NULL; 01237 ActionCode Act = AC_FAIL; 01238 01239 // Create a redo action for this action, which is a RemoveFloaterAction 01240 if (pLineTool != NULL) 01241 { 01242 Act = RemoveFloaterAction::Init(pOperation, 01243 pOppositeActLst, 01244 pLineTool, 01245 (Action**)(&ReAction)); 01246 if (Act == AC_FAIL) 01247 return AC_FAIL; 01248 01249 // Now do the actual action 01250 pLineTool->SetMoveTo(Point, pSpread, GetWorkingDoc()); 01251 } 01252 01253 return Act; 01254 } 01255 01256 InsertFloaterAction::~InsertFloaterAction() 01257 { 01258 } 01259 01260 01261 01263 // The RemoveFloaterAction class // 01265 01266 /******************************************************************************************** 01267 01268 > RemoveFloaterAction::RemoveFloaterAction() 01269 01270 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01271 Created: 05/12/94 01272 Inputs: - 01273 Outputs: - 01274 Returns: - 01275 Purpose: Constructor for the action to remove a floating endpoint. 01276 Errors: - 01277 SeeAlso: - 01278 01279 ********************************************************************************************/ 01280 RemoveFloaterAction::RemoveFloaterAction() 01281 { 01282 pLineTool = NULL; 01283 } 01284 01285 01286 /******************************************************************************************** 01287 01288 > ActionCode RemoveFloaterAction::Init( Operation* pOp, 01289 ActionList* pActionList, 01290 BezierTool* pTool, 01291 Action** NewAction) 01292 01293 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01294 Created: 05/12/94 01295 Inputs: pOp is the pointer to the operation to which this action belongs 01296 pTool is a pointer to the Line tool so the action can access the SetLineTo 01297 and ClearLineTo functions 01298 pActionList is the action list to which this action should be added 01299 Outputs: NewAction is a pointer to a pointer to an action, allowing the function to 01300 return a pointer to the created action 01301 Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL 01302 Purpose: This is the function which creates an instance of this action. If there is no 01303 room in the undo buffer (which is determined by the base class Init function 01304 called within) the function will either return AC_NO_RECORD which means the 01305 operation can continue, but no undo information needs to be stored, or AC_OK 01306 which means the operation should continue AND record undo information. If 01307 the function returns AC_FAIL, there was not enough memory to record the undo 01308 information, and the user has decided not to continue with the operation. 01309 Errors: - 01310 SeeAlso: Action::Init() 01311 01312 ********************************************************************************************/ 01313 ActionCode RemoveFloaterAction::Init( Operation* pOp, 01314 ActionList* pActionList, 01315 BezierTool* pTool, 01316 Action** NewAction) 01317 { 01318 UINT32 ActSize = sizeof(RemoveFloaterAction); 01319 01320 ActionCode Ac = Action::Init( pOp, pActionList, ActSize, CC_RUNTIME_CLASS(RemoveFloaterAction), NewAction); 01321 if ((Ac == AC_OK) && (*NewAction != NULL)) 01322 { 01323 ((RemoveFloaterAction*)*NewAction)->pLineTool = pTool; 01324 } 01325 return Ac; 01326 } 01327 01328 01329 01330 /******************************************************************************************** 01331 01332 > ActionCode RemoveFloaterAction::DoRemove(Operation* pOp, 01333 ActionList* pActionList, 01334 BezierTool* pTool) 01335 01336 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01337 Created: 05/12/94 01338 Inputs: pOp is the currently running operation 01339 pActionList is a pointer ot the action list to which the action should be appended 01340 pTool is a pointer to the Line tool. 01341 Outputs: - 01342 Returns: Action code which indicates success or failure to create the action 01343 Purpose: This static function makes it a little easier to use this action. It creates an instance 01344 of this action and appends it to the action list. 01345 Errors: - 01346 SeeAlso: InsertFloaterAction::DoInsert 01347 01348 ********************************************************************************************/ 01349 01350 ActionCode RemoveFloaterAction::DoRemove(Operation* pOp, 01351 ActionList* pActionList, 01352 BezierTool* pTool) 01353 { 01354 RemoveFloaterAction* RecAction; 01355 ActionCode Act = RemoveFloaterAction::Init(pOp, pActionList, pTool, (Action**)&RecAction); 01356 return Act; 01357 } 01358 01359 01360 01361 /******************************************************************************************** 01362 01363 > ActionCode RemoveFloaterAction::Execute() 01364 01365 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01366 Created: 05/12/94 01367 Inputs: - 01368 Outputs: - 01369 Returns: ActionCode, either AC_OK, AC_NORECORD or AC_FAIL 01370 Purpose: Removes the floating endpoint from the Line Tool, creating an undo action to 01371 insert the endpoint. 01372 Errors: - 01373 SeeAlso: InsertFloaterAction::Execute 01374 01375 ********************************************************************************************/ 01376 ActionCode RemoveFloaterAction::Execute() 01377 { 01378 ERROR3IF(pLineTool == NULL, "Pointer to line tool was NULL"); 01379 01380 InsertFloaterAction* ReAction = NULL; 01381 ActionCode Act = AC_FAIL; 01382 01383 // Create a redo action for this action, which is an InsertFloaterAction 01384 if (pLineTool != NULL) 01385 { 01386 DocCoord OldPos; 01387 Spread* OldpSpread; 01388 Document* OldpDoc; 01389 01390 if (pLineTool->GetMoveTo(&OldpSpread, &OldPos, &OldpDoc)) 01391 { 01392 Act = InsertFloaterAction::Init(pOperation, pOppositeActLst, (Action**)(&ReAction)); 01393 if (ReAction != NULL) 01394 { 01395 ReAction->pLineTool = pLineTool; 01396 ReAction->pSpread = OldpSpread; 01397 ReAction->Point = OldPos; 01398 } 01399 01400 if (Act == AC_FAIL) 01401 return AC_FAIL; 01402 } 01403 01404 // Now do the actual action 01405 pLineTool->ClearMoveTo(); 01406 } 01407 01408 return Act; 01409 } 01410 01411 RemoveFloaterAction::~RemoveFloaterAction() 01412 { 01413 } 01414