#include <penedit.h>
Inheritance diagram for OpClosePathWithPath:
Public Member Functions | |
OpClosePathWithPath () | |
OpClosePathWithPath constructor. | |
void | GetOpName (String_256 *OpName) |
The GetOpName fn is overridden so that we return back a description appropriate to the type of attribute that the operation applies. | |
void | DoClosePathWithPath (NodePath *pDestinNode, Path *pAddPath, INT32 index) |
This op takes as parameters a destination path being affected, and a source path which may be the result of a drag edit operation. The idea is that the op will take the components of the source path and add them in a deterministic way to the destination path, resulting in a closed destination path. The source path is assumed to have either 1 or 2 elements in it. The first element will be added to the end of the destination path and act as a closing piece. The second element of the source path will affect the first element in the destination path. If both elements match in type, ie are two curves, the none end control handles of the source will be copied to the destination. This op as can be seen is rather specific, and is used by the pen tool to close an open path. Imagine clicking on the first control point of a path and draging out control handles. The handles will affect the previous and next elements of the path. The previous being a close element and the next being the first element of the path. Hence the need for this strange op. | |
Static Public Member Functions | |
static BOOL | Init () |
OpClosePathWithPath initialiser method. | |
static OpState | GetState (String_256 *, OpDescriptor *) |
For finding the OpClosePathWithPath's state. |
Definition at line 614 of file penedit.h.
|
OpClosePathWithPath constructor.
Definition at line 2992 of file penedit.cpp.
|
|
This op takes as parameters a destination path being affected, and a source path which may be the result of a drag edit operation. The idea is that the op will take the components of the source path and add them in a deterministic way to the destination path, resulting in a closed destination path. The source path is assumed to have either 1 or 2 elements in it. The first element will be added to the end of the destination path and act as a closing piece. The second element of the source path will affect the first element in the destination path. If both elements match in type, ie are two curves, the none end control handles of the source will be copied to the destination. This op as can be seen is rather specific, and is used by the pen tool to close an open path. Imagine clicking on the first control point of a path and draging out control handles. The handles will affect the previous and next elements of the path. The previous being a close element and the next being the first element of the path. Hence the need for this strange op.
Definition at line 3111 of file penedit.cpp. 03112 { 03113 #ifndef STANDALONE 03114 03115 BeginSlowJob(); 03116 03117 DoStartSelOp(TRUE,TRUE); 03118 03119 DocView* pDocView = DocView::GetSelected(); 03120 ERROR2IF( pDocView == NULL, (void)0, "There was no selected doc view when closing a path" ); 03121 03122 // Save the bounds of the path for undo/redo 03123 if (RecalcBoundsAction::DoRecalc(this, &UndoActions, pDestinNode) == AC_FAIL) 03124 { 03125 FailAndExecute(); 03126 End(); 03127 return; 03128 } 03129 03130 // go and count the number of elements given to us in the edit path 03131 INT32 ind = 0; 03132 INT32 i; 03133 for (i=0; pEditPath->FindNext(&ind); i++); 03134 ENSURE(i<3, "There are two many elements in the edit path when closing a path" ); 03135 03136 if (i<1 || i>2) 03137 { 03138 FailAndExecute(); 03139 End(); 03140 return; 03141 } 03142 03143 // get a pointer to the destination path 03144 Path* pDestinPath = &(pDestinNode->InkPath); 03145 03146 // Get the arrays for these paths 03147 PathFlags* SFlags = pEditPath->GetFlagArray(); 03148 PathVerb* SVerbs = pEditPath->GetVerbArray(); 03149 PathVerb* DVerbs = pDestinPath->GetVerbArray(); 03150 03151 BOOL OnMove = (DVerbs[index] == PT_MOVETO); 03152 03153 INT32 SEnd = 0; 03154 pEditPath->FindEndOfSubPath(&SEnd); 03155 03156 if (i==2) 03157 { 03158 // if we have two elements in the path, go and affect the first element in 03159 // the destin path with the data held in the second element of the edit path 03160 // Er, this could be the other way around so watch out! 03161 03162 INT32 First = index; 03163 INT32 Second; 03164 03165 if (OnMove) 03166 { 03167 First++; 03168 Second = First+1; 03169 } 03170 else 03171 { 03172 First--; 03173 Second = First-1; 03174 } 03175 03176 // If the elements match in type, affect the destination 03177 if ((SVerbs[SEnd] == DVerbs[First]) && (DVerbs[First] == PT_BEZIERTO)) 03178 { 03179 03180 DocCoord* SCoords = pEditPath->GetCoordArray(); 03181 DocCoord* DCoords = pDestinPath->GetCoordArray(); 03182 PathFlags* DFlags = pDestinPath->GetFlagArray(); 03183 03184 ModifyElementAction* UnAction; 03185 ActionCode Act; 03186 03187 // Alter the moveto's flags 03188 Act = ModifyElementAction::Init(this, 03189 &UndoActions, 03190 DVerbs[index], 03191 DFlags[index], 03192 DCoords[index], 03193 index, 03194 pDestinNode, 03195 (Action**)&UnAction); 03196 if (Act == AC_FAIL) 03197 { 03198 FailAndExecute(); 03199 End(); 03200 return; 03201 } 03202 DFlags[index].IsRotate = TRUE; 03203 03204 // Move the first control point 03205 Act = ModifyElementAction::Init(this, 03206 &UndoActions, 03207 DVerbs[First], 03208 DFlags[First], 03209 DCoords[First], 03210 First, 03211 pDestinNode, 03212 (Action**)&UnAction); 03213 if (Act == AC_FAIL) 03214 { 03215 FailAndExecute(); 03216 End(); 03217 return; 03218 } 03219 DCoords[First] = SCoords[SEnd]; 03220 DFlags[First].IsRotate = TRUE; 03221 03222 // Move the second control point 03223 Act = ModifyElementAction::Init(this, 03224 &UndoActions, 03225 DVerbs[Second], 03226 DFlags[Second], 03227 DCoords[Second], 03228 Second, 03229 pDestinNode, 03230 (Action**)&UnAction); 03231 if (Act == AC_FAIL) 03232 { 03233 FailAndExecute(); 03234 End(); 03235 return; 03236 } 03237 DCoords[Second] = SCoords[SEnd+1]; 03238 DFlags[Second].IsRotate = TRUE; 03239 } 03240 03241 // now bin the last element of the path 03242 pEditPath->DeleteFromElement(SEnd); 03243 } 03244 03245 INT32 DStart = index; 03246 INT32 DEnd = index; 03247 pDestinPath->FindStartOfSubPath(&DStart); 03248 pDestinPath->FindEndElOfSubPath(&DEnd); 03249 03250 if (!OnMove) 03251 { 03252 // if OnMove is false ie someone is closing a curve from the 03253 // selected moveto backwards, then we need to deselect the moveto 03254 // element and reverse the path. 03255 03256 ActionCode Act = DeselectHandle(pDestinNode, DStart); 03257 if (Act == AC_FAIL) 03258 { 03259 FailAndExecute(); 03260 End(); 03261 return; 03262 } 03263 pEditPath->Reverse(); 03264 } 03265 03266 // set a close figure on the element we're about to add and bin any selection 03267 SEnd = (pEditPath->GetNumCoords())-1; 03268 SVerbs[SEnd] = SVerbs[SEnd] | PT_CLOSEFIGURE; 03269 SFlags[SEnd].IsSelected = FALSE; 03270 03271 // now set the filled bit on the path to make sure it really does 03272 // get filled once closed. 03273 ModifyFilledAction* pAction; 03274 03275 if (ModifyFilledAction::Init(this, &UndoActions, TRUE, FALSE, pDestinNode, (Action**)(&pAction))== AC_FAIL) 03276 { 03277 FailAndExecute(); 03278 End(); 03279 return; 03280 } 03281 03282 pDestinNode->InkPath.IsFilled = TRUE; 03283 03284 // Go and copy the edited path to the end of the original 03285 ExecuteType Exe = AugmentPathWithPath(pEditPath, pDestinNode, DEnd); 03286 if (Exe != ExeNone) 03287 { 03288 InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) ); 03289 if (Exe == ExeInclusive) 03290 FailAndExecute(); 03291 if (Exe == ExeExclusive) 03292 FailAndExecuteAllButLast(); 03293 End(); 03294 return; 03295 } 03296 03297 // Recalculate the path's bounding box 03298 pDestinNode->InvalidateBoundingRect(); 03299 03300 // tell the world that something in the selection has changed 03301 // so that selection bounds are updated 03302 GetApplication()->FindSelection()->Update(TRUE); 03303 03304 // record new bounds action undo/redo 03305 if (RecordBoundsAction::DoRecord(this, &UndoActions, pDestinNode) == AC_FAIL) 03306 { 03307 FailAndExecute(); 03308 End(); 03309 return; 03310 } 03311 03312 #endif 03313 03314 End(); 03315 }
|
|
The GetOpName fn is overridden so that we return back a description appropriate to the type of attribute that the operation applies.
Reimplemented from Operation. Definition at line 3070 of file penedit.cpp. 03071 { 03072 *OpName = String_256(_R(IDS_UNDO_CLOSEPATHWITHPATHOP)); 03073 }
|
|
For finding the OpClosePathWithPath's state.
Definition at line 3046 of file penedit.cpp. 03047 { 03048 OpState OpSt; 03049 return OpSt; 03050 }
|
|
OpClosePathWithPath initialiser method.
Reimplemented from SimpleCCObject. Definition at line 3016 of file penedit.cpp. 03017 { 03018 return (RegisterOpDescriptor(0, // tool ID 03019 _R(IDS_CLOSEPATHWITHPATHOP), // string resource ID 03020 CC_RUNTIME_CLASS(OpClosePathWithPath), // runtime class for Op 03021 OPTOKEN_CLOSEPATHWITHPATH, // Ptr to token string 03022 OpClosePathWithPath::GetState, // GetState function 03023 0, // help ID = 0 03024 _R(IDBBL_CLOSEPATHWITHPATHOP), // bubble help ID = 0 03025 0 // resource ID = 0 03026 )); 03027 03028 }
|