Salome HOME
Create goups for stream.
[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 {
54   CurveCreator_Operation::Type aType = CurveCreator_Operation::Clear;
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(aType)) {
64       isOK = true;
65
66       const int aNbSections = theCurve->getNbSections();
67
68       // Construct undo for Clear command.
69       if (aNbSections > 0) {
70         setNbUndos(aNbSections);
71
72         for (int i = 0; i < aNbSections && isOK; i++) {
73           // Add AddSection command.
74           isOK = addSectionToUndo(theCurve, i, myPUndo[i]);
75         }
76       }
77     }
78
79     if (!isOK) {
80       clear();
81     }
82   }
83
84   return isOK;
85 }
86
87 //=======================================================================
88 // function: init
89 // purpose:
90 //=======================================================================
91 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
92                              const CurveCreator_Operation::Type theType,
93                              const int theIntParam)
94 {
95   bool isOK = false;
96
97   if (theCurve != NULL) {
98     clear();
99
100     // Set redo.
101     myPRedo = new CurveCreator_Operation;
102
103     if (myPRedo->init(theType, theIntParam)) {
104       // Construct undo for RemoveSection command.
105       // If the last section is removed, one AddSection command is enough.
106       // If not last section is removed, two commands are requred: AddSection
107       // and MoveSection.
108       const int aLastIndex = theCurve->getNbSections() - 1;
109
110       if (theIntParam == aLastIndex) {
111         setNbUndos(1);
112       } else {
113         setNbUndos(2);
114       }
115
116       isOK = addSectionToUndo(theCurve, theIntParam, myPUndo[0]);
117
118       if (isOK && theIntParam != aLastIndex) {
119         isOK = myPUndo[1].init(CurveCreator_Operation::MoveSection,
120                                aLastIndex, theIntParam);
121       }
122     }
123
124     if (!isOK) {
125       clear();
126     }
127   }
128
129   return isOK;
130 }
131
132 //=======================================================================
133 // function: init
134 // purpose:
135 //=======================================================================
136 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
137                              const CurveCreator_Operation::Type theType,
138                              const int theIntParam1,
139                              const int theIntParam2)
140 {
141   bool isOK = false;
142
143   if (theCurve != NULL) {
144     clear();
145
146     // Set redo.
147     myPRedo = new CurveCreator_Operation;
148
149     if (myPRedo->init(theType, theIntParam1, theIntParam2)) {
150       // Construct undo for different commands.
151       switch (theType) {
152         case CurveCreator_Operation::SetType:
153         case CurveCreator_Operation::SetClosed:
154             isOK = setTypeOrClosedToUndo
155               (theCurve, theType, theIntParam1, theIntParam2);
156           break;
157         case CurveCreator_Operation::MoveSection:
158           setNbUndos(1);
159           isOK = myPUndo[0].init(theType, theIntParam2, theIntParam1);
160           break;
161         case CurveCreator_Operation::Join:
162           {
163             // If the last section is removed, one AddSection command is
164             // enough. If not last section is removed, two commands are
165             // requred: AddSection and MoveSection.
166             const int aLastIndex = theCurve->getNbSections() - 1;
167             const int aNbPoints  = theCurve->getNbPoints(theIntParam1);
168
169             if (theIntParam2 == aLastIndex) {
170               setNbUndos(2);
171             } else {
172               setNbUndos(3);
173             }
174
175             // Construct undo for RemovePoints command.
176             int anISection = theIntParam1;
177             const int aNbPoints2  = theCurve->getNbPoints(theIntParam2);
178             CurveCreator_ICurve::SectionToPointList aSectionToPointList;
179             int aJoinedSize = aNbPoints + aNbPoints2;
180             for (int anIPoint = aNbPoints; anIPoint < aJoinedSize; anIPoint++)
181               aSectionToPointList.push_back(std::make_pair( anISection, anIPoint ) );
182             isOK = myPUndo[0].init(CurveCreator_Operation::RemovePoints,
183                                    aSectionToPointList);
184
185             //isOK = myPUndo[0].init(CurveCreator_Operation::RemovePoints,
186             //                       theIntParam1, aNbPoints, -1);
187
188             if (isOK) {
189               isOK = addSectionToUndo(theCurve, theIntParam2, myPUndo[1]);
190
191               if (isOK && theIntParam2 != aLastIndex) {
192                 isOK = myPUndo[2].init(CurveCreator_Operation::MoveSection,
193                                        aLastIndex, theIntParam2);
194               }
195             }
196           }
197           break;
198         default:
199           break;
200       }
201     }
202
203     if (!isOK) {
204       clear();
205     }
206   }
207
208   return isOK;
209 }
210
211 //=======================================================================
212 // function: init
213 // purpose:
214 //=======================================================================
215 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
216                              const CurveCreator_Operation::Type theType,
217                              const std::string& theName,
218                              const CurveCreator::Coordinates &theCoords,
219                              const int theIntParam1,
220                              const int theIntParam2)
221 {
222     bool isOK = false;
223
224     if (theCurve != NULL) {
225       clear();
226
227       // Set redo.
228       myPRedo = new CurveCreator_Operation;
229
230       if (myPRedo->init(theType, theName, theCoords, theIntParam1, theIntParam2)) {
231         // Construct undo for different commands.
232         switch (theType) {
233           case CurveCreator_Operation::AddSection:
234             setNbUndos(1);
235             isOK = myPUndo[0].init(CurveCreator_Operation::RemoveSection, -1);
236             break;
237         }
238       }
239     }
240     if( !isOK )
241         clear();
242     return isOK;
243 }
244
245 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
246                              const CurveCreator_Operation::Type theType,
247                              const std::string &theName,
248                              const int theIntParam1 )
249 {
250   bool isOK = false;
251   myPRedo = new CurveCreator_Operation;
252
253   if (myPRedo->init(theType, theName, theIntParam1 )) {
254     // Construct undo for different commands.
255     switch (theType) {
256       case CurveCreator_Operation::RenameSection:
257         setNbUndos(1);
258         isOK = myPUndo[0].init(CurveCreator_Operation::RenameSection,
259                                theCurve->getSectionName(theIntParam1), theIntParam1);
260         break;
261     }
262   }
263   if( !isOK ){
264     clear();
265   }
266   return isOK;
267 }
268
269 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
270                              const CurveCreator_Operation::Type theType,
271                              const CurveCreator_ICurve::SectionToPointList &theParamList1)
272 {
273   bool isOK = false;
274
275   if (theCurve != NULL) {
276     clear();
277
278     // Set redo.
279     myPRedo = new CurveCreator_Operation;
280
281     if (myPRedo->init(theType, theParamList1)) {
282       // Construct undo for different commands.
283       switch (theType) {
284         case CurveCreator_Operation::RemovePoints:
285           {
286             // Construct undo for RemovePoints command.
287             CurveCreator_ICurve::SectionToPointCoordsList aSectionToPointCoords;
288             CurveCreator::Coordinates aPointsToAdd;
289             const CurveCreator::Dimension aDim = theCurve->getDimension();
290             CurveCreator_ICurve::SectionToPointList::const_iterator anIt = theParamList1.begin(), aLast = theParamList1.end();
291             std::list<int> aPoints;
292             int aSectionId, aPointId;
293             for ( ; anIt != aLast; anIt++ ) {
294               aPointsToAdd.clear();
295               aSectionId = anIt->first;
296               aPointId = anIt->second;
297               const CurveCreator::Coordinates &aPoints =
298                       theCurve->getPoints(aSectionId);
299               CurveCreator::Coordinates::const_iterator anIterBegin =
300                   aPoints.begin() + (aDim*aPointId);
301               CurveCreator::Coordinates::const_iterator anIterEnd = 
302                 anIterBegin + aDim;
303               aPointsToAdd.insert(aPointsToAdd.end(), anIterBegin, anIterEnd);
304               aSectionToPointCoords.push_back(std::make_pair(*anIt, aPointsToAdd));
305             }
306             setNbUndos(1);
307             isOK = myPUndo[0].init(CurveCreator_Operation::InsertPoints,
308                                    aSectionToPointCoords);
309           }
310           break;
311         default:
312           break;
313       }
314     }
315
316     if (!isOK) {
317       clear();
318     }
319   }
320
321   return isOK;
322 }
323
324 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
325                              const CurveCreator_Operation::Type theType,
326                              const CurveCreator_ICurve::SectionToPointCoordsList &theParamList1)
327 {
328   bool isOK = false;
329
330   if (theCurve != NULL) {
331     clear();
332
333     // Set redo.
334     myPRedo = new CurveCreator_Operation;
335
336     if (myPRedo->init(theType, theParamList1)) {
337       // Construct undo for different commands.
338       switch (theType) {
339         case CurveCreator_Operation::InsertPoints:
340           {
341             // Construct undo for RemovePoints command.
342             CurveCreator_ICurve::SectionToPointList aSectionToPointList;
343             CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt = theParamList1.begin(), aLast = theParamList1.end();
344             for ( ; anIt != aLast; anIt++ ) {
345               aSectionToPointList.push_back(anIt->first);
346             }
347             setNbUndos(1);
348             isOK = myPUndo[0].init(CurveCreator_Operation::RemovePoints,
349                                    aSectionToPointList);
350           }
351           break;
352         case CurveCreator_Operation::SetCoordinates:
353           {
354             // Construct undo for SetCoordinates command.
355             CurveCreator_ICurve::SectionToPointCoordsList aSectionToPointOldCoords;
356             CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt = theParamList1.begin(), aLast = theParamList1.end();
357             for ( ; anIt != aLast; anIt++ ) {
358               CurveCreator::Coordinates anOldCoords = theCurve->getPoint(anIt->first.first, anIt->first.second);
359               aSectionToPointOldCoords.push_back(std::make_pair(anIt->first, anOldCoords));
360             }
361
362             setNbUndos(1);
363             isOK = myPUndo[0].init(CurveCreator_Operation::SetCoordinates,
364                                    aSectionToPointOldCoords);
365           }
366           break;
367         default:
368           break;
369       }
370     }
371
372     if (!isOK) {
373       clear();
374     }
375   }
376
377   return isOK;
378 }
379
380 bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
381                              const CurveCreator_ICurve::SectionToPointCoordsList &theOldParamList)
382 {
383   bool isOK = false;
384
385   if (theCurve != NULL && theOldParamList.size() > 0) {
386     clear();
387
388     // Set redo.
389     myPRedo = new CurveCreator_Operation;
390
391     // Construct redo for SetCoordinates command.
392     CurveCreator_ICurve::SectionToPointCoordsList aSectionToPointActualCoords;
393     CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt = 
394       theOldParamList.begin(), aLast = theOldParamList.end();
395     for ( ; anIt != aLast; anIt++ ) {
396       CurveCreator::Coordinates anActualCoords = theCurve->getPoint(anIt->first.first, anIt->first.second);
397       aSectionToPointActualCoords.push_back(std::make_pair(anIt->first, anActualCoords));
398     }
399
400     if (myPRedo->init(CurveCreator_Operation::SetCoordinates, aSectionToPointActualCoords)) {
401       // Undo for SetCoordinates command.
402       setNbUndos(1);
403       isOK = myPUndo[0].init(CurveCreator_Operation::SetCoordinates,
404                              theOldParamList);
405     }
406
407     if (!isOK) {
408       clear();
409     }
410   }
411
412   return isOK;
413 }
414
415 //=======================================================================
416 // function: applyUndo
417 // purpose:
418 //=======================================================================
419 void CurveCreator_Diff::applyUndo(CurveCreator_Curve *theCurve)
420 {
421   if (myNbUndos > 0 && myPUndo != NULL) {
422     for (int i = 0; i < myNbUndos; i++) {
423       myPUndo[i].apply(theCurve);
424     }
425   }
426 }
427
428 //=======================================================================
429 // function: applyRedo
430 // purpose:
431 //=======================================================================
432 void CurveCreator_Diff::applyRedo(CurveCreator_Curve *theCurve)
433 {
434   if (myPRedo != NULL) {
435     myPRedo->apply(theCurve);
436   }
437 }
438
439 //=======================================================================
440 // function: clear
441 // purpose:
442 //=======================================================================
443 void CurveCreator_Diff::clear()
444 {
445   if (myPUndo != NULL) {
446     delete [] myPUndo;
447     myPUndo = NULL;
448   }
449
450   myNbUndos = 0;
451
452   if (myPRedo != NULL) {
453     delete myPRedo;
454     myPRedo = NULL;
455   }
456 }
457
458 //=======================================================================
459 // function: setNbUndos
460 // purpose:
461 //=======================================================================
462 void CurveCreator_Diff::setNbUndos(const int theNbUndos)
463 {
464   myNbUndos = theNbUndos;
465   myPUndo = new CurveCreator_Operation[myNbUndos];
466 }
467
468 //=======================================================================
469 // function: getSectionIndex
470 // purpose:
471 //=======================================================================
472 int CurveCreator_Diff::getSectionIndex(const CurveCreator_Curve *theCurve,
473                                        const int theIndex) const
474 {
475   return (theIndex == -1 ? theCurve->getNbSections() - 1 : theIndex);
476 }
477
478 //=======================================================================
479 // function: addSectionToUndo
480 // purpose:
481 //=======================================================================
482 bool CurveCreator_Diff::addSectionToUndo
483                       (const CurveCreator_Curve *theCurve,
484                        const int theIndex,
485                        CurveCreator_Operation &theOperation) const
486 {
487   const std::string aName = theCurve->getSectionName(theIndex);
488   const CurveCreator::Coordinates &aPnts = theCurve->getPoints(theIndex);
489   const CurveCreator::SectionType aType = theCurve->getSectionType(theIndex);
490   const bool isClosed = theCurve->isClosed(theIndex);
491
492   bool isOK = theOperation.init(CurveCreator_Operation::AddSection,
493                                 aName, aPnts, aType, isClosed);
494
495   return isOK;
496 }
497
498 //=======================================================================
499 // function: setTypeOrClosedToUndo
500 // purpose:
501 //=======================================================================
502 bool CurveCreator_Diff::setTypeOrClosedToUndo
503                             (const CurveCreator_Curve *theCurve,
504                              const CurveCreator_Operation::Type theType,
505                              const int theIntParam1,
506                              const int theIntParam2)
507 {
508   bool isOK = true;
509
510   // Compute number of modified sections.
511   const bool isSetType = (theType == CurveCreator_Operation::SetType);
512   int aNbModif = 0;
513   std::list<int> aListOfInd;
514   int aValue;
515   int i;
516
517   if (theIntParam2 == -1) {
518     // The operation is applied to all sections. We need to collect
519     // really modified sections for undo.
520     const int aNbSections = theCurve->getNbSections();
521
522     if (aNbSections > 0) {
523       // Get sections to be modified.
524       for (i = 0; i < aNbSections; i++) {
525         if (isSetType) {
526           aValue = theCurve->getSectionType(i);
527         } else {
528           aValue = theCurve->isClosed(i);
529         }
530
531         if (theIntParam1 != aValue) {
532           aNbModif++;
533           aListOfInd.push_back(i);
534         }
535       }
536
537       if (aNbSections == aNbModif) {
538         // All sections are modified. We can use one single command
539         // with -1 section index.
540         aNbModif = 1;
541         aListOfInd.clear();
542         aListOfInd.push_back(-1);
543       }
544     }
545   } else {
546     // There is only particular section modified.
547     // Check if there is a real modification required.
548     if (isSetType) {
549       aValue = theCurve->getSectionType(theIntParam2);
550     } else {
551       aValue = theCurve->isClosed(theIntParam2);
552     }
553
554     if (theIntParam1 != aValue) {
555       aNbModif = 1;
556       aListOfInd.push_back(theIntParam2);
557     }
558   }
559
560   if (aNbModif > 0) {
561     // Store the undos
562     std::list<int>::iterator anIter = aListOfInd.begin();
563
564     if (isSetType) {
565       aValue = theCurve->getSectionType(*anIter);
566     } else {
567       aValue = theCurve->isClosed(*anIter);
568     }
569
570     setNbUndos(aNbModif);
571
572     for (i = 0; anIter != aListOfInd.end() && isOK; i++, anIter++) {
573       isOK = myPUndo[i].init(theType, aValue, *anIter);
574     }
575   }
576
577   return isOK;
578 }