Salome HOME
e69e51bbd039d6f19ef7c02e4b38c9523866e498
[modules/geom.git] / src / CurveCreator / CurveCreator_Diff.cxx
1 // Copyright (C) 2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // File:        CurveCreator_Diff.cxx
21 // Author:      Sergey KHROMOV
22
23 #include "CurveCreator_Diff.hxx"
24 #include "CurveCreator_Curve.hxx"
25
26 #include <list>
27
28 //=======================================================================
29 // function: Constructor
30 // purpose:
31 //=======================================================================
32 CurveCreator_Diff::CurveCreator_Diff()
33 : myNbUndos (0),
34   myPUndo   (NULL),
35   myPRedo   (NULL)
36 {
37 }
38
39 //=======================================================================
40 // function: Destructor
41 // purpose:
42 //=======================================================================
43 CurveCreator_Diff::~CurveCreator_Diff()
44 {
45   clear();
46 }
47
48 //=======================================================================
49 // function: init
50 // purpose:
51 //=======================================================================
52 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
53                              const CurveCreator_Operation::Type theType)
54 {
55   bool isOK = false;
56
57   if (theCurve != NULL) {
58     clear();
59
60     // Set redo.
61     myPRedo = new CurveCreator_Operation;
62
63     if (myPRedo->init(theType)) {
64       isOK = true;
65
66       const int aNbSections = theCurve->getNbSections();
67
68       if (theType == CurveCreator_Operation::Clear) {
69         // Construct undo for Clear command.
70         if (aNbSections > 0) {
71           setNbUndos(aNbSections);
72
73           for (int i = 0; i < aNbSections && isOK; i++) {
74             // Add AddSection command.
75             isOK = addSectionToUndo(theCurve, i, myPUndo[i]);
76           }
77         }
78       } else { // theType == CurveCreator_Operation::Join
79         // Construct undo for Join command.
80         if (aNbSections > 1) {
81           // Add the RemovePoints command to remove points of
82           // the second section fron the first one.
83           const int aNbPoints = theCurve->getNbPoints(0);
84
85           setNbUndos(aNbSections);
86           isOK = myPUndo[0].init(CurveCreator_Operation::RemovePoints,
87                                  0, aNbPoints, -1);
88
89           for (int i = 1; i < aNbSections && isOK; i++) {
90             // Add AddSection command.
91             isOK = addSectionToUndo(theCurve, i, myPUndo[i]);
92           }
93         }
94       }
95     }
96
97     if (!isOK) {
98       clear();
99     }
100   }
101
102   return isOK;
103 }
104
105 //=======================================================================
106 // function: init
107 // purpose:
108 //=======================================================================
109 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
110                              const CurveCreator_Operation::Type theType,
111                              const int theIntParam)
112 {
113   bool isOK = false;
114
115   if (theCurve != NULL) {
116     clear();
117
118     // Set redo.
119     myPRedo = new CurveCreator_Operation;
120
121     if (myPRedo->init(theType, theIntParam)) {
122       // Construct undo for RemoveSection command.
123       // If the last section is removed, one AddSection command is enough.
124       // If not last section is removed, two commands are requred: AddSection
125       // and MoveSection.
126       const int aLastIndex = theCurve->getNbSections() - 1;
127
128       if (theIntParam == aLastIndex) {
129         setNbUndos(1);
130       } else {
131         setNbUndos(2);
132       }
133
134       isOK = addSectionToUndo(theCurve, theIntParam, myPUndo[0]);
135
136       if (isOK && theIntParam != aLastIndex) {
137         isOK = myPUndo[1].init(CurveCreator_Operation::MoveSection,
138                                aLastIndex, theIntParam);
139       }
140     }
141
142     if (!isOK) {
143       clear();
144     }
145   }
146
147   return isOK;
148 }
149
150 //=======================================================================
151 // function: init
152 // purpose:
153 //=======================================================================
154 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
155                              const CurveCreator_Operation::Type theType,
156                              const int theIntParam1,
157                              const int theIntParam2)
158 {
159   bool isOK = false;
160
161   if (theCurve != NULL) {
162     clear();
163
164     // Set redo.
165     myPRedo = new CurveCreator_Operation;
166
167     if (myPRedo->init(theType, theIntParam1, theIntParam2)) {
168       // Construct undo for different commands.
169       switch (theType) {
170         case CurveCreator_Operation::SetType:
171         case CurveCreator_Operation::SetClosed:
172             isOK = setTypeOrClosedToUndo
173               (theCurve, theType, theIntParam1, theIntParam2);
174           break;
175         case CurveCreator_Operation::MoveSection:
176           setNbUndos(1);
177           isOK = myPUndo[0].init(theType, theIntParam2, theIntParam1);
178           break;
179         case CurveCreator_Operation::Join:
180           {
181             // If the last section is removed, one AddSection command is
182             // enough. If not last section is removed, two commands are
183             // requred: AddSection and MoveSection.
184             const int aLastIndex = theCurve->getNbSections() - 1;
185             const int aNbPoints  = theCurve->getNbPoints(theIntParam1);
186
187             if (theIntParam2 == aLastIndex) {
188               setNbUndos(2);
189             } else {
190               setNbUndos(3);
191             }
192
193             isOK = myPUndo[0].init(CurveCreator_Operation::RemovePoints,
194                                    theIntParam1, aNbPoints, -1);
195
196             if (isOK) {
197               isOK = addSectionToUndo(theCurve, theIntParam2, myPUndo[1]);
198
199               if (isOK && theIntParam2 != aLastIndex) {
200                 isOK = myPUndo[2].init(CurveCreator_Operation::MoveSection,
201                                        aLastIndex, theIntParam2);
202               }
203             }
204           }
205           break;
206         default:
207           break;
208       }
209     }
210
211     if (!isOK) {
212       clear();
213     }
214   }
215
216   return isOK;
217 }
218
219 //=======================================================================
220 // function: init
221 // purpose:
222 //=======================================================================
223 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
224                              const CurveCreator_Operation::Type theType,
225                              const int theIntParam1,
226                              const int theIntParam2,
227                              const int theIntParam3)
228 {
229   bool isOK = false;
230
231   if (theCurve != NULL) {
232     clear();
233
234     // Set redo.
235     myPRedo = new CurveCreator_Operation;
236
237     if (myPRedo->init(theType, theIntParam1, theIntParam2, theIntParam3)) {
238       // Construct undo for RemovePoints command.
239       const CurveCreator::Dimension aDim = theCurve->getDimension();
240       const CurveCreator::Coordinates &aPoints =
241               theCurve->getPoints(theIntParam1);
242       CurveCreator::Coordinates::const_iterator anIterBegin =
243           aPoints.begin() + (aDim*theIntParam2);
244       CurveCreator::Coordinates::const_iterator anIterEnd;
245
246       if (theIntParam3 == -1) {
247         anIterEnd = aPoints.end();
248       } else {
249         anIterEnd = anIterBegin + (aDim*theIntParam3);
250       }
251
252       CurveCreator::Coordinates aPointsToAdd;
253
254       setNbUndos(1);
255       aPointsToAdd.insert(aPointsToAdd.end(), anIterBegin, anIterEnd);
256       isOK = myPUndo[0].init(CurveCreator_Operation::InsertPoints,
257                              aPointsToAdd, theIntParam1, theIntParam2);
258     }
259
260     if (!isOK) {
261       clear();
262     }
263   }
264
265   return isOK;
266 }
267
268 //=======================================================================
269 // function: init
270 // purpose:
271 //=======================================================================
272 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
273                              const CurveCreator_Operation::Type theType,
274                              const CurveCreator::Coordinates &theCoords,
275                              const int theIntParam)
276 {
277   bool isOK = false;
278
279   if (theCurve != NULL) {
280     clear();
281
282     // Set redo.
283     myPRedo = new CurveCreator_Operation;
284
285     if (myPRedo->init(theType, theCoords, theIntParam)) {
286       // Construct undo for AddPoints command.
287       const int aSectionInd = getSectionIndex(theCurve, theIntParam);
288       const CurveCreator::Dimension aDim = theCurve->getDimension();
289       const CurveCreator::Coordinates &aPoints =
290               theCurve->getPoints(aSectionInd);
291       const int aNbPoints = (aPoints.size()/aDim);
292
293       setNbUndos(1);
294       isOK = myPUndo[0].init(CurveCreator_Operation::RemovePoints,
295                              aSectionInd, aNbPoints, -1);
296     }
297
298     if (!isOK) {
299       clear();
300     }
301   }
302
303   return isOK;
304 }
305
306 //=======================================================================
307 // function: init
308 // purpose:
309 //=======================================================================
310 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
311                              const CurveCreator_Operation::Type theType,
312                              const std::string& theName,
313                              const CurveCreator::Coordinates &theCoords,
314                              const int theIntParam1,
315                              const int theIntParam2)
316 {
317     bool isOK = false;
318
319     if (theCurve != NULL) {
320       clear();
321
322       // Set redo.
323       myPRedo = new CurveCreator_Operation;
324
325       if (myPRedo->init(theType, theName, theCoords, theIntParam1, theIntParam2)) {
326         // Construct undo for different commands.
327         switch (theType) {
328           case CurveCreator_Operation::AddSection:
329             setNbUndos(1);
330             isOK = myPUndo[0].init(CurveCreator_Operation::RemoveSection, -1);
331             break;
332         }
333       }
334     }
335     if( !isOK )
336         clear();
337     return isOK;
338 }
339
340 //=======================================================================
341 // function: init
342 // purpose:
343 //=======================================================================
344 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
345                              const CurveCreator_Operation::Type theType,
346                              const CurveCreator::Coordinates &theCoords,
347                              const int theIntParam1,
348                              const int theIntParam2)
349 {
350   bool isOK = false;
351
352   if (theCurve != NULL) {
353     clear();
354
355     // Set redo.
356     myPRedo = new CurveCreator_Operation;
357
358     if (myPRedo->init(theType, theCoords, theIntParam1, theIntParam2)) {
359       // Construct undo for different commands.
360       switch (theType) {
361         case CurveCreator_Operation::InsertPoints:
362           {
363             const CurveCreator::Dimension aDim = theCurve->getDimension();
364             const int aNbPoints = (theCoords.size()/aDim);
365             const int aSectionInd = getSectionIndex(theCurve, theIntParam1);
366             int aPointInd;
367
368             if (theIntParam2 == -1) {
369               aPointInd = theCurve->getNbPoints(aSectionInd);
370             } else {
371               aPointInd = theIntParam2;
372             }
373
374             setNbUndos(1);
375             isOK = myPUndo[0].init(CurveCreator_Operation::RemovePoints,
376                                    aSectionInd, aPointInd, aNbPoints);
377           }
378           break;
379         case CurveCreator_Operation::SetCoordinates:
380           {
381             const CurveCreator::Coordinates anOldCoords =
382               theCurve->getCoordinates(theIntParam1, theIntParam2);
383
384             setNbUndos(1);
385             isOK = myPUndo[0].init(CurveCreator_Operation::SetCoordinates,
386                                    anOldCoords, theIntParam1, theIntParam2);
387           }
388           break;
389         default:
390           break;
391       }
392     }
393
394     if (!isOK) {
395       clear();
396     }
397   }
398
399   return isOK;
400 }
401
402 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
403                              const CurveCreator_Operation::Type theType,
404                              const std::string &theName,
405                              const int theIntParam1 )
406 {
407   bool isOK = false;
408   myPRedo = new CurveCreator_Operation;
409
410   if (myPRedo->init(theType, theName, theIntParam1 )) {
411     // Construct undo for different commands.
412     switch (theType) {
413       case CurveCreator_Operation::RenameSection:
414         setNbUndos(1);
415         isOK = myPUndo[0].init(CurveCreator_Operation::RenameSection,
416                                theCurve->getSectionName(theIntParam1), theIntParam1);
417         break;
418     }
419   }
420   if( !isOK ){
421     clear();
422   }
423   return isOK;
424 }
425
426 //=======================================================================
427 // function: applyUndo
428 // purpose:
429 //=======================================================================
430 void CurveCreator_Diff::applyUndo(CurveCreator_Curve *theCurve)
431 {
432   if (myNbUndos > 0 && myPUndo != NULL) {
433     for (int i = 0; i < myNbUndos; i++) {
434       myPUndo[i].apply(theCurve);
435     }
436   }
437 }
438
439 //=======================================================================
440 // function: applyRedo
441 // purpose:
442 //=======================================================================
443 void CurveCreator_Diff::applyRedo(CurveCreator_Curve *theCurve)
444 {
445   if (myPRedo != NULL) {
446     myPRedo->apply(theCurve);
447   }
448 }
449
450 //=======================================================================
451 // function: clear
452 // purpose:
453 //=======================================================================
454 void CurveCreator_Diff::clear()
455 {
456   if (myPUndo != NULL) {
457     delete [] myPUndo;
458     myPUndo = NULL;
459   }
460
461   myNbUndos = 0;
462
463   if (myPRedo != NULL) {
464     delete myPRedo;
465     myPRedo = NULL;
466   }
467 }
468
469 //=======================================================================
470 // function: setNbUndos
471 // purpose:
472 //=======================================================================
473 void CurveCreator_Diff::setNbUndos(const int theNbUndos)
474 {
475   myNbUndos = theNbUndos;
476   myPUndo = new CurveCreator_Operation[myNbUndos];
477 }
478
479 //=======================================================================
480 // function: getSectionIndex
481 // purpose:
482 //=======================================================================
483 int CurveCreator_Diff::getSectionIndex(const CurveCreator_Curve *theCurve,
484                                        const int theIndex) const
485 {
486   return (theIndex == -1 ? theCurve->getNbSections() - 1 : theIndex);
487 }
488
489 //=======================================================================
490 // function: addSectionToUndo
491 // purpose:
492 //=======================================================================
493 bool CurveCreator_Diff::addSectionToUndo
494                       (const CurveCreator_Curve *theCurve,
495                        const int theIndex,
496                        CurveCreator_Operation &theOperation) const
497 {
498   const CurveCreator::Coordinates &aPnts = theCurve->getPoints(theIndex);
499   const CurveCreator::Type aType = theCurve->getType(theIndex);
500   const bool isClosed = theCurve->isClosed(theIndex);
501
502   bool isOK = theOperation.init(CurveCreator_Operation::AddSection,
503                                 aPnts, aType, isClosed);
504
505   return isOK;
506 }
507
508 //=======================================================================
509 // function: setTypeOrClosedToUndo
510 // purpose:
511 //=======================================================================
512 bool CurveCreator_Diff::setTypeOrClosedToUndo
513                             (const CurveCreator_Curve *theCurve,
514                              const CurveCreator_Operation::Type theType,
515                              const int theIntParam1,
516                              const int theIntParam2)
517 {
518   bool isOK = true;
519
520   // Compute number of modified sections.
521   const bool isSetType = (theType == CurveCreator_Operation::SetType);
522   int aNbModif = 0;
523   std::list<int> aListOfInd;
524   int aValue;
525   int i;
526
527   if (theIntParam2 == -1) {
528     // The operation is applied to all sections. We need to collect
529     // really modified sections for undo.
530     const int aNbSections = theCurve->getNbSections();
531
532     if (aNbSections > 0) {
533       // Get sections to be modified.
534       for (i = 0; i < aNbSections; i++) {
535         if (isSetType) {
536           aValue = theCurve->getType(i);
537         } else {
538           aValue = theCurve->isClosed(i);
539         }
540
541         if (theIntParam1 != aValue) {
542           aNbModif++;
543           aListOfInd.push_back(i);
544         }
545       }
546
547       if (aNbSections == aNbModif) {
548         // All sections are modified. We can use one single command
549         // with -1 section index.
550         aNbModif = 1;
551         aListOfInd.clear();
552         aListOfInd.push_back(-1);
553       }
554     }
555   } else {
556     // There is only particular section modified.
557     // Check if there is a real modification required.
558     if (isSetType) {
559       aValue = theCurve->getType(theIntParam2);
560     } else {
561       aValue = theCurve->isClosed(theIntParam2);
562     }
563
564     if (theIntParam1 != aValue) {
565       aNbModif = 1;
566       aListOfInd.push_back(theIntParam2);
567     }
568   }
569
570   if (aNbModif > 0) {
571     // Store the undos
572     std::list<int>::iterator anIter = aListOfInd.begin();
573
574     if (isSetType) {
575       aValue = theCurve->getType(*anIter);
576     } else {
577       aValue = theCurve->isClosed(*anIter);
578     }
579
580     setNbUndos(aNbModif);
581
582     for (i = 0; anIter != aListOfInd.end() && isOK; i++, anIter++) {
583       isOK = myPUndo[i].init(theType, aValue, *anIter);
584     }
585   }
586
587   return isOK;
588 }