#include <pentool.h>
Inheritance diagram for PenTool:
Public Member Functions | |
PenTool () | |
Dummy Constructor - It does nothing. All the real initialisation is done in PenTool::Init which is called by the Tool Manager. | |
~PenTool () | |
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. | |
virtual void | OnClick (DocCoord, ClickType, ClickModifiers, Spread *) |
To handle a Mouse Click event for the Pen Tool. | |
virtual void | RenderToolBlobs (Spread *, DocRect *) |
The blobs this tool renders are (1) a moveto floating endpoint (2) a dragto floating endpoint These are usually rendered after the first click/drag on a document. | |
virtual BOOL | GetStatusLineText (String_256 *, Spread *, DocCoord, ClickModifiers) |
generate up-to-date text for the status line (called on idles) | |
virtual void | OnMouseMove (DocCoord, Spread *, ClickModifiers) |
This routine is called whenever the mouse moves while we're in the pen tool. it sees what is under the pointer, and flips the cursor if clicking will have a different effect. | |
virtual BOOL | OnKeyPress (KeyPress *pKeyPress) |
To handle keypress events for the Pen 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 | GenerateStatusLineText (NodePath *pNodePath, penclick WhatToDo, String_256 *pStatusMsg) |
Loads up an appropriate help string into the text buffer pointed to by pStatusMsg, using the nodepath and 'whattodo' information passed. | |
void | SetInternalState () |
This function is called from an operation which tells the tool that there should be a virtual moveto coordinate and dragto coordinate set within the tool. If the dragto is equal to the moveto, then an internal move should be created, rather than an internal drag. | |
void | ClearInternalState () |
Clears the internal condition. | |
BOOL | OverPathEnd (DocCoord, Spread *, NodePath **) |
penclick | DetermineClickEffect (DocCoord, Spread *, NodePath **) |
Used when single clicking. This routine determines what effect a click will have. In this tool, clicking will add a segment to the end of a line, adjust the last element of a path or start a new path entirely. | |
void | RemoveSelection (DocCoord PointerPos, Spread *pSpread, NodePath *pNodePath=NULL) |
This routine scans the specified spread for all path objects and checks whether the mouse coord is over an open end point. It can be used to work out whether to change the mouse shape or not. This routine should really exist in some other file, available to all tools but I dont know where to put it yet so it shall have to stay here for the mo. | |
void | ClearPath () |
Throw away the internal data of the pen path. | |
void | ClearOp () |
Throw away the internal op state we've been holding. | |
void | CreateNewPath () |
Once a drag has finished we need to build a new path with the data. | |
void | AddElementToPath () |
Once a drag has finished we need to add the newly edited element to the specified path. | |
void | CloseWithPath () |
Once a drag has finished we need to add the newly edited element to the specified path. | |
penopstate | GetPenOpState () const |
return the operation state the pen tool thinks its in. | |
Private Member Functions | |
CC_DECLARE_MEMDUMP (PenTool) | |
void | ClickOnEndPoint (ClickType Click, ClickModifiers ClickMods, Spread *pSpread, NodePath *pNodePath) |
An end point click has occured. This function acts on such a click by selecting the point or editing the point dependent on the click type. | |
BOOL | CreatePenCursors () |
Pen tool cursor creation. | |
void | DeletePenCursors () |
Pen tool cursor deletion. | |
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. | |
Private Attributes | |
penstate | CurrPenState |
penopstate | CurrPenOpState |
Path | EditPath |
ControlPts | EditHandles |
NodePath * | pNodePath |
INT32 | NodeIndex |
Cursor * | pcPenCursor |
Cursor * | pcPenAdjustCursor |
Cursor * | pcPenReshapeCursor |
Cursor * | pcMoveBezCursor |
Cursor * | MyCurrentCursor |
INT32 | CurrentCursorID |
PenToolInfoBarOp * | pPenInfoBarOp |
Static Private Attributes | |
static TCHAR * | FamilyName = _T("Drawing Tools") |
static TCHAR * | ToolName = _T("Pen Tool") |
static TCHAR * | Purpose = _T("To draw lines and curves") |
static TCHAR * | Author = _T("Mike") |
Definition at line 158 of file pentool.h.
|
Dummy Constructor - It does nothing. All the real initialisation is done in PenTool::Init which is called by the Tool Manager.
Definition at line 162 of file pentool.cpp. 00163 { 00164 pcPenCursor = NULL; 00165 pcPenAdjustCursor = NULL; 00166 pcPenReshapeCursor = NULL; 00167 pcMoveBezCursor = NULL; 00168 MyCurrentCursor = NULL; 00169 00170 CurrPenState = IS_Undefined; 00171 }
|
|
Destructor (Virtual). Does nothing.
Definition at line 186 of file pentool.cpp.
|
|
Once a drag has finished we need to add the newly edited element to the specified path.
Definition at line 1668 of file pentool.cpp. 01669 { 01670 // Right, the last drag has created a new path section for me 01671 // I need to add it in to the specified nodepath object 01672 01673 OpAddPathToPath* pOpAddPathToPath = new OpAddPathToPath; 01674 pOpAddPathToPath->DoAddPathToPath(pNodePath, &EditPath, NodeIndex); 01675 }
|
|
|
|
Changes to the specified cursor. Will only change the cursor if it isn't already this cursor, so it doesn't flicker.
Definition at line 1492 of file pentool.cpp. 01493 { 01494 // only change if this cursor is different from the current cursor 01495 if (cursor != MyCurrentCursor) 01496 { 01497 // set this cursor as the current cursor and immediately display it 01498 CursorStack::GSetTop(cursor, CurrentCursorID); 01499 // remember this is our current cursor 01500 MyCurrentCursor = cursor; 01501 } 01502 }
|
|
Clears the internal condition.
Definition at line 1556 of file pentool.cpp. 01557 { 01558 if (CurrPenState == IS_MoveTo || CurrPenState == IS_DragTo) 01559 { 01560 BlobManager* BlobMgr = GetApplication()->GetBlobManager(); 01561 ENSURE(BlobMgr!=NULL, "Blob Manager was not there"); 01562 BlobMgr->RenderToolBlobsOff(this, EditHandles.pHndSpread,NULL); 01563 } 01564 CurrPenState = IS_Undefined; 01565 }
|
|
Throw away the internal op state we've been holding.
Definition at line 1604 of file pentool.cpp. 01605 { 01606 CurrPenOpState = OS_Undefined; 01607 }
|
|
Throw away the internal data of the pen path.
Definition at line 1585 of file pentool.cpp. 01586 { 01587 // call the path clearing function! 01588 01589 ClearInternalState(); 01590 EditPath.ClearPath(); 01591 }
|
|
An end point click has occured. This function acts on such a click by selecting the point or editing the point dependent on the click type.
Definition at line 913 of file pentool.cpp. 00914 { 00915 Path* pPath = &(pNodePath->InkPath); 00916 00917 DocCoord* Coords = pPath->GetCoordArray(); 00918 PathFlags* Flags = pPath->GetFlagArray(); 00919 PathVerb* Verbs = pPath->GetVerbArray(); 00920 INT32 NumCoords = pPath->GetNumCoords(); 00921 00922 // grab the index of the point actually clicked on! 00923 INT32 Pos = pPath->GetPathPosition(); 00924 00925 // Clicks on control points have no effect 00926 // but clicks on endpoints do have an effect 00927 00928 switch (Click) 00929 { 00930 case CLICKTYPE_SINGLE: 00931 { 00932 if (Flags[Pos].IsEndPoint) 00933 { 00934 pPath->RenderPathPenBlobs(pSpread); 00935 00936 BOOL CurSelState = Flags[Pos].IsSelected; 00937 BOOL NewSelState = TRUE; 00938 BOOL ClearOthers = FALSE; 00939 00940 // if shift held down then toggle the point whatever 00941 if (ClickMods.Adjust) 00942 NewSelState = !CurSelState; 00943 00944 // if the end point is not selected and we're not toggling 00945 if (!CurSelState && !ClickMods.Adjust) 00946 ClearOthers=TRUE; 00947 00948 if (ClearOthers) 00949 { 00950 for (INT32 i=0; i<NumCoords; i++) 00951 { 00952 Flags[i].IsSelected = FALSE; 00953 } 00954 } 00955 00956 // Now change the selection of this point 00957 Flags[Pos].IsSelected = NewSelState; 00958 00959 if ((Pos>0) && (!Flags[Pos-1].IsEndPoint)) 00960 Flags[Pos-1].IsSelected = NewSelState; 00961 00962 if ((Pos+1<NumCoords) && (!Flags[Pos+1].IsEndPoint)) 00963 Flags[Pos+1].IsSelected = NewSelState; 00964 00965 // Check for this being the first element in a closed subpath 00966 // If this element is a moveto, and the end of the path has the 00967 // CLOSEFIGURE flag set, we should select the endpoint as well 00968 if (Verbs[Pos] == PT_MOVETO) 00969 { 00970 // This for loop will find either the end of the path, or the next moveto 00971 INT32 j; 00972 for (j=Pos+1;j<NumCoords && Verbs[j] != PT_MOVETO;j++); // ; is intentional! 00973 j--; 00974 if (Verbs[j] & PT_CLOSEFIGURE) 00975 { 00976 //HandleBlobClick(Coords,Flags,j,NumCoords,TRUE); 00977 Flags[j].IsSelected = NewSelState; 00978 // If the previous point is a control point then deal with it 00979 if ((j>0) && (!Flags[j-1].IsEndPoint)) 00980 { 00981 // Change the control point's selection state 00982 Flags[j-1].IsSelected = NewSelState; 00983 } 00984 } 00985 00986 } 00987 00988 pPath->RenderPathPenBlobs(pSpread); 00989 } 00990 break; 00991 } 00992 00993 case CLICKTYPE_DOUBLE: 00994 break; 00995 00996 case CLICKTYPE_DRAG: 00997 { 00998 if ((Flags[Pos].IsEndPoint) && (!ClickMods.Menu)) 00999 { 01000 // Need to do a drag on the selected points, so we had better start an operation 01001 OpNodePathEditBlob* pOpNodePath = new OpNodePathEditBlob; 01002 if (pOpNodePath == NULL) 01003 InformError(); 01004 else 01005 pOpNodePath->DoStartDragEdit(pNodePath, Coords[Pos], pSpread); 01006 } 01007 } 01008 break; 01009 01010 default: 01011 { 01012 } 01013 break; 01014 } 01015 }
|
|
Once a drag has finished we need to add the newly edited element to the specified path.
Definition at line 1694 of file pentool.cpp. 01695 { 01696 // Right, the last drag has closed a path. 01697 // I need to add it in to the specified nodepath object 01698 01699 OpClosePathWithPath* pOpClosePathWithPath = new OpClosePathWithPath; 01700 pOpClosePathWithPath->DoClosePathWithPath(pNodePath, &EditPath, NodeIndex); 01701 }
|
|
Once a drag has finished we need to build a new path with the data.
Definition at line 1642 of file pentool.cpp. 01643 { 01644 // Ok, the last drag has altered our internal drag path. We now 01645 // have a path ready to add to the tree, so we need to get on with it! 01646 OpAddNewPath* pOpAddNewPath = new OpAddNewPath; 01647 pOpAddNewPath->DoAddNewPath(&EditPath, EditHandles.pHndSpread); 01648 }
|
|
Pen tool cursor creation. BOOL PenTool::CreatePenCursors()
Definition at line 406 of file pentool.cpp. 00407 { 00408 pcPenAdjustCursor = new Cursor(this, _R(IDC_PENADJUSTCURSOR)); 00409 if (!pcPenAdjustCursor || !pcPenAdjustCursor->IsValid()) 00410 { 00411 DeletePenCursors(); 00412 InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) ); 00413 return FALSE; 00414 } 00415 00416 pcPenCursor = new Cursor(this, _R(IDC_NEWPATHCURSOR)); 00417 if (!pcPenCursor || !pcPenCursor->IsValid()) 00418 { 00419 DeletePenCursors(); 00420 InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) ); 00421 return FALSE; 00422 } 00423 00424 pcPenReshapeCursor = new Cursor(this, _R(IDC_RESHAPECURSOR)); 00425 if (!pcPenReshapeCursor || !pcPenReshapeCursor->IsValid()) 00426 { 00427 DeletePenCursors(); 00428 InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) ); 00429 return FALSE; 00430 } 00431 00432 pcMoveBezCursor = new Cursor(this, _R(IDC_MOVEBEZIERCURSOR)); 00433 if (!pcMoveBezCursor || !pcMoveBezCursor->IsValid()) 00434 { 00435 DeletePenCursors(); 00436 InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) ); 00437 return FALSE; 00438 } 00439 00440 return TRUE; 00441 }
|
|
Pen tool cursor deletion. BOOL PenTool::DeletePenCursors()
Definition at line 457 of file pentool.cpp. 00458 { 00459 if (pcPenCursor!=NULL) 00460 { 00461 delete pcPenCursor; 00462 pcPenCursor=NULL; 00463 } 00464 00465 if (pcPenAdjustCursor!=NULL) 00466 { 00467 delete pcPenAdjustCursor; 00468 pcPenAdjustCursor=NULL; 00469 } 00470 00471 if (pcPenReshapeCursor!=NULL) 00472 { 00473 delete pcPenReshapeCursor; 00474 pcPenReshapeCursor=NULL; 00475 } 00476 00477 if (pcMoveBezCursor!=NULL) 00478 { 00479 delete pcMoveBezCursor; 00480 pcMoveBezCursor=NULL; 00481 } 00482 }
|
|
Allows the tool manager to extract information about the tool.
Reimplemented from Tool_v1. Definition at line 277 of file pentool.cpp. 00278 { 00279 // Cast structure into the latest one we understand. 00280 ToolInfo_v1 *Info = (ToolInfo_v1 *) InfoPtr; 00281 00282 Info -> InfoVersion = 1; 00283 00284 Info -> InterfaceVersion = GetToolInterfaceVersion(); // You should always have this line. 00285 00286 // These are all arbitrary at present. 00287 Info -> Version = 1; 00288 Info -> ID = GetID(); 00289 Info -> TextID = _R(IDS_PEN_TOOL); 00290 00291 Info -> Family = FamilyName; 00292 Info -> Name = ToolName; 00293 Info -> Purpose = Purpose; 00294 Info -> Author = Author; 00295 00296 Info -> InfoBarDialog = _R(IDD_FREEHANDTOOL); 00297 00298 Info -> BubbleID = _R(IDBBL_PEN_TOOL); 00299 00300 }
|
|
Used when single clicking. This routine determines what effect a click will have. In this tool, clicking will add a segment to the end of a line, adjust the last element of a path or start a new path entirely.
Definition at line 752 of file pentool.cpp. 00753 { 00754 penclick WhatToDo = PenNewPath; // tells me what effect the click would have 00755 NodePath* WhichNode = NULL; // Saves me using a pointer to a pointer 00756 00757 // Now scan through the selected paths, and see if we've clicked on any endpoints 00758 DocView* pDocView = DocView::GetSelected(); 00759 ENSURE( pDocView != NULL, "PenTool::DetermineClickEffect: Can't find selected DocView"); 00760 if (pDocView==NULL) 00761 return(PenNewPath); 00762 00763 // Find the Rect round the mouse pos that counts as a hit 00764 DocRect BlobRect; 00765 OSRenderRegion::GetBlobRect(pDocView->GetViewScale(), PointerPos, BT_SELECTEDLARGEST, &BlobRect); 00766 00767 // if we're in an internal state and someone has clicked on the moveto 00768 // again then go and edit it. 00769 if (CurrPenState == IS_MoveTo || CurrPenState == IS_DragTo) 00770 { 00771 if (BlobRect.ContainsCoord(EditHandles.HndClick)) 00772 return (PenEditInternalMove); 00773 } 00774 00775 00776 // Find the selected range of objects 00777 SelRange* Selected = GetApplication()->FindSelection(); 00778 Node* pNode = Selected->FindFirst(); 00779 00780 INT32 TotSelectedEndpoints = 0; // Count selected points in paths 00781 BOOL MultiSegments = FALSE; 00782 00783 if (pNode != NULL) 00784 { 00785 Spread* NodeSpread = pNode->FindParentSpread(); 00786 if (NodeSpread == pSpread) 00787 { 00788 // On the same spread, so see if the pointer is over an endpoint 00789 while ((pNode!=NULL) && ((WhatToDo==PenNewPath) || (WhatToDo==PenAddSegment))) 00790 { 00791 if (pNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodePath)) 00792 { 00793 // Now we know it's a NodePath, get a pointer to the Path object within it, so 00794 // we can find any endpoints 00795 Path* ThisPath = &(((NodePath*)pNode)->InkPath); 00796 00797 // count the number of selected points on the path (excluding control points) 00798 INT32 NumCoords = ThisPath->GetNumCoords(); 00799 PathFlags* Flags = ThisPath->GetFlagArray(); 00800 00801 // Count selected points in this path 00802 INT32 NumSelectedEndpoints = 0; 00803 INT32 lastsel = 0; 00804 for (INT32 i=0; i<NumCoords; i++) 00805 { 00806 if (Flags[i].IsSelected && Flags[i].IsEndPoint) 00807 { 00808 lastsel = i; 00809 NumSelectedEndpoints++; 00810 } 00811 } 00812 // Sum up 00813 TotSelectedEndpoints+=NumSelectedEndpoints; 00814 00815 INT32 point; 00816 // First, see if the mouse is over a point. 00817 if (ThisPath->FindNearestPoint(PointerPos, POINTFLAG_ENDPOINTS | POINTFLAG_ENDSFIRST, &point)) 00818 { 00819 WhichNode = (NodePath*)pNode; 00820 WhatToDo = PenOnPoint; 00821 ThisPath->SetPathPosition(point); 00822 00823 // if the mouse was over an open end and the other end of this sub 00824 // path is selected then we need to close the path 00825 // find the start and end of the subpath the point was found in 00826 INT32 start = point; 00827 INT32 end = point; 00828 ThisPath->FindStartOfSubPath(&start); 00829 ThisPath->FindEndElOfSubPath(&end); 00830 if (point==start || point==end) 00831 { 00832 INT32 other; 00833 (point==start) ? (other=end) : (other=start); 00834 if ((Flags[other].IsSelected) && (!Flags[point].IsSelected)) 00835 WhatToDo = PenClosePath; 00836 } 00837 continue; 00838 } 00839 00840 // if the mouse is close to an element, then it might be close 00841 // enough to reshape the line 00842 if (ThisPath->PointCloseToLine(PointerPos, &point)) 00843 { 00844 WhichNode=(NodePath*)pNode; 00845 WhatToDo=PenReshapeLine; 00846 ThisPath->SetPathPosition(point); 00847 continue; 00848 } 00849 00850 if (!MultiSegments && NumSelectedEndpoints==1) 00851 { 00852 INT32 start = lastsel; 00853 INT32 end = lastsel; 00854 ThisPath->FindStartOfSubPath(&start); 00855 ThisPath->FindEndElOfSubPath(&end); 00856 if (lastsel==start || lastsel==end) 00857 { 00858 if (WhatToDo==PenNewPath) 00859 { 00860 WhichNode=(NodePath*)pNode; 00861 WhatToDo=PenAddSegment; 00862 ThisPath->SetPathPosition(lastsel); 00863 } 00864 else 00865 { 00866 // We have more than one path with a selected end point. 00867 // Adding elements is ambiguous so force a NewPath creation 00868 WhichNode=(NodePath*)pNode; 00869 WhatToDo=PenNewPath; 00870 MultiSegments=TRUE; 00871 } 00872 } 00873 } 00874 } 00875 // Now find the next selected node 00876 pNode = Selected->FindNext(pNode); 00877 } 00878 } 00879 } 00880 00881 // WhatToDo tells us what the action will be 00882 // WhichNode points to the node we are dealing with 00883 // PathPosition is the index into that path of the element we are using 00884 00885 *ReturnNode = WhichNode; 00886 return (WhatToDo); 00887 }
|
|
Loads up an appropriate help string into the text buffer pointed to by pStatusMsg, using the nodepath and 'whattodo' information passed.
Definition at line 1200 of file pentool.cpp. 01201 { 01202 switch (WhatToDo) 01203 { 01204 case PenNewPath: 01205 switch(CurrPenState) 01206 { 01207 case IS_MoveTo: 01208 pStatusMsg->Load(_R(IDS_PENADDPOINT), Tool::GetModuleID(GetID())); 01209 break; 01210 case IS_DragTo: 01211 pStatusMsg->Load(_R(IDS_PENADDCURVE), Tool::GetModuleID(GetID())); 01212 break; 01213 default: 01214 pStatusMsg->Load(_R(IDS_PENNEWPATH), Tool::GetModuleID(GetID())); 01215 break; 01216 } 01217 break; 01218 01219 case PenAddSegment: 01220 if (pNodePath != NULL) 01221 { 01222 PathVerb Verb = (pNodePath->InkPath).GetVerb(); 01223 PathFlags Flags = (pNodePath->InkPath).GetFlags(); 01224 switch (Verb) 01225 { 01226 case PT_BEZIERTO: 01227 if (Flags.IsRotate) 01228 pStatusMsg->Load(_R(IDS_PENADDCURVE), Tool::GetModuleID(GetID())); 01229 else 01230 pStatusMsg->Load(_R(IDS_PENADDPOINT), Tool::GetModuleID(GetID())); 01231 break; 01232 default: 01233 pStatusMsg->Load(_R(IDS_PENADDPOINT), Tool::GetModuleID(GetID())); 01234 break; 01235 } 01236 } 01237 else 01238 pStatusMsg->Load(_R(IDS_PENADDPOINT), Tool::GetModuleID(GetID())); 01239 break; 01240 01241 case PenEditInternalMove: 01242 pStatusMsg->Load(_R(IDS_PENEDITINT), Tool::GetModuleID(GetID())); 01243 break; 01244 01245 case PenClosePath: 01246 pStatusMsg->Load(_R(IDS_PENCLOSEPATH), Tool::GetModuleID(GetID())); 01247 break; 01248 01249 case PenReshapeLine: 01250 pStatusMsg->Load(_R(IDS_RESHAPE_LINE),Tool::GetModuleID(GetID())); 01251 break; 01252 01253 case PenOnPoint: 01254 if (pNodePath != NULL) 01255 { 01256 PathFlags Flags = (pNodePath->InkPath).GetFlags(); 01257 if (Flags.IsSelected) 01258 pStatusMsg->Load(_R(IDS_PENONSELPOINT), Tool::GetModuleID(GetID())); 01259 else 01260 pStatusMsg->Load(_R(IDS_PENONPOINT), Tool::GetModuleID(GetID())); 01261 } 01262 break; 01263 01264 default: 01265 pStatusMsg->Load(_R(IDS_PENADDPOINT), Tool::GetModuleID(GetID())); 01266 break; 01267 } 01268 }
|
|
Reimplemented from Tool_v1. Definition at line 169 of file pentool.h. 00169 { return TOOLID_PEN; };
|
|
return the operation state the pen tool thinks its in.
Definition at line 1621 of file pentool.cpp. 01622 { 01623 return (CurrPenOpState); 01624 }
|
|
generate up-to-date text for the status line (called on idles)
Reimplemented from Tool_v1. Definition at line 1161 of file pentool.cpp. 01162 { 01163 ERROR1IF(ptext==NULL,FALSE,"PenTool::GetStatusLineText() passed a NULL text buffer"); 01164 01165 *ptext = ""; 01166 01167 NodePath* pNodePath = NULL; 01168 01169 // find what type of click we will generate 01170 penclick WhatToDo = DetermineClickEffect(coord, pSpread, &pNodePath); 01171 GenerateStatusLineText(pNodePath, WhatToDo, ptext); 01172 01173 return TRUE; 01174 }
|
|
Used to check if the Tool was properly constructed.
Reimplemented from Tool_v1. Definition at line 204 of file pentool.cpp. 00205 { 00206 00207 BOOL ok; 00208 CCResTextFile file; // Resource File 00209 PenToolInfoBarOpCreate BarCreate; // Object that creates PenInfoBarOp objects 00210 00211 // This should be set to NULL by default. It will be set properly below, if 00212 // everthing is working as it should 00213 pPenInfoBarOp = NULL; 00214 00215 // initially, no cursor 00216 pcPenCursor = 0; 00217 00218 pPenInfoBarOp = new PenToolInfoBarOp(); 00219 ok = (pPenInfoBarOp != NULL); 00220 if (ok) pPenInfoBarOp->pPenTool = this; // Set a pointer from the op to this tool 00221 00222 #if 0 00223 ok = file.open(_R(IDM_PENTOOL_BAR), _R(IDT_INFO_BAR_RES)); // Open resource 00224 if (ok) ok = DialogBarOp::ReadBarsFromFile(file,BarCreate); // Read and create info bar 00225 if (ok) file.close(); // Close resource. 00226 00227 ENSURE(ok,"Unable to load penbar.ini from resource\n"); 00228 00229 if (ok) 00230 { 00231 // Info bar now exists. Now get a pointer to it 00232 String_32 str = String_32(_R(IDS_PENTOOL_INFOBARNAME)); 00233 DialogBarOp* pDialogBarOp = DialogBarOp::FindDialogBarOp(str); 00234 00235 ok = (pDialogBarOp != NULL); 00236 if (ok) ok = pDialogBarOp->IsKindOf(CC_RUNTIME_CLASS(PenToolInfoBarOp)); 00237 if (ok) pPenInfoBarOp = (PenToolInfoBarOp*)pDialogBarOp; 00238 if (ok) pPenInfoBarOp->pPenTool = this; // Set a pointer from the op to this tool 00239 00240 ENSURE(ok,"Failed to create PENTOOL info bar"); 00241 } 00242 #endif 00243 00244 if (ok) ok = EditPath.Initialise(12,24); // create the edit path buffers please 00245 00246 // Register our pen operation(s). 00247 if (ok) 00248 { 00249 ok = OpPenCreateInternal::Init(); 00250 if (ok) ok = OpPenEditInternal::Init(); 00251 if (ok) ok = OpPenCreatePath::Init(); 00252 if (ok) ok = OpPenAddElement::Init(); 00253 if (ok) ok = OpAddNewPath::Init(); 00254 if (ok) ok = OpPenClosePath::Init(); 00255 } 00256 00257 return ok; 00258 00259 }
|
|
To handle a Mouse Click event for the Pen Tool.
Reimplemented from Tool_v1. Definition at line 592 of file pentool.cpp. 00594 { 00595 if (ClickMods.Menu) return; // Don't do anything if the user clicked the Menu button 00596 00597 // determine what to do with this click 00598 penclick WhatToDo = DetermineClickEffect(PointerPos, pSpread, &pNodePath); 00599 00600 // if someones holding the adjust down and we're not on a point then clear the sel 00601 if (Click==CLICKTYPE_SINGLE && ClickMods.Adjust && WhatToDo!=PenOnPoint) 00602 { 00603 RemoveSelection(PointerPos,pSpread); 00604 ClearInternalState(); 00605 return; 00606 } 00607 00608 switch (Click) 00609 { 00610 case CLICKTYPE_SINGLE: 00611 switch (WhatToDo) 00612 { 00613 case PenNewPath: 00614 { 00615 BOOL MakeInternal = TRUE; 00616 if ((CurrPenState == IS_MoveTo) || (CurrPenState == IS_DragTo)) 00617 { 00618 // create a new path using the internal data points. 00619 // If LastDragTo==LastMoveTo, then the internal is a point, 00620 // else a curve control end exists. 00621 if (EditHandles.pHndSpread==pSpread) 00622 { 00623 MakeInternal = FALSE; 00624 OpPenCreatePath* pOpCreatePath = new OpPenCreatePath; 00625 if (pOpCreatePath!=NULL) 00626 { 00627 pOpCreatePath->DoPenCreatePath(&EditHandles, PointerPos, pSpread, &EditPath); 00628 CurrPenOpState = OS_CreatePath; 00629 } 00630 } 00631 } 00632 00633 if (MakeInternal) 00634 { 00635 // First remove any selected points in the spread and create an 00636 // internal move or dragto 00637 RemoveSelection(PointerPos,pSpread); 00638 OpPenCreateInternal* pOpCreateInternal = new OpPenCreateInternal; 00639 if (pOpCreateInternal!=NULL) 00640 { 00641 pOpCreateInternal->DoPenCreateInternal(PointerPos, pSpread, &EditHandles); 00642 CurrPenOpState = OS_EditInternal; 00643 } 00644 } 00645 } 00646 break; 00647 00648 case PenClosePath: 00649 { 00650 NodeIndex = pNodePath->InkPath.GetPathPosition(); 00651 OpPenClosePath* pOpPenClosePath = new OpPenClosePath; 00652 if (pOpPenClosePath!=NULL) 00653 { 00654 pOpPenClosePath->DoPenClosePath(pNodePath, NodeIndex, pSpread, &EditPath); 00655 CurrPenOpState = OS_ClosePath; 00656 } 00657 } 00658 break; 00659 00660 case PenOnPoint: 00661 { 00662 // Ordinary click from OnPoint 00663 // Currently this does not work correctly because of eor'ing. The wrong 00664 // Eor blobs get put on by the node path click handler 00665 RemoveSelection(PointerPos,pSpread,pNodePath); 00666 ClickOnEndPoint(Click, ClickMods, pSpread, pNodePath); 00667 } 00668 break; 00669 00670 case PenAddSegment: 00671 { 00672 NodeIndex = pNodePath->InkPath.GetPathPosition(); 00673 OpPenAddElement* pOpPenAddElement = new OpPenAddElement; 00674 if (pOpPenAddElement!=NULL) 00675 { 00676 pOpPenAddElement->DoPenAddElement(pNodePath, NodeIndex, PointerPos, pSpread, &EditPath); 00677 CurrPenOpState = OS_AddElement; 00678 } 00679 } 00680 break; 00681 00682 case PenEditInternalMove: 00683 { 00684 OpPenEditInternal* pOpEditInternal = new OpPenEditInternal; 00685 if (pOpEditInternal!=NULL) 00686 { 00687 pOpEditInternal->DoPenEditInternal(&EditHandles); 00688 CurrPenOpState = OS_EditInternal; 00689 } 00690 } 00691 break; 00692 00693 case PenReshapeLine: 00694 { 00695 double pdist; 00696 INT32 tempel; 00697 pNodePath->InkPath.SqrDistanceToPoint(PointerPos, &tempel, &pdist); 00698 INT32 PathPos = pNodePath->InkPath.GetPathPosition(); 00699 00700 OpReshapeOrAddPoint* pOpReshape = new OpReshapeOrAddPoint; 00701 if (pOpReshape!=NULL) 00702 pOpReshape->DoStartDragEdit(pNodePath, PointerPos, pSpread, PathPos, pdist); 00703 else 00704 InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) ); 00705 } 00706 break; 00707 00708 } 00709 break; 00710 00711 case CLICKTYPE_DOUBLE: 00712 break; 00713 00714 case CLICKTYPE_DRAG: 00715 switch (WhatToDo) 00716 { 00717 case PenOnPoint: 00718 if (pNodePath) 00719 ClickOnEndPoint(Click, ClickMods, pSpread, pNodePath); 00720 break; 00721 00722 default: 00723 break; 00724 } 00725 break; 00726 00727 default: 00728 break; 00729 } 00730 00731 }
|
|
To handle keypress events for the Pen 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.
Reimplemented from Tool_v1. Definition at line 1034 of file pentool.cpp. 01035 { 01036 // We don't want to know about key release events 01037 if (pKeyPress->IsRelease()) 01038 return FALSE; 01039 01040 // If ESCAPE is pressed then clear the floating endpoint, but don't claim the keypress 01041 // so the selection is also cleared. 01042 if (*pKeyPress == KeyPress(CAMKEY(ESCAPE))) 01043 { 01044 if ((CurrPenState == IS_MoveTo) || (CurrPenState == IS_DragTo)) 01045 { 01046 ClearInternalState(); 01047 return TRUE; 01048 } 01049 } 01050 01051 // break at points op key short cut. 01052 if (*pKeyPress == KeyPress(CAMKEY(B))) 01053 { 01054 OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpBreakAtPoints)); 01055 String_256 UIDesc; 01056 if (pOpDesc != NULL) 01057 { 01058 OpState State = OpBreakAtPoints::GetState(&UIDesc, pOpDesc); 01059 if (!State.Greyed) 01060 { 01061 pOpDesc->Invoke(); 01062 return TRUE; 01063 } 01064 } 01065 } 01066 01067 // if delete pressed, try to delete the selected points in this path 01068 if ((pKeyPress->GetVirtKey() == CAMKEY(DELETE)) || (*pKeyPress == KeyPress(CAMKEY(BACK))) ) 01069 { 01070 OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpDeletePoints)); 01071 String_256 UIDesc; 01072 if (pOpDesc != NULL) 01073 { 01074 OpState State = OpDeletePoints::GetState(&UIDesc, NULL); 01075 if (!State.Greyed) 01076 { 01077 pOpDesc->Invoke(); 01078 return TRUE; 01079 } 01080 } 01081 } 01082 01083 // If we get this far then the keypress wasn't handled 01084 return FALSE; 01085 }
|
|
This routine is called whenever the mouse moves while we're in the pen tool. it sees what is under the pointer, and flips the cursor if clicking will have a different effect.
Reimplemented from Tool_v1. Definition at line 1107 of file pentool.cpp. 01108 { 01109 NodePath* pNodePath = NULL; 01110 Cursor* whichCursor = NULL; 01111 01112 // find what type of click we will generate 01113 penclick WhatToDo = DetermineClickEffect(coord, pSpread, &pNodePath); 01114 01115 String_256 StatusMsg(""); 01116 GenerateStatusLineText(pNodePath, WhatToDo, &StatusMsg); 01117 GetApplication()->UpdateStatusBarText(&StatusMsg); 01118 01119 switch (WhatToDo) 01120 { 01121 case PenNewPath: 01122 case PenAddSegment: 01123 case PenEditInternalMove: 01124 whichCursor = pcPenCursor; 01125 break; 01126 case PenOnPoint: 01127 whichCursor = pcMoveBezCursor; 01128 break; 01129 case PenClosePath: 01130 whichCursor = pcPenAdjustCursor; 01131 break; 01132 case PenReshapeLine: 01133 whichCursor = pcPenReshapeCursor; 01134 break; 01135 default: 01136 whichCursor = pcPenCursor; 01137 } 01138 ChangeCursor(whichCursor); 01139 }
|
|
|
|
This routine scans the specified spread for all path objects and checks whether the mouse coord is over an open end point. It can be used to work out whether to change the mouse shape or not. This routine should really exist in some other file, available to all tools but I dont know where to put it yet so it shall have to stay here for the mo.
Definition at line 1358 of file pentool.cpp. 01359 { 01360 // deselect any points within the spread the click occured over 01361 SelRange* Selected = GetApplication()->FindSelection(); 01362 Node* pNode = Selected->FindFirst(); 01363 if (pNode && pNode->FindParentSpread() == pSpread ) 01364 { 01365 while (pNode) 01366 { 01367 if (pNode!=pNodePath) 01368 { 01369 if (pNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodePath)) 01370 { 01371 Path* ThisPath = &(((NodePath*)pNode)->InkPath); 01372 PathFlags* Flags = ThisPath->GetFlagArray(); 01373 INT32 UsedSlots = ThisPath->GetNumCoords(); 01374 01375 BOOL selected = FALSE; 01376 for (INT32 i=0; i<UsedSlots; i++) 01377 { 01378 if (Flags[i].IsSelected) 01379 { 01380 if (!selected) 01381 { 01382 // right, red selection blobs off! 01383 ThisPath->RenderPathPenBlobs(pSpread); 01384 selected = TRUE; 01385 } 01386 Flags[i].IsSelected=FALSE; 01387 } 01388 } 01389 // now, black selection blobs back on! 01390 if (selected) 01391 ThisPath->RenderPathPenBlobs(pSpread); 01392 } 01393 } 01394 pNode = Selected->FindNext(pNode); 01395 } 01396 } 01397 }
|
|
The blobs this tool renders are (1) a moveto floating endpoint (2) a dragto floating endpoint These are usually rendered after the first click/drag on a document.
Reimplemented from Tool_v1. Definition at line 1417 of file pentool.cpp. 01418 { 01419 // Can only draw the path if there is a path to draw 01420 ERROR3IF(pSpread==NULL,"PenTool::RenderToolBlobs() called with a null spread"); 01421 01422 RenderRegion* pRegion; 01423 DocCoord LastMove = EditHandles.HndClick; 01424 DocCoord LastDrag = EditHandles.HndDrag; 01425 01426 switch (CurrPenState) 01427 { 01428 case IS_MoveTo: 01429 pRegion = DocView::RenderOnTop(pClipRect, pSpread, ClippedEOR); 01430 while (pRegion) 01431 { 01432 // Draw a moveto blob 01433 pRegion->SetLineColour(COLOUR_BEZIERBLOB); 01434 pRegion->SetFillColour(COLOUR_TRANS); 01435 pRegion->DrawBlob(LastMove,BT_SELECTED); 01436 01437 // Get the next region in the list 01438 pRegion = DocView::GetNextOnTop(pClipRect); 01439 } 01440 break; 01441 01442 case IS_DragTo: 01443 { 01444 pRegion = DocView::RenderOnTop(pClipRect, pSpread, ClippedEOR); 01445 DocCoord OtherDrag; 01446 OtherDrag.x = LastMove.x - (LastDrag.x - LastMove.x); 01447 OtherDrag.y = LastMove.y - (LastDrag.y - LastMove.y); 01448 01449 while (pRegion) 01450 { 01451 // Draw three end blobs and an eor'd dotted line 01452 pRegion->SetLineColour(COLOUR_BEZIERLINE); 01453 pRegion->DrawLine(OtherDrag,LastDrag); 01454 pRegion->SetLineColour(COLOUR_BEZIERBLOB); 01455 pRegion->SetFillColour(COLOUR_TRANS); 01456 pRegion->DrawBlob(LastMove,BT_SELECTED); 01457 pRegion->SetFillColour(COLOUR_UNSELECTEDBLOB); 01458 pRegion->SetLineColour(COLOUR_TRANS); 01459 pRegion->DrawBlob(LastDrag,BT_UNSELECTED); 01460 pRegion->DrawBlob(OtherDrag,BT_UNSELECTED); 01461 01462 // Get the next region in the list 01463 pRegion = DocView::GetNextOnTop(pClipRect); 01464 } 01465 break; 01466 } 01467 default: 01468 break; 01469 } 01470 }
|
|
Called when the tool is selected or deselected. Creates and pushes the tool's cursor; pops and destroys it.
Reimplemented from Tool_v1. Definition at line 319 of file pentool.cpp. 00320 { 00321 if (isSelected) 00322 { 00323 // This tool has just been selected. Create an appropriate cursor, and push it 00324 // onto the top of the cursor stack so it'll appear when the pointer moves into 00325 // our window. 00326 00327 MyCurrentCursor = NULL; 00328 00329 if (!CreatePenCursors()) 00330 return; 00331 00332 CurrentCursorID = CursorStack::GPush(pcPenCursor, FALSE); // Push, but don't display now 00333 MyCurrentCursor = pcPenCursor; 00334 00335 // Create and display my info bar please 00336 if (pPenInfoBarOp != NULL) 00337 pPenInfoBarOp->Create(); 00338 00339 // Which blobs do I want displayed 00340 BlobManager* BlobMgr = GetApplication()->GetBlobManager(); 00341 if (BlobMgr != NULL) 00342 { 00343 // Decide which blobs we will display 00344 BlobStyle MyBlobs; 00345 MyBlobs.Pen = TRUE; 00346 00347 // Tell the blob manager 00348 BlobMgr->ToolInterest(MyBlobs); 00349 } 00350 00351 // Now set some local variables so we know what state we are 00352 // in to start with 00353 CurrPenState = IS_Undefined; 00354 00355 // alias the delete function to delete points. 00356 // OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_DELETE); 00357 // pOpDesc->AliasOperation(CC_RUNTIME_CLASS(OpDeletePoints),OpDeletePoints::GetState,0); 00358 00359 // remove the alias to the delete function 00360 // OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_DELETE); 00361 // pOpDesc->RemoveAlias(); 00362 } 00363 else 00364 { 00365 // Deselection - destroy the tool's current cursor, if there is one. 00366 if (MyCurrentCursor) 00367 { 00368 CursorStack::GPop(CurrentCursorID); 00369 MyCurrentCursor = NULL; 00370 CurrentCursorID = 0; 00371 } 00372 DeletePenCursors(); 00373 00374 // Hide and destroy my info bar please 00375 if (pPenInfoBarOp != NULL) 00376 pPenInfoBarOp->Delete(); 00377 00378 // ensure any tool object blobs are removed. 00379 BlobManager* BlobMgr = GetApplication()->GetBlobManager(); 00380 if (BlobMgr != NULL) 00381 { 00382 BlobStyle bsRemoves; 00383 bsRemoves.ToolObject = TRUE; 00384 BlobMgr->RemoveInterest(bsRemoves); 00385 } 00386 00387 ClearInternalState(); 00388 } 00389 }
|
|
This function is called from an operation which tells the tool that there should be a virtual moveto coordinate and dragto coordinate set within the tool. If the dragto is equal to the moveto, then an internal move should be created, rather than an internal drag.
Definition at line 1523 of file pentool.cpp. 01524 { 01525 // Check that the handles are actually defined. 01526 if (EditHandles.pHndSpread==NULL) 01527 return; 01528 01529 if (EditHandles.HndClick == EditHandles.HndDrag) 01530 CurrPenState = IS_MoveTo; 01531 else 01532 CurrPenState = IS_DragTo; 01533 01534 // Now display the blobs 01535 BlobManager* BlobMgr = GetApplication()->GetBlobManager(); 01536 ENSURE(BlobMgr!=NULL, "Blob Manager was not there"); 01537 BlobMgr->RenderToolBlobsOn(this, EditHandles.pHndSpread, NULL); 01538 01539 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|