#include <opfree.h>
Inheritance diagram for OpFreeHand:

Public Member Functions | |
| OpFreeHand () | |
| Constructor. This simply sets a few of the operation flags. | |
| void | DoDrag (DocCoord Anchor, Spread *, INT32, FreeHandJoinInfo *pJoinInfo, Path *ToolPath) |
| Starts up the drag operation by storing all start positions and setting up a Path to store the mouse movement in. | |
| virtual BOOL | SnappingDrag () |
| virtual BOOL | DragKeyPress (KeyPress *pKeyPress, BOOL bSolidDrag) |
| Find out if any of the key modifiers are being pressed when the mouse is not moving. | |
| virtual void | DragPointerMove (DocCoord PointerPos, ClickModifiers ClickMods, Spread *, BOOL bSolidDrag) |
| Handles the event of the mouse moving during a drag. | |
| virtual void | DragPointerIdle (DocCoord PointerPos, ClickModifiers ClickMods, Spread *, BOOL bSolidDrag) |
| This function checks the Adjust Click modifier while the mouse is not moving to see if it is released during a straight line mode edit. This means that the shift key can be toggled in mid drag to create a straight line shape. | |
| virtual void | DragFinished (DocCoord PointerPos, ClickModifiers ClickMods, Spread *, BOOL Success, BOOL bSolidDrag) |
| Handles the drag finishing by rubbing out an EOR on the screen and adding the path to the tree and building all the undo that will be needed. | |
| void | RenderDragBlobs (DocRect, Spread *, BOOL bSolidDrag) |
| EORs the whole path onto the screen a segment at a time. It needs to do it a segment at a time as that is how it is drawn as the path is created. This has to redraw it identically or there will be bits of EORed stuff left all over the place. | |
| virtual BOOL | IsBrushOp () |
Static Public Member Functions | |
| static BOOL | Declare () |
| Adds the operation to the list of all known operations. | |
| static OpState | GetState (String_256 *Description, OpDescriptor *) |
| Find out the state of the operation at the specific time. | |
Protected Member Functions | |
| BOOL | LoadCursors () |
| Tries to Load all the cursors used by the Free Hand Operation. | |
| void | RemoveCursors () |
| Gets rid of all this operations cursors. It takes the cursor I was using off the top of the stack and deletes all the cursors I had allocated. | |
| void | SetCursorOnMove (ClickModifiers ClickMods, Spread *pSpread, DocCoord *PointerPos) |
| Decides which cursor to display depending on which modifiers are pressed and where the mouse is. PointerPos can be changed in this function. | |
| virtual void | SetCursorAndStatus (CursorType CurType) |
| Chanages the cursor to the type requested and sets the status bar message to the appropriate message for the mode we are in. | |
| BOOL | PrepareTrackDataPath () |
| Tries to initialise the path that we will store the track data in. It also sets up the pressure info stuff it there is pressure info coming in. If the path initialise ok, then it inserts the initial position (including its pressure) into the path. This function will only fail if there is no memory to init the path with. | |
| void | RubOutPath (DocCoord Pos, Spread *pSpread) |
| Tries to rub out sections of the path that have already been drawn. | |
| void | AddPointsToPath (DocCoord Pos, Spread *pSpread) |
| Adds a new point to the path of mouse moves. When the drag finishes the mouse moves will be smoothed. | |
| BOOL | CheckMouseOverSelectedPath (DocCoord *Pos, Spread *pSpread, BOOL *IsNearEndpoint) |
| Checks to see if the mouse is over the endpoint of any of the selected paths in the document and if it is, it makes a note of the path and which end it was attached to. | |
| BOOL | AreSlotsInSameSubPath (INT32 Slot1, INT32 Slot2, Path *pPath) |
| This function is used when editing lines with the freehand tool. If the drag was started in the middle of a path and the cursor is over that path again, we need to know if we can complete the edit. This is only possible if the start and end points are both on the same sub-path in the path. This function is used to determine if the 2 points are indeed in the same sub-path to allow the tool to display correct cursor etc. | |
| BOOL | CompleteOperation () |
| Does all the steps required to build a new path, smooth it, try to join it with others and finally insert it into the tree. | |
| BOOL | CreateNewPath (NodePath **pNewPath) |
| Builds a new Node Path ready to have a Curve fitted into it. If anything goes wrong (not enough memory, the path was not worth fitting etc) then this function fails. | |
| BOOL | SmoothNewCurve (NodePath *pNewNodePath) |
| Sets up the curve fitter and finally smooths the data in the Track data buffer into the new node path. | |
| BOOL | InsertSmoothCurveWithUndo (NodePath *pNewNodePath) |
| Starts the Selection operation (recording the selection state etc) and trys to join our new path with any others touching it, before inserting it into the tree. | |
| virtual BOOL | TryToReplaceSection (NodePath *pNewNodePath) |
| Replaces a section from the path that the drag was started and finished on with the newly drawn curve section. | |
| BOOL | SplitAtPoint (const DocCoord &SplitPoint, INT32 *, INT32 *) |
| Splits the path, building undo info, at the coord supplied. | |
| BOOL | ReplaceMiddleOfPath (NodePath *pNewPath, INT32 FirstChangedIndex, INT32 NumElements) |
| This will replace a section of the path with a new path, building undo as it goes. This function will also set up the Retro Curve fitting data so that it is able to retro fit the new section of the path. | |
| virtual BOOL | EditBrushLists (NodePath *pNewPath, INT32 FirstChangedIndex, INT32 NumElements) |
| When a path is edited that has a timestamping brush applied to it we those points are stored in a list that is generated when the path is drawn. If we subsequently want to edit that path we have to insert or remove points from that list. This function works out what points should be inserted or removed, and performs that action on the applied brush. | |
| virtual BOOL | SimpleJoinBrush (NodePath *pNodePath, Path *pPath) |
| Currently this only has to do work if we are editing a brush containing pressure data. In this case we must generate a new list of pressure info and insert it into the brush. | |
| virtual BOOL | ReverseBrushPressure () |
| The base class version does nothing, derived class should reverse its pressure cache. | |
| virtual BOOL | RetroSmoothBrush (NodePath *pNodePath) |
| As above, the base class version does nothing. | |
| BOOL | TryToJoinNewPathWithOthers (NodePath *FreePath) |
| Tries to Join the new path with any of the existing paths. | |
| BOOL | SimpleJoin (NodePath *FreePath, NodePath *OldPath) |
| Joins a Simple path with the new freehand path and builds all the undo that is needed in the process. | |
| BOOL | ComplexJoin (NodePath *FreePath, NodePath *OldPath) |
| Joins a Complex path with the new freehand path and builds all the undo that is needed in the process. | |
| BOOL | ComplexToComplexJoin (NodePath *FreePath, NodePath *OldPath) |
| Joins a Complex path with the new freehand path and builds all the undo that is needed in the process. The new freehand path joins two of the complex paths sub-paths together. | |
| BOOL | VeryComplexToComplexJoin (NodePath *FreePath, NodePath *TopPath, NodePath *BotPath) |
| Joins the new freehand path with two other paths (Which may or may not be complex) and builds all the undo info that is needed. | |
| virtual BOOL | ApplyAttributes (NodePath *NewPath, Document *pDocument) |
| Applies the current attributes to the Node passed in. It has to find the current document to do this and will ENSURE if it fails to find one. | |
| BOOL | AddPressureAttribute (NodePath *NewPath) |
| If pressure recording is enabled, this method builds attributes to apply to the path in order to attach the pressure as a variable-width stroking description. | |
| NodePath * | MakeCopy (Node *pOriginalNode) |
| Copies the node pOriginalNode and all its children an returns a pointer to them. It makes sure that the Node is a NodePath (Which it should be). | |
| BOOL | InsertNewNode (NodePath *pNewNode, DocRect &Invalid, Node *pOldNode, Node *pOtherOld=NULL) |
| Inserts a new path into the tree and hides the original node that it was Joined to. It will also invalidate the region of the new path that is different. | |
| void | SetRetroPath (NodePath *pNodePath, INT32 Start, INT32 Len) |
| Calls the freehand tool with details about the new path, so that future changes in the smoothness will re-build the new path. | |
| void | AddStraightLine () |
| Adds a straight line to the Path, that has been made by the Straight Line Mode. This means it has to set some flags in the path to stop the curve fitter from smoothing this straight line segment out. | |
| void | RenderLine (RenderRegion *pRender, Path *pPath, INT32 CoordIndex, BOOL StartCoord=FALSE) |
| Renders an EORed line between 2 coordinates in the path. May render pressure information feedback using the pressure stored with the path corrdinates. | |
| void | RenderLine (DocRect *Rect, Spread *pSpread, Path *pPath, INT32 Index, BOOL StartCoord=FALSE) |
| Renders an EORed line between 2 coordinates in the path. May render pressure information feedback using the pressure stored with the path corrdinates. | |
| void | RenderEorStraightLine (DocRect *, Spread *pSpread, DocCoord *Start=NULL, DocCoord *End=NULL) |
| Renders the EORed rubber band straight line that is used in Straight Line Mode. It simply draws a single Straight Line segment. | |
| void | RenderEorStraightLine (RenderRegion *pRender, DocCoord *pStart, INT32 StartWidth, DocCoord *pEnd, INT32 EndWidth) |
| Simply renders a straight-line segment to the given render region. | |
| SimpleJoinType | GetSimpleJoinType (Path *pNewPath, Path *ExistingPath) |
| This function works out how the new path joins onto the existing path. | |
| INT32 | GetCurrentLineWidth (void) |
| Determines the current line width (the width of any future lines the user will draw) by asking the attribute manager. | |
| NodeGroup * | GetParentOfNodePath () |
| To determine if the current selection is a blend on a curve. | |
| BOOL | InsertChangeBlendStepsAction (NodeBlend *pNodeBlend) |
| To adjust the number of steps in a blend on a path as a result of the path being edited (which is why its here rather than in the blend code). First the number of steps is calculated from the new path distance and if different a new action is inserted. | |
| BOOL | InvalidateBrushRegion (NodePath *pNodePath) |
| We may be editing a brushed path with the FHT so this function makes sure the correct region is invalidated. | |
Protected Attributes | |
| Path * | TrackData |
| DocCoord | StartPoint |
| Spread * | StartSpread |
| Spread * | PreviousSpread |
| INT32 | Smoothness |
| DocCoord | PreviousPoint |
| INT32 | LineSegmentCount |
| BOOL | CanLineJoin |
| BOOL | IsStraightLineMode |
| DocCoord | StraightLinePos |
| BOOL | AddPressureToPath |
| UINT32 | FreeHandPressure |
| FreeHandJoinInfo * | pJoinInfo |
| NodePath * | StartPath |
| NodePath * | EndPath |
| INT32 | CloseTo |
| double | Mu |
| BOOL | IsEndNearEndpoint |
| Cursor * | pFreeHandCursor |
| Cursor * | pJoinCursor |
| Cursor * | pRubOutCursor |
| Cursor * | pStraightCursor |
| Cursor * | pModifyCursor |
| Cursor * | MyCurrentCursor |
| INT32 | CurrentCursorID |
| NodePath * | m_pNewNodePath |
Private Member Functions | |
| CC_DECLARE_DYNCREATE (OpFreeHand) | |
Definition at line 167 of file opfree.h.
|
|
Constructor. This simply sets a few of the operation flags.
Definition at line 168 of file opfree.cpp. 00169 { 00170 // Set all our cursors to NULL to start with 00171 pFreeHandCursor = NULL; 00172 pJoinCursor = NULL; 00173 pStraightCursor = NULL; 00174 pRubOutCursor = NULL; 00175 pModifyCursor = NULL; 00176 00177 // Set other default values 00178 TrackData = NULL; 00179 StartSpread = NULL; 00180 PreviousSpread = NULL; 00181 Smoothness = 512; 00182 LineSegmentCount = 0; 00183 CanLineJoin = FALSE; 00184 IsStraightLineMode = FALSE; 00185 AddPressureToPath = FALSE; 00186 FreeHandPressure = 0; 00187 00188 // The paths that we are joined to, or NULL if we are joined to none 00189 pJoinInfo = NULL; 00190 StartPath = NULL; 00191 EndPath = NULL; 00192 CloseTo = 0; 00193 Mu = 0.0; 00194 IsEndNearEndpoint = FALSE; 00195 CurrentCursorID = 0; 00196 00197 m_pNewNodePath = NULL; 00198 00199 }
|
|
||||||||||||
|
Adds a new point to the path of mouse moves. When the drag finishes the mouse moves will be smoothed.
Reimplemented in OpDrawBrush. Definition at line 1079 of file opfree.cpp. 01080 { 01081 // If this coord is the same as the last one, then do not bother adding to the track data 01082 if (PreviousPoint == PointerPos) 01083 return; 01084 01085 // Insert the move 01086 if (TrackData->InsertLineTo(PointerPos)) 01087 { 01088 // and add pressure info if needed 01089 if (AddPressureToPath) 01090 TrackData->AddExtraInfo(CI_PRESSURE, FreeHandPressure); 01091 } 01092 else 01093 { 01094 // Oh no, we ran out of mem in the middle of making a new path 01095 // Tidy up and report back to HQ 01096 EndDrag(); 01097 01098 // Tell the World that it all went horribly wrong 01099 InformError(); 01100 01101 // Remove it from the tree and delete it 01102 TrackData->ClearPath(); 01103 01104 // End this operation and return 01105 FailAndExecute(); 01106 End(); 01107 return; 01108 } 01109 01110 // Now we have to render a new bit of EORed data to the screen 01111 RenderLine(NULL, pSpread, TrackData, TrackData->GetNumCoords()-1); 01112 01113 // Make a note of the coord, inc the line count and mark joining to the start as active. 01114 PreviousPoint = PointerPos; 01115 LineSegmentCount++; 01116 CanLineJoin = TRUE; 01117 }
|
|
|
If pressure recording is enabled, this method builds attributes to apply to the path in order to attach the pressure as a variable-width stroking description.
Definition at line 1858 of file opfree.cpp. 01859 { 01860 if (IsBrushOp()) 01861 return TRUE; 01862 // Taken out by vector stroking code Neville 2/10/97 01863 #ifdef VECTOR_STROKING 01864 01865 ERROR3IF(GetWorkingDoc() == NULL, "No working doc"); 01866 ERROR3IF(pNewPath == NULL, "Illegal NULL param"); 01867 ERROR3IF(TrackData == NULL, "Trackdata is NULL"); 01868 01869 // If pressure recording is disabled, then we don't need to do anything 01870 if (TrackData == NULL || !AddPressureToPath) 01871 return(TRUE); 01872 01873 // --- Generate a smoothed pressure function from the recorded pressure samples 01874 // If this fails, then we still return TRUE, and the path just loses pressure information 01875 PressureSmoother Bob; 01876 ValueFunction *pValFunc = Bob.Smooth(TrackData, GetCurrentLineWidth()); 01877 if (pValFunc == NULL) 01878 return(TRUE); 01879 01880 // We only want to override the stroke type if it is a simple constant-width line 01881 // - if there is any new-style stroke type applied, we won't try to override it 01882 BOOL ApplyType = FALSE; 01883 01884 // BLOCK 01885 { 01886 Node *pNode = pNewPath->FindFirstChild(); 01887 if (pNode != NULL) 01888 pNode = pNode->FindNext(CC_RUNTIME_CLASS(AttrStrokeType)); 01889 01890 ApplyType = (pNode == NULL); // If there are no StrokeType attrs applied already, we must apply one 01891 if (!ApplyType) 01892 { 01893 // If there is another StrokeType, but it will not stroke using the variable width info, 01894 // (i.e. has a NULL PathProcessor attached to it) we will need to replace it. 01895 StrokeTypeAttrValue *pSAV = (StrokeTypeAttrValue *) ((AttrStrokeType *)pNode)->GetAttributeValue(); 01896 if (pSAV->GetPathProcessor() == NULL) 01897 ApplyType = TRUE; 01898 } 01899 } 01900 01901 // --- Create a simple variable-width path stroke attribute 01902 AttrStrokeType *pStrokeType = NULL; 01903 if (ApplyType) 01904 { 01905 pStrokeType = new AttrStrokeType; 01906 if (pStrokeType == NULL) 01907 return(TRUE); // Return TRUE - we'll only lose the pressure info 01908 01909 PathProcessorStroke *pProcessor = new PathProcessorStroke; 01910 if (pProcessor == NULL) 01911 { 01912 delete pStrokeType; 01913 return(TRUE); // Return TRUE - we'll only lose the pressure info 01914 } 01915 01916 // And attach the stroker to the attribute 01917 ((StrokeTypeAttrValue *)pStrokeType->GetAttributeValue())->SetPathProcessor(pProcessor); 01918 } 01919 01920 // --- Create a pressure table variable-width attribute 01921 AttrVariableWidth *pVarWidth = new AttrVariableWidth; 01922 if (pVarWidth != NULL) 01923 ((VariableWidthAttrValue *)pVarWidth->GetAttributeValue())->SetWidthFunction(pValFunc); 01924 01925 if (pVarWidth == NULL) 01926 { 01927 if (pStrokeType != NULL) 01928 delete pStrokeType; 01929 return(TRUE); // Return TRUE - we'll only lose the pressure info 01930 } 01931 01932 // --- Now apply the attributes to the path, removing any of a similar type which 01933 // are already applied to it. 01934 if (ApplyType) 01935 { 01936 DoRemoveAttrTypeFromSubtree(pNewPath, pStrokeType->GetRuntimeClass()); 01937 pStrokeType->AttachNode(pNewPath, FIRSTCHILD, FALSE, FALSE); 01938 } 01939 01940 // And apply the variable width attribute 01941 DoRemoveAttrTypeFromSubtree(pNewPath, pVarWidth->GetRuntimeClass()); 01942 pVarWidth->AttachNode(pNewPath, FIRSTCHILD, FALSE, FALSE); 01943 01944 #endif // VECTOR_STROKING 01945 01946 return(TRUE); 01947 }
|
|
|
Adds a straight line to the Path, that has been made by the Straight Line Mode. This means it has to set some flags in the path to stop the curve fitter from smoothing this straight line segment out.
Definition at line 1132 of file opfree.cpp. 01133 { 01134 PathFlags Flags; 01135 Flags.Spare1 = TRUE; 01136 01137 // If this coord is the same as the last one, then do not bother adding to the track data 01138 if (PreviousPoint == StraightLinePos) 01139 return; 01140 01141 // add the line segment into the path 01142 if (TrackData->InsertLineTo(StraightLinePos, &Flags)) 01143 { 01144 // and add pressure info if needed 01145 if (AddPressureToPath) 01146 TrackData->AddExtraInfo(CI_PRESSURE, FreeHandPressure); 01147 } 01148 else 01149 { 01150 // Oh no, we ran out of mem in the middle of making a new path 01151 // Tidy up and report back to HQ 01152 EndDrag(); 01153 01154 // Tell the World that it all went horribly wrong 01155 InformError(); 01156 01157 // Remove it from the tree and delete it 01158 TrackData->ClearPath(); 01159 01160 // End this operation and return 01161 FailAndExecute(); 01162 End(); 01163 return; 01164 } 01165 01166 // Count this bit of line 01167 LineSegmentCount++; 01168 CanLineJoin = TRUE; 01169 }
|
|
||||||||||||
|
Applies the current attributes to the Node passed in. It has to find the current document to do this and will ENSURE if it fails to find one.
Reimplemented in OpDrawBrush. Definition at line 1812 of file opfree.cpp. 01813 { 01814 // Find the current document to get the current attributes from 01815 ENSURE(pDocument!=NULL, "Null Document while setting attributes for new NodePath"); 01816 if (pDocument!=NULL) 01817 { 01818 // Apply the current attributes to the path 01819 if (pDocument->GetAttributeMgr().ApplyCurrentAttribsToNode((NodeRenderableInk*)NewPath)) 01820 { 01821 // ok special case exception here, if we have a brush attribute then delete it 01822 Node* pNode = NewPath->FindFirstChild(CC_RUNTIME_CLASS(AttrBrushType)); 01823 if (pNode) 01824 { 01825 pNode->CascadeDelete(); 01826 delete pNode; 01827 } 01828 01829 return TRUE; 01830 } 01831 } 01832 01833 // We failed to apply the attributes, so fail 01834 return FALSE; 01835 }
|
|
||||||||||||||||
|
This function is used when editing lines with the freehand tool. If the drag was started in the middle of a path and the cursor is over that path again, we need to know if we can complete the edit. This is only possible if the start and end points are both on the same sub-path in the path. This function is used to determine if the 2 points are indeed in the same sub-path to allow the tool to display correct cursor etc.
Definition at line 1304 of file opfree.cpp. 01305 { 01306 // saftey check 01307 ERROR2IF(pPath==NULL, FALSE, "NULL pointer passed to OpFreeHand::AreSlotsInSameSubPath"); 01308 01309 // We need to look at the verb array in the path. 01310 PathVerb* pVerbs = pPath->GetVerbArray(); 01311 INT32 NumSlots = pPath->GetNumCoords(); 01312 01313 // find the largest and smallest slot numbers 01314 INT32 First = Slot1<Slot2 ? Slot1 : Slot2; 01315 INT32 Last = Slot1<Slot2 ? Slot2 : Slot1; 01316 01317 // Make sure that the slot numbers make sense 01318 ERROR2IF(Last>NumSlots, FALSE, "Bad Slot numbers in OpFreeHand::AreSlotsInSameSubPath"); 01319 01320 // loop from the first to the last slot looking for MoveTos 01321 while (Last>First) 01322 { 01323 // See if the current last slot is a MoveTo 01324 if (pVerbs[Last]==PT_MOVETO) 01325 return FALSE; 01326 01327 // move the last point back 01328 Last--; 01329 } 01330 01331 // We did not find any MoveTos between the points 01332 return TRUE; 01333 }
|
|
|
|
|
||||||||||||||||
|
Checks to see if the mouse is over the endpoint of any of the selected paths in the document and if it is, it makes a note of the path and which end it was attached to.
Definition at line 1191 of file opfree.cpp. 01192 { 01193 // Assume we do not find a path 01194 EndPath = NULL; 01195 01196 // Find out about the blob manager so we can find the size of a blob 01197 BlobManager* pBlobMgr = GetApplication()->GetBlobManager(); 01198 if (pBlobMgr==NULL) 01199 return FALSE; 01200 01201 // Find out about the size of a blob 01202 DocRect BlobRect; 01203 pBlobMgr->GetBlobRect(*PointerPos, &BlobRect); 01204 01205 // Find the selected range of objects 01206 SelRange* Selected = GetApplication()->FindSelection(); 01207 Node* pNode = Selected->FindFirst(); 01208 01209 // see if the selection is on the same spread as the drag 01210 if (pNode!=NULL) 01211 { 01212 // Get the spread and return if it is different from the one with the cursor 01213 Spread* pNodeSpread = pNode->FindParentSpread(); 01214 if (pNodeSpread!=pSpread) 01215 return FALSE; 01216 } 01217 01218 // Walk through the selection 01219 while (pNode!=NULL) 01220 { 01221 if (pNode->IsNodePath()) 01222 { 01223 // Now we know it's a NodePath, get a pointer to the Path object within it, so 01224 // we can find any endpoints 01225 Path* ThisPath = &(((NodePath*)pNode)->InkPath); 01226 01227 // See if it touches any point in this path 01228 INT32 CloseSlot = 0; 01229 if (ThisPath->IsNearOpenEnd(BlobRect, &CloseSlot)) 01230 { 01231 // Yep, better work out where and set the path where is all happens 01232 ThisPath->SetPathPosition(CloseSlot); 01233 *PointerPos = ThisPath->GetCoord(); 01234 *IsNearEndpoint = TRUE; 01235 EndPath = (NodePath*)pNode; 01236 return TRUE; 01237 } 01238 01239 // See if it is near the middle of the path 01240 // This is only relavent if this node is the same as the one we started on 01241 // and we started in the middle of it 01242 if ((StartPath!=NULL) && (StartPath==pNode) && (pJoinInfo->IsNearEndPoint==FALSE)) 01243 { 01244 INT32 Range = BlobRect.Width() / 2; 01245 if (ThisPath->IsPointCloseTo(*PointerPos, Range*Range, &CloseTo, &Mu)) 01246 { 01247 // OK, we are near the path we started on 01248 // see if we are in the same sub-path as we started on 01249 if (AreSlotsInSameSubPath(CloseTo, pJoinInfo->CloseSlot, ThisPath)) 01250 { 01251 // Yep, better work out where and set the path where is all happens 01252 *IsNearEndpoint = FALSE; 01253 EndPath = (NodePath*)pNode; 01254 return TRUE; 01255 } 01256 } 01257 } 01258 } 01259 01260 // Now find the next selected node 01261 pNode = Selected->FindNext(pNode); 01262 } 01263 01264 // we will see if this point is anywhere near the start point 01265 if ((BlobRect.ContainsCoord(StartPoint)) && (StartPath==NULL)) 01266 { 01267 // Note the path that we are starting at and modify the coord 01268 // This will make the start and end points the same, causing the path to be closed 01269 *PointerPos = StartPoint; 01270 01271 // Wait till the cursor has moved out of the original snap range before we start joining 01272 if (CanLineJoin==TRUE) 01273 { 01274 *IsNearEndpoint = TRUE; 01275 return TRUE; 01276 } 01277 } 01278 01279 // Did not find a join 01280 return FALSE; 01281 }
|
|
|
Does all the steps required to build a new path, smooth it, try to join it with others and finally insert it into the tree.
Definition at line 783 of file opfree.cpp. 00784 { 00785 // Create a new path to be inserted into the tree 00786 NodePath* pNewNodePath = NULL; 00787 if (!CreateNewPath(&pNewNodePath)) 00788 return FALSE; 00789 00790 if (!SmoothNewCurve(pNewNodePath)) 00791 { 00792 // Get rid of the path we created and fail 00793 delete pNewNodePath; 00794 return FALSE; 00795 } 00796 00797 if (!InsertSmoothCurveWithUndo(pNewNodePath)) 00798 { 00799 // Get rid of the path we created, and fail 00800 pNewNodePath->CascadeDelete(); 00801 delete pNewNodePath; 00802 return FALSE; 00803 } 00804 00805 // Mark the selection as no longer valid (the Bounding Box will have changed) 00806 SelRange* Selection = GetApplication()->Selection; 00807 if (Selection) 00808 Selection->Update(); 00809 00810 00811 // All worked 00812 return TRUE; 00813 }
|
|
||||||||||||
|
Joins a Complex path with the new freehand path and builds all the undo that is needed in the process.
Definition at line 1653 of file opfree.cpp. 01654 { 01655 // First we should make a note of the region that we will need redrawing 01656 DocRect InvalidRect = FreePath->GetBlobBoundingRect(); 01657 01658 // Need to know where in the joined path that the new section will be 01659 INT32 NumSlots = FreePath->InkPath.GetNumCoords(); 01660 INT32 StartSlot; 01661 01662 // Make a copy of the node we are joining with 01663 NodePath* JoinPath = MakeCopy(OldPath); 01664 if (JoinPath == NULL) 01665 return FALSE; 01666 01667 // before Joining them 01668 BOOL NewPathReversed = FALSE; 01669 if (!JoinPath->InkPath.ComplexJoin(&FreePath->InkPath, &StartSlot, &NewPathReversed)) 01670 return FALSE; 01671 01672 // Insert the new object 01673 if (!InsertNewNode(JoinPath, InvalidRect, OldPath)) 01674 return FALSE; 01675 01676 // Reverse the original mouse move data if the fitted path was reversed 01677 if (NewPathReversed) 01678 TrackData->Reverse(); 01679 01680 // Tell the freehand tool all about it 01681 SetRetroPath(JoinPath, StartSlot, NumSlots); 01682 01683 m_pNewNodePath = JoinPath; 01684 // It Worked! 01685 return TRUE; 01686 }
|
|
||||||||||||
|
Joins a Complex path with the new freehand path and builds all the undo that is needed in the process. The new freehand path joins two of the complex paths sub-paths together.
Definition at line 1705 of file opfree.cpp. 01706 { 01707 // First we should make a note of the region that we will need redrawing 01708 DocRect InvalidRect = FreePath->GetBlobBoundingRect(); 01709 01710 // Need to know where in the joined path that the new section will be 01711 INT32 NumSlots = FreePath->InkPath.GetNumCoords(); 01712 INT32 StartSlot; 01713 01714 // Make a copy of the of the path we are Joining to 01715 NodePath* JoinPath = MakeCopy(OldPath); 01716 if (JoinPath==NULL) 01717 return FALSE; 01718 01719 // Join the new path with the one already there 01720 BOOL NewPathReversed = FALSE; 01721 if (!JoinPath->InkPath.ComplexToSameComplexJoin(&FreePath->InkPath, &StartSlot, &NewPathReversed)) 01722 return FALSE; 01723 01724 // Insert the new object 01725 if (!InsertNewNode(JoinPath, InvalidRect, OldPath)) 01726 return FALSE; 01727 01728 // Reverse the original mouse move data if the fitted path was reversed 01729 if (NewPathReversed) 01730 TrackData->Reverse(); 01731 01732 // Tell the freehand tool all about it 01733 SetRetroPath(JoinPath, StartSlot, NumSlots); 01734 01735 // It Worked! 01736 return TRUE; 01737 }
|
|
|
Builds a new Node Path ready to have a Curve fitted into it. If anything goes wrong (not enough memory, the path was not worth fitting etc) then this function fails.
Definition at line 831 of file opfree.cpp. 00832 { 00833 // Get a pointer to the path and set it to NULL 00834 NodePath*& pFreeHandPath = *pNewPath; 00835 pFreeHandPath = NULL; 00836 00837 // Only bother if they had actually drawn something 00838 if (LineSegmentCount==0) 00839 return FALSE; 00840 00841 // See if the path ever got away from the initial snap coord 00842 DocCoord* Coords = TrackData->GetCoordArray(); 00843 INT32 NumCoords = TrackData->GetNumCoords(); 00844 BOOL IsAllSame = TRUE; 00845 00846 // loop through all the coords comparing them with the first one 00847 for (INT32 i=0; (i<NumCoords) && (IsAllSame); i++) 00848 { 00849 // if this coord is different from the first one, then we are ok 00850 if (Coords[0] != Coords[i]) 00851 IsAllSame = FALSE; 00852 } 00853 00854 // If it did not (ie all the coordinates were the same, then chuck it away) 00855 if (IsAllSame) 00856 return FALSE; 00857 00858 // Init the path with the default memory block sizes 00859 pFreeHandPath = new NodePath; 00860 if (pFreeHandPath==NULL) 00861 return FALSE; 00862 00863 // Ok, we got a new NodePath, try and init the Path inside it 00864 if (!pFreeHandPath->SetUpPath(24, 12)) 00865 { 00866 // The path failed to init, so get rid of it and fail 00867 delete pFreeHandPath; 00868 pFreeHandPath = NULL; 00869 return FALSE; 00870 } 00871 00872 // Must have worked 00873 return TRUE; 00874 }
|
|
|
Adds the operation to the list of all known operations.
Reimplemented in OpDrawBrush. Definition at line 3278 of file opfree.cpp. 03279 { 03280 return (RegisterOpDescriptor( 03281 0, 03282 _R(IDS_FREE_HAND_TOOL), 03283 CC_RUNTIME_CLASS(OpFreeHand), 03284 OPTOKEN_FREEHAND, 03285 OpFreeHand::GetState, 03286 0, /* help ID */ 03287 _R(IDBBL_FREEHANDTOOLOP), 03288 0 /* bitmap ID */)); 03289 }
|
|
||||||||||||||||||||||||
|
Starts up the drag operation by storing all start positions and setting up a Path to store the mouse movement in.
Definition at line 221 of file opfree.cpp. 00223 { 00224 TRACEUSER( "Diccon", _T("Do Drag Free, StartPos = %d, %d\n"), Anchor.x, Anchor.y); 00225 // WEBSTER - markn 25/4/97 00226 // No pen stuff required in Webster 00227 // Taken out by vector stroking code Neville 2/10/97 00228 #ifdef VECTOR_STROKING 00229 // Tell the pressure pen that we're starting a new stroke 00230 CCPen *pPen = GetApplication()->GetPressurePen(); 00231 if (pPen != NULL) 00232 pPen->StartStroke(); 00233 #endif // VECTOR_STROKING 00234 00235 // Snap the starting coord if we are not joining to something else 00236 if ((pFreeHandInfo==NULL) || (pFreeHandInfo->pJoinPath==NULL)) 00237 DocView::SnapCurrent(pSpread, &Anchor, FALSE, TRUE); 00238 00239 // Make a note of various starting conditions 00240 TrackData = ToolPath; 00241 Smoothness = Smooth; 00242 pJoinInfo = pFreeHandInfo; 00243 StartPath = pJoinInfo->pJoinPath; 00244 EndPath = NULL; 00245 00246 // Make a mental note of the start point 00247 StartPoint = Anchor; 00248 StartSpread = pSpread; 00249 PreviousSpread= pSpread; 00250 PreviousPoint = Anchor; 00251 LineSegmentCount = 0; 00252 IsStraightLineMode = FALSE; 00253 CanLineJoin = FALSE; 00254 00255 // Prepare the Track data path and add in the initial click point to the path 00256 if (!PrepareTrackDataPath()) 00257 { 00258 // We failed to get the memory to initialise the track data 00259 InformError(_R(IDS_OUT_OF_MEMORY), _R(IDS_OK)); 00260 FailAndExecute(); 00261 End(); 00262 return; 00263 } 00264 00265 // Create some cursors that I might need 00266 if (!LoadCursors()) 00267 { 00268 // The cursors did not load, so fail? 00269 FailAndExecute(); 00270 End(); 00271 return; 00272 } 00273 00274 // Push my new cursor onto the stack 00275 CurrentCursorID = CursorStack::GPush(pFreeHandCursor, TRUE); 00276 MyCurrentCursor = pFreeHandCursor; 00277 00278 // And tell the Dragging system that we need drags to happen 00279 StartDrag( DRAGTYPE_NOSCROLL ); 00280 }
|
|
||||||||||||||||||||||||
|
Handles the drag finishing by rubbing out an EOR on the screen and adding the path to the tree and building all the undo that will be needed.
Reimplemented from Operation. Reimplemented in OpDrawBrush. Definition at line 647 of file opfree.cpp. 00649 { 00650 // Erase the whole EORed line 00651 DocRect ClipRect(0,0,0,0); 00652 RenderDragBlobs(ClipRect, StartSpread, bSolidDrag); 00653 00654 // Get rid of all the cursors 00655 RemoveCursors(); 00656 00657 // Put the hour glass up as we have to and end the drag 00658 BeginSlowJob(); 00659 EndDrag(); 00660 00661 // Add the new path to the tree if it was valid 00662 BOOL Worked = FALSE; 00663 if (Success) 00664 { 00665 // were we in the middle of drawing a straight line 00666 if (IsStraightLineMode) 00667 { 00668 // we were so add it in to the track data 00669 AddStraightLine(); 00670 PreviousPoint = StraightLinePos; 00671 IsStraightLineMode = FALSE; 00672 } 00673 00674 // try and smooth the path and insert it into the tree 00675 Worked = CompleteOperation(); 00676 00677 // DY 9/99 Check to see if we are editing a blend on a curve, if so we may wish to 00678 // change the number of steps in the blend (making use of the path distance). 00679 NodeGroup* pParent = GetParentOfNodePath(); 00680 if (pParent!= NULL) 00681 { 00682 if (pParent->IS_KIND_OF(NodeBlend)) 00683 { 00684 InsertChangeBlendStepsAction((NodeBlend*)pParent); 00685 00686 ObjChangeFlags cFlags( |