Salome HOME
OCC functionality moving out from the widget
[modules/hydro.git] / src / HYDROCurveCreator / 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     }
239
240     if (!isOK) {
241       clear();
242     }
243   }
244
245   return isOK;
246 }
247
248 //=======================================================================
249 // function: init
250 // purpose:
251 //=======================================================================
252 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
253                              const CurveCreator_Operation::Type theType,
254                              const CurveCreator::Coordinates &theCoords,
255                              const int theIntParam)
256 {
257   bool isOK = false;
258
259   if (theCurve != NULL) {
260     clear();
261
262     // Set redo.
263     myPRedo = new CurveCreator_Operation;
264
265     if (myPRedo->init(theType, theCoords, theIntParam)) {
266       // Construct undo for AddPoints command.
267       const int aSectionInd = getSectionIndex(theCurve, theIntParam);
268       const CurveCreator::Dimension aDim = theCurve->getDimension();
269       const CurveCreator::Coordinates &aPoints =
270               theCurve->getPoints(aSectionInd);
271       const int aNbPoints = (aPoints.size()/aDim);
272
273       setNbUndos(1);
274       isOK = myPUndo[0].init(CurveCreator_Operation::RemovePoints,
275                              aSectionInd, aNbPoints, -1);
276     }
277
278     if (!isOK) {
279       clear();
280     }
281   }
282
283   return isOK;
284 }
285
286 //=======================================================================
287 // function: init
288 // purpose:
289 //=======================================================================
290 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
291                              const CurveCreator_Operation::Type theType,
292                              const std::string& theName,
293                              const CurveCreator::Coordinates &theCoords,
294                              const int theIntParam1,
295                              const int theIntParam2)
296 {
297     bool isOK = false;
298
299     if (theCurve != NULL) {
300       clear();
301
302       // Set redo.
303       myPRedo = new CurveCreator_Operation;
304
305       if (myPRedo->init(theType, theName, theCoords, theIntParam1, theIntParam2)) {
306         // Construct undo for different commands.
307         switch (theType) {
308           case CurveCreator_Operation::AddSection:
309             setNbUndos(1);
310             isOK = myPUndo[0].init(CurveCreator_Operation::RemoveSection, -1);
311             break;
312         }
313       }
314     }
315     if( !isOK )
316         clear();
317     return isOK;
318 }
319
320 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
321                              const CurveCreator_Operation::Type theType,
322                              const std::string &theName,
323                              const int theIntParam1 )
324 {
325   bool isOK = false;
326   myPRedo = new CurveCreator_Operation;
327
328   if (myPRedo->init(theType, theName, theIntParam1 )) {
329     // Construct undo for different commands.
330     switch (theType) {
331       case CurveCreator_Operation::RenameSection:
332         setNbUndos(1);
333         isOK = myPUndo[0].init(CurveCreator_Operation::RenameSection,
334                                theCurve->getSectionName(theIntParam1), theIntParam1);
335         break;
336     }
337   }
338   if( !isOK ){
339     clear();
340   }
341   return isOK;
342 }
343
344 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
345                              const CurveCreator_Operation::Type theType,
346                              const CurveCreator_ICurve::SectionToPointList &theParamList1)
347 {
348   bool isOK = false;
349
350   if (theCurve != NULL) {
351     clear();
352
353     // Set redo.
354     myPRedo = new CurveCreator_Operation;
355
356     if (myPRedo->init(theType, theParamList1)) {
357       // Construct undo for different commands.
358       switch (theType) {
359         case CurveCreator_Operation::RemovePoints:
360           {
361             // Construct undo for RemovePoints command.
362             CurveCreator_ICurve::SectionToPointCoordsList aSectionToPointCoords;
363             CurveCreator::Coordinates aPointsToAdd;
364             const CurveCreator::Dimension aDim = theCurve->getDimension();
365             CurveCreator_ICurve::SectionToPointList::const_iterator anIt = theParamList1.begin(), aLast = theParamList1.end();
366             std::list<int> aPoints;
367             int aSectionId, aPointId;
368             for ( ; anIt != aLast; anIt++ ) {
369               aPointsToAdd.clear();
370               aSectionId = anIt->first;
371               aPointId = anIt->second;
372               const CurveCreator::Coordinates &aPoints =
373                       theCurve->getPoints(aSectionId);
374               CurveCreator::Coordinates::const_iterator anIterBegin =
375                   aPoints.begin() + (aDim*aPointId);
376               CurveCreator::Coordinates::const_iterator anIterEnd = 
377                 anIterBegin + aDim;
378               aPointsToAdd.insert(aPointsToAdd.end(), anIterBegin, anIterEnd);
379               aSectionToPointCoords.push_back(std::make_pair(*anIt, aPointsToAdd));
380             }
381             setNbUndos(1);
382             isOK = myPUndo[0].init(CurveCreator_Operation::InsertPoints,
383                                    aSectionToPointCoords);
384           }
385           break;
386         default:
387           break;
388       }
389     }
390
391     if (!isOK) {
392       clear();
393     }
394   }
395
396   return isOK;
397 }
398
399 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
400                              const CurveCreator_Operation::Type theType,
401                              const CurveCreator_ICurve::SectionToPointCoordsList &theParamList1)
402 {
403   bool isOK = false;
404
405   if (theCurve != NULL) {
406     clear();
407
408     // Set redo.
409     myPRedo = new CurveCreator_Operation;
410
411     if (myPRedo->init(theType, theParamList1)) {
412       // Construct undo for different commands.
413       switch (theType) {
414         case CurveCreator_Operation::InsertPoints:
415           {
416             // Construct undo for RemovePoints command.
417             CurveCreator_ICurve::SectionToPointList aSectionToPointList;
418             CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt = theParamList1.begin(), aLast = theParamList1.end();
419             int aSectionId, aPointId;
420             for ( ; anIt != aLast; anIt++ ) {
421               aSectionToPointList.push_back(anIt->first);
422             }
423             setNbUndos(1);
424             isOK = myPUndo[0].init(CurveCreator_Operation::RemovePoints,
425                                    aSectionToPointList);
426           }
427           break;
428         case CurveCreator_Operation::SetCoordinates:
429           {
430             // Construct undo for SetCoordinates command.
431             CurveCreator_ICurve::SectionToPointCoordsList aSectionToPointOldCoords;
432             CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt = theParamList1.begin(), aLast = theParamList1.end();
433             for ( ; anIt != aLast; anIt++ ) {
434               CurveCreator::Coordinates anOldCoords = theCurve->getPoint(anIt->first.first, anIt->first.second);
435               aSectionToPointOldCoords.push_back(std::make_pair(anIt->first, anOldCoords));
436             }
437
438             setNbUndos(1);
439             isOK = myPUndo[0].init(CurveCreator_Operation::SetCoordinates,
440                                    aSectionToPointOldCoords);
441           }
442           break;
443         default:
444           break;
445       }
446     }
447
448     if (!isOK) {
449       clear();
450     }
451   }
452
453   return isOK;
454 }
455
456 //=======================================================================
457 // function: applyUndo
458 // purpose:
459 //=======================================================================
460 void CurveCreator_Diff::applyUndo(CurveCreator_Curve *theCurve)
461 {
462   if (myNbUndos > 0 && myPUndo != NULL) {
463     for (int i = 0; i < myNbUndos; i++) {
464       myPUndo[i].apply(theCurve);
465     }
466   }
467 }
468
469 //=======================================================================
470 // function: applyRedo
471 // purpose:
472 //=======================================================================
473 void CurveCreator_Diff::applyRedo(CurveCreator_Curve *theCurve)
474 {
475   if (myPRedo != NULL) {
476     myPRedo->apply(theCurve);
477   }
478 }
479
480 //=======================================================================
481 // function: clear
482 // purpose:
483 //=======================================================================
484 void CurveCreator_Diff::clear()
485 {
486   if (myPUndo != NULL) {
487     delete [] myPUndo;
488     myPUndo = NULL;
489   }
490
491   myNbUndos = 0;
492
493   if (myPRedo != NULL) {
494     delete myPRedo;
495     myPRedo = NULL;
496   }
497 }
498
499 //=======================================================================
500 // function: setNbUndos
501 // purpose:
502 //=======================================================================
503 void CurveCreator_Diff::setNbUndos(const int theNbUndos)
504 {
505   myNbUndos = theNbUndos;
506   myPUndo = new CurveCreator_Operation[myNbUndos];
507 }
508
509 //=======================================================================
510 // function: getSectionIndex
511 // purpose:
512 //=======================================================================
513 int CurveCreator_Diff::getSectionIndex(const CurveCreator_Curve *theCurve,
514                                        const int theIndex) const
515 {
516   return (theIndex == -1 ? theCurve->getNbSections() - 1 : theIndex);
517 }
518
519 //=======================================================================
520 // function: addSectionToUndo
521 // purpose:
522 //=======================================================================
523 bool CurveCreator_Diff::addSectionToUndo
524                       (const CurveCreator_Curve *theCurve,
525                        const int theIndex,
526                        CurveCreator_Operation &theOperation) const
527 {
528   const std::string aName = theCurve->getSectionName(theIndex);
529   const CurveCreator::Coordinates &aPnts = theCurve->getPoints(theIndex);
530   const CurveCreator::SectionType aType = theCurve->getSectionType(theIndex);
531   const bool isClosed = theCurve->isClosed(theIndex);
532
533   bool isOK = theOperation.init(CurveCreator_Operation::AddSection,
534                                 aName, aPnts, aType, isClosed);
535
536   return isOK;
537 }
538
539 //=======================================================================
540 // function: setTypeOrClosedToUndo
541 // purpose:
542 //=======================================================================
543 bool CurveCreator_Diff::setTypeOrClosedToUndo
544                             (const CurveCreator_Curve *theCurve,
545                              const CurveCreator_Operation::Type theType,
546                              const int theIntParam1,
547                              const int theIntParam2)
548 {
549   bool isOK = true;
550
551   // Compute number of modified sections.
552   const bool isSetType = (theType == CurveCreator_Operation::SetType);
553   int aNbModif = 0;
554   std::list<int> aListOfInd;
555   int aValue;
556   int i;
557
558   if (theIntParam2 == -1) {
559     // The operation is applied to all sections. We need to collect
560     // really modified sections for undo.
561     const int aNbSections = theCurve->getNbSections();
562
563     if (aNbSections > 0) {
564       // Get sections to be modified.
565       for (i = 0; i < aNbSections; i++) {
566         if (isSetType) {
567           aValue = theCurve->getSectionType(i);
568         } else {
569           aValue = theCurve->isClosed(i);
570         }
571
572         if (theIntParam1 != aValue) {
573           aNbModif++;
574           aListOfInd.push_back(i);
575         }
576       }
577
578       if (aNbSections == aNbModif) {
579         // All sections are modified. We can use one single command
580         // with -1 section index.
581         aNbModif = 1;
582         aListOfInd.clear();
583         aListOfInd.push_back(-1);
584       }
585     }
586   } else {
587     // There is only particular section modified.
588     // Check if there is a real modification required.
589     if (isSetType) {
590       aValue = theCurve->getSectionType(theIntParam2);
591     } else {
592       aValue = theCurve->isClosed(theIntParam2);
593     }
594
595     if (theIntParam1 != aValue) {
596       aNbModif = 1;
597       aListOfInd.push_back(theIntParam2);
598     }
599   }
600
601   if (aNbModif > 0) {
602     // Store the undos
603     std::list<int>::iterator anIter = aListOfInd.begin();
604
605     if (isSetType) {
606       aValue = theCurve->getSectionType(*anIter);
607     } else {
608       aValue = theCurve->isClosed(*anIter);
609     }
610
611     setNbUndos(aNbModif);
612
613     for (i = 0; anIter != aListOfInd.end() && isOK; i++, anIter++) {
614       isOK = myPUndo[i].init(theType, aValue, *anIter);
615     }
616   }
617
618   return isOK;
619 }