BezierTool Class Reference

This class handles the Free Hand Tool that is used to draw lines that follow the path of the Mouse Pointer. More...

#include <beztool.h>

Inheritance diagram for BezierTool:

Tool_v1 List of all members.

Public Types

enum  CurrentMode { New, Add, Change }

Public Member Functions

 BezierTool ()
 Dump Constructor - It does nothing. All the real initialisation is done in BezierTool::Init which is called by the Tool Manager.
 ~BezierTool ()
 Destructor (Virtual). Does nothing.
BOOL Init ()
 Used to check if the Tool was properly constructed.
void Describe (void *InfoPtr)
 Allows the tool manager to extract information about the tool.
UINT32 GetID ()
void SelectChange (BOOL)
 Called when the tool is selected or deselected. Creates and pushes the tool's cursor; pops and destroys it.
void OnClick (DocCoord, ClickType, ClickModifiers, Spread *)
 To handle a Mouse Click event for the Bezier Tool. It starts up a Bezier Operation.
virtual void RenderToolBlobs (Spread *, DocRect *)
 Renders the Tools Blobs. The only blob this tool renders is the floating endpoint which only appears the the flag is set.
void HandleInfoBarMessage (CDlgMessage DlgMsg, CGadgetID Gadget)
void OnMouseMove (DocCoord, Spread *, ClickModifiers)
 This routine is called whenever the mouse moves while we're in the freehand tool. it sees what is under the pointer, and flips the cursor if clicking will have a different effect. The rules are:.
BOOL OnKeyPress (KeyPress *)
 To handle keypress events for the Bezier Tool. If it is a keypress that it know about it starts up an appropiate operation. THIS IS BADLY WRONG AT THE MOMENT - WHEN THERE IS THE TECHNOLOGY FOR USER DEFINABLE KEY-SHORTCUTS THIS FUNCTION WILL NEED FIXING.
void SetMoveTo (DocCoord MovePos, Spread *pSpread, Document *pDoc)
 This function is called from an operation which tells the tool that there should be a virtual moveTo coordinate at the given point. This virtual coordinate looks much like the old single moveto used to in ArtWorks, with the added advantage that it doesn't really exist, so it can't cock up the tree like they used to do in ArtWorks.
void ClearMoveTo ()
 Clears the floating endpoint condition.
BOOL GetMoveTo (Spread **ppSpread, DocCoord *pCoord, Document **ppDoc)
 Read the state of the floating endpoint.
void SetModeFlag ()
 Sets the current tool mode (new/add/change) and gets the infobar to redraw the text item that shows it. We are in New mode if there are no selected lines. We are in Add mode if there is just one endpoint on the end od a path selected. Otherwise we are in Change mode.
BOOL GetStatusLineText (String_256 *ptext, Spread *pSpread, DocCoord DocPos, ClickModifiers ClickMods)
 generate up-to-date text for the status line (called on idles)
void GenerateStatusLineText (String_256 *ptext, Spread *pSpread, DocCoord DocPos, ClickModifiers ClickMods)
 To find the string to display on the status line given the current mouse position.

Protected Member Functions

BOOL CyclePathPoints (BOOL Fowards)
 Performs the cycle the selected points task. The selection status of each endpoint on selected paths is applied to the next endpoint.
BOOL HomePathPoints ()
 Moves the selected endpoints back along the selected path(s) so that the first point is selected. The pattern of selection remains the same.
BOOL EndPathPoints ()
 Moves the selected endpoints foward along the selected path(s) so that the last point is selected. The pattern of selection remains the same.
BOOL AutoClosePaths ()
 Runs through all selected lines. If the path is open and either of the ends are selected then the path is closed.
void RemoveFloater (DocCoord *FloatPos, Spread *FloatSpread, Document *pDoc)
 Invokes the operation to remove the floating endpoint.
void RetroSmoothChanging (double Smooth)
 Scan the selection for a path to smooth. If we find only one path object selected then we should tell the retro smooth code to begin smoothing. Arh!, actually we need to be able to keep track of the selected object? possibly.... Surely its fast enough already to find the selected objects, there must be some caching going on somewhere. Ok, best thing to do is to make sure theres only one selected object and ignore the slider change if there isn't.
void RetroSmoothFinished ()
 Calls the retro smooth finalisation code to perform the completed smoothing action.
void RetroSmoothSet (INT32 percent, BOOL Enabled)
 Set the position of the retro smooth slider, given a percentage value. The function will also update the percent text field.
void RetroSmoothInvalidate ()
 Invalidate the retro smooth cached information.
void UpdateRetroSlider (Path *pPath)
 Sets the retro smooth slider position for a given path.
void ResetRetroSlider ()
 There has been a change in the selection so we need to update the retro slider state.
NodeOneNodePathSelected ()
 Checks the selection and determins whether exactly one nodepath object is selected.
void ChangeCursor (Cursor *cursor)
 Changes to the specified cursor. Will only change the cursor if it isn't already this cursor, so it doesn't flicker.
clickeffect DetermineClickEffect (DocCoord PointerPos, Spread *pSpread, NodeRenderableInk **ReturnNode, INT32 *ReturnPosition, INT32 *NumSelectedPaths, INT32 *NumSelectedPoints)
 Used when the cursor moves and when single clicking. This routine determines what effect a click will have. In this tool, clicking will either select a point on an already selected line, reshape a line segment (a la Corel), add a segment to the end of a line, or start a new path entirely.
NodePathFindEditablePath (Node *pSelected)
 Finds the node to edit (if it exists). This node could actually be the selected node passed as a parameter or one of its children which the node wants to be editable.

Protected Attributes

DocCoord StartPos
SpreadStartSpread
CursorpcMoveBezCursor
CursorpcReshapeLineCursor
CursorpcNewPathCursor
CursorpcAddPathCursor
CursorpcClosePathCursor
CursorMyCurrentCursor
INT32 CurrentCursorID
BOOL FloatingEndpoint
DocumentMoveToDoc
DocCoord MoveToPoint
SpreadMoveToSpread
RetroSmoothpSmooth
BOOL RetroFlag
NodepRetroNode
SpreadpRetroSpread
BOOL DontDrawOnClearMoveTo
CurrentMode CurrentToolMode

Static Protected Attributes

static TCHARFamilyName = _T("Drawing Tools")
static TCHARToolName = _T("Bezier Tool")
static TCHARPurpose = _T("To Draw arbitrary lines")
static TCHARAuthor = _T("Jim (latterly Peter)")
static BezToolInfoBarOppBezToolInfoBarOp = NULL
static BOOL CreateCurve = TRUE
static BOOL CreateCusp = FALSE

Private Member Functions

 CC_DECLARE_MEMDUMP (BezierTool)

Friends

class BezToolInfoBarOp

Detailed Description

This class handles the Free Hand Tool that is used to draw lines that follow the path of the Mouse Pointer.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/7/93

Definition at line 242 of file beztool.h.


Member Enumeration Documentation

enum BezierTool::CurrentMode
 

Enumerator:
New 
Add 
Change 

Definition at line 250 of file beztool.h.

00250 {New, Add, Change};


Constructor & Destructor Documentation

BezierTool::BezierTool  ) 
 

Dump Constructor - It does nothing. All the real initialisation is done in BezierTool::Init which is called by the Tool Manager.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/6/93
See also:
BezierTool::Init

Definition at line 197 of file beztool.cpp.

00198 {
00199     StartSpread = NULL;
00200     FloatingEndpoint = FALSE;
00201     MoveToDoc = NULL;
00202     MoveToSpread = NULL;
00203     pSmooth = NULL;
00204     RetroFlag = FALSE;
00205     DontDrawOnClearMoveTo = FALSE;
00206     CurrentToolMode = New;
00207 }

BezierTool::~BezierTool  ) 
 

Destructor (Virtual). Does nothing.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/6/93

Definition at line 221 of file beztool.cpp.

00222 {
00223     // Destroy any resident retro smooth object
00224     if (pSmooth != NULL)
00225     {
00226         delete pSmooth;
00227         pSmooth = NULL;
00228     }
00229 
00230     pBezToolInfoBarOp->pBezTool = NULL;
00231 }


Member Function Documentation

BOOL BezierTool::AutoClosePaths  )  [protected]
 

Runs through all selected lines. If the path is open and either of the ends are selected then the path is closed.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
19/12/95
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
TRUE if all went well, FALSE if an error occured.
See also:
-

Definition at line 4363 of file beztool.cpp.

04364 {
04365     OpState Calcium = OpCloseNodePaths::GetState(NULL, NULL);
04366 
04367     if (!Calcium.Greyed)
04368     {
04369         OpParam Param(CreateCurve, !CreateCusp);
04370         OpDescriptor* Apple = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpCloseNodePaths));
04371         if (Apple != NULL)
04372             Apple->Invoke(&Param);
04373     }
04374 
04375     return TRUE;
04376 }

BezierTool::CC_DECLARE_MEMDUMP BezierTool   )  [private]
 

void BezierTool::ChangeCursor Cursor cursor  )  [protected]
 

Changes to the specified cursor. Will only change the cursor if it isn't already this cursor, so it doesn't flicker.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/3/94
Parameters:
ID of the cursor you want to flip to [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: can fail if the cursor cannot be created - the cursor code will fail.

See also:
-

Definition at line 1472 of file beztool.cpp.

01473 {
01474     // only change if this cursor is different from the current cursor
01475     if (cursor != MyCurrentCursor)
01476     {
01477         // set this cursor as the current cursor and immediately display it
01478         CursorStack::GSetTop(cursor, CurrentCursorID);
01479         // remember this is our current cursor
01480         MyCurrentCursor = cursor;
01481     }
01482 
01483 }

void BezierTool::ClearMoveTo  ) 
 

Clears the floating endpoint condition.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
19/7/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
BezierTool::SetMoveTo

Definition at line 1539 of file beztool.cpp.

01540 {
01541     if (FloatingEndpoint && IsCurrent() && !DontDrawOnClearMoveTo)
01542     {
01543         BlobManager* pBlobManager = GetApplication()->GetBlobManager();
01544         ENSURE(pBlobManager, "Can't get BlobManager");
01545         pBlobManager->RenderToolBlobsOff(this, MoveToSpread,NULL);
01546     }
01547     FloatingEndpoint = FALSE;
01548 }

BOOL BezierTool::CyclePathPoints BOOL  Fowards  )  [protected]
 

Performs the cycle the selected points task. The selection status of each endpoint on selected paths is applied to the next endpoint.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
19/10/94
Parameters:
Fowards - TRUE if the point selection status are to move fowards, otherwise [INPUTS] they move backwards.
Returns:
TRUE if all went well, FALSE if an error occured

Errors: -

See also:
-

Definition at line 2968 of file beztool.cpp.

02969 {   
02970     // Obtain the current selections and the first node in the selection
02971     SelRange*   Selected = GetApplication()->FindSelection();
02972     Node*       pNode = Selected->FindFirst();
02973     NodePath*   ThisPath;
02974 
02975     // Holds the coords of the last selected point we find on our travels,
02976     // we then call DocView::ScrolToShowWithMargin to ensure that this point is visible
02977     DocCoord LastSelectedPoint;
02978     BOOL LastSelectedPointValid = FALSE;    // does LastSelectedPoint hold a valid value?
02979 
02980     while (pNode != NULL)
02981     {   // we're only interested in NodePaths which have selected points
02982         NodePath* pSelected = FindEditablePath(pNode);
02983         if (pSelected)
02984         {
02985                 // for convenience, cast the pointer to a pointer to a NodePath
02986                 ThisPath = pSelected;
02987 
02988                 // First get pointers to the arrays
02989                 PathFlags*  Flags = ThisPath->InkPath.GetFlagArray();
02990                 PathVerb*   Verbs = ThisPath->InkPath.GetVerbArray();
02991                 DocCoord*   Coords = ThisPath->InkPath.GetCoordArray();
02992                 const INT32 NumCoords = ThisPath->InkPath.GetNumCoords();
02993             
02994             if (pSelected->InkPath.IsSubSelection())
02995             {   
02996                 // Render off the current selection blobs
02997                 ThisPath->InkPath.RenderPathSelectedControlBlobs(pNode->FindParentSpread());
02998 
02999                 if (Fowards)
03000                 {   
03001                     INT32 Current = 0;
03002                     INT32 Next = 0;
03003                     BOOL MoreEndpoints = TRUE;
03004                     BOOL PrevSelected = Flags[0].IsSelected;
03005 
03006                     while (MoreEndpoints)
03007                     {
03008                         // Find the next endpoint
03009                         MoreEndpoints = ThisPath->InkPath.FindNextEndPoint(&Next);  
03010                         if (MoreEndpoints && (Verbs[Next] & PT_CLOSEFIGURE))
03011                             MoreEndpoints = ThisPath->InkPath.FindNextEndPoint(&Next);
03012                         if (MoreEndpoints)
03013                         {
03014                             BOOL temp = Flags[Next].IsSelected;
03015                             Flags[Next].IsSelected = PrevSelected;
03016                             if (Flags[Next].IsSelected)
03017                             {
03018                             LastSelectedPoint = Coords[Next];
03019                             LastSelectedPointValid = TRUE;
03020                             }
03021                             PrevSelected= temp;
03022                             Current = Next;
03023                         }
03024                         else
03025                         {
03026                             Flags[0].IsSelected = PrevSelected;
03027                             if (Flags[0].IsSelected)
03028                             {
03029                                 LastSelectedPoint = Coords[0];
03030                                 LastSelectedPointValid = TRUE;
03031                             }
03032                         }
03033                     }
03034 
03035                     // Tidy up the selection state
03036                     ThisPath->InkPath.EnsureSelection(TRUE);
03037                 }
03038                 else                                                        
03039                 {
03040                     INT32 Current = NumCoords-1;
03041                     INT32 Next = Current;
03042                     BOOL MoreEndpoints = TRUE;
03043                     BOOL PrevSelected = Flags[Current].IsSelected;
03044                     BOOL ClosedPath = (Verbs[Next] & PT_CLOSEFIGURE);
03045 
03046                     while (MoreEndpoints)
03047                     {
03048                         // Find the previous endpoint
03049                         MoreEndpoints = ThisPath->InkPath.FindPrevEndPoint(&Next);  
03050                         if (MoreEndpoints && ClosedPath && (Verbs[Next] == PT_MOVETO))
03051                             MoreEndpoints = ThisPath->InkPath.FindPrevEndPoint(&Next);
03052                         if (MoreEndpoints)
03053                         {
03054                             BOOL temp = Flags[Next].IsSelected;
03055                             Flags[Next].IsSelected = PrevSelected;
03056                             if (Flags[Next].IsSelected)
03057                             {
03058                                 LastSelectedPoint = Coords[Next];
03059                                 LastSelectedPointValid = TRUE;
03060                             }
03061                             PrevSelected = temp;
03062                             Current = Next;
03063                         }
03064                         else
03065                         {
03066                             Flags[NumCoords-1].IsSelected = PrevSelected;
03067                             if (Flags[NumCoords-1].IsSelected)
03068                             {
03069                                 LastSelectedPoint = Coords[NumCoords-1];
03070                                 LastSelectedPointValid = TRUE;
03071                             }
03072                         }
03073                     }
03074 
03075                     // Tidy up the selection state
03076                     ThisPath->InkPath.EnsureSelection(FALSE);
03077                 }
03078 
03079             }
03080             // If no SubSelection
03081             else
03082             {
03083                 if (Fowards) 
03084                 {
03085                     Flags[0].IsSelected = TRUE;
03086                     ThisPath->InkPath.EnsureSelection(TRUE);
03087                 }
03088                 else
03089                     Flags[NumCoords-1].IsSelected = TRUE; 
03090                     ThisPath->InkPath.EnsureSelection(FALSE);
03091             }
03092     
03093             // Render on the new selection blobs
03094             ThisPath->InkPath.RenderPathSelectedControlBlobs(pNode->FindParentSpread());
03095         }
03096         pNode = Selected->FindNext(pNode);
03097     }
03098     DialogBarOp::SetSystemStateChanged();       
03099     if (LastSelectedPointValid)
03100     {
03101         DocView* pDocView = DocView::GetSelected();
03102         if (pDocView != NULL)
03103         {
03104             pDocView->ScrollToShowWithMargin(&LastSelectedPoint);
03105         }
03106     }
03107     return TRUE;
03108 }

void BezierTool::Describe void *  InfoPtr  )  [virtual]
 

Allows the tool manager to extract information about the tool.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/6/93
Parameters:
InfoPtr - A pointer to a tool info block. It is passed cast to void* as [INPUTS] the version of the tool is unknown at this point. Later versions of the Tool class may have more items in this block, that this tool will not use
InfoPtr - The structure pointed to by InfoPtr will have had all the info [OUTPUTS] that this version of the Tool knows about

Reimplemented from Tool_v1.

Definition at line 334 of file beztool.cpp.

00335 {
00336     // Cast structure into the latest one we understand.
00337     ToolInfo_v1 *Info = (ToolInfo_v1 *) InfoPtr;
00338 
00339     Info -> InfoVersion = 1;
00340     
00341     Info -> InterfaceVersion = GetToolInterfaceVersion();  // You should always have this line.
00342         
00343     // These are all arbitrary at present.
00344     Info -> Version = 1;
00345     Info -> ID      = GetID();
00346     Info -> TextID  = _R(IDS_BEZIER_TOOL);
00347 
00348     Info -> Family  = FamilyName;
00349     Info -> Name    = ToolName;
00350     Info -> Purpose = Purpose;
00351     Info -> Author  = Author;
00352 
00353     Info -> InfoBarDialog = _R(IDD_BEZTOOLBAR);
00354 
00355     Info -> BubbleID = _R(IDBBL_LINETOOL);
00356     Info -> StatusID = _R(IDS_LINETOOL);
00357 }

clickeffect BezierTool::DetermineClickEffect DocCoord  PointerPos,
Spread pSpread,
NodeRenderableInk **  ReturnNode,
INT32 *  ReturnPosition,
INT32 *  NumSelectedPaths,
INT32 *  NumSelectedPoints
[protected]
 

Used when the cursor moves and when single clicking. This routine determines what effect a click will have. In this tool, clicking will either select a point on an already selected line, reshape a line segment (a la Corel), add a segment to the end of a line, or start a new path entirely.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/4/94
Parameters:
PointerPos is the mouse position [INPUTS] pSpread is a pointer to the spread containing the mouse position
ReturnNode returns a pointer to the node the mouse would click on [OUTPUTS] ReturnPosition returns the index into the nodepath of the affected point NumSelectedPaths is the number of paths in the selection NumSelectedPoints is the total number of selected points (on all paths)
Returns:
The effect of clicking - one of NewPath, AddSegment, OnPoint or ReshapeLine

Definition at line 1199 of file beztool.cpp.

01202 {
01203     clickeffect WhatToDo = NewPath; // tells me what effect the click would have
01204     INT32 PathPosition = 0;         // temp var for return value
01205     INT32 TempIndex = 0;                // Temporary index into a path
01206     INT32 NumSelPaths = 0;          // Number of selected paths
01207     double Distance = 0;            // gets the returned distance from the nearest point
01208     double Nearest = 0;             // distance of current nearest point
01209     NodeRenderableInk* WhichNode = NULL;    // Saves me using a pointer to a pointer
01210 
01211     // Scan through the selected paths, and see if any of them want the click
01212 
01213     DocRect BlobRect;
01214     DocView* pDocView = DocView::GetCurrent();
01215     ERROR2IF( pDocView==NULL, NewPath, "BezierTool::DetermineClickEffect: Can't find current DocView");
01216 
01217     // Find the selected range of objects
01218     SelRange* Selected = GetApplication()->FindSelection();
01219     Node* pNode = Selected->FindFirst();
01220 
01221     INT32 NumSelectedEndpoints = 0;     // Count selected points in paths
01222 
01223     if (pNode != NULL)
01224     {
01225         Spread* NodeSpread = pNode->FindParentSpread();
01226         if (NodeSpread == pSpread)
01227         {
01228             // On the same spread, so see if the pointer is over an endpoint
01229             while ((pNode != NULL) && WhatToDo!=OnPoint)
01230             {
01231                 NodePath* pActNode = FindEditablePath(pNode);
01232                 if (pActNode)
01233                 {
01234 
01235                     // Now we know it's a NodePath, get a pointer to the Path object within it, so
01236                     // we can find any endpoints
01237                 
01238                     Path* ThisPath = &((pActNode)->InkPath);
01239 
01240                     // Increment the number of selected paths
01241                     NumSelPaths++;
01242                     
01243                     // count the number of selected points on the path (excluding control points)
01244                     INT32 NumCoords = ThisPath->GetNumCoords();
01245                     PathFlags* Flags = ThisPath->GetFlagArray();
01246 
01247                     for (INT32 i=0; i<NumCoords; i++)
01248                     {
01249                         if (Flags[i].IsSelected && Flags[i].IsEndPoint)
01250                             NumSelectedEndpoints++;
01251                     }
01252 
01253                     if (ThisPath->FindStartOfPath())
01254                     {
01255                         // First, check to see if this click occurs on a selected point
01256                         INT32 tempPos;
01257                         if (ThisPath->FindNearestPoint(PointerPos,
01258                                                        POINTFLAG_ENDPOINTS |
01259                                                        POINTFLAG_CONTROLPOINTS |
01260                                                        POINTFLAG_ENDSFIRST,
01261                                                        &tempPos)
01262                            )
01263                         {
01264                             // The click occurred on one of the points on the line
01265                             // so remember this path, the position, and the fact that
01266                             // the user clicked on a point
01267 
01268                             WhatToDo = OnPoint;
01269                             WhichNode = (NodeRenderableInk*)pActNode;
01270                             PathPosition = tempPos;
01271                         }
01272                         else if (WhatToDo != OnPoint && ThisPath->PointCloseToLine(PointerPos, &tempPos))
01273                         {
01274                             WhatToDo = ReshapeLine;
01275                             WhichNode = (NodeRenderableInk*)pActNode;
01276                             PathPosition = tempPos;
01277                         }
01278                         else if ((WhatToDo == AddSegment || WhatToDo == NewPath) && ThisPath->ClosestSelectedEndpoint(PointerPos,&TempIndex,&Distance))
01279                         {
01280                             // TempIndex is the index into the path for the closest selected endpoint
01281                             // Distance is the distance
01282                             if (WhatToDo == NewPath)
01283                             {
01284                                 WhatToDo = AddSegment;
01285                                 WhichNode = (NodeRenderableInk*)pActNode;
01286                                 Nearest = Distance;
01287                                 PathPosition = TempIndex;
01288                             }
01289                             else if (Nearest > Distance)
01290                             {
01291                                 Nearest = Distance;
01292                                 WhichNode = (NodeRenderableInk*)pActNode;
01293                                 PathPosition = TempIndex;
01294                             }
01295                         }
01296                     }
01297                 }
01298                 // Now find the next selected node
01299                 pNode = Selected->FindNext(pNode);
01300             }
01301         }
01302     }
01303 
01304     // WhatToDo tells us what the action will be
01305     // WhichNode points to the node we are dealing with
01306     // PathPosition is the index into that path of the element we are using
01307 
01308     // If WhatToDo == OnPoint and it's the end of a subpath, and the opposite
01309     // end is selected, and the path isn't closed we should change WhatToDo 
01310     // to be ClosePath
01311 
01312     if (WhatToDo == OnPoint && NumSelectedEndpoints == 1)
01313     {
01314         Path* ThisPath = &(((NodePath*)WhichNode)->InkPath);
01315         PathFlags* Flags = ThisPath->GetFlagArray();
01316         PathVerb* Verbs = ThisPath->GetVerbArray();
01317 //      DocCoord* Coords = ThisPath->GetCoordArray();
01318         INT32 NumCoords = ThisPath->GetNumCoords();
01319         if (Verbs[PathPosition] == PT_MOVETO)           // Start of subpath
01320         {
01321             INT32 i = PathPosition;
01322             ThisPath->FindEndElOfSubPath(&i);               // i = index to end element
01323             
01324             if ((Flags[i].IsSelected) && !(Verbs[i] & PT_CLOSEFIGURE))
01325                 WhatToDo = ClosePath;
01326         }
01327         else if (PathPosition+1 == NumCoords || Verbs[PathPosition+1] == PT_MOVETO)
01328         {
01329             if (!(Verbs[PathPosition] & PT_CLOSEFIGURE))
01330             {
01331                 INT32 i = PathPosition;
01332                 ThisPath->FindStartOfSubPath(&i);
01333                 if (Flags[i].IsSelected)
01334                     WhatToDo = ClosePath;
01335             }
01336         }
01337         // Now we must detect the case of an attempted closepath on a path consisting
01338         // of a moveto and one segment
01339         if ((WhatToDo == ClosePath) && ( (((NodePath*)WhichNode)->InkPath.GetNumCoords() == 2) ||
01340             ((((NodePath*)WhichNode)->InkPath.GetNumCoords() == 4) && (Verbs[3] == PT_BEZIERTO)) ) )
01341         {
01342             WhatToDo = OnPoint;
01343         }
01344     }
01345 
01346 
01347     if ((WhatToDo == AddSegment || WhatToDo == ClosePath) && NumSelectedEndpoints > 1)
01348         WhatToDo = NewPath;
01349 
01350     if (WhatToDo == AddSegment || WhatToDo == ReshapeLine)
01351     {
01352         // If we're pointing at a curve, make sure we're pointing to the first element
01353         Path* ThisPath = &(((NodePath*)WhichNode)->InkPath);
01354         PathFlags* flags = ThisPath->GetFlagArray();
01355         while(!(flags[PathPosition].IsEndPoint ))
01356             PathPosition++;
01357         ThisPath->SetPathPosition(PathPosition);
01358         if (ThisPath->GetVerb() == PT_BEZIERTO)
01359             PathPosition-=2;
01360     }
01361 
01362     *ReturnPosition = PathPosition;
01363     *ReturnNode = WhichNode;
01364     *NumSelectedPoints = NumSelectedEndpoints;
01365     *NumSelectedPaths = NumSelPaths;
01366     return (WhatToDo);
01367 }

BOOL BezierTool::EndPathPoints  )  [protected]
 

Moves the selected endpoints foward along the selected path(s) so that the last point is selected. The pattern of selection remains the same.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
5/1/94
Parameters:
- [INPUTS]
Returns:
TRUE if all went well, FALSE if an error occured

Errors: -

See also:
BezierTool::HomePathPoints

Definition at line 3247 of file beztool.cpp.

03248 {   
03249     // Obtain the current selections and the first node in the selection
03250     SelRange*   Selected = GetApplication()->FindSelection();
03251     Node*       pNode = Selected->FindFirst();
03252     NodePath*   ThisPath;
03253 
03254     // Variable to hold the position of the last 'end point'. This is updated as we
03255     // loop through the selection until it holds the end point of the last line
03256     // in the selection with subselection.
03257     DocCoord LastEndPoint;
03258     BOOL LastEndPointValid = FALSE;
03259 
03260     while (pNode != NULL)
03261     {   // we're only interested in NodePaths which have selected points
03262             NodePath* pSelected = FindEditablePath(pNode);
03263             if (pSelected)
03264             {
03265                 // for convenience, cast the pointer to a pointer to a NodePath
03266                 ThisPath = pSelected;
03267 
03268                 // First get pointers to the arrays
03269                 PathFlags*  Flags = ThisPath->InkPath.GetFlagArray();
03270                 PathVerb*   Verbs = ThisPath->InkPath.GetVerbArray();
03271                 DocCoord*   Coords = ThisPath->InkPath.GetCoordArray();
03272                 INT32   NumCoords = ThisPath->InkPath.GetNumCoords()-1;
03273                 if (pSelected->InkPath.IsSubSelection() ) 
03274                 {
03275                     // We only need to bother if the last endpoint is not selected!
03276                     if (!Flags[NumCoords].IsSelected)
03277                     {
03278                         // Render off the current selection blobs
03279                         ThisPath->InkPath.RenderPathSelectedControlBlobs(pNode->FindParentSpread());
03280 
03281                         // Find the last selected point
03282                         INT32 Offset = NumCoords;
03283                         while ((Offset > -1) && !(Flags[Offset].IsSelected && Flags[Offset].IsEndPoint))
03284                     
03285                         {
03286                             Offset--;
03287                         }
03288 
03289                         ERROR3IF(Offset == -1,"No selected endpoint found when there was one");
03290 
03291                         // Now we can move the selection on to the end
03292                         INT32 Current = NumCoords;
03293                         BOOL MoreEndpoints = TRUE;
03294 
03295                         while (MoreEndpoints)
03296                         {
03297                             Flags[Current].IsSelected = Flags[Offset].IsSelected;
03298                             MoreEndpoints = ThisPath->InkPath.FindPrevEndPoint(&Offset);    
03299                             if (MoreEndpoints && (Verbs[Offset] & PT_CLOSEFIGURE))
03300                                 MoreEndpoints = ThisPath->InkPath.FindPrevEndPoint(&Offset);
03301                             if (MoreEndpoints)
03302                             {
03303                                 ThisPath->InkPath.FindPrevEndPoint(&Current);   
03304                                 if (Verbs[Current] & PT_CLOSEFIGURE)
03305                                     ThisPath->InkPath.FindPrevEndPoint(&Current);   
03306                             }   
03307                             else
03308                                 Current --;
03309                         }
03310 
03311                         // Unselect the remaining endpoints
03312                         while (Current > -1)
03313                         {
03314                             Flags[Current--].IsSelected = FALSE;
03315                         }
03316 
03317                         // Now fix up the selections so if the starts of subpaths are selected then so are the ends
03318                         ThisPath->InkPath.EnsureSelection(FALSE);
03319     
03320                         // Render on the new selection blobs
03321                         ThisPath->InkPath.RenderPathSelectedControlBlobs(pNode->FindParentSpread());
03322                     }
03323                 
03324                     // this path is in the selection, and has a subselection, so remember its end point
03325                     // position, as it may be the last end point
03326                     LastEndPoint = Coords[NumCoords];
03327                     LastEndPointValid = TRUE;
03328             }
03329 
03330             else
03331             {
03332                     Flags[NumCoords].IsSelected = TRUE;
03333                     // Now fix up the selections so if the starts of subpaths are selected then so are the ends
03334                     ThisPath->InkPath.EnsureSelection(FALSE);
03335                     // Render on the new selection blobs
03336                     ThisPath->InkPath.RenderPathSelectedControlBlobs(pNode->FindParentSpread());        
03337             }                               
03338         }
03339         pNode = Selected->FindNext(pNode);
03340     }
03341     DialogBarOp::SetSystemStateChanged();       
03342 
03343     // scroll to show the last end point (if it exists) at the coordinates we remembered earlier
03344     if (LastEndPointValid)
03345     {
03346         DocView* pDocView = DocView::GetSelected();
03347         if (pDocView != NULL)
03348         {
03349             pDocView->ScrollToShowWithMargin(&LastEndPoint);
03350         }
03351     }
03352 
03353     return TRUE;
03354 }

NodePath * BezierTool::FindEditablePath Node pSelected  )  [protected]
 

Finds the node to edit (if it exists). This node could actually be the selected node passed as a parameter or one of its children which the node wants to be editable.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
19/3/95
Parameters:
pSelected = A pointer to the selected node to check [INPUTS]
- [OUTPUTS]
Returns:
A pointer to an editable node path (or derived) object NULL if there isn't one.

Definition at line 1387 of file beztool.cpp.

01388 {
01389     if (pSelected->IsNodePath())
01390         return ((NodePath*)pSelected);
01391 
01392     return ((NodePath*)pSelected->HasEditableChild(CC_RUNTIME_CLASS(NodePath), NULL));
01393 }

void BezierTool::GenerateStatusLineText String_256 ptext,
Spread pSpread,
DocCoord  coord,
ClickModifiers  mods
 

To find the string to display on the status line given the current mouse position.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
08/12/94
Parameters:
pSpread - pointer to spread under mouse (else NULL) [INPUTS] DocPos - position of mouse in doc (in spread coords) ClickMods - mouse click modifiers
ptext - text for status line [OUTPUTS]
Returns:
-

Errors: -

Definition at line 3623 of file beztool.cpp.

03624 {
03625     // Call DetermineClickEffect to see what a click will do at this position
03626 
03627     INT32 PathPosition;         // Needed to receive a return, not used otherwise
03628     NodeRenderableInk* node;    // again, only temporary
03629     INT32 NumPts;               // Number of selected points
03630     INT32 NumPaths;             // Number of selected paths
03631     clickeffect WhatToDo = DetermineClickEffect(coord, pSpread, &node, &PathPosition, &NumPaths, &NumPts);
03632 
03633     switch (WhatToDo)
03634     {
03635     case AddSegment:
03636         if (CreateCurve)
03637             ptext->Load(_R(IDS_ADD_SEGMENT),Tool::GetModuleID(GetID()));
03638         else
03639             ptext->Load(_R(IDS_ADDLINESEGMENT),Tool::GetModuleID(GetID()));
03640         break;
03641     case NewPath:
03642         if (FloatingEndpoint)
03643         {
03644             if (CreateCurve)
03645             {
03646                 if (NumPts == 0)
03647                     ptext->Load(_R(IDS_CLICK_TO_MAKE_NEW),Tool::GetModuleID(GetID()));
03648                 else
03649                     ptext->Load(_R(IDS_CLICK_TO_MAKE_NEW),Tool::GetModuleID(GetID()));
03650             }
03651             else
03652             {
03653                 ptext->Load(_R(IDS_CLICKMAKENEWLINE),Tool::GetModuleID(GetID()));
03654             }
03655         }
03656         else
03657         {
03658             if (CreateCurve)
03659             {
03660                 if (NumPts == 0)
03661                     ptext->Load(_R(IDS_STARTNEWCURVENOSEL),Tool::GetModuleID(GetID()));
03662                 else
03663                     ptext->Load(_R(IDS_CREATE_NEW_PATH),Tool::GetModuleID(GetID()));
03664             }
03665             else
03666             {
03667                 if (NumPts == 0)
03668                     ptext->Load(_R(IDS_STARTNEWLINENOSEL),Tool::GetModuleID(GetID()));
03669                 else
03670                     ptext->Load(_R(IDS_STARTNEWLINE),Tool::GetModuleID(GetID()));
03671             }
03672         }
03673         break;
03674     case OnPoint:
03675         // There are various different combinations of selected/unselected, which require
03676         // different status line messages
03677         {
03678             NodePath* ThisPath = (NodePath*)node;
03679 //          PathVerb* Verbs = ThisPath->InkPath.GetVerbArray();
03680             PathFlags* Flags = ThisPath->InkPath.GetFlagArray();
03681             INT32 ptype = 0;
03682             if (Flags[PathPosition].IsSelected)
03683                 ptype |= 1;
03684             if (Flags[PathPosition].IsEndPoint)
03685                 ptype |= 2;
03686             if (Flags[PathPosition].IsRotate)
03687                 ptype |= 4;
03688 
03689             // Now ptype holds a number from 0 to 7 which completely describes what type of
03690             // point this is, so we can use that to select the correct string
03691             switch(ptype)
03692             {
03693                 case 0:     //Unselected, unsmoothed control point
03694                 case 4:     // UnSelected, smoothed control point 
03695                 case 1:     // Selected, unsmoothed control point
03696                 case 5:     // Selected, smoothed control point
03697                     ptext->Load(_R(IDS_SELCONTROL),Tool::GetModuleID(GetID()));
03698                     break;
03699                 case 2:     // UnSelected, unsmoothed end point
03700                     ptext->Load(_R(IDS_UNSELCUSP),Tool::GetModuleID(GetID()));
03701                     break;
03702                 case 3:     // Selected, unsmoothed end point
03703                     ptext->Load(_R(IDS_SELCUSP),Tool::GetModuleID(GetID()));
03704                     break;
03705                 case 6:     // UnSelected, smoothed end point
03706                     ptext->Load(_R(IDS_UNSELSMOOTH),Tool::GetModuleID(GetID()));
03707                     break;
03708                 case 7:     // Selected, smoothed end point
03709                     ptext->Load(_R(IDS_SELSMOOTH),Tool::GetModuleID(GetID()));
03710                     break;
03711             }
03712         }
03713         break;
03714     case ReshapeLine:
03715         ptext->Load(_R(IDS_RESHAPE_LINE),Tool::GetModuleID(GetID()));
03716         break;
03717     case ClosePath:
03718         ptext->Load(_R(IDS_CLOSEPATH),Tool::GetModuleID(GetID()));
03719         break;
03720     }
03721 }

UINT32 BezierTool::GetID void   )  [inline, virtual]
 

Reimplemented from Tool_v1.

Definition at line 256 of file beztool.h.

00256 { return TOOLID_BEZTOOL; };

BOOL BezierTool::GetMoveTo Spread **  ppSpread,
DocCoord pCoord,
Document **  ppDoc
 

Read the state of the floating endpoint.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
05/12/94
Parameters:
ppSpread - pointer to a pointer to a spread [INPUTS] pCoord - pointer to a DocCoord
*ppSpread is set to point to the spread the floating endpoint is on [OUTPUTS] pCoord is set to the location of the floating endpoint
Returns:
TRUE if there was a floating endpoint, FALSE if not (in this case there is no outputs)

Errors: -

See also:
BezierTool::SetMoveTo, BezierTool::ClearMoveTo

Definition at line 1570 of file beztool.cpp.

01571 {
01572     if (FloatingEndpoint)
01573     {
01574         *ppSpread = MoveToSpread;
01575         *pCoord = MoveToPoint;
01576         *ppDoc = MoveToDoc;
01577         return TRUE;
01578     }
01579     else
01580         return FALSE;
01581 }

BOOL BezierTool::GetStatusLineText String_256 ptext,
Spread pSpread,
DocCoord  DocPos,
ClickModifiers  ClickMods
[virtual]
 

generate up-to-date text for the status line (called on idles)

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
08/12/94
Parameters:
pSpread - pointer to spread under mouse (else NULL) [INPUTS] DocPos - position of mouse in doc (in spread coords) ClickMods - mouse click modifiers
ptext - text for status line [OUTPUTS]
Returns:
TRUE if outputting valid text

Errors: ERROR3 if ptext is NULL

Reimplemented from Tool_v1.

Definition at line 3592 of file beztool.cpp.

03593 {
03594     ERROR2IF(ptext==NULL,FALSE,"ptext was NULL");
03595 
03596     *ptext = "";
03597 
03598     GenerateStatusLineText(ptext, pSpread, DocPos, ClickMods);
03599 
03600     return TRUE;
03601 }

void BezierTool::HandleInfoBarMessage CDlgMessage  DlgMsg,
CGadgetID  Gadget
 

BOOL BezierTool::HomePathPoints  )  [protected]
 

Moves the selected endpoints back along the selected path(s) so that the first point is selected. The pattern of selection remains the same.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
5/1/94
Parameters:
- [INPUTS]
Returns:
TRUE if all went well, FALSE if an error occured

Errors: -

See also:
BezierTool::EndPathPoints

Definition at line 3125 of file beztool.cpp.

03126 {   
03127     // Obtain the current selections and the first node in the selection
03128     SelRange*   Selected = GetApplication()->FindSelection();
03129     Node*       pNode = Selected->FindFirst();
03130     NodePath*   ThisPath;
03131 
03132     // Variable to hold the position of the last 'first point'. This is updated as we
03133     // loop through the selection until it holds the first point of the last line
03134     // in the selection with subselection.
03135     DocCoord LastFirstPoint;
03136     BOOL LastFirstPointValid = FALSE;
03137 
03138     while (pNode != NULL)
03139     {   // we're only interested in NodePaths which have selected points
03140         NodePath* pSelected = FindEditablePath(pNode);
03141         if (pSelected) 
03142         {
03143             // for convenience, cast the pointer to a pointer to a NodePath
03144             ThisPath = pSelected;
03145 
03146             // First get pointers to the arrays
03147             PathFlags*  Flags = ThisPath->InkPath.GetFlagArray();
03148             PathVerb*   Verbs = ThisPath->InkPath.GetVerbArray();
03149             DocCoord*   Coords = ThisPath->InkPath.GetCoordArray();
03150             INT32   NumCoords = ThisPath->InkPath.GetNumCoords()-1;
03151             // We only need to bother if the first endpoint is not selected!
03152             if (pSelected->InkPath.IsSubSelection())        
03153             {
03154                 if (!Flags[0].IsSelected)
03155                 {
03156                     // Render off the current selection blobs
03157                     ThisPath->InkPath.RenderPathSelectedControlBlobs(pNode->FindParentSpread());
03158 
03159                     // Find the first selected point
03160                     INT32 Offset = 0;
03161                     while ((Offset <= NumCoords) && !(Flags[Offset].IsSelected && Flags[Offset].IsEndPoint))
03162                     {
03163                         Offset ++;
03164                     }
03165 
03166                     ERROR3IF(Offset > NumCoords,"No selected endpoint found when there was one");
03167                 
03168                     // Now we can move the selection back to the start
03169                     BOOL MoreEndpoints = TRUE;
03170                     INT32 Current = 0;
03171 
03172                     while (MoreEndpoints)
03173                     {
03174                         Flags[Current].IsSelected = Flags[Offset].IsSelected;
03175                         MoreEndpoints = ThisPath->InkPath.FindNextEndPoint(&Offset);    
03176                         if (Verbs[Offset] & PT_CLOSEFIGURE)
03177                             MoreEndpoints = ThisPath->InkPath.FindNextEndPoint(&Offset);
03178                         if (MoreEndpoints)
03179                         {
03180                             ThisPath->InkPath.FindNextEndPoint(&Current);   
03181                             if (Verbs[Current] & PT_CLOSEFIGURE)
03182                             ThisPath->InkPath.FindNextEndPoint(&Current);   
03183                         }
03184                         else
03185                             Current ++;
03186                     }
03187 
03188                     // Unselect the remaining endpoints from Current onwards
03189                     while (Current <= NumCoords)
03190                     {
03191                         Flags[Current++].IsSelected = FALSE;
03192                     }
03193 
03194                     // Now fix up the selection status of the path
03195                     ThisPath->InkPath.EnsureSelection(TRUE);
03196 
03197                     // Render on the new selection blobs
03198                     ThisPath->InkPath.RenderPathSelectedControlBlobs(pNode->FindParentSpread());
03199                 }
03200 
03201                 // current pNode is selected and has a seubselection, so update FirstPointCoord to
03202                 // point to the first end point of this path
03203                 LastFirstPoint = Coords[0];
03204                 LastFirstPointValid = TRUE;
03205             }       
03206             else
03207             {
03208                 Flags [0].IsSelected = TRUE;
03209                 // Now fix up the selection status of the path
03210                 ThisPath->InkPath.EnsureSelection(TRUE);
03211                 // Render on the new selection blobs
03212                 ThisPath->InkPath.RenderPathSelectedControlBlobs(pNode->FindParentSpread());    
03213             }
03214         }
03215         pNode = Selected->FindNext(pNode);
03216     }
03217     DialogBarOp::SetSystemStateChanged();       
03218 
03219     // scroll to show the last first point (if it exists) at the coordinates we remembered earlier
03220     if (LastFirstPointValid)
03221     {
03222         DocView* pDocView = DocView::GetSelected();
03223         if (pDocView != NULL)
03224         {
03225             pDocView->ScrollToShowWithMargin(&LastFirstPoint);
03226         }
03227     }
03228 
03229     return TRUE;
03230 }

BOOL BezierTool::Init void   )  [virtual]
 

Used to check if the Tool was properly constructed.

Author:
Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/6/93
Returns:
FALSE if it does not want to be created, TRUE otherwise
See also:
BezierTool::BezierTool

Reimplemented from Tool_v1.

Definition at line 247 of file beztool.cpp.

00248 {
00249     CCResTextFile       file;               // Resource File
00250     BezToolInfoBarOpCreate BarCreate;       // Object that creates InfoBarOp objects
00251 
00252     #if 0
00253     BOOL                ok;
00254     ok = file.open(_R(IDM_BEZTOOL_BAR), _R(IDT_INFO_BAR_RES));          // Open resource
00255     if (ok) ok = DialogBarOp::ReadBarsFromFile(file,BarCreate); // Read and create info bar
00256     if (ok) file.close();                                       // Close resource
00257 
00258     ERROR2IF(!ok, FALSE, "Unable to load bezbar.ini from resource\n"); 
00259 
00260     // Info bar now exists.  Now get a pointer to it
00261     String_32 str = String_32(_R(IDS_BEZTOOL_INFOBARNAME));
00262     DialogBarOp* pDialogBarOp = DialogBarOp::FindDialogBarOp(str);
00263     
00264     ERROR2IF(pDialogBarOp==NULL, FALSE, "Line tool infobar not found\n");
00265 
00266     ERROR3IF(!(pDialogBarOp->IS_KIND_OF(BezToolInfoBarOp)), "Line tool infobar wrong type");
00267     #endif
00268 
00269     pBezToolInfoBarOp = new BezToolInfoBarOp();
00270     if (!pBezToolInfoBarOp)
00271     {
00272         ERROR3("Could not load bezier tool info bar");
00273         return FALSE;
00274     }   
00275 
00276     FloatingEndpoint = FALSE;
00277     MoveToDoc = NULL;
00278     MoveToSpread = NULL;
00279 
00280     pBezToolInfoBarOp->pBezTool = this;             // Set a pointer from the op to this tool
00281     pBezToolInfoBarOp->CurrentIndex = -1;
00282     pBezToolInfoBarOp->CurrentNodePath = NULL;
00283     pBezToolInfoBarOp->CurrentInkPath = NULL;
00284     pBezToolInfoBarOp->CurrentSpread = NULL;
00285     pBezToolInfoBarOp->IgnoreNextUpdate = FALSE;
00286     pBezToolInfoBarOp->LastShownPrevLength = 0;
00287     pBezToolInfoBarOp->LastShownNextLength = 0;
00288 
00289     // Read in the preference settings from the file
00290     GetApplication()->DeclareSection(_T("ShapeEditorTool"),2);
00291     GetApplication()->DeclarePref(_T("ShapeEditorTool"),_T("CreateCusp"), &CreateCusp, 0, 1);
00292     GetApplication()->DeclarePref(_T("ShapeEditorTool"),_T("CreateCurved"), &CreateCurve, 0, 1);
00293 
00294     // create a retro smooth regions object
00295     if (pSmooth != NULL)
00296     {
00297         ERROR3("Initialisation failure in class BezierTool: smooth ptr not NULL");
00298         return FALSE;
00299     }
00300 
00301     pSmooth = new RetroSmooth;
00302     if (pSmooth == NULL)
00303         return FALSE;
00304 
00305     if (!pSmooth->Initialise())
00306         return FALSE;
00307 
00308     // Initialise operations in opbezier.cpp
00309     if (!( OpSelectPathPoints::Declare() && OpInsertFloater::Declare() && OpRemoveFloater::Declare() ) )
00310         return FALSE;
00311 
00312     return TRUE;
00313 }

void BezierTool::OnClick DocCoord  PointerPos,
ClickType  Click,
ClickModifiers  ClickMods,
Spread pSpread
[virtual]
 

To handle a Mouse Click event for the Bezier Tool. It starts up a Bezier Operation.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com> (via Rik)
Date:
21/4/94
Parameters:
PointerPos - The Coords (in spread coords) of the point where the mouse [INPUTS] button was clicked Click - Describes the type of click that was detected. ClickMods - Indicates which buttons caused the click and which modifers were pressed at the same time pSpread - the spread in which the click happened
Returns:
TRUE if it handled the Click, FALSE otherwise
See also:
Tool::MouseClick; ClickType; ClickModifiers

Reimplemented from Tool_v1.

Definition at line 859 of file beztool.cpp.

00861 {
00862     if (ClickMods.Menu) return;                         // Don't do anything if the user clicked the Menu button
00863 
00864     // Have a flag telling me what we have to do (either click on an existing point, 
00865     // create a new point on a path, create an all new path or reshape an existing line)
00866     // clickeffect is defined in the class header.
00867 
00868     INT32 PathPosition;     // index into the path of interesting elements
00869     NodeRenderableInk* WhichNode = NULL;
00870     INT32   NumPts;
00871     INT32   NumPaths;
00872 
00873     // Set the infobars spread pointer so if any kernel op wants to force edit field values
00874     // there is a spread to get units from.
00875     pBezToolInfoBarOp->CurrentSpread = pSpread;
00876 
00877     clickeffect WhatToDo = DetermineClickEffect(PointerPos, pSpread,&WhichNode, &PathPosition, &NumPaths, &NumPts);
00878 
00879     // So, like, WhatToDo tells me what to do, WhichNode points at the node that's involved
00880     // and PathPosition is the index into WhichNode of the element we are dealing with.
00881     // if WhatToDo = OnPoint we have to pass the click onto the path
00882     // if WhatToDo = AddSegment we have to add a curve or line segment to the given path.
00883     // we should also remember to do things with the selected points.
00884     // if WhatToDo = NewPath there wasn't a suitable selected path, so we have to start a new
00885     // path. A stupid person (i.e. me) might create a new path, but I think this could be done
00886     // better. When they click in this mode, I'll start an operation which drags out a single
00887     // line/curve element, but if they release immediately I won't insert anything - I'll set
00888     // the FloatingEndpoint flag and set the MoveToPoint coords to that point.
00889 
00890     // Take note of the else ifs - this should help to ensure that only one event is ever triggered
00891     // by an incoming click event. Care should be taken in ordering these clauses so that the correct 
00892     // results ensue from each click.
00893 
00894     // Special case: WhatToDo = ClosePath and the Adjust button is used. Instead of closing the path
00895     // we should select the point. Thus, we change it to OnPoint
00896 
00897     if ( WhatToDo == ClosePath && ClickMods.Adjust)
00898         WhatToDo = OnPoint;
00899     
00900     // Ordinary click from OnPoint
00901     if ( Click == CLICKTYPE_SINGLE && WhatToDo == OnPoint )
00902     {
00903         WhichNode->OnClick(PointerPos, Click, ClickMods, pSpread);
00904 
00905         // Need to clear any exiting floating endpoint condition
00906         if (FloatingEndpoint)
00907             RemoveFloater(&MoveToPoint, MoveToSpread, NULL);
00908     }
00909 
00910     // If the click is AddSegment, I should add a segment to the end of the given path (WhichNode,
00911     // returned by DetermineClickEffect(). Unlike the clicking on existing nodes, it is the tool's
00912     // job to initiate this operation
00913 
00914     else if (Click == CLICKTYPE_SINGLE && WhatToDo == AddSegment && !ClickMods.Adjust)
00915     {
00916         OpNodePathAddEndpoint* pOpAddEnd = new OpNodePathAddEndpoint;
00917         if (!pOpAddEnd)
00918             InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) );
00919         else
00920             pOpAddEnd->DoStartDragEdit((NodePath*) WhichNode, PointerPos, pSpread, ClickMods, PathPosition, CreateCurve, FALSE, !CreateCusp);
00921     }
00922 
00923     else if (Click == CLICKTYPE_SINGLE && (WhatToDo == NewPath || (WhatToDo == AddSegment && ClickMods.Adjust)))
00924     {
00925         if (FloatingEndpoint)
00926         {   
00927             if (ClickMods.Adjust)
00928             {
00929                 // Clear the floating endpoint condition
00930                 RemoveFloater(&MoveToPoint, MoveToSpread, NULL);
00931             }
00932             else
00933             {
00934                 // Handle adding of new path
00935                 OpNewPath* pOpNew = new OpNewPath;
00936                 if (!pOpNew)
00937                     InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK));
00938                 else
00939                 {
00940                     pOpNew->DoStartDragEdit(MoveToPoint, PointerPos, MoveToSpread, ClickMods, CreateCurve, !CreateCusp);
00941 
00942                         
00943                 
00944                 }
00945             }
00946         }
00947         else
00948         {
00949             if (!OpSelectPathPoints::DragInProgress())
00950             {
00951                 // Start a drag operation to marquee select points
00952                 OpSelectPathPoints* pOpSelect = new OpSelectPathPoints;
00953                 if (!pOpSelect)
00954                 {
00955                     InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) );
00956                 }
00957                 else
00958                 {
00959                     // Start the drag, giving a pointer back to this tool so that if
00960                     // the drag was not really a drag, we can insert a floater.
00961                     pOpSelect->DoDrag( PointerPos, pSpread, ClickMods.Adjust , this, ClickMods);
00962                 }       
00963             } 
00964         }
00965     }
00966 
00967     else if ( Click == CLICKTYPE_DOUBLE && WhatToDo == OnPoint && !ClickMods.Adjust)
00968     {
00969         WhichNode->OnClick(PointerPos, Click, ClickMods, pSpread);
00970 //      DialogBarOp::SetSystemStateChanged();       // Inform the system that greying needs updating
00971     }
00972 
00973     else if ( Click == CLICKTYPE_SINGLE && WhatToDo == ClosePath)
00974     {
00975         // Create the same operation as for adding an endpoint, but call it using
00976         // the flag that tells the operation to close the path.
00977 
00978         OpNodePathAddEndpoint* pOpAddEnd = new OpNodePathAddEndpoint;
00979         if (!pOpAddEnd)
00980         {
00981             InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) );
00982         }
00983         else
00984         {
00985             // Start dragging the path. The TRUE flag at the end tells the operation 
00986             // to close the path
00987             // I have to flip the PathPosition index from the clicked-on point to the opposite
00988             // point so that the right segment is inserted
00989             ((NodePath*)WhichNode)->InkPath.SetPathPosition(PathPosition);
00990             ((NodePath*)WhichNode)->InkPath.FindStartOfSubPath();
00991             if (PathPosition == ((NodePath*)WhichNode)->InkPath.GetPathPosition())
00992             {
00993                 ((NodePath*)WhichNode)->InkPath.FindEndOfSubPath();
00994                 PathPosition = ((NodePath*)WhichNode)->InkPath.GetPathPosition();
00995             }
00996             else
00997                 PathPosition = ((NodePath*)WhichNode)->InkPath.GetPathPosition();
00998 
00999             pOpAddEnd->DoStartDragEdit((NodePath*) WhichNode, PointerPos, pSpread, ClickMods, PathPosition, CreateCurve, TRUE, !CreateCusp);
01000         }
01001     }
01002     else if (Click == CLICKTYPE_SINGLE && WhatToDo == ReshapeLine)
01003     {
01004         // Create the same operation as for adding an endpoint, but call it using
01005         // the flag that tells the operation to close the path.
01006 
01007         double pdist;
01008         INT32 tempel;
01009         ((NodePath*) WhichNode)->InkPath.SqrDistanceToPoint(PointerPos, &tempel, &pdist);
01010 
01011         OpReshapeOrAddPoint* pOpReshape = new OpReshapeOrAddPoint;
01012         if (!pOpReshape)
01013             InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) );
01014         else
01015             pOpReshape->DoStartDragEdit((NodePath*) WhichNode, PointerPos, pSpread, PathPosition, pdist);
01016         
01017     }
01018 /*
01019     else if (Click == CLICKTYPE_DRAG && WhatToDo == NewPath && FloatingEndpoint && pSpread == MoveToSpread)
01020     {
01021         OpNodePathStartNew* pOpStartNew = new OpNodePathStartNew;
01022         if (!pOpStartNew)
01023         {
01024             if (IsUserName("Jim"))
01025             {
01026                 TRACE( _T("Unable to create operation to start new path in Beztool\n"));
01027             }
01028             
01029             // Inform the user that we are out of memory
01030             InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) );
01031         }
01032         else
01033         {
01034             // Start dragging the path
01035             pOpStartNew->DoStartDragEdit( PointerPos, pSpread );
01036         }
01037     }
01038 */
01039 
01040     else if ( Click == CLICKTYPE_DRAG && WhatToDo == OnPoint && (WhichNode != NULL) )
01041     {
01042         WhichNode->OnClick(PointerPos, Click, ClickMods, pSpread);
01043 //      ((NodeRenderableInk*)LastPathClicked)->OnClick(LastPointClicked,Click, ClickMods, LastSpreadClicked);
01044 //      DialogBarOp::SetSystemStateChanged();       // Inform the system that greying needs updating
01045     }
01046 
01047     // Now update the cursor and status bar
01048     OnMouseMove(PointerPos, pSpread, ClickMods);
01049     SetModeFlag();
01050     ResetRetroSlider();
01051 }

Node * BezierTool::OneNodePathSelected  )  [protected]
 

Checks the selection and determins whether exactly one nodepath object is selected.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/11/94
Parameters:
- [INPUTS]
Returns:
a pointer to the node if there is a single node path object selected NULL if no nodepath or more than one object is selected

Definition at line 3439 of file beztool.cpp.

03440 {
03441     // Find the selected range of objects
03442     SelRange* Selected = GetApplication()->FindSelection();
03443 
03444     Node* pNode = Selected->FindFirst();
03445     if (pNode == NULL)
03446         return NULL;
03447     Node* qNode = Selected->FindNext(pNode);
03448     if (qNode != NULL)
03449         return NULL;
03450 
03451     // ok there's only one selected object so what kind is it?
03452     if (pNode->GetRuntimeClass() != CC_RUNTIME_CLASS(NodePath))
03453         return NULL;
03454 
03455     return pNode;
03456 }

BOOL BezierTool::OnKeyPress KeyPress pKeyPress  )  [virtual]
 

To handle keypress events for the Bezier Tool. If it is a keypress that it know about it starts up an appropiate operation. THIS IS BADLY WRONG AT THE MOMENT - WHEN THERE IS THE TECHNOLOGY FOR USER DEFINABLE KEY-SHORTCUTS THIS FUNCTION WILL NEED FIXING.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
13/10/94
Parameters:
pKeyPress - pointer to a keypress object [INPUTS]
Returns:
TRUE if it handled the keypress, FALSE otherwise

Reimplemented from Tool_v1.

Definition at line 1069 of file beztool.cpp.

01070 {
01071     // We don't want to know about key release or character events
01072     if (!pKeyPress->IsPress())
01073         return FALSE;
01074 
01075     // Comparing keypresses is exceeding greif!
01076 
01077     if (*pKeyPress == KeyPress(CAMKEY(TAB)))
01078     {
01079         CyclePathPoints(TRUE);
01080         goto UsedKey;
01081     } 
01082 
01083     if (*pKeyPress == KeyPress(CAMKEY(TAB), TRUE))
01084     {
01085         CyclePathPoints(FALSE);
01086         goto UsedKey;
01087     } 
01088 
01089     if (*pKeyPress == KeyPress(CAMKEY(RETURN)))
01090     {
01091         if (!AutoClosePaths())
01092             InformError();
01093         goto UsedKey;
01094     } 
01095 
01096     if ((pKeyPress->GetVirtKey() == CAMKEY(HOME)) && !pKeyPress->IsAdjust() &&
01097                                             !pKeyPress->IsConstrain() && !pKeyPress->IsAlternative())
01098     {
01099         HomePathPoints();
01100         goto UsedKey;
01101     } 
01102 
01103     if ((pKeyPress->GetVirtKey() == CAMKEY(END)) && !pKeyPress->IsAdjust() &&
01104                                             !pKeyPress->IsConstrain() && !pKeyPress->IsAlternative())
01105     {
01106         EndPathPoints();
01107         goto UsedKey;
01108     } 
01109 
01110     if (*pKeyPress == KeyPress(CAMKEY(Z)))
01111     {
01112         pBezToolInfoBarOp->HandleClickOnCuspButton(FALSE);
01113         goto UsedKey;
01114     } 
01115 
01116     if (*pKeyPress == KeyPress(CAMKEY(S)))
01117     {
01118         pBezToolInfoBarOp->HandleClickOnSmoothButton();
01119         goto UsedKey;
01120     } 
01121 
01122     if (*pKeyPress == KeyPress(CAMKEY(L)))
01123     {
01124         pBezToolInfoBarOp->HandleClickOnLineButton();
01125         goto UsedKey;
01126     } 
01127 
01128     if (*pKeyPress == KeyPress(CAMKEY(C)))
01129     {
01130         pBezToolInfoBarOp->HandleClickOnCurveButton();
01131         goto UsedKey;
01132     } 
01133 
01134     if (*pKeyPress == KeyPress(CAMKEY(B)))
01135     {
01136         OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpBreakAtPoints));
01137         String_256      UIDesc;
01138         if (pOpDesc != NULL)
01139         {
01140             OpState State = OpBreakAtPoints::GetState(&UIDesc, pOpDesc);
01141             if (!State.Greyed)
01142             {
01143                 pOpDesc->Invoke();
01144                 goto UsedKey;
01145             }
01146         }
01147     } 
01148 
01149     if ((pKeyPress->GetVirtKey() == CAMKEY(DELETE)) || (*pKeyPress == KeyPress(WXK_BACK)) ) 
01150     {
01151         // Run a delete selected points operation
01152         String_256      UIDesc;
01153         OpState State = OpDeletePoints::GetState(&UIDesc, NULL);
01154         OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpDeletePoints));
01155         if ((!State.Greyed) && (pOpDesc != NULL))
01156         {
01157             pOpDesc->Invoke();
01158             goto UsedKey;
01159         }
01160     } 
01161 
01162     // If ESCAPE is pressed then clear the floating endpoint, but don't claim the keypress
01163     // so the selection is also cleared.
01164     if ((*pKeyPress == KeyPress(CAMKEY(ESCAPE))) && FloatingEndpoint)
01165         RemoveFloater(&MoveToPoint, MoveToSpread, Document::GetSelected());
01166 
01167     // If we get this far then the keypress wasn't handled
01168     return FALSE;
01169 
01170 UsedKey:
01171     pBezToolInfoBarOp->IgnoreNextUpdate = FALSE;
01172     return TRUE;
01173 }

void BezierTool::OnMouseMove DocCoord  coord,
Spread pSpread,
ClickModifiers  mods
[virtual]
 

This routine is called whenever the mouse moves while we're in the freehand tool. it sees what is under the pointer, and flips the cursor if clicking will have a different effect. The rules are:.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
15/3/94
Parameters:
coordinate of mouse move, pointer to spread containing coord, mouse modifiers [INPUTS]
- [OUTPUTS]
Returns:
-
Over space, no selection - freehand cursor Over selected endpoint - add freehand to line

Returns:
Errors: -
See also:
-

Reimplemented from Tool_v1.

Definition at line 1419 of file beztool.cpp.

01420 {
01421     // Call DetermineClickEffect to see what a click will do at this position
01422 
01423     INT32 PathPosition;         // Needed to receive a return, not used otherwise
01424     NodeRenderableInk* node;    // again, only temporary
01425     INT32 NumPts;               // Number of selected points
01426     INT32 NumPaths;             // Number of selected paths
01427     clickeffect WhatToDo = DetermineClickEffect(coord, pSpread, &node, &PathPosition, &NumPaths, &NumPts);
01428     
01429     // Generate the status line help string
01430     String_256 status("");
01431     GenerateStatusLineText(&status, pSpread, coord, mods);
01432     GetApplication()->UpdateStatusBarText(&status);
01433 
01434     // Now change the cursor
01435     switch (WhatToDo)
01436     {
01437         case AddSegment:
01438             ChangeCursor(pcAddPathCursor);
01439             break;
01440         case NewPath:
01441             ChangeCursor(pcNewPathCursor);
01442             break;
01443         case OnPoint:
01444             ChangeCursor(pcMoveBezCursor);
01445             break;
01446         case ReshapeLine:
01447             ChangeCursor(pcReshapeLineCursor);
01448             break;
01449         case ClosePath:
01450             ChangeCursor(pcClosePathCursor);
01451             break;
01452     }
01453 }

void BezierTool::RemoveFloater DocCoord FloatPos,
Spread FloatSpread,
Document pDoc
[protected]
 

Invokes the operation to remove the floating endpoint.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/1/96
Parameters:
FloatPos - the current position of the floating endpoint [INPUTS] FloatSpread - the spread it's on pDoc - points to document with the endpoint
- [OUTPUTS]
Returns:
-
See also:
OpRemoveFloater

Definition at line 4485 of file beztool.cpp.

04486 {
04487     if (FloatingEndpoint)
04488     {   
04489         InsertFloaterParam Param(FloatPos, FloatSpread, this, pDoc);
04490         OpDescriptor* Apple = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpRemoveFloater));
04491         if (Apple != NULL)
04492             Apple->Invoke(&Param);
04493         else
04494             InformError();
04495     }
04496     else
04497     {
04498         ERROR3("Attempted to remove floating endpoint but it wasn't there!");
04499     }
04500 }

void BezierTool::RenderToolBlobs Spread pSpread,
DocRect pClipRect
[virtual]
 

Renders the Tools Blobs. The only blob this tool renders is the floating endpoint which only appears the the flag is set.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/7/94
Parameters:
pSpread - The spread that the blob is to appear on [INPUTS] pClipRect - Pointer to the rect that contains the blobs

Reimplemented from Tool_v1.

Definition at line 1598 of file beztool.cpp.

01599 {
01600     // Can only draw the path if there is a path to draw
01601     if (FloatingEndpoint)
01602     {
01603         RenderRegion* pRegion = DocView::RenderOnTop(pClipRect, pSpread, ClippedEOR);
01604         while (pRegion)
01605         {
01606             // Draw a Cross Hair
01607             pRegion->SetLineColour(COLOUR_BEZIERBLOB);
01608             pRegion->SetFillColour(COLOUR_TRANS);
01609             pRegion->DrawBlob(MoveToPoint,BT_SELECTED);
01610 
01611             // Get the next region in the list
01612             pRegion = DocView::GetNextOnTop(pClipRect);
01613         }
01614     }   
01615 }

void BezierTool::ResetRetroSlider  )  [protected]
 

There has been a change in the selection so we need to update the retro slider state.

void BezierTool::ResetRetroSlider()

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/11/94
Parameters:
- [INPUTS]
Returns:

Definition at line 3472 of file beztool.cpp.

03473 {
03474     Node* pNode = OneNodePathSelected();
03475     Path* pPath = NULL;
03476 
03477     if (pNode)
03478         pPath = &(((NodePath*)pNode)->InkPath);
03479     
03480     if (pPath && (!pPath->IsSubSelection()))
03481         pPath=NULL;
03482 
03483     UpdateRetroSlider(pPath); 
03484 }

void BezierTool::RetroSmoothChanging double  smooth  )  [protected]
 

Scan the selection for a path to smooth. If we find only one path object selected then we should tell the retro smooth code to begin smoothing. Arh!, actually we need to be able to keep track of the selected object? possibly.... Surely its fast enough already to find the selected objects, there must be some caching going on somewhere. Ok, best thing to do is to make sure theres only one selected object and ignore the slider change if there isn't.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/11/94
Parameters:
smooth = smoothness level to use [INPUTS]
Returns:

Definition at line 3376 of file beztool.cpp.

03377 {
03378 
03379     if (!RetroFlag)
03380     {
03381         Node* pNode = OneNodePathSelected();
03382         if (pNode == NULL)
03383             return;
03384     
03385         Spread* pSpread = pNode->FindParentSpread();
03386         if (pSpread == NULL)
03387             return;
03388 
03389         RetroFlag = TRUE;
03390         pRetroNode = pNode;
03391         pRetroSpread = pSpread;
03392 
03393     }
03394 
03395     // ok, at this stage we should have a path to work with.
03396     pSmooth->Changing((NodePath*)pRetroNode, pRetroSpread, smooth);
03397 }

void BezierTool::RetroSmoothFinished  )  [protected]
 

Calls the retro smooth finalisation code to perform the completed smoothing action.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/11/94
Parameters:
[INPUTS] 
Returns:

Definition at line 3414 of file beztool.cpp.

03415 {
03416     // ok, at this stage we should have a path to work with.
03417     if (RetroFlag)
03418     {
03419         pSmooth->Finished();
03420         RetroFlag = FALSE;
03421     }
03422 }

void BezierTool::RetroSmoothInvalidate  )  [protected]
 

Invalidate the retro smooth cached information.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/11/94
Parameters:
- [INPUTS]
Returns:

Definition at line 3564 of file beztool.cpp.

03565 {
03566     // set the slider to full
03567     RetroSmoothSet(100, TRUE);
03568     // and tell the reto smooth op.
03569     if (pSmooth != NULL)
03570         pSmooth->Invalidate();
03571 }

void BezierTool::RetroSmoothSet INT32  percent,
BOOL  Enabled
[protected]
 

Set the position of the retro smooth slider, given a percentage value. The function will also update the percent text field.

void BezierTool::RetroSmoothSet(INT32 percent, BOOL Enabled)

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/11/94
Parameters:
percent = the value to set the smooth slider to (0..100) [INPUTS]
Returns:

Definition at line 3526 of file beztool.cpp.

03527 {
03528     // Set the pip position
03529     if (pBezToolInfoBarOp)
03530     {
03531         if (pBezToolInfoBarOp->IsOpen())
03532         {
03533             pBezToolInfoBarOp->SetLongGadgetValue(_R(IDC_SMOOTHSLIDER), percent);
03534             
03535             // Set the percentage string
03536             TCHAR Str[32];
03537             String_32 jcf(_R(IDS_PERCENT_FORMAT));
03538             camSnprintf(Str, 31, jcf, (INT32) percent);
03539             String_32 PercentStr(Str);
03540             pBezToolInfoBarOp->SetStringGadgetValue(_R(IDC_SMOOTHPERCENT), PercentStr);
03541 
03542             pBezToolInfoBarOp->EnableGadget(_R(IDC_SMOOTHSLIDER), Enabled);
03543             pBezToolInfoBarOp->EnableGadget(_R(IDC_SMOOTHPERCENT), Enabled);
03544 
03545         }
03546     }
03547 }

void BezierTool::SelectChange BOOL  isSelected  )  [virtual]
 

Called when the tool is selected or deselected. Creates and pushes the tool's cursor; pops and destroys it.

Author:
Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/11/93
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: If creating any cursor fails, all are deleted and the user is told about lack of memory

See also:
-

Reimplemented from Tool_v1.

Definition at line 376 of file beztool.cpp.

00377 {
00378     if (isSelected)
00379     {
00380         // This tool has just been selected.  Create an appropriate cursor, and push it
00381         // onto the top of the cursor stack so it'll appear when the pointer moves into
00382         // our window.
00383         
00384         MyCurrentCursor = NULL;     // in case we couldn't create one!
00385         
00386         pcMoveBezCursor = new Cursor(this, _R(IDC_MOVEBEZIERCURSOR));
00387         if (!pcMoveBezCursor || !pcMoveBezCursor->IsValid())
00388         {
00389             InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) );
00390             return;                                      
00391         }
00392 
00393         pcReshapeLineCursor = new Cursor(this, _R(IDC_RESHAPECURSOR));
00394         if (!pcReshapeLineCursor || !pcReshapeLineCursor->IsValid())
00395         {
00396             delete pcMoveBezCursor;
00397             InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) );
00398             return;
00399         }
00400 
00401         pcNewPathCursor = new Cursor(this, _R(IDC_NEWPATHCURSOR));
00402         if (!pcNewPathCursor || !pcNewPathCursor->IsValid())
00403         {
00404             delete pcMoveBezCursor;
00405             delete pcReshapeLineCursor;
00406             InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) );
00407             return;
00408         }
00409 
00410         pcClosePathCursor = new Cursor(this, _R(IDC_CLOSEPATHCURSOR));
00411         if (!pcClosePathCursor || !pcClosePathCursor->IsValid())
00412         {
00413             delete pcMoveBezCursor;
00414             delete pcReshapeLineCursor;
00415             delete pcNewPathCursor;
00416             InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) );
00417             return;
00418         }
00419 
00420         pcAddPathCursor = new Cursor(this, _R(IDC_ADDPATHCURSOR));
00421         if (!pcAddPathCursor || !pcAddPathCursor->IsValid())
00422         {
00423             delete pcMoveBezCursor;
00424             delete pcReshapeLineCursor;
00425             delete pcNewPathCursor;
00426             delete pcClosePathCursor;
00427             InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) );
00428             return;
00429         }
00430 
00431         CurrentCursorID = CursorStack::GPush(pcNewPathCursor, FALSE);
00432         MyCurrentCursor = pcNewPathCursor;
00433 
00434         // Which blobs do I want displayed
00435         BlobManager* BlobMgr = GetApplication()->GetBlobManager();
00436         if (BlobMgr != NULL)
00437         {
00438             // Decide which blobs we will display
00439             BlobStyle MyBlobs;
00440             MyBlobs.Object = TRUE;
00441 
00442             // Tell the blob manager
00443             BlobMgr->ToolInterest(MyBlobs);
00444         }
00445         
00446         if (FloatingEndpoint)
00447             BlobMgr->RenderToolBlobsOn(this, MoveToSpread,NULL);
00448 
00449         pBezToolInfoBarOp->Create();
00450         SetModeFlag();
00451         RetroFlag = FALSE;
00452         ResetRetroSlider();
00453 
00454         //Alias all the nudge ops to the path specific ones.
00455         OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUP1);  
00456         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeUp1),NULL,0);  
00457         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUP5);            
00458         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeUp5),NULL,0);  
00459         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUP10);  
00460         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeUp10),NULL,0);
00461         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUPFIFTH);  
00462         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeUpFifth),NULL,0);
00463         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUPPIXEL1);
00464         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeUpPixel1),NULL,0);
00465         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEUPPIXEL10);
00466         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeUpPixel10),NULL,0);
00467 
00468 
00469         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWN1);  
00470         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeDown1),NULL,0);  
00471         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWN5);  
00472         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeDown5),NULL,0);  
00473         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWN10);  
00474         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeDown10),NULL,0);  
00475         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWNFIFTH);
00476         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeDownFifth),NULL,0);
00477         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWNPIXEL1);
00478         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeDownPixel1),NULL,0);
00479         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGEDOWNPIXEL10);
00480         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeDownPixel10),NULL,0);
00481 
00482 
00483         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFT1);  
00484         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeLeft1),NULL,0);  
00485         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFT5);  
00486         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeLeft5),NULL,0);  
00487         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFT10);  
00488         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeLeft10),NULL,0);  
00489         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFTFIFTH);
00490         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeLeftFifth),NULL,0);
00491         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFTPIXEL1);
00492         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeLeftPixel1),NULL,0);
00493         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGELEFTPIXEL10);
00494         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeLeftPixel10),NULL,0);
00495 
00496 
00497         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHT1);  
00498         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeRight1),NULL,0);  
00499         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHT5);  
00500         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeRight5),NULL,0);  
00501         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHT10);  
00502         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeRight10),NULL,0);  
00503         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHTFIFTH);
00504         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeRightFifth),NULL,0);
00505         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHTPIXEL1);
00506         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeRightPixel1),NULL,0);
00507         pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NUDGERIGHTPIXEL10);
00508         pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpPathNudgeRightPixel10),NULL,0);
00509 
00510         // If there is are TextStories or Blends with paths selected then select the paths
00511         // (PS. This is a rather disgusting way of doing things, and one you can't blame on me - MarkN 17-5-99)
00512         // Now its made even more disgusting - since we wan't to do this for bevels, contours and shadows as well! (CGS 18/9/2000)
00513         Range SelRng(*(GetApplication()->FindSelection()));
00514         Node* pNode = SelRng.FindFirst();
00515     
00516         while (pNode != NULL)
00517         {
00518             if (IS_A(pNode, TextStory))
00519             {
00520                 TextStory* pStory = (TextStory*)pNode;
00521                 if (pStory->GetTextPath() != NULL)
00522                     pStory->GetTextPath()->Select(TRUE);
00523             }
00524 
00525             else if (IS_A(pNode, NodeBlend))
00526             {
00527                 NodeBlend* pNodeBlend = (NodeBlend*)pNode;
00528                 UINT32 NBPCounter = 0;
00529                 NodeBlendPath* pNodeBlendPath = pNodeBlend->GetNodeBlendPath(NBPCounter++);
00530                 while (pNodeBlendPath != NULL)
00531                 {
00532                     pNodeBlendPath->Select(TRUE);
00533                     pNodeBlendPath = pNodeBlend->GetNodeBlendPath(NBPCounter++);
00534                 }
00535             }
00536 
00537             else if ((IS_A (pNode, NodeContour)) || (IS_A (pNode, NodeBevel)) || (IS_A (pNode, NodeShadow)))
00538             {
00539                 Node* pControl = pNode->FindParent ();
00540 
00541                 Node* pNode = SliceHelper::FindNextOfClass(pControl, pControl, CC_RUNTIME_CLASS (NodePath));
00542 
00543                 while (pNode)
00544                 {
00545                     ((NodeRenderable*) pNode)->Select (TRUE);
00546                     pNode = (AttrFillGeometry*) SliceHelper::FindNextOfClass(pNode, pControl, CC_RUNTIME_CLASS (NodePath));
00547                 }
00548 
00549                 pNode = SliceHelper::FindNextOfClass(pControl, pControl, CC_RUNTIME_CLASS (NodeRegularShape));
00550 
00551                 while (pNode)
00552                 {
00553                     ((NodeRenderable*) pNode)->Select (TRUE);
00554                     pNode = (AttrFillGeometry*) SliceHelper::FindNextOfClass(pNode, pControl, CC_RUNTIME_CLASS (NodeRegularShape));
00555                 }
00556             }
00557             
00558             pNode = SelRng.FindNext(pNode);
00559         }
00560     }
00561     else
00562     {
00563         // Deselection - destroy the tool's cursor, if there is one.
00564         if (MyCurrentCursor)
00565         {
00566             CursorStack::GPop(CurrentCursorID);
00567             MyCurrentCursor = NULL;
00568             CurrentCursorID = 0;
00569             delete pcNewPathCursor;
00570             delete pcMoveBezCursor;
00571             delete pcReshapeLineCursor;
00572             delete pcClosePathCursor;
00573             delete pcAddPathCursor;
00574         }
00575         
00576         // ensure any tool object blobs are removed.
00577         BlobManager* BlobMgr = GetApplication()->GetBlobManager();
00578         if (BlobMgr != NULL)
00579         {
00580             BlobStyle bsRemoves;
00581             bsRemoves.ToolObject = TRUE;
00582             BlobMgr->RemoveInterest(bsRemoves);
00583         }
00584 
00585         // Clear the floating endpoint condition if it exists
00586         // If camelot is shutting down then dont do it as the operation history has already been
00587         // vaped from the document!
00588         if (FloatingEndpoint && !GetApplication()->CamelotIsDying())
00589             RemoveFloater(&MoveToPoint, MoveToSpread, Document::GetSelected());
00590         
00591         pBezToolInfoBarOp->Delete();
00592     }
00593 }

void BezierTool::SetModeFlag  ) 
 

Sets the current tool mode (new/add/change) and gets the infobar to redraw the text item that shows it. We are in New mode if there are no selected lines. We are in Add mode if there is just one endpoint on the end od a path selected. Otherwise we are in Change mode.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
26/9/94
Parameters:
- [INPUTS]
CurrentToolMode is set the the current tool mode [OUTPUTS]

Definition at line 1634 of file beztool.cpp.

01635 {
01636     SelRange*   Selected = GetApplication()->FindSelection();
01637     Node*   pNode = Selected->FindFirst();
01638 //  CurrentMode OldMode = CurrentToolMode;
01639     CurrentToolMode = New;
01640 
01641     while ((pNode != NULL) && (CurrentToolMode != Change))
01642     {
01643         NodePath* pSelected = FindEditablePath(pNode);
01644         
01645         if (pSelected)
01646         {
01647             Path* ThisPath = &(pSelected->InkPath);
01648             PathFlags* Flags = ThisPath->GetFlagArray();
01649             INT32 UsedSlots = ThisPath->GetNumCoords();
01650 
01651             // Go through the points in this path summing the selected endpoints
01652             for (INT32 i=0; i<UsedSlots; i++)
01653             {   
01654                 if (Flags[i].IsSelected && Flags[i].IsEndPoint)
01655                 {
01656                     if ( (i!=0) && (i!=(UsedSlots-1)) )
01657                     {
01658                         CurrentToolMode = Change;
01659                         break;
01660                     }
01661                     else
01662                     {
01663                         if (CurrentToolMode == Add)
01664                         {
01665                             CurrentToolMode = Change;
01666                             break;
01667                         }
01668                         else
01669                             CurrentToolMode = Add;
01670                     }
01671                 }
01672             }
01673         }
01674         pNode = Selected->FindNext(pNode);
01675     }
01676     
01677     DialogBarOp::SetSystemStateChanged();
01678 }

void BezierTool::SetMoveTo DocCoord  MovePos,
Spread pSpread,
Document pDoc
 

This function is called from an operation which tells the tool that there should be a virtual moveTo coordinate at the given point. This virtual coordinate looks much like the old single moveto used to in ArtWorks, with the added advantage that it doesn't really exist, so it can't cock up the tree like they used to do in ArtWorks.

Author:
Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
Date:
18/7/94
Parameters:
MovePos is the coordinate of the virtual moveto [INPUTS] pSpread points at the spread containing the coordinate pDoc pointer to the document that contains the endpoint
- [OUTPUTS]
Returns:
-

Errors: -

See also:
BezierTool::ClearMoveTo

Definition at line 1506 of file beztool.cpp.

01507 {
01508     // Set the member variables of the tool
01509     MoveToDoc = pDoc;
01510     MoveToPoint = MovePos;
01511     MoveToSpread = pSpread;
01512     FloatingEndpoint = TRUE;
01513 
01514     // Now display the blob
01515     if (IsCurrent())
01516     {
01517         BlobManager* BlobMgr = GetApplication()->GetBlobManager();
01518         if (BlobMgr) BlobMgr->RenderToolBlobsOn(this, pSpread, NULL);
01519     }
01520 }

void BezierTool::UpdateRetroSlider Path pPath  )  [protected]
 

Sets the retro smooth slider position for a given path.

void BezierTool::UpdateRetroSlider(Path* pPath)

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/11/94
Parameters:
pPath = a path pointer, if NULL then the slider is set to zero [INPUTS]

Definition at line 3499 of file beztool.cpp.

03500 {
03501     if (pSmooth && pPath)
03502     {
03503         double acc = pSmooth->ReturnCachedAccuracy(pPath);
03504         INT32 lacc = (INT32) (acc+0.5);
03505         RetroSmoothSet(lacc, TRUE);
03506     }
03507     else
03508         RetroSmoothSet(0, FALSE);
03509 }


Friends And Related Function Documentation

friend class BezToolInfoBarOp [friend]
 

Definition at line 244 of file beztool.h.


Member Data Documentation

TCHAR * BezierTool::Author = _T("Jim (latterly Peter)") [static, protected]
 

Definition at line 302 of file beztool.h.

BOOL BezierTool::CreateCurve = TRUE [static, protected]
 

Definition at line 338 of file beztool.h.

BOOL BezierTool::CreateCusp = FALSE [static, protected]
 

Definition at line 339 of file beztool.h.

INT32 BezierTool::CurrentCursorID [protected]
 

Definition at line 316 of file beztool.h.

CurrentMode BezierTool::CurrentToolMode [protected]
 

Definition at line 348 of file beztool.h.

BOOL BezierTool::DontDrawOnClearMoveTo [protected]
 

Definition at line 346 of file beztool.h.

TCHAR * BezierTool::FamilyName = _T("Drawing Tools") [static, protected]
 

Definition at line 299 of file beztool.h.

BOOL BezierTool::FloatingEndpoint [protected]
 

Definition at line 322 of file beztool.h.

Document* BezierTool::MoveToDoc [protected]
 

Definition at line 323 of file beztool.h.

DocCoord BezierTool::MoveToPoint [protected]
 

Definition at line 324 of file beztool.h.

Spread* BezierTool::MoveToSpread [protected]
 

Definition at line 325 of file beztool.h.

Cursor* BezierTool::MyCurrentCursor [protected]
 

Definition at line 314 of file beztool.h.

BezToolInfoBarOp * BezierTool::pBezToolInfoBarOp = NULL [static, protected]
 

Definition at line 335 of file beztool.h.

Cursor* BezierTool::pcAddPathCursor [protected]
 

Definition at line 312 of file beztool.h.

Cursor* BezierTool::pcClosePathCursor [protected]
 

Definition at line 313 of file beztool.h.

Cursor* BezierTool::pcMoveBezCursor [protected]
 

Definition at line 309 of file beztool.h.

Cursor* BezierTool::pcNewPathCursor [protected]
 

Definition at line 311 of file beztool.h.

Cursor* BezierTool::pcReshapeLineCursor [protected]
 

Definition at line 310 of file beztool.h.

Node* BezierTool::pRetroNode [protected]
 

Definition at line 343 of file beztool.h.

Spread* BezierTool::pRetroSpread [protected]
 

Definition at line 344 of file beztool.h.

RetroSmooth* BezierTool::pSmooth [protected]
 

Definition at line 341 of file beztool.h.

TCHAR * BezierTool::Purpose = _T("To Draw arbitrary lines") [static, protected]
 

Definition at line 301 of file beztool.h.

BOOL BezierTool::RetroFlag [protected]
 

Definition at line 342 of file beztool.h.

DocCoord BezierTool::StartPos [protected]
 

Definition at line 305 of file beztool.h.

Spread* BezierTool::StartSpread [protected]
 

Definition at line 306 of file beztool.h.

TCHAR * BezierTool::ToolName = _T("Bezier Tool") [static, protected]
 

Definition at line 300 of file beztool.h.


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