00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 #include "camtypes.h"
00104 #include "pathops.h"
00105                                 
00106 
00107 
00108 
00109 #include "nodepath.h"                                       
00110 #include "pathedit.h"
00111 #include "objchge.h"
00112 
00113 #include "progress.h"
00114 
00115 
00116 
00117 DECLARE_SOURCE("$Revision: 1282 $");
00118 
00119 CC_IMPLEMENT_DYNCREATE( OpBaseConvertPathSegment, SelOperation)
00120 CC_IMPLEMENT_DYNCREATE( OpMakeSegmentsCurves, OpBaseConvertPathSegment)
00121 CC_IMPLEMENT_DYNCREATE( OpMakeSegmentsLines, OpBaseConvertPathSegment)
00122 CC_IMPLEMENT_DYNCREATE( OpReversePath, SelOperation)
00123 CC_IMPLEMENT_DYNCREATE( OpMovePathPoint, TransOperation)
00124 CC_IMPLEMENT_DYNCREATE( OpMenuSelectPathPoints, Operation)
00125 CC_IMPLEMENT_DYNCREATE( OpSelectAllPathPoints, OpMenuSelectPathPoints)
00126 CC_IMPLEMENT_DYNCREATE( OpDeSelectAllPathPoints, OpMenuSelectPathPoints)
00127 
00128 CC_IMPLEMENT_DYNAMIC( NewPathCreatedMsg, Msg)
00129 CC_IMPLEMENT_DYNAMIC( PathEditedMsg, Msg)
00130 CC_IMPLEMENT_MEMDUMP( MovePointsParams, OpParam)
00131 
00132 
00133 #define new CAM_DEBUG_NEW
00134 
00135 
00136 
00137 
00138 
00139 
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 NewPathCreatedMsg::NewPathCreatedMsg(NodePath* pPath, Operation* CurOp, ActionList* Undos)                          
00149 {                              
00150     CurrentOp = CurOp;
00151     NewPath = pPath;    
00152     UndoActs = Undos;
00153 }
00154 
00155 
00156 
00157 
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166 
00167 
00168 PathEditedMsg::	PathEditedMsg(Path* pPath, Spread* pSpread, INT32 Index)
00169                             
00170 {                              
00171     EditPath = pPath;
00172     EditSpread = pSpread;
00173     EndPoint = Index;
00174 }
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 
00185 OpBaseConvertPathSegment::OpBaseConvertPathSegment(): SelOperation()                                
00186 {                              
00187 }
00188 
00189 
00190 
00191 
00192 
00193 
00194 
00195 
00196 
00197 
00198 
00199 
00200 
00201 OpState OpBaseConvertPathSegment::BaseGetState(INT32 PathType)
00202 {
00203     OpState OpSt;
00204 
00205 #ifndef STANDALONE
00206 
00207     SelRange*   Selected = GetApplication()->FindSelection();
00208 
00209     if ((Document::GetSelected() == NULL) || (Selected == NULL) )
00210     {   
00211         OpSt.Greyed = TRUE;
00212         return OpSt;                                 
00213     }
00214 
00215     Node*   pNode = Selected->FindFirst();
00216     BOOL    FoundSegment = FALSE;
00217     BOOL    AllConverted = TRUE;
00218     BOOL    PrevSelected = FALSE;
00219 
00220     while ((pNode != NULL) && AllConverted)
00221     {
00222         if (pNode->IsNodePath() && ((NodePath*)pNode)->IsPathAllowable())
00223         {
00224             Path* ThisPath = &(((NodePath*)pNode)->InkPath);
00225             PathFlags* Flags = ThisPath->GetFlagArray();
00226             PathVerb* Verbs = ThisPath->GetVerbArray();
00227             INT32 UsedSlots = ThisPath->GetNumCoords();
00228             PrevSelected = FALSE;
00229 
00230             for (INT32 i=0; i<UsedSlots; i++)
00231             {
00232                 if (Flags[i].IsEndPoint)
00233                 {
00234                     if (Flags[i].IsSelected)
00235                     {
00236                         if (PrevSelected && ((Verbs[i] & ~PT_CLOSEFIGURE) != PT_MOVETO) )
00237                         {
00238                             FoundSegment = TRUE;
00239                             if ((Verbs[i] & ~PT_CLOSEFIGURE) != PathType)
00240                                 AllConverted = FALSE;
00241                         }
00242                         PrevSelected = TRUE;
00243                     }
00244                     else                            
00245                     {
00246                         PrevSelected = FALSE;
00247                     }
00248                 }
00249             }
00250         }
00251         pNode = Selected->FindNext(pNode);
00252     }
00253 
00254     OpSt.Greyed = !FoundSegment;
00255     OpSt.Ticked = AllConverted && FoundSegment;
00256 
00257 #endif  // #ifdef STANDALONE
00258 
00259     return OpSt;
00260 }
00261 
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269 
00270 
00271 
00272 
00273 
00274 
00275 void OpBaseConvertPathSegment::Do(OpDescriptor*)
00276 {   
00277 #ifndef STANDALONE
00278 
00279     
00280     SelRange* Selected = GetApplication()->FindSelection();
00281     BOOL ok = (Selected != NULL);
00282 
00283     
00284     BeginSlowJob();
00285     if (ok)
00286         ok = DoStartSelOp(TRUE,TRUE);
00287 
00288     
00289     ObjChangeFlags cFlags;
00290     ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
00291     if (ok)
00292     {
00293         if (!Selected->AllowOp(&ObjChange))
00294         {
00295             EndSlowJob();
00296             FailAndExecute();
00297             End();
00298             return;
00299         }
00300     }
00301 
00302     Node* pNode = Selected->FindFirst();
00303     NodePath* ThisPath = NULL;
00304 
00305     while (ok && (pNode != NULL))
00306     {   
00307         BOOL DoThisNode = pNode->IsNodePath();
00308         if (DoThisNode)
00309             DoThisNode = (((NodePath*)pNode)->InkPath.IsSubSelection());
00310         if (DoThisNode)
00311             DoThisNode = (((NodePath*)pNode)->IsPathAllowable());
00312 
00313         if  ( DoThisNode )
00314         {
00315             
00316             ThisPath = (NodePath*)pNode;
00317 
00318             
00319             PathVerb* Verbs = NULL;
00320             PathFlags* Flags = NULL;
00321             DocCoord* Coords = NULL;
00322             ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
00323             INT32 NumCoords = ThisPath->InkPath.GetNumCoords();
00324             BOOL PrevSelected = FALSE;
00325             INT32 PrevPos = 0;
00326 
00327             
00328             INT32       loop;
00329             for (loop = 0; loop < NumCoords; loop++)
00330             {
00331                 if (Flags[loop].IsEndPoint && Flags[loop].IsSelected)
00332                     Flags[loop].NeedToRender = TRUE;
00333                 else
00334                     Flags[loop].NeedToRender = FALSE;
00335             }
00336 
00337             
00338             if (ok)
00339                 ok = (RecalcBoundsAction::DoRecalc(this, &UndoActions, ThisPath, TRUE) != AC_FAIL);
00340 
00341             
00342             for (loop = 0; loop<NumCoords; loop++)
00343             {
00344                 if (Flags[loop].IsEndPoint)
00345                 {   
00346                     if (Flags[loop].IsSelected)
00347                     {   
00348                         if (PrevSelected && ((Verbs[loop] & ~PT_CLOSEFIGURE) == GetProcessPathType()) )
00349                         {   
00350                             if (ok)
00351                                 ok = ProcessSegment(ThisPath, &loop, PrevPos);
00352                             
00353                             ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
00354                             NumCoords = ThisPath->InkPath.GetNumCoords();
00355                             Flags[loop].NeedToRender = TRUE;
00356                         }
00357                         PrevSelected = TRUE;
00358                         PrevPos = loop;
00359                     }
00360                     else
00361                         PrevSelected = FALSE;
00362                 }
00363             }
00364 
00365             
00366             DocCoord NewCoord;
00367             for (loop = 0; (ok && (loop < NumCoords)); loop++)
00368             {
00369                 if (Verbs[loop] == PT_BEZIERTO && !(Flags[loop].IsEndPoint) && Flags[loop].IsSmooth)
00370                 {
00371                     NewCoord = ThisPath->InkPath.SmoothControlPoint(loop);
00372                     if (ok && (NewCoord != Coords[loop]))
00373                     {
00374                         ok = DoAlterPathElement(ThisPath, loop, NewCoord, Flags[loop], Verbs[loop], FALSE);
00375                         ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
00376                     }
00377                 }
00378             }
00379 
00380             ThisPath->InvalidateBoundingRect();
00381 
00382             
00383             if (ok)
00384                 ok = (RecordBoundsAction::DoRecord(this, &UndoActions, ThisPath, TRUE) != AC_FAIL);
00385         }
00386         pNode = Selected->FindNext(pNode);
00387     }
00388 
00389     if (ok)
00390     {
00391         ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this);
00392         if (!UpdateChangedNodes(&ObjChange))
00393         {
00394             FailAndExecute();
00395             End();
00396             return;
00397         }
00398     }
00399 
00400     EndSlowJob();
00401 
00402     if (!ok)
00403     {   
00404         FailAndExecute();
00405         InformError();
00406     }
00407 
00408 #endif
00409 
00410     End();
00411 }
00412 
00413 
00414 
00415 
00416 
00417 
00418 
00419 
00420 
00421 
00422 
00423 
00424 OpMakeSegmentsLines::OpMakeSegmentsLines()
00425 {                              
00426 }
00427 
00428 
00429 
00430  
00431 
00432 
00433 
00434 
00435 
00436 
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 BOOL OpMakeSegmentsLines::Init()
00445 {
00446     return (RegisterOpDescriptor(   0, 
00447                                     _R(IDS_MAKELINES),
00448                                     CC_RUNTIME_CLASS(OpMakeSegmentsLines), 
00449                                     OPTOKEN_MAKELINESOP,
00450                                     OpMakeSegmentsLines::GetState,
00451                                     0,  
00452                                     _R(IDBBL_MAKELINES),
00453                                     0   ));
00454 }               
00455 
00456 
00457 
00458 OpState OpMakeSegmentsLines::GetState(String_256*, OpDescriptor*)
00459 {
00460     return OpBaseConvertPathSegment::BaseGetState(PT_LINETO);
00461 }
00462 
00463 
00464 
00465 
00466 
00467 
00468 
00469 
00470 
00471 
00472 
00473 
00474 
00475 
00476 
00477 
00478 
00479 BOOL OpMakeSegmentsLines::ProcessSegment(NodePath* pPath, INT32* Index, INT32 PrevIndex)
00480 {
00481     
00482     PathVerb* Verbs;
00483     PathFlags* Flags;
00484     DocCoord* Coords;
00485     pPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
00486 
00487     
00488     ERROR2IF(((Verbs[*Index] & ~PT_CLOSEFIGURE) != PT_BEZIERTO), FALSE, "Unknown segment encountered");
00489     ERROR2IF(((PrevIndex+3) != *Index), FALSE, "Not two points between segment start and end");
00490 
00491 
00492 
00493     DocCoord EndCoord = Coords[*Index];
00494     PathFlags EndFlags = Flags[*Index];
00495     PathVerb NewEndVerb = Verbs[*Index];
00496     NewEndVerb = (NewEndVerb == PT_BEZIERTO) ? PT_LINETO : PT_LINETO | PT_CLOSEFIGURE;
00497 
00498     BOOL DoneOK = TRUE;
00499 
00500     
00501     if (DoneOK)
00502         DoneOK = DoInsertPathElement(pPath, PrevIndex, EndCoord, EndFlags, NewEndVerb, FALSE);
00503 
00504     
00505     if (DoneOK)
00506         DoneOK = DoDeletePathSection(pPath, PrevIndex+2, 3, FALSE);
00507 
00508     *Index = PrevIndex+1;
00509 
00510     return DoneOK;
00511 }
00512 
00513 
00514 
00515 
00516 
00517 
00518 
00519 
00520 
00521 
00522 
00523 
00524 OpMakeSegmentsCurves::OpMakeSegmentsCurves()
00525 {                              
00526 }
00527 
00528 
00529 
00530 
00531 
00532 
00533 
00534 
00535 
00536 
00537 
00538 
00539 
00540 
00541 
00542 
00543 
00544 BOOL OpMakeSegmentsCurves::Init()
00545 {
00546     return (RegisterOpDescriptor(   0, 
00547                                     _R(IDS_MAKECURVES),
00548                                     CC_RUNTIME_CLASS(OpMakeSegmentsCurves), 
00549                                     OPTOKEN_MAKECURVESOP,
00550                                     OpMakeSegmentsCurves::GetState,
00551                                     0,  
00552                                     _R(IDBBL_MAKELINES),
00553                                     0   ));
00554 }               
00555 
00556 
00557 
00558 OpState OpMakeSegmentsCurves::GetState(String_256*, OpDescriptor*)
00559 {
00560       return OpBaseConvertPathSegment::BaseGetState(PT_BEZIERTO);
00561 }
00562     
00563 
00564 
00565 
00566 
00567 
00568 
00569 
00570 
00571 
00572 
00573 
00574 
00575 
00576 
00577 
00578 
00579 BOOL OpMakeSegmentsCurves::ProcessSegment(NodePath* pPath, INT32* Index, INT32 PrevIndex)
00580 {
00581     
00582     PathVerb* Verbs;
00583     PathFlags* Flags;
00584     DocCoord* Coords;
00585     pPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
00586 
00587     
00588     ERROR2IF(((Verbs[*Index] & ~PT_CLOSEFIGURE) != PT_LINETO), FALSE, "Unknown segment encountered");
00589     ERROR2IF(((PrevIndex+1) != *Index), FALSE, "Points between segment start and end");
00590 
00591     BOOL ok = CarryOut(*Index, PrevIndex, pPath, this, &UndoActions);
00592     *Index = PrevIndex + 3;
00593 
00594     return ok;
00595 }
00596 
00597 
00598 
00599 
00600 
00601 
00602 
00603 
00604 
00605 
00606 
00607 
00608 
00609 
00610 
00611 
00612 
00613 
00614 
00615 
00616 
00617 
00618 BOOL OpMakeSegmentsCurves::CarryOut(INT32 Count, INT32 PrevPos, NodePath* ThisPath, 
00619                                         UndoableOperation* pOp, ActionList* pActions)
00620 {
00621 #ifndef STANDALONE
00622 
00623     ERROR2IF(pOp == NULL,FALSE, "Operation pointer was NULL");
00624     ERROR2IF(ThisPath == NULL,FALSE, "Path pointer was NULL");
00625 
00626     DocCoord* Coords = ThisPath->InkPath.GetCoordArray();
00627 
00628     PathVerb* Verbs = ThisPath->InkPath.GetVerbArray();
00629 
00630     DocCoord    First;
00631     DocCoord    Second;
00632     PathFlags   NewFlags;
00633     NewFlags.IsEndPoint = FALSE; 
00634     NewFlags.NeedToRender = FALSE; 
00635     NewFlags.IsSelected = TRUE;
00636     NewFlags.IsSmooth = TRUE;
00637     NewFlags.IsRotate = TRUE;
00638 
00639 
00640 
00641 
00642     First.x = Coords[PrevPos].x-(Coords[PrevPos].x-Coords[Count].x)/3;    
00643     First.y = Coords[PrevPos].y-(Coords[PrevPos].y-Coords[Count].y)/3;
00644     Second.x = Coords[PrevPos].x-((Coords[PrevPos].x-Coords[Count].x)/3)*2;   
00645     Second.y = Coords[PrevPos].y-((Coords[PrevPos].y-Coords[Count].y)/3)*2;
00646 
00647     PathVerb EndVerb = Verbs[Count];
00648     DocCoord EndCoord = Coords[Count];
00649 
00650     ERROR2IF((EndVerb & ~PT_CLOSEFIGURE) != PT_LINETO, FALSE, "Attempt to convert a non-line to a curve!");
00651 
00652     EndVerb = ((EndVerb & PT_CLOSEFIGURE) | PT_BEZIERTO) ;
00653 
00654     
00655     BOOL DoneOK  = TRUE;
00656 
00657     
00658     if (DoneOK)
00659     {
00660         if ((PrevPos+2) >= ThisPath->InkPath.GetNumCoords())
00661         {
00662             DoneOK = ThisPath->InkPath.AddCurveTo(First, Second, EndCoord, &NewFlags);
00663         }
00664         else
00665         {
00666             ThisPath->InkPath.SetPathPosition(PrevPos+2);
00667             DoneOK = ThisPath->InkPath.InsertCurveTo(First, Second, EndCoord, &NewFlags);
00668         }
00669     }
00670 
00671     
00672     if (DoneOK)
00673     {
00674         Verbs = ThisPath->InkPath.GetVerbArray();
00675         Verbs[PrevPos+4] = EndVerb;
00676     }
00677 
00678     
00679     if (DoneOK)
00680     {
00681         Action* UnAction;           
00682         ActionCode Act;             
00683         Act = RemovePathElementAction::Init(pOp, pActions, 3, PrevPos+2, (Action**)(&UnAction));
00684         if (Act == AC_OK)
00685             ((RemovePathElementAction*)UnAction)->RecordPath(ThisPath);
00686         DoneOK = !(Act == AC_FAIL);
00687     }
00688 
00689     
00690     if (DoneOK)
00691         DoneOK = pOp->DoDeletePathSection(ThisPath, PrevPos+1, 1, FALSE);
00692 
00693     return DoneOK;
00694 
00695 #else
00696     return TRUE;
00697 #endif
00698 }
00699 
00700 
00701 
00702 
00703 
00704 
00705 
00706 
00707 
00708 
00709 
00710 
00711 OpMovePathPoint::OpMovePathPoint(): TransOperation()                                
00712 {                              
00713 }
00714 
00715 
00716 
00717  
00718 
00719 
00720 
00721 
00722 
00723 
00724 
00725 
00726 
00727 
00728 
00729 
00730 
00731 BOOL OpMovePathPoint::Init()
00732 {
00733     return (RegisterOpDescriptor(   0, 
00734                                     _R(IDS_MOVEPATHPOINT),
00735                                     CC_RUNTIME_CLASS(OpMovePathPoint), 
00736                                     OPTOKEN_MOVEPATHPOINT,
00737                                     OpMovePathPoint::GetState,
00738                                     0,  
00739                                     _R(IDBBL_MOVEPATHPOINT),
00740                                     0   ));
00741 }               
00742     
00743 
00744 
00745 
00746 
00747 
00748 
00749 
00750 
00751 
00752 
00753 
00754 
00755 OpState OpMovePathPoint::GetState(String_256* UIDescription, OpDescriptor* fred)
00756 {
00757     OpState OpSt;
00758 
00759     return(OpSt);   
00760 }
00761 
00762 
00763 
00764 
00765 
00766 
00767 
00768 
00769 
00770 
00771 
00772 
00773 
00774 
00775 
00776 
00777 void OpMovePathPoint::DoWithParam(OpDescriptor* Fred, OpParam* Params)
00778 {
00779     
00780     MovePointsParams*   MyParams = (MovePointsParams*)Params;
00781 
00782     ERROR3IF(MyParams == NULL, "Parameter block pointer was NULL");
00783     ERROR3IF(MyParams->ChangesCount == 0, "No elements to alter!");
00784     ERROR3IF(MyParams->PathChanges == NULL, "No changes data supplied (NULL pointer passed)");
00785     ERROR3IF(MyParams->PathToEdit == NULL, "No changes path supplied (NULL pointer passed)");
00786 
00787     
00788     if ( (MyParams == NULL) || (MyParams->ChangesCount == 0) || (MyParams->PathChanges == NULL)
00789                                                                 || (MyParams->PathToEdit == NULL) )
00790     {
00791         End();
00792         return;
00793     }
00794 
00795     
00796     PathFlags*  Flags = MyParams->PathToEdit->InkPath.GetFlagArray();
00797     PathVerb*   Verbs = MyParams->PathToEdit->InkPath.GetVerbArray();
00798     DocCoord*   Coords= MyParams->PathToEdit->InkPath.GetCoordArray();
00799     INT32       NumElements = MyParams->PathToEdit->InkPath.GetNumCoords();
00800     BOOL        NotFailed = TRUE;
00801 
00802     
00803     if (!DoStartTransOp(FALSE,MyParams->PathToEdit))
00804     {
00805         FailAndExecute();
00806         End();                              
00807         return;
00808     }
00809 
00810     for (INT32 Loop = 0; (Loop < MyParams->ChangesCount) && NotFailed; Loop++)
00811     {
00812         
00813         INT32 Index = MyParams->PathChanges[Loop].Element;
00814         DocCoord NewCoord = MyParams->PathChanges[Loop].Coordinate;
00815 
00816         ERROR3IF(((Index >= NumElements) || (Index < 0)), "Invalid index into path (either -ve or off end of path)");
00817         if ((Index >= NumElements) || (Index < 0))
00818         {
00819             FailAndExecute();
00820             End();                              
00821             return;
00822         }
00823 
00824         
00825         INT32 EndOfSubPathIndex = Index;
00826         MyParams->PathToEdit->InkPath.FindEndElOfSubPath(&EndOfSubPathIndex);
00827         INT32 StartOfSubPathIndex = EndOfSubPathIndex;
00828         while ((Verbs[StartOfSubPathIndex] != PT_MOVETO) && (StartOfSubPathIndex > 0))
00829             StartOfSubPathIndex--;
00830         BOOL IsSubPathClosed = (Verbs[EndOfSubPathIndex] & PT_CLOSEFIGURE);
00831 
00832         
00833         NotFailed = DoAlterPathElement(MyParams->PathToEdit, Index, NewCoord, Flags[Index], Verbs[Index]);
00834     
00835         
00836         
00837         if ( NotFailed && IsSubPathClosed )
00838         {
00839             if (Index == EndOfSubPathIndex)
00840             {
00841                 NotFailed = DoAlterPathElement(MyParams->PathToEdit, StartOfSubPathIndex, NewCoord,
00842                                                 Flags[StartOfSubPathIndex], Verbs[StartOfSubPathIndex]);
00843             }
00844             if (Index == StartOfSubPathIndex)
00845             {
00846                 NotFailed = DoAlterPathElement(MyParams->PathToEdit, EndOfSubPathIndex, NewCoord,
00847                                                     Flags[EndOfSubPathIndex], Verbs[EndOfSubPathIndex]);
00848             }
00849         }
00850 
00851         
00852         
00853         
00854         if (NotFailed && ( (Verbs[Index] == PT_BEZIERTO) && !Flags[Index].IsEndPoint) )
00855         {
00856             INT32 BezEndpoint = -1;
00857 
00858             if ((Verbs[Index+1] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
00859                 BezEndpoint = Index + 1;
00860             else
00861             {
00862                 ERROR3IF(((Verbs[Index-1] & ~PT_CLOSEFIGURE) != PT_BEZIERTO),"Invalid path detected");
00863                 if ((Verbs[Index-1] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
00864                     BezEndpoint = Index - 1;
00865                 else
00866                     NotFailed = FALSE;
00867             }
00868 
00869             
00870             if (NotFailed)
00871             {
00872                 NotFailed = ClearSmoothAndRotate(MyParams->PathToEdit,BezEndpoint);
00873             }
00874 
00875             
00876             if (NotFailed && IsSubPathClosed)
00877             {
00878                 if ( (Index == EndOfSubPathIndex-1) || (Index == EndOfSubPathIndex+1) )
00879                     NotFailed = ClearSmoothAndRotate(MyParams->PathToEdit,StartOfSubPathIndex);
00880                 if ( (Index == StartOfSubPathIndex-1) || (Index == StartOfSubPathIndex+1) )
00881                     NotFailed = ClearSmoothAndRotate(MyParams->PathToEdit,EndOfSubPathIndex);
00882             }
00883 
00884             
00885             if (NotFailed)
00886             {
00887                 NotFailed = ClearSmoothAndRotate(MyParams->PathToEdit,Index);
00888             }
00889 
00890             
00891             if (NotFailed)
00892             {
00893                 INT32 OtherControlPoint = MyParams->PathToEdit->InkPath.FindOppositeControlPoint(Index);
00894                 if (OtherControlPoint != -1)
00895                 {
00896                     NotFailed = ClearSmoothAndRotate(MyParams->PathToEdit,OtherControlPoint);
00897                 }
00898             }
00899         }
00900     }
00901 
00902     
00903     if (NotFailed)
00904     {
00905         DocCoord NewCoord;
00906         for (INT32 i = 0; (i < NumElements) && NotFailed; i++)
00907         {
00908             if (Verbs[i] == PT_BEZIERTO && !(Flags[i].IsEndPoint) && Flags[i].IsSmooth)
00909             {
00910                 NewCoord = MyParams->PathToEdit->InkPath.SmoothControlPoint(i);
00911                 if (NewCoord != Coords[i])
00912                     NotFailed = DoAlterPathElement(MyParams->PathToEdit, i, NewCoord, Flags[i], Verbs[i]);
00913             }
00914         }
00915     }
00916 
00917     if (NotFailed)
00918         GetApplication()->FindSelection()->UpdateBounds();
00919 
00920     if (!NotFailed)
00921     {
00922         InformError();
00923         FailAndExecute();
00924     }
00925 
00926     End();
00927 }
00928 
00929 
00930 
00931 
00932 
00933 
00934 
00935 
00936 
00937 
00938 
00939 
00940 
00941 
00942 
00943 
00944 
00945 
00946 
00947 BOOL OpMovePathPoint::ClearSmoothAndRotate(NodePath* pPath, INT32 PathIndex)
00948 {
00949     PathFlags*  Flags = pPath->InkPath.GetFlagArray();
00950     PathVerb*   Verbs = pPath->InkPath.GetVerbArray();
00951     DocCoord*   Coords= pPath->InkPath.GetCoordArray();
00952 
00953     PathFlags tFlags = Flags[PathIndex];
00954     tFlags.IsSmooth = FALSE;
00955     tFlags.IsRotate = FALSE;
00956     return DoAlterPathElement(pPath, PathIndex, Coords[PathIndex], tFlags, Verbs[PathIndex]);
00957 }
00958 
00959 
00960 
00961 
00962 
00963 
00964 
00965 
00966 
00967 
00968 
00969 
00970 
00971 
00972 
00973 
00974 MovePointsParams::MovePointsParams(NodePath* pPath, ElementCoord* ChangeData, INT32 NumChanges) : OpParam( INT32(0), INT32(0) ) \
00975 { 
00976     PathToEdit = pPath;
00977     PathChanges = ChangeData;
00978     ChangesCount = NumChanges;
00979 };
00980 
00981 
00982 
00984 
00985 
00986 
00987 
00988 
00989 
00990 
00991 
00992 
00993 
00994 
00995 
00996 
00997 
00998 BOOL OpMenuSelectPathPoints::Init() 
00999 {
01000     BOOL ok = RegisterOpDescriptor( 0, 
01001                                     _R(IDS_SELECTALLPATHPOINTS),
01002                                     CC_RUNTIME_CLASS(OpSelectAllPathPoints), 
01003                                     OPTOKEN_SELECTALLPATHPOINTS,
01004                                     OpMenuSelectPathPoints::GetState);
01005 
01006     if (ok)
01007         ok = RegisterOpDescriptor(  0, 
01008                                     _R(IDS_DESELECTALLPATHPOINTS),
01009                                     CC_RUNTIME_CLASS(OpDeSelectAllPathPoints), 
01010                                     OPTOKEN_DESELECTALLPATHPOINTS,
01011                                     OpMenuSelectPathPoints::GetState);
01012 
01013     return ok;
01014 }
01015 
01016 
01017 
01018 
01019 
01020 
01021 
01022 
01023 
01024 
01025 
01026 
01027 
01028 
01029 OpState OpMenuSelectPathPoints::GetState(String_256*, OpDescriptor*)
01030 {
01031     OpState Banana;
01032 
01033     return Banana;      
01034 }
01035 
01036 
01037 
01038 
01039 
01040 
01041 
01042 
01043 
01044 
01045 
01046 
01047 
01048 
01049 
01050 
01051 BOOL OpMenuSelectPathPoints::DoAction(BOOL SelectPoints)
01052 {
01053     SelRange* pSelection = GetApplication()->FindSelection();
01054     Node* pNode = pSelection->FindFirst();
01055 
01056     
01057     while (pNode != NULL)
01058     {
01059         if (pNode->IsNodePath())
01060         {
01061             NodePath* pPath = (NodePath*)pNode;
01062             Spread* pSpread = pNode->FindParentSpread();
01063             ERROR2IF(pSpread == NULL, FALSE, "NodePath didn't have a parent spread");
01064 
01065             
01066             RenderRegion* pRegion = DocView::RenderOnTop(NULL, pSpread, ClippedEOR);
01067             while (pRegion != NULL)
01068             {
01069                 pPath->RenderObjectBlobs(pRegion);
01070                 pRegion = DocView::GetNextOnTop(NULL);
01071             }
01072             
01073             
01074             const INT32 NumCoords = pPath->InkPath.GetNumCoords();
01075             for (INT32 loop = 0; loop<NumCoords; loop++)
01076             {
01077                 pPath->InkPath.GetFlagArray()[loop].IsSelected = SelectPoints;
01078             }
01079 
01080             
01081             pRegion = DocView::RenderOnTop(NULL, pSpread, ClippedEOR);
01082             while (pRegion != NULL)
01083             {
01084                 pPath->RenderObjectBlobs(pRegion);
01085                 pRegion = DocView::GetNextOnTop(NULL);
01086             }
01087 
01088             GetApplication()->UpdateSelection();
01089         }
01090 
01091         pNode = pSelection->FindNext(pNode);
01092     }
01093 
01094     return TRUE;
01095 }   
01096 
01097 
01098 
01099 
01100 
01101 
01102 
01103 
01104 
01105 
01106 
01107 
01108 
01109 
01110 void OpSelectAllPathPoints::Do(OpDescriptor*)
01111 {
01112     if (!DoAction(TRUE))
01113         InformError();
01114 
01115     End();
01116 }
01117 
01118 
01119 
01120 
01121 
01122 
01123 
01124 
01125 
01126 
01127 
01128 
01129 
01130 
01131 void OpDeSelectAllPathPoints::Do(OpDescriptor*)
01132 {
01133     if (!DoAction(FALSE))
01134         InformError();
01135 
01136     End();
01137 }
01138 
01139 
01140 
01141 
01142 
01143 
01144 
01145 
01146 
01147 
01148 
01149 
01150 
01151 
01152 OpReversePath::OpReversePath()
01153 {
01154 }
01155 
01156 
01157 
01158 
01159 
01160 
01161 
01162 
01163 
01164 
01165 
01166 
01167 
01168 
01169 OpReversePath::~OpReversePath()
01170 {
01171 }
01172 
01173 
01174 
01175 
01176 
01177 
01178 
01179 
01180 
01181 
01182 
01183 
01184 
01185 
01186 
01187 
01188 
01189 BOOL OpReversePath::Init()
01190 {
01191     return (RegisterOpDescriptor(   0, 
01192                                     _R(IDS_MAKEREVERSE),
01193                                     CC_RUNTIME_CLASS(OpReversePath), 
01194                                     OPTOKEN_REVERSEPATH,
01195                                     OpReversePath::GetState,
01196                                     0,  
01197                                     _R(IDBBL_MAKEREVERSE),
01198                                     0   ));
01199 }               
01200 
01201 
01202 
01203 
01204 
01205 
01206 
01207 
01208 
01209 
01210 
01211 
01212 
01213 
01214 OpState OpReversePath::GetState (String_256* Description, OpDescriptor*)
01215 {
01216     OpState OpSt;
01217 
01218     SelRange*   Selected = GetApplication ()->FindSelection ();
01219 
01220     if ((Document::GetSelected () == NULL) || (Selected == NULL) )
01221     {   
01222         OpSt.Greyed = TRUE;
01223         return (OpSt);
01224     }
01225 
01226     if (Selected->Count () == 0)    
01227                                     
01228     {
01229         OpSt.Greyed = TRUE;
01230         return (OpSt);
01231     }
01232 
01233     Node* pNode = Selected->FindFirst ();
01234 
01235     
01236     
01237 
01238     while (pNode != NULL)
01239     {   
01240         BOOL DoThisNode = pNode->IsNodePath ();
01241         
01242         
01243         if (DoThisNode)
01244             DoThisNode = (((NodePath*)pNode)->IsPathAllowable ());
01245 
01246         if (DoThisNode)
01247         {
01248             pNode = Selected->FindNext (pNode);
01249         }
01250         else
01251         {
01252             pNode = NULL;
01253             OpSt.Greyed = TRUE;
01254         }
01255     }
01256 
01257     return (OpSt);
01258 }
01259 
01260 
01261 
01262 
01263 
01264 
01265 
01266 
01267 
01268 
01269 
01270 
01271 
01272 
01273 void OpReversePath::Do (OpDescriptor*)
01274 {
01275     
01276     SelRange* Selected = GetApplication()->FindSelection();
01277     BOOL ok = (Selected != NULL);
01278 
01279     
01280     BeginSlowJob();
01281     if (ok)
01282         ok = DoStartSelOp(TRUE,TRUE);
01283 
01284     
01285     ObjChangeFlags cFlags;
01286     ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
01287     if (ok)
01288     {
01289         if (!Selected->AllowOp(&ObjChange))
01290         {
01291             EndSlowJob();
01292             FailAndExecute();
01293             End();
01294             return;
01295         }
01296     }
01297 
01298     Node* pNode = Selected->FindFirst();
01299     NodePath* ThisPath = NULL;
01300 
01301     
01302 
01303     while (ok && (pNode != NULL))
01304     {   
01305         BOOL DoThisNode = pNode->IsNodePath();
01306         
01307         
01308         if (DoThisNode)
01309             DoThisNode = (((NodePath*)pNode)->IsPathAllowable());
01310 
01311         if  ( DoThisNode )
01312         {
01313             
01314             ThisPath = (NodePath*)pNode;
01315 
01316             
01317             PathVerb* Verbs = NULL;
01318             PathFlags* Flags = NULL;
01319             DocCoord* Coords = NULL;
01320             ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
01321             INT32 NumCoords = ThisPath->InkPath.GetNumCoords();
01322 
01323 
01324 
01325             ObjChangeFlags cFlags;
01326             cFlags.TransformNode = TRUE;
01327             ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,ThisPath,this);
01328             if (!ThisPath->AllowOp(&ObjChange, TRUE))
01329             {
01330                 return;
01331             }
01332 
01333             
01334             for (INT32 loop = 0; loop < NumCoords; loop++)
01335             {
01336                 if (Flags[loop].IsEndPoint && Flags[loop].IsSelected)
01337                     Flags[loop].NeedToRender = TRUE;
01338                 else
01339                     Flags[loop].NeedToRender = FALSE;
01340             }
01341 
01342             
01343             if (ok)
01344                 ok = (RecalcBoundsAction::DoRecalc(this, &UndoActions, ThisPath, TRUE) != AC_FAIL);
01345 
01346             DoReversePath (ThisPath);
01347 
01348             
01349             if (ok)
01350                 ok = (RecordBoundsAction::DoRecord(this, &UndoActions, ThisPath, TRUE) != AC_FAIL);
01351         }
01352         pNode = Selected->FindNext(pNode);
01353     }
01354 
01355     if (ok)
01356     {
01357         ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this);
01358         if (!UpdateChangedNodes(&ObjChange))
01359         {
01360             FailAndExecute();
01361             End();
01362             return;
01363         }
01364     }
01365 
01366     EndSlowJob();
01367 
01368     if (!ok)
01369     {   
01370         FailAndExecute();
01371         InformError();
01372     }
01373 
01374     End();
01375 }