OpReshapeOrAddPoint Class Reference

This operation serves two purposes - while dragging, it will reshape a bezier segment, changing the path on ending the drag. However, if the drag is released immediately after it is initiated, a point is added to the bezier curve (or line) at the click point. More...

#include <pathedit.h>

Inheritance diagram for OpReshapeOrAddPoint:

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

Public Member Functions

 OpReshapeOrAddPoint ()
 Constructor to initialise the members variables.
void DoStartDragEdit (NodePath *, DocCoord Anchor, Spread *pSpread, INT32, double)
 This is called when a Drag operation has been started on the middle of a path. It will try and reshape the curve as it's dragging according to the maths in the function RecalculatePath.
virtual void DragPointerMove (DocCoord PointerPos, ClickModifiers ClickMods, Spread *, BOOL bSolidDrag)
 This is called every time the mouse moves, during a drag.
virtual void DragFinished (DocCoord Pos, ClickModifiers Mods, Spread *pSpread, BOOL Success, BOOL bSolidDrag)
 This is called when a drag operation finishes.

Static Public Member Functions

static BOOL Init ()
 Adds the operation to the list of all known operations.
static OpState GetState (String_256 *Description, OpDescriptor *)
 Find out the state of the operation at the specific time.

Protected Member Functions

BOOL BuildEditPath ()
 Builds a copy of the path that we can edit, without destroying the original data. If the dragged segment is a line then it is converted to a curve segment Also sets the NeedToRenderFlags for the EOR rendering during the drag. The parts of the path need to be rendered during the drag is the segment being dragged and the next and previous segmetns if the rotate flags are on the endpoints at each end of the dragged segment.
void RecalculatePath (DocCoord Offset)
 Will reshape a curve segment using a bit of voodoo maths.
BOOL DragFinishedAddPoint ()
 This is called when a drag on a path segment finishes and we want to add a new point on the segment.
BOOL DragFinishedReshapeLine ()
 This is called when a drag on a path line segment finishes and we want to reshape it.
void SetStatusLineHelp ()
 For getting a message for the status line during drag operations.

Protected Attributes

INT32 Index
double paramdist
DocCoord OrigControl1
DocCoord OrigControl2
DocCoord FurthestPoint
BOOL HaveMadeCurve

Detailed Description

This operation serves two purposes - while dragging, it will reshape a bezier segment, changing the path on ending the drag. However, if the drag is released immediately after it is initiated, a point is added to the bezier curve (or line) at the click point.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/8/94

Definition at line 404 of file pathedit.h.


Constructor & Destructor Documentation

OpReshapeOrAddPoint::OpReshapeOrAddPoint  ) 
 

Constructor to initialise the members variables.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/03/95

Definition at line 8539 of file pathedit.cpp.

08539                                          : OpNodePathEditBlob()
08540 {
08541     Index = -1;             
08542     paramdist = -1;     
08543     HaveMadeCurve = FALSE;      
08544 };


Member Function Documentation

BOOL OpReshapeOrAddPoint::BuildEditPath  )  [protected]
 

Builds a copy of the path that we can edit, without destroying the original data. If the dragged segment is a line then it is converted to a curve segment Also sets the NeedToRenderFlags for the EOR rendering during the drag. The parts of the path need to be rendered during the drag is the segment being dragged and the next and previous segmetns if the rotate flags are on the endpoints at each end of the dragged segment.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> - later attacked by Peter
Date:
17/02/94
Returns:
TRUE if it managed to build the path, FALSE if it failed

Errors: If it runs out of memory then it will return FALSE

Reimplemented from OpNodePathEditBlob.

Definition at line 8314 of file pathedit.cpp.

08315 {
08316     // Make a copy of the path
08317     UINT32 NumCoords = OriginalPath->InkPath.GetNumCoords();
08318     if (!EditPath.Initialise(NumCoords, 24))
08319         return FALSE;
08320     if (!EditPath.CopyPathDataFrom(&(OriginalPath->InkPath)))
08321         return FALSE;
08322 
08323     // If the drag segment is a line then convert it to a curve
08324     PathFlags* Flags;
08325     PathVerb* Verbs;
08326     DocCoord* Coords;
08327     EditPath.GetPathArrays(&Verbs, &Coords, &Flags);
08328     if ((Verbs[Index] & ~PT_CLOSEFIGURE) == PT_LINETO)
08329     {
08330         const DocCoord Start = Coords[Index-1];
08331         const DocCoord End = Coords[Index];
08332         BOOL IsClosed = OriginalPath->InkPath.GetVerbArray()[Index] & PT_CLOSEFIGURE;
08333         BOOL IsSelected = OriginalPath->InkPath.GetFlagArray()[Index].IsSelected;
08334 
08335         // Insert a curve segment
08336         DocCoord OneThird((Start.x+(End.x-Start.x)/3), (Start.y+(End.y-Start.y)/3) );
08337         DocCoord TwoThird((End.x+(Start.x-End.x)/3), (End.y+(Start.y-End.y)/3) );
08338         EditPath.SetPathPosition(Index);
08339         if (!EditPath.InsertCurveTo(OneThird, TwoThird, End))
08340             return FALSE;
08341 
08342         // Remove the line segment
08343         if (!EditPath.DeleteSection(Index+3, 1))
08344             return FALSE;
08345 
08346         // Copy the selection and closure state of the LineTo
08347         EditPath.GetPathArrays(&Verbs, &Coords, &Flags);
08348         Flags[Index+2].IsSelected = IsSelected;
08349         if (IsClosed)
08350             Verbs[Index+2] = Verbs[Index+2] | PT_CLOSEFIGURE; 
08351 
08352         // We need to recalc paramdist now
08353         HaveMadeCurve = TRUE;
08354         INT32 tempel;
08355         EditPath.SqrDistanceToPoint(StartMousePos, &tempel, &paramdist);
08356     }
08357 
08358     // Clear the NeedToRender flags
08359     EditPath.ClearNeedToRender();
08360 
08361     // Set the render flag on this segment
08362     EditPath.GetPathArrays(&Verbs, &Coords, &Flags);
08363     if ((Verbs[Index] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
08364         Flags[Index+2].NeedToRender = TRUE;
08365     else
08366         Flags[Index].NeedToRender = TRUE;
08367 
08368     // Clear the smooth bit on the endpoints of this curve
08369     Flags[Index-1].IsSmooth = FALSE;
08370     Flags[Index+2].IsSmooth = FALSE;
08371 
08372     // Check before setting the NeedToRender on the adjacent segments as well
08373     if ((Verbs[Index] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
08374     {
08375         INT32 Opposite = EditPath.FindOppositeControlPoint(Index);
08376         if ( (Opposite>=0) && (Flags[Opposite+1].IsRotate || Flags[Index-1].IsRotate) )
08377             Flags[Opposite+1].NeedToRender = TRUE;
08378 
08379         Opposite = EditPath.FindOppositeControlPoint(Index+1);
08380         if ( (Opposite>=0) && (Flags[Opposite-1].IsRotate || Flags[Index+2].IsRotate) )
08381             Flags[Opposite+2].NeedToRender = TRUE;
08382     }
08383 
08384     // It worked
08385     return TRUE;
08386 }

void OpReshapeOrAddPoint::DoStartDragEdit NodePath OrigPath,
DocCoord  Anchor,
Spread pSpread,
INT32  SegmentIndex,
double  pdist
 

This is called when a Drag operation has been started on the middle of a path. It will try and reshape the curve as it's dragging according to the maths in the function RecalculatePath.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
5/7/93
Parameters:
OrigPath - The original Node path object [INPUTS] Anchor - The position of the mouse at the start of the Drag pSpread - the spread that the drag started on ControlIndex - The Coord number of the control point that we are dragging this is the index of the first element of the segment plus 1 pdist - parametric distance along the curve we're dragging from (0 to 1)
See also:
OpReshapeOrAddPoint::RecalculatePath

Definition at line 7869 of file pathedit.cpp.

07871 {
07872     // We had better take a note of the starting point of the drag
07873     LastMousePos = Anchor;
07874     StartMousePos = Anchor;
07875     FurthestPoint = Anchor;
07876     StartSpread  = pSpread;
07877     OriginalPath = OrigPath;
07878     Index = SegmentIndex;
07879     paramdist = pdist;
07880 
07881     CreateCursors();
07882 
07883     // We also need to make a version of the path that we can change
07884     if (!BuildEditPath())
07885     {
07886         // Failed to get the memory that we needed to copy the path, so moan
07887         TRACEUSER( "Jim", _T("Failed to get the mem to copy the path data for editing\n") );
07888         
07889         // Inform the person doing the clicking that life is not looking so good
07890         InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) );
07891         End();
07892         return;
07893     }
07894 
07895     // Render the bits of the path that are different
07896     DocRect EditPathBBox = EditPath.GetBoundingRect();
07897     RenderPathEditBlobs(EditPathBBox, pSpread);
07898 
07899     // Record the original positions of the two control points
07900     DocCoord* Coords = EditPath.GetCoordArray();
07901     PathVerb* Verbs = EditPath.GetVerbArray();
07902     if (Verbs[Index] == PT_BEZIERTO)
07903     {
07904         OrigControl1 = Coords[Index];
07905         OrigControl2 = Coords[Index+1];
07906     }
07907     else
07908     {
07909         ERROR3("Control Point wasn't a control point!");
07910     }
07911 
07912     // And tell the Dragging system that we need drags to happen
07913     StartDrag(DRAGTYPE_AUTOSCROLL, &EditPathBBox, &LastMousePos);
07914 
07915     SetStatusLineHelp();
07916 }

void OpReshapeOrAddPoint::DragFinished DocCoord  PointerPos,
ClickModifiers  ClickMods,
Spread pSpread,
BOOL  Success,
BOOL  bSolidDrag
[virtual]
 

This is called when a drag operation finishes.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/8/94
Parameters:
PointerPos - The position of the mouse at the end of the drag [INPUTS] ClickMods - the key modifiers being pressed Success - TRUE if the drag was terminated properly, FALSE if it was ended with the escape key being pressed
See also:
ClickModifiers

Reimplemented from OpNodePathEditBlob.

Definition at line 7987 of file pathedit.cpp.

07989 {
07990     RenderPathEditBlobs( EditPath.GetBoundingRect(), StartSpread );
07991     EndDrag();
07992     DestroyCursors();
07993     BeginSlowJob();
07994     
07995     BOOL Worked = TRUE;
07996 
07997     if ( Success )
07998     {
07999         ObjChangeFlags cFlags;
08000         cFlags.TransformNode = TRUE;
08001         ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,OriginalPath,this);
08002 
08003         Worked = DoStartSelOp(TRUE,TRUE) ;
08004 
08005         // Create and send a change message about this path edit
08006         if (Worked)
08007         {
08008             Worked = OriginalPath->AllowOp(&ObjChange) ;
08009         }
08010 
08011         // If the furthest mouse position is close to the start, add a point instead
08012         if (Worked)
08013         {
08014 //          // Store the paths sub-selection state
08015 //          if (Worked)
08016 //              Worked = (StorePathSubSelStateAction::DoRecord(this, &UndoActions, &OriginalPath->InkPath) != AC_FAIL);
08017 
08018             // Due to popular request, I've changed this test so that moving by even a pixel
08019             // will reshape the line, so a single click has to be a single click to add a 
08020             // point.
08021             if (StartMousePos == FurthestPoint)
08022             {
08023                 Worked = DragFinishedAddPoint(); 
08024             }
08025             else
08026             {
08027                 BOOL Optimise = CopyNeedToRenderFlags() && !(EndSnapped || SnapToAnother);
08028 
08029                 // Check we are dealing with a node path. If not, we shouldn't optimise the redraw.
08030                 // Really we should ask the node whether it can cope with optimised redraw. This means
08031                 // whether its correct simply to redraw the changed rectangular section around the moved
08032                 // coordinate. For envelope and perspective moulds whose shapes are govened by derived
08033                 // path objects its not correct to redraw optimally as this can result in sections of the
08034                 // object being left undrawn when the whole surface / contents have changed.
08035 
08036                 if (!IS_A(OriginalPath,NodePath))
08037                     Optimise = FALSE;
08038 
08039                 // Force a re-draw of the place where the path used to be
08040                 if (RecalcBoundsAction::DoRecalc(this, &UndoActions, OriginalPath, Optimise) == AC_FAIL)
08041                     Worked = FALSE;
08042 
08043                 if (Worked && HaveMadeCurve)
08044                 {
08045                     Worked = DragFinishedReshapeLine();
08046                 }
08047 
08048                 if (Worked)
08049                 {
08050                     // The drag was a real drag (man) so replace the edited path
08051                     // Go and copy the edited path back over the original path
08052                     if (!CopyEditedPathBack())
08053                     {
08054 //                      if (IsUserName("Jim")) TRACE( _T("Failed to copy the edited path back to the original") );
08055                         Error::SetError( _R(IDS_OUT_OF_MEMORY) );
08056                         Worked = FALSE;
08057                     }
08058                 }
08059         
08060                 // Recalculate the path's bounding box
08061                 OriginalPath->InvalidateBoundingRect();
08062         
08063                 // tell the world that something in the selection has changed 
08064                 // so that selection bounds are updated
08065                 GetApplication()->UpdateSelection();
08066 
08067                 // Force a redraw of the place where the path is now.
08068                 if (Worked && (RecordBoundsAction::DoRecord(this, &UndoActions, OriginalPath, Optimise) == AC_FAIL))
08069                 {
08070                     Worked = FALSE;
08071                 }
08072             }
08073         }
08074 
08075         // Inform all the parents of this node that it has been changed.
08076         if (Worked)
08077         {
08078             ObjChange.Define(OBJCHANGE_FINISHED,cFlags,OriginalPath,this);
08079             Worked = UpdateChangedNodes(&ObjChange);
08080         }
08081     }
08082     else
08083         FailAndExecute();
08084 
08085     if (!Worked)
08086     {
08087 //      InformError();
08088         FailAndExecute();
08089     }
08090     End();
08091 }

BOOL OpReshapeOrAddPoint::DragFinishedAddPoint  )  [protected]
 

This is called when a drag on a path segment finishes and we want to add a new point on the segment.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/3/95
Parameters:
- [INPUTS]
Changes OriginalPath, adding a point when the drag started, creating two new [OUTPUTS] path segments, one either side. Also builds undo information into the operation history.
Returns:
TRUE/FALSE for success/failure.
See also:
OpReshapeOrAddPoint::DragFinished

Definition at line 8111 of file pathedit.cpp.

08112 {
08113     // First, find the closest point, the element it's at, and go from there
08114     INT32 SplitElement = 0;
08115     PathVerb    NewVerbs[6];
08116     DocCoord    NewCoords[6];
08117     PathFlags   NewFlags[6];
08118     for (INT32 j=0;j<6;j++)
08119     {
08120         NewCoords[j].x = 0;
08121         NewCoords[j].y = 0;
08122     }
08123     UINT32 NumElements = 0;
08124     if (OriginalPath->InkPath.SplitAtPoint(StartMousePos, &SplitElement, &NumElements, NewVerbs, NewCoords))
08125     {
08126         // The path was split, so we know where, and how, so let's party on the path
08127         PathVerb* Verbs = NULL;
08128         PathFlags* Flags = NULL;
08129         DocCoord* Coords = NULL;
08130         OriginalPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
08131         ERROR2IF((Verbs == NULL) || (Flags == NULL) || (Coords == NULL), FALSE, "Path array pointer was NULL");
08132 //      UINT32 NumCoords = OriginalPath->InkPath.GetNumCoords();
08133 
08134         // Before we go any further we want to deselect all current points
08135 //      for (UINT32 loop = 0; loop < NumCoords; loop++)
08136 //      {
08137 //          if (!DoChangeSelection(OriginalPath, loop, FALSE))
08138 //              return FALSE;
08139 //      }
08140         OriginalPath->InkPath.ClearSubSelection();
08141 
08142         INT32 NumToChange = 0;
08143         // We're adding something, either a line or curve - check which
08144         if ((Verbs[SplitElement] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
08145         {
08146             // Adding a curve - number to change = 6
08147             NumToChange = 6;
08148             // Initialise the flags appropriately
08149             INT32 i;
08150             for (i=0;i<3;i++)
08151             {
08152                 NewFlags[i] = Flags[SplitElement+i];
08153                 NewFlags[i+3] = Flags[SplitElement+i];
08154             }
08155             for (i = 1; i <=3; i++)
08156             {
08157                 NewFlags[i].IsSelected = TRUE;      
08158                 NewFlags[i].IsSmooth = FALSE;
08159                 NewFlags[i].IsRotate = TRUE;
08160             }
08161             NewFlags[0].IsSmooth = Flags[SplitElement].IsSmooth;
08162             NewFlags[0].IsRotate = Flags[SplitElement].IsRotate;
08163             NewFlags[4].IsSmooth = Flags[SplitElement+1].IsSmooth;
08164             NewFlags[4].IsRotate = Flags[SplitElement+1].IsRotate;
08165             NewFlags[5].IsSmooth = Flags[SplitElement+2].IsSmooth;
08166             NewFlags[5].IsRotate = Flags[SplitElement+2].IsRotate;
08167 
08168             if (Verbs[SplitElement+2] & PT_CLOSEFIGURE)
08169                 NewVerbs[5] |= PT_CLOSEFIGURE;
08170         }
08171         else
08172         {
08173             NumToChange = 2;
08174             NewFlags[0] = NewFlags[1] = Flags[SplitElement];
08175             NewFlags[0].IsSmooth = NewFlags[0].IsRotate = FALSE;
08176             NewFlags[0].IsSelected = TRUE;
08177             if (Verbs[SplitElement] & PT_CLOSEFIGURE)
08178                 NewVerbs[1] |= PT_CLOSEFIGURE;
08179         }
08180 
08181         // NumToChange is the number of elements that want changing
08182 
08183         Action* UnAction;
08184         ActionCode Act = RemovePathElementAction::Init(this, &UndoActions, NumToChange / 2, SplitElement, (Action**)(&UnAction));
08185         if (Act == AC_FAIL)
08186         {
08187             return FALSE;
08188         }
08189         ((RemovePathElementAction*)UnAction)->RecordPath(OriginalPath);
08190         PathFlags tempflags;
08191         tempflags.IsSmooth = TRUE;
08192         tempflags.IsRotate = TRUE;
08193         tempflags.IsSelected = TRUE;
08194 
08195         if (NumToChange == 6)
08196         {
08197             OriginalPath->InkPath.SetPathPosition(SplitElement);
08198             if (!(OriginalPath->InkPath.InsertCurveTo(NewCoords[0], NewCoords[1], NewCoords[2], &tempflags)))
08199             {
08200                 return FALSE;
08201             }
08202         }
08203         else
08204         {
08205             if (!(OriginalPath->InkPath.InsertLineTo(NewCoords[0], &tempflags)))
08206             {
08207                 return FALSE;
08208             }
08209         }
08210         
08211         // Refresh the path pointers in case things have moved
08212         OriginalPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
08213 
08214         // Build an action to record the changes we're about to make to the path
08215         ModifyPathAction* ModAction;
08216         Act = ModifyPathAction::Init(this, &UndoActions, NumToChange, (Action**)(&ModAction));
08217         if (Act == AC_FAIL)
08218         {
08219             return FALSE;
08220         }
08221         
08222         if ((Act!=AC_NORECORD) && (ModAction!=NULL))
08223         {
08224             PathVerb* ChangedVerbs;
08225             PathFlags* ChangedFlags;
08226             DocCoord* ChangedCoords;
08227             INT32* ChangedIndices;
08228 
08229             ALLOC_WITH_FAIL(ChangedVerbs, (PathVerb*) CCMalloc(NumToChange * sizeof(PathVerb)), this);
08230             ALLOC_WITH_FAIL(ChangedFlags, (PathFlags*) CCMalloc(NumToChange* sizeof(PathFlags)), this);
08231             ALLOC_WITH_FAIL(ChangedCoords, (DocCoord*) CCMalloc(NumToChange* sizeof(DocCoord)), this);
08232             ALLOC_WITH_FAIL(ChangedIndices, (INT32*) CCMalloc(NumToChange* sizeof(INT32)), this);
08233 
08234             if (!ChangedVerbs || !ChangedFlags || !ChangedCoords || !ChangedIndices)
08235             {
08236                 if (ChangedVerbs) CCFree(ChangedVerbs);
08237                 if (ChangedFlags) CCFree(ChangedFlags);
08238                 if (ChangedCoords) CCFree(ChangedCoords);
08239                 if (ChangedIndices) CCFree(ChangedIndices);
08240                 return FALSE;
08241             }
08242 
08243             // Now record the arrays...
08244             for (INT32 i=0; i<NumToChange; i++)
08245             {
08246                 ChangedIndices[i]   = SplitElement+i;
08247                 ChangedVerbs[i]     = Verbs[SplitElement+i];
08248                 ChangedFlags[i]     = Flags[SplitElement+i];
08249                 ChangedCoords[i]    = Coords[SplitElement+i];
08250             }
08251             
08252             ModAction->StoreArrays(ChangedVerbs, ChangedFlags, ChangedCoords, ChangedIndices, OriginalPath);
08253         }
08254 
08255         // Reread the pointers, in case they've changed
08256         OriginalPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
08257 
08258         // Now that the undo rigmarole has been done, let's change the path
08259         for (INT32 i=0; i<NumToChange; i++)
08260         {
08261             Verbs[SplitElement+i] = NewVerbs[i];
08262             Flags[SplitElement+i] = NewFlags[i];
08263             Coords[SplitElement+i] = NewCoords[i];
08264         }
08265 
08266         GetApplication()->FindSelection()->UpdateBounds();
08267     }
08268     else
08269     {
08270         return FALSE;
08271     }
08272 
08273     return TRUE;
08274 }

BOOL OpReshapeOrAddPoint::DragFinishedReshapeLine  )  [protected]
 

This is called when a drag on a path line segment finishes and we want to reshape it.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/3/95
Parameters:
- [INPUTS]
Changes OriginalPath, converting the dragged line segment into a curve, then [OUTPUTS] reshaping it as required by the drag.
Returns:
TRUE/FALSE for success/failure.
See also:
OpReshapeOrAddPoint::DragFinished, OpMakeSegmentsCurves::CarryOut

Definition at line 8293 of file pathedit.cpp.

08294 {
08295     return OpMakeSegmentsCurves::CarryOut(Index, Index-1, OriginalPath, this, &UndoActions);
08296 }

void OpReshapeOrAddPoint::DragPointerMove DocCoord  PointerPos,
ClickModifiers  ClickMods,
Spread pSpread,
BOOL  bSolidDrag
[virtual]
 

This is called every time the mouse moves, during a drag.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
5/7/93
Parameters:
PointerPos - The current position of the mouse in Doc Coords [INPUTS] ClickMods - Which key modifiers are being pressed pSpread - the spread that the cursor is over now
See also:
ClickModifiers

Reimplemented from OpNodePathEditBlob.

Definition at line 7935 of file pathedit.cpp.

07936 {
07937     EndSnapped = FALSE;     // Always false in this operation
07938     
07939     // If drag has moved onto a different spread, convert the coord to be relative to the
07940     // original spread.
07941     if (pSpread != StartSpread)
07942         PointerPos = MakeRelativeToSpread(StartSpread, pSpread, PointerPos);
07943 
07944     // Now snap it to the current grid
07945     DocView::SnapCurrent(StartSpread,&PointerPos);
07946 
07947     // Rub out the old EORed version of the path
07948     RenderPathEditBlobs( EditPath.GetBoundingRect(), StartSpread );
07949 
07950     // This is the bit where we go off and re-calculate the paths position,
07951     // based on how much the mouse has moved
07952     DocCoord Offset;
07953     Offset.x = PointerPos.x - StartMousePos.x;
07954     Offset.y = PointerPos.y - StartMousePos.y;
07955     RecalculatePath( Offset );
07956 
07957     // Compare this point with the furthest point so far
07958     if (PointerPos.Distance(StartMousePos) > FurthestPoint.Distance(StartMousePos))
07959     {
07960         FurthestPoint.x = PointerPos.x;
07961         FurthestPoint.y = PointerPos.y;
07962     }
07963 
07964     // Draw in the new version of the path and update the Last Mouse Position
07965     LastMousePos = PointerPos;
07966     RenderPathEditBlobs( EditPath.GetBoundingRect(), StartSpread );
07967 
07968     SetStatusLineHelp();
07969 }

OpState OpReshapeOrAddPoint::GetState String_256 Description,
OpDescriptor
[static]
 

Find out the state of the operation at the specific time.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
5/7/93
Parameters:
Description - GetState fills this string with an approriate description [OUTPUTS] of the current state of the selector tool
Returns:
The state of the operation, so that menu items (ticks and greying can be done properly

Reimplemented from OpNodePathEditBlob.

Definition at line 8562 of file pathedit.cpp.

08563 {
08564     OpState Blobby;
08565     
08566     return Blobby;
08567 }

BOOL OpReshapeOrAddPoint::Init void   )  [static]
 

Adds the operation to the list of all known operations.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
5/7/93
Returns:
TRUE if all went OK, False otherwise

Reimplemented from OpNodePathEditBlob.

Definition at line 8513 of file pathedit.cpp.

08514 {
08515     return (RegisterOpDescriptor(
08516                                     0, 
08517                                     _R(IDS_NODEPATH_EDIT),
08518                                     CC_RUNTIME_CLASS(OpReshapeOrAddPoint), 
08519                                     OPTOKEN_NODEPATH,
08520                                     OpReshapeOrAddPoint::GetState,
08521                                     0,                                      // help ID
08522                                     _R(IDBBL_NODEPATHOP),
08523                                     0 ) );                                  // bitmap ID
08524 }

void OpReshapeOrAddPoint::RecalculatePath DocCoord  Offset  )  [protected]
 

Will reshape a curve segment using a bit of voodoo maths.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
1/9/94
Parameters:
Offset - The Amount the pointer has moved from the *original* position (i.e. not [INPUTS] the last position). Scope: Private
Assuming the mouse was originally clicked on the path a certain distance along it (say 1/4 of the whole curve). The parametric distance would thus be 0.25 - this is the distance that controls the first control point. 1-0.25 controls the second control point.

Given: (px,py) = current pointer position (ox,oy) = original pointer position (x0,y0) = first control point (x1,y1) = second control point (x2,y2) = endpoint of curve pdist = parametric distance

then: newx0 = x0+(px-ox)*3/pdist newy0 = y0+(py-oy)*3/pdist newx1 = x1+(px-ox)*3/(1-pdist) newy1 = y1+(py-oy)*3/(1-pdist)

Disclaimer: This maths was plucked out of the blue, and so might not be the best way of doing it.

Definition at line 8422 of file pathedit.cpp.

08423 {
08424     // Don't recalculate if the segment is a straight line...
08425     const double factor = 0.656875;
08426     PathVerb* Verbs = EditPath.GetVerbArray();
08427     DocCoord* Coords = EditPath.GetCoordArray();
08428     PathFlags* Flags = EditPath.GetFlagArray();
08429     if (Verbs[Index] == PT_BEZIERTO)        // first ctrl pt won't have closefigure set
08430     {
08431         // We have to calculate by how much to move the two control points on the curve,
08432         // and if the endpoints are set to rotate, we have to rotate the opposite control
08433         // points as well
08434 
08435         // Since the routine CalcRotate will change the *current* coords of the control point,
08436         // and we calculate the new coords from the *original* control point (to avoid accumulated
08437         // inaccuracies) we have to generate an offset that CalcRotate can use.
08438         
08439         DocCoord ControlOffset;
08440         INT32 OppositeIndex = EditPath.FindOppositeControlPoint(Index);
08441         ControlOffset.x = (INT32)(OrigControl1.x + (Offset.x) * factor / paramdist);
08442         ControlOffset.y = (INT32)(OrigControl1.y + (Offset.y) * factor / paramdist);
08443 
08444         ControlOffset.x -= Coords[Index].x;
08445         ControlOffset.y -= Coords[Index].y;
08446 
08447         if (Flags[Index-1].IsRotate && OppositeIndex >= 0)
08448         {
08449             EditPath.CalcRotate(Coords[Index-1], &Coords[Index], &Coords[OppositeIndex], ControlOffset);
08450         }
08451         else
08452         {
08453             Coords[Index].x += ControlOffset.x;
08454             Coords[Index].y += ControlOffset.y;
08455         }
08456 
08457         // We need to clear the smooth flags off the endpoints and control points around where
08458         // the path is being dragged.  We know Index-1 to Index+2 are Beziers.
08459         if ((Index > 1) && ((Verbs[Index-1] & ~PT_CLOSEFIGURE) == PT_BEZIERTO) )
08460             Flags[Index-2].IsSmooth = FALSE;
08461         Flags[Index-1].IsSmooth = FALSE;
08462         Flags[Index].IsSmooth = FALSE;
08463         Flags[Index+1].IsSmooth = FALSE;
08464         Flags[Index+2].IsSmooth = FALSE;
08465         if ((Index < EditPath.GetNumCoords()-3) && ((Verbs[Index+3] & ~PT_CLOSEFIGURE) == PT_BEZIERTO) )
08466             Flags[Index+3].IsSmooth = FALSE;
08467 
08468         // If the index was at the very start or end of the path then we also need to turn off the
08469         // rotate flags so future path extension is correct
08470         if (Index == 1)
08471 
08472         {
08473             Flags[Index].IsRotate = FALSE;
08474             Flags[Index-1].IsRotate = FALSE;
08475         }                                                 
08476         if (Index == EditPath.GetNumCoords()-3)
08477         {
08478             Flags[Index+1].IsRotate = FALSE;
08479             Flags[Index+2].IsRotate = FALSE;
08480         }
08481     
08482         ControlOffset.x = (INT32)(OrigControl2.x + (Offset.x) * factor / (1.0-paramdist));
08483         ControlOffset.y = (INT32)(OrigControl2.y + (Offset.y) * factor / (1.0-paramdist));
08484 
08485         ControlOffset.x -= Coords[Index+1].x;
08486         ControlOffset.y -= Coords[Index+1].y;
08487         OppositeIndex = EditPath.FindOppositeControlPoint(Index+1);
08488 
08489         if (Flags[Index+2].IsRotate && OppositeIndex >= 0)
08490         {
08491             EditPath.CalcRotate(Coords[Index+2], &Coords[Index+1], &Coords[OppositeIndex], ControlOffset);
08492         }
08493         else
08494         {
08495             Coords[Index+1].x += ControlOffset.x;
08496             Coords[Index+1].y += ControlOffset.y;
08497         }
08498     }
08499 }

void OpReshapeOrAddPoint::SetStatusLineHelp  )  [protected, virtual]
 

For getting a message for the status line during drag operations.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
4/1/96

Reimplemented from OpNodePathEditBlob.

Definition at line 8577 of file pathedit.cpp.

08578 {
08579     String_256 HelpString;
08580     if (StartMousePos == FurthestPoint)
08581         HelpString = String_256(_R(IDS_PATHDRAGADDREFORM));
08582     else
08583         HelpString = String_256(_R(IDS_PATHDRAGFINISHREFORM));
08584 
08585     GetApplication()->UpdateStatusBarText(&HelpString, FALSE);
08586 }


Member Data Documentation

DocCoord OpReshapeOrAddPoint::FurthestPoint [protected]
 

Definition at line 441 of file pathedit.h.

BOOL OpReshapeOrAddPoint::HaveMadeCurve [protected]
 

Definition at line 442 of file pathedit.h.

INT32 OpReshapeOrAddPoint::Index [protected]
 

Definition at line 437 of file pathedit.h.

DocCoord OpReshapeOrAddPoint::OrigControl1 [protected]
 

Definition at line 439 of file pathedit.h.

DocCoord OpReshapeOrAddPoint::OrigControl2 [protected]
 

Definition at line 440 of file pathedit.h.

double OpReshapeOrAddPoint::paramdist [protected]
 

Definition at line 438 of file pathedit.h.


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