opbezier.cpp

Go to the documentation of this file.
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 

Generated on Sat Nov 10 03:47:43 2007 for Camelot by  doxygen 1.4.4