Salome HOME
0023505: Sigsegv with fuse on cylinder and cone
[modules/geom.git] / src / CurveCreator / CurveCreator_Widget.cxx
1 // Copyright (C) 2013-2016  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, or (at your option) any later version.
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 #include "CurveCreator_Widget.h"
21 #include "CurveCreator_TreeView.h"
22 #include "CurveCreator_NewSectionDlg.h"
23 #include "CurveCreator_Utils.hxx"
24 #include "CurveCreator_UtilsICurve.hxx"
25 #include "CurveCreator_TableView.h"
26
27 #include <SUIT_Session.h>
28 #include <SUIT_Desktop.h>
29 #include <SUIT_ResourceMgr.h>
30 #include <SUIT_ViewManager.h>
31
32 #include <OCCViewer_ViewManager.h>
33 #include <OCCViewer_ViewPort3d.h>
34 #include <OCCViewer_Utilities.h>
35
36 #include <QHBoxLayout>
37 #include <QVBoxLayout>
38 #include <QLabel>
39 #include <QLineEdit>
40 #include <QGroupBox>
41 #include <QToolButton>
42 #include <QToolBar>
43 #include <QAction>
44 #include <QMenu>
45 #include <QMouseEvent>
46 #include <QApplication>
47 #include <QTableWidget>
48 #include <QTime>
49 #include <QSplitter>
50
51 #include <utilities.h>
52
53 //#define MEASURE_TIME
54
55 #ifdef MEASURE_TIME
56
57   #define START_MEASURE_TIME \
58     QTime aTimer;            \
59     aTimer.start();          \
60
61   #define END_MEASURE_TIME( theMsg )                      \
62     double aTime = aTimer.elapsed() * 0.001;              \
63     FILE* aFile = fopen( "performance", "a" );            \
64     fprintf( aFile, "%s = %.3lf sec\n", theMsg, aTime );  \
65     fclose( aFile );                                      \
66
67 #else
68
69   #define START_MEASURE_TIME
70   #define END_MEASURE_TIME( theMsg )
71
72 #endif
73
74
75
76
77
78
79 CurveCreator_Widget::CurveCreator_Widget(QWidget* parent,
80                                          CurveCreator_ICurve *theCurve,
81                                          const int theActionFlags,
82                                          const QStringList& theCoordTitles,
83                                          Qt::WindowFlags fl,
84                                          int theLocalPointRowLimit )
85 : QWidget(parent), myNewSectionEditor(NULL), myCurve(theCurve), mySection(0),
86   myDragStarted( false ), myDragInteractionStyle( SUIT_ViewModel::STANDARD ),
87   myOCCViewer( 0 ), myLocalPointRowLimit( theLocalPointRowLimit ),
88   myOld2DMode(OCCViewer_ViewWindow::No2dMode)
89 {
90   bool isToEnableClosed = !( theActionFlags & DisableClosedSection );
91   myNewSectionEditor = new CurveCreator_NewSectionDlg( this, isToEnableClosed );
92   myNewSectionEditor->hide();
93   connect( myNewSectionEditor, SIGNAL(addSection()), this, SLOT(onAddNewSection()) );
94   connect( myNewSectionEditor, SIGNAL(modifySection()), this, SLOT(onModifySection()) );
95   connect( myNewSectionEditor, SIGNAL(cancelSection()), this, SLOT(onCancelSection()) );
96
97   QGroupBox* aSectionGroup = new QGroupBox(tr("SECTION_GROUP_TITLE"),this);
98
99   mySectionView = new CurveCreator_TreeView(myCurve, aSectionGroup);
100   mySectionView->setSelectionMode( QTreeView::ExtendedSelection );
101   connect( mySectionView, SIGNAL(selectionChanged()), this, SLOT( onSelectionChanged() ) );
102   connect( mySectionView, SIGNAL(sectionEntered(int)), this, SLOT(onEditSection(int)) );
103   connect( mySectionView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onContextMenu(QPoint)) );
104
105   myLocalPointView = new CurveCreator_TableView( myCurve, this, theCoordTitles );
106   connect( myLocalPointView, SIGNAL( cellChanged( int, int ) ),
107            this, SLOT( onCellChanged( int, int ) ) );
108
109   QToolBar* aTB = new QToolBar(tr("SECTION_GROUP_TITLE"), aSectionGroup);
110 //    QToolButton* anUndoBtn = new QToolButton(aTB);
111
112   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
113   QPixmap anUndoPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_UNDO")));
114   QPixmap aRedoPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_REDO")));
115   QPixmap aNewSectionPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_NEW_SECTION")));
116   QPixmap aNewPointPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_NEW_POINT")));
117   QPixmap anEditPointsPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_EDIT_POINTS")));
118   QPixmap aDetectPointsPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_EDIT_POINTS")));
119   QPixmap aPolylinePixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_POLYLINE")));
120   QPixmap aSplinePixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_SPLINE")));
121   QPixmap aRemovePixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_DELETE")));
122   QPixmap aJoinPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_JOIN")));
123   QPixmap aBringTogetherPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_BRING_TOGETHER")));
124   QPixmap aStepUpPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_ARROW_UP")));
125   QPixmap aStepDownPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_ARROW_DOWN")));
126
127   QAction* anAct = createAction( UNDO_ID, tr("UNDO"), anUndoPixmap, tr("UNDO_TLT"), 
128                                  QKeySequence(Qt::ControlModifier|Qt::Key_Z) );
129   connect(anAct, SIGNAL(triggered()), this, SLOT(onUndo()) );
130   aTB->addAction(anAct);
131
132   anAct = createAction( REDO_ID, tr("REDO"), aRedoPixmap, tr("REDO_TLT"), 
133                         QKeySequence(Qt::ControlModifier|Qt::Key_Y) );
134   connect(anAct, SIGNAL(triggered()), this, SLOT(onRedo()) );
135   aTB->addAction(anAct);
136
137   aTB->addSeparator();
138   
139   anAct = createAction( NEW_SECTION_ID, tr("NEW_SECTION"), aNewSectionPixmap, tr("NEW_SECTION_TLT"), 
140                         QKeySequence(Qt::ControlModifier|Qt::Key_N) );
141   connect(anAct, SIGNAL(triggered()), this, SLOT(onNewSection()) );
142   if ( !(theActionFlags & DisableNewSection) ) {
143     aTB->addAction(anAct);
144     aTB->addSeparator();
145   }
146
147   anAct = createAction( ADDITION_MODE_ID, tr("ADDITION_MODE"), aNewPointPixmap, tr("ADDITION_MODE_TLT"), 
148                         QKeySequence() );
149   anAct->setCheckable(true);
150   connect(anAct, SIGNAL(triggered(bool)), this, SLOT(onAdditionMode(bool)) );
151   connect(anAct, SIGNAL(toggled(bool)), this, SLOT(onModeChanged(bool)) );
152   aTB->addAction(anAct);
153   
154   anAct = createAction( MODIFICATION_MODE_ID, tr("MODIFICATION_MODE"), anEditPointsPixmap, tr("MODIFICATION_MODE_TLT"), 
155                         QKeySequence() );
156   anAct->setCheckable(true);
157   connect(anAct, SIGNAL(triggered(bool)), this, SLOT(onModificationMode(bool)) );
158   connect(anAct, SIGNAL(toggled(bool)), this, SLOT(onModeChanged(bool)) );
159   aTB->addAction(anAct);
160
161   anAct = createAction( DETECTION_MODE_ID, tr("DETECTION_MODE"), aDetectPointsPixmap, tr("DETECTION_MODE_TLT"), 
162                         QKeySequence() );
163   anAct->setCheckable(true);
164   connect(anAct, SIGNAL(triggered(bool)), this, SLOT(onDetectionMode(bool)) );
165   connect(anAct, SIGNAL(toggled(bool)), this, SLOT(onModeChanged(bool)) );
166 //  if ( !(theActionFlags & DisableDetectionMode) ) {
167 //    aTB->addAction(anAct);
168 //  }
169   
170   anAct = createAction( CLOSE_SECTIONS_ID, tr("CLOSE_SECTIONS"), QPixmap(), tr("CLOSE_SECTIONS_TLT"), 
171                         QKeySequence(Qt::ControlModifier|Qt::Key_W) );
172   connect(anAct, SIGNAL(triggered()), this, SLOT(onCloseSections()) );
173
174   anAct = createAction( UNCLOSE_SECTIONS_ID, tr("UNCLOSE_SECTIONS"), QPixmap(), 
175                         tr("UNCLOSE_SECTIONS_TLT"), QKeySequence(Qt::ControlModifier|Qt::Key_S) );
176   connect(anAct, SIGNAL(triggered()), this, SLOT(onUncloseSections()) );
177
178   anAct = createAction( SET_SECTIONS_POLYLINE_ID, tr("SET_SECTIONS_POLYLINE"), 
179                         aPolylinePixmap, tr("SET_SECTIONS_POLYLINE_TLT"), 
180                         QKeySequence(Qt::ControlModifier|Qt::Key_E) );
181   connect(anAct, SIGNAL(triggered()), this, SLOT(onSetPolyline()) );
182
183   anAct = createAction( SET_SECTIONS_SPLINE_ID, tr("SET_SECTIONS_SPLINE"), aSplinePixmap, 
184                         tr("SET_SECTIONS_SPLINE_TLT"), QKeySequence(Qt::ControlModifier|Qt::Key_R) );
185   connect(anAct, SIGNAL(triggered()), this, SLOT(onSetSpline()) );
186
187   aTB->addSeparator();
188
189   anAct = createAction( REMOVE_ID, tr("REMOVE"), aRemovePixmap, tr("REMOVE_TLT"), 
190                         QKeySequence(Qt::ControlModifier|Qt::Key_Delete ) );
191   connect(anAct, SIGNAL(triggered()), this, SLOT(onRemove()) );
192   aTB->addAction(anAct);
193   
194   anAct = createAction( JOIN_ID, tr("JOIN"), aJoinPixmap, tr("JOIN_TLT"), 
195                         QKeySequence(Qt::ControlModifier|Qt::Key_Plus ) );
196   connect( anAct, SIGNAL(triggered()), this, SLOT(onJoin()) );
197   aTB->addAction(anAct);
198
199   anAct = createAction( BRING_TOGETHER_ID, tr("BRING_TOGETHER"), aBringTogetherPixmap, tr("BRING_TOGETHER_TLT"),
200                         QKeySequence(Qt::ControlModifier|Qt::Key_Equal ) );
201   connect( anAct, SIGNAL(triggered()), this, SLOT(onBringTogether()) );
202   aTB->addAction(anAct);
203
204   anAct = createAction( CLEAR_ALL_ID, tr("CLEAR_ALL"), QPixmap(), tr("CLEAR_ALL_TLT"), 
205                         QKeySequence(Qt::ControlModifier | Qt::ShiftModifier | Qt::Key_Delete ) );
206   connect( anAct, SIGNAL(triggered()), this, SLOT( onClearAll()) );
207
208   anAct = createAction( JOIN_ALL_ID, tr("JOIN_ALL"), QPixmap(), tr("JOIN_ALL_TLT"), 
209                         QKeySequence(Qt::ControlModifier | Qt::ShiftModifier | Qt::Key_Plus ) );
210   connect( anAct, SIGNAL(triggered()), this, SLOT(onJoinAll()) );
211
212   QVBoxLayout* aSectLayout = new QVBoxLayout();
213   aSectLayout->setMargin( 5 );
214   aSectLayout->setSpacing( 5 );
215   aSectLayout->addWidget(aTB);
216
217   QSplitter* aSplitter = new QSplitter(aSectionGroup);
218   aSplitter->setOrientation(Qt::Vertical);
219
220   aSplitter->addWidget(mySectionView);
221   aSplitter->addWidget( myLocalPointView );
222
223   aSectLayout->addWidget(aSplitter);
224   aSectionGroup->setLayout(aSectLayout);
225   QVBoxLayout* aLay = new QVBoxLayout();
226   aLay->setMargin( 0 );
227   aLay->setSpacing( 5 );
228 //    aLay->addLayout(aNameLayout);
229   aLay->addWidget(aSectionGroup);
230   setLayout(aLay);
231
232   updateActionsStates();
233   updateUndoRedo();
234 }
235
236 /**
237  * Set an OCC viewer
238  */
239 void CurveCreator_Widget::setOCCViewer( OCCViewer_Viewer* theViewer )
240 {
241   if ( myOCCViewer == theViewer )
242     return;
243
244   if ( myOCCViewer ) {
245     OCCViewer_ViewManager* aViewManager = dynamic_cast<OCCViewer_ViewManager*>
246                                                     ( myOCCViewer->getViewManager() );
247     disconnect( aViewManager, SIGNAL( mousePress( SUIT_ViewWindow*, QMouseEvent* ) ),
248            this, SLOT( onMousePress( SUIT_ViewWindow*, QMouseEvent* ) ) );
249     disconnect( aViewManager, SIGNAL( mouseRelease( SUIT_ViewWindow*, QMouseEvent* ) ),
250            this, SLOT( onMouseRelease( SUIT_ViewWindow*, QMouseEvent* ) ) );
251     disconnect( aViewManager, SIGNAL( mouseMove( SUIT_ViewWindow*, QMouseEvent* ) ),
252            this, SLOT( onMouseMove( SUIT_ViewWindow*, QMouseEvent* ) ) );
253     disconnect( aViewManager, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
254            this, SLOT( onLastViewClosed( SUIT_ViewManager* ) ) );
255     // restore normal mode in the viewer
256     SetViewer2DMode(false);
257     // all local contexts should be closed if the viewer is not more used
258     setLocalPointContext( false, true );
259   }
260
261   myOCCViewer = theViewer;
262   if ( myOCCViewer ) {
263     OCCViewer_ViewManager* aViewManager = dynamic_cast<OCCViewer_ViewManager*>
264                                                     ( myOCCViewer->getViewManager() );
265     connect( aViewManager, SIGNAL( mousePress( SUIT_ViewWindow*, QMouseEvent* ) ),
266            this, SLOT( onMousePress( SUIT_ViewWindow*, QMouseEvent* ) ) );
267     connect( aViewManager, SIGNAL( mouseRelease( SUIT_ViewWindow*, QMouseEvent* ) ),
268            this, SLOT( onMouseRelease( SUIT_ViewWindow*, QMouseEvent* ) ) );
269     connect( aViewManager, SIGNAL( mouseMove( SUIT_ViewWindow*, QMouseEvent* ) ),
270            this, SLOT( onMouseMove( SUIT_ViewWindow*, QMouseEvent* ) ) );
271     connect( aViewManager, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
272            this, SLOT( onLastViewClosed( SUIT_ViewManager* ) ) );
273     SetViewer2DMode(true);
274   }
275 }
276
277 /**
278  * Returns current OCC viewer
279  */
280 OCCViewer_Viewer* CurveCreator_Widget::getOCCViewer()
281 {
282   return myOCCViewer;
283 }
284
285 /**
286  * Returns OCC viewer context
287  */
288 Handle(AIS_InteractiveContext) CurveCreator_Widget::getAISContext()
289 {
290   Handle(AIS_InteractiveContext) aContext;
291   OCCViewer_Viewer* aViewer = getOCCViewer();
292   if ( aViewer )
293     aContext = aViewer->getAISContext();
294
295   return aContext;
296 }
297
298 /**
299  * Returns OCC viewer view port
300  */
301 OCCViewer_ViewPort3d* CurveCreator_Widget::getViewPort()
302 {
303   OCCViewer_ViewPort3d* aViewPort = 0;
304   OCCViewer_Viewer* aViewer = getOCCViewer();
305   if ( aViewer )
306     aViewPort = ((OCCViewer_ViewWindow*)aViewer->getViewManager()->getActiveView())->getViewPort();
307     
308   return aViewPort;
309 }
310
311 /**
312  * Set interaction style in the OCC viewer
313  * \param theStyle a new style
314  * \return the previous style
315  */
316 int CurveCreator_Widget::changeInteractionStyle( int theStyle )
317 {
318   OCCViewer_Viewer* aViewer = getOCCViewer();
319   if ( !aViewer )
320     return -1;
321
322   int aPrevStyle = aViewer->interactionStyle();
323   aViewer->setInteractionStyle( theStyle );
324
325   return aPrevStyle;
326 }
327
328 //=======================================================================
329 // function: reset
330 // purpose: reset the widget viewer, close local context, clear selection
331 //=======================================================================
332 void CurveCreator_Widget::reset()
333 {
334   stopActionMode();
335 }
336
337 void CurveCreator_Widget::setCurve( CurveCreator_ICurve* theCurve )
338 {
339   myCurve = theCurve;
340   mySectionView->setCurve( myCurve );
341   myLocalPointView->setCurve( myCurve );
342   updateActionsStates();
343   updateUndoRedo();
344 }
345
346 void CurveCreator_Widget::onSelectionChanged()
347 {
348   updateActionsStates();
349   updateUndoRedo();
350   emit selectionChanged();
351 }
352
353 void CurveCreator_Widget::updateActionsStates()
354 {
355   QList<ActionId> anEnabledAct;
356   if( myCurve ){
357     anEnabledAct << NEW_SECTION_ID << MODIFICATION_MODE_ID;
358     if ( removeEnabled() )
359       anEnabledAct << REMOVE_ID;
360     QList<int> aSelSections = mySectionView->getSelectedSections();
361     CurveCreator_TreeView::SelectionType aSelType = mySectionView->getSelectionType();
362     switch( aSelType ){
363     case CurveCreator_TreeView::ST_NOSEL:{
364       break;
365     }
366     case CurveCreator_TreeView::ST_SECTIONS:{
367       /*if( aSelSections[0] > 0 ){
368         anEnabledAct << UP_ID;
369       }*/
370       if( aSelSections.size() == 1 ){
371         anEnabledAct << ADDITION_MODE_ID << DETECTION_MODE_ID;
372       }
373       switch ( getActionMode() ) {
374         case AdditionMode: {
375           mySection = -1;
376           myPointNum = -1;
377           QList<int> aSelSection = mySectionView->getSelectedSections();
378           if( aSelSection.size() > 0 ){
379             mySection = aSelSection[0];
380             myPointNum = myCurve->getNbPoints(mySection);
381           }
382         }
383         break;
384         case ModificationMode: {
385           if ( myNewSectionEditor->isEnableClosed() )
386             anEnabledAct << CLOSE_SECTIONS_ID << UNCLOSE_SECTIONS_ID;
387           anEnabledAct << SET_SECTIONS_POLYLINE_ID << SET_SECTIONS_SPLINE_ID;
388           int aSectCnt = myCurve->getNbSections();
389           if( aSectCnt > 0 )
390             anEnabledAct << CLEAR_ALL_ID;
391           if( aSectCnt > 1 )
392             anEnabledAct << JOIN_ALL_ID;
393           if( aSelSections.size() > 1 ){
394             anEnabledAct << JOIN_ID << BRING_TOGETHER_ID;
395           }
396         }
397         break;
398         case DetectionMode: {
399         }
400         break;
401         case NoneMode:
402           {
403             int aSectCnt = myCurve->getNbSections();
404             if( aSectCnt > 1 )
405               anEnabledAct << JOIN_ALL_ID;
406             if( aSelSections.size() > 1 )
407               anEnabledAct << JOIN_ID;
408           }
409           break;
410         default:
411         break;
412       }
413       /*if( aSelSections[ aSelSections.size() - 1 ] < ( myCurve->getNbSections() - 1 ) ){
414         anEnabledAct << DOWN_ID;
415       }*/
416       break;
417     }
418     /*case CurveCreator_TreeView::ST_POINTS_ONE_SECTION:{
419       if( aSelPoints[0].second > 0 ){
420         anEnabledAct << UP_ID;
421       }
422       int aLastIndex = aSelPoints.size()-1;
423       int aSect = aSelPoints[0].first;
424       if( aSelPoints[aLastIndex].second < (myCurve->getNbPoints(aSect) - 1)){
425         anEnabledAct << DOWN_ID;
426       }
427       if( aSelPoints.size() == 1){
428         anEnabledAct << INSERT_POINT_BEFORE_ID << INSERT_POINT_AFTER_ID;
429       }
430       break;
431     }*/
432
433     }
434     
435     /*int aSelObjsCnt = aSelPoints.size() + aSelSections.size();
436     if( aSelObjsCnt > 0 ){
437       anEnabledAct << REMOVE_ID;
438     }
439     if( (myCurve->getNbSections() + myCurve->getNbPoints()) > 0 ){
440       anEnabledAct << REMOVE_ALL_ID;
441     }*/
442     if( myCurve->getNbSections() > 1 ){
443       anEnabledAct << JOIN_ALL_ID;
444     }
445   }
446   QList<ActionId> anIds = myActionMap.keys();
447   for( int i = 0 ; i < anIds.size() ; i++ ){
448     if( myActionMap.contains(anIds[i]) ){
449       if( anEnabledAct.contains(anIds[i]) ){
450         myActionMap[anIds[i]]->setEnabled(true);
451       }
452       else{
453         myActionMap[anIds[i]]->setEnabled(false);
454       }
455     }
456   }
457 }
458
459 void CurveCreator_Widget::onAdditionMode(bool checked)
460 {
461   if (!checked)
462     return;
463
464   Handle(AIS_InteractiveContext) aContext = getAISContext();
465   if( !myCurve || aContext.IsNull() )
466     return;
467
468   mySection= -1;
469   myPointNum = -1;
470   QList<int> aSelSection = mySectionView->getSelectedSections();
471   if( aSelSection.size() > 0 ){
472     mySection = aSelSection[0];
473   }
474 //  emit subOperationStarted( myNewPointEditor );
475 }
476
477 void CurveCreator_Widget::onModificationMode(bool checked)
478 {
479   myLocalPointView->setVisible( checked );
480 }
481
482 void CurveCreator_Widget::onDetectionMode(bool checked)
483 {
484 }
485
486 void CurveCreator_Widget::onModeChanged(bool checked)
487 {
488   ActionMode aMode = NoneMode;
489   if (checked) {
490     QAction* anAction = (QAction*)sender();
491     switch(myActionMap.key(anAction)) {
492       case ADDITION_MODE_ID:
493         aMode = AdditionMode;
494         if (myActionMap[MODIFICATION_MODE_ID]->isChecked())
495           myActionMap[MODIFICATION_MODE_ID]->trigger();
496         else if (myActionMap[DETECTION_MODE_ID]->isChecked())
497           myActionMap[DETECTION_MODE_ID]->trigger();
498         break;
499       case MODIFICATION_MODE_ID:
500         aMode = ModificationMode;
501         if (myActionMap[ADDITION_MODE_ID]->isChecked())
502           myActionMap[ADDITION_MODE_ID]->trigger();
503         else if (myActionMap[DETECTION_MODE_ID]->isChecked())
504           myActionMap[DETECTION_MODE_ID]->trigger();
505         break;
506       case DETECTION_MODE_ID:
507         aMode = DetectionMode;
508         if (myActionMap[ADDITION_MODE_ID]->isChecked())
509           myActionMap[ADDITION_MODE_ID]->trigger();
510         else if (myActionMap[MODIFICATION_MODE_ID]->isChecked())
511           myActionMap[MODIFICATION_MODE_ID]->trigger();
512         break;
513     }
514   }
515   updateActionsStates();
516   updateUndoRedo();
517   setLocalPointContext( aMode == ModificationMode, true );
518 }
519
520 void CurveCreator_Widget::onNewSection()
521 {
522   if( !myCurve )
523     return;
524
525   stopActionMode();
526   myNewSectionEditor->clear();
527   myNewSectionEditor->setEditMode(false);
528   QString aSectName = QString( CurveCreator_UtilsICurve::getUniqSectionName( myCurve ).c_str() );
529   myNewSectionEditor->setSectionParameters(aSectName, true, CurveCreator::Polyline );
530   emit subOperationStarted( myNewSectionEditor, false );
531 }
532
533 void CurveCreator_Widget::onAddNewSection()
534 {
535   if( !myCurve )
536     return;
537   myCurve->addSection( myNewSectionEditor->getName().toStdString(),
538                        myNewSectionEditor->getSectionType(),
539                        myNewSectionEditor->isClosed() );
540   mySectionView->sectionAdded( -1 ); // add a new section to the end of list
541   QString aNewName = QString( CurveCreator_UtilsICurve::getUniqSectionName( myCurve ).c_str() );
542   myNewSectionEditor->setSectionName(aNewName);
543   updateActionsStates();
544   updateUndoRedo();
545   onCancelSection();
546 }
547
548 void CurveCreator_Widget::onCancelSection()
549 {
550   emit subOperationFinished( myNewSectionEditor );
551 }
552
553 QAction* CurveCreator_Widget::createAction( ActionId theId, const QString& theName, const QPixmap& theImage,
554                                             const QString& theToolTip, const QKeySequence& theShortcut )
555 {
556   QAction* anAct = new QAction(theName,this);
557   if( !theImage.isNull() ){
558     anAct->setIcon(theImage);
559   }
560   anAct->setShortcut(theShortcut);
561   anAct->setToolTip(theToolTip);
562   myActionMap[theId] = anAct;
563   return anAct;
564 }
565
566 QAction* CurveCreator_Widget::getAction( ActionId theId )
567 {
568   if( myActionMap.contains(theId) )
569     return myActionMap[theId];
570   return NULL;
571 }
572
573 QAction* CurveCreator_Widget::getAction( ActionMode theMode )
574 {
575   ActionId anActionId = NONE_ID;
576   switch ( theMode ) {
577     case AdditionMode:
578       anActionId = ADDITION_MODE_ID;
579       break;
580     case ModificationMode:
581       anActionId = MODIFICATION_MODE_ID;
582       break;
583     case DetectionMode:
584       anActionId = DETECTION_MODE_ID;
585       break;
586     default:
587       break;
588   }
589   QAction* anAction = 0;
590   if ( anActionId != NONE_ID && myActionMap.contains( anActionId ) )
591     anAction = myActionMap[anActionId];
592   return anAction;
593 }
594
595 void CurveCreator_Widget::onEditSection( int theSection )
596 {
597   if( !myCurve )
598     return;
599   
600   stopActionMode();
601   mySection = theSection;
602   QString aSectName = QString::fromStdString( myCurve->getSectionName(theSection));
603   bool isClosed = myCurve->isClosed(theSection);
604   CurveCreator::SectionType aType = myCurve->getSectionType(theSection);
605   myNewSectionEditor->setEditMode(true);
606   myNewSectionEditor->setSectionParameters( aSectName, isClosed, aType );
607
608   emit subOperationStarted( myNewSectionEditor, true );
609 }
610
611 void CurveCreator_Widget::onModifySection()
612 {
613   if( !myCurve )
614     return;
615   QString aName = myNewSectionEditor->getName();
616   bool isClosed = myNewSectionEditor->isClosed();
617   CurveCreator::SectionType aSectType = myNewSectionEditor->getSectionType();
618   if( myCurve->getSectionName(mySection) != aName.toStdString() )
619     myCurve->setSectionName( mySection , aName.toStdString() );
620
621   bool isGeomModified = false;
622
623   if( myCurve->getSectionType(mySection) != aSectType ) {
624     myCurve->setSectionType( mySection, aSectType );
625     isGeomModified = true;
626   }
627
628   if( myCurve->isClosed(mySection) != isClosed ) {
629     myCurve->setClosed( mySection, isClosed );
630     isGeomModified = true;
631   }
632   mySectionView->sectionChanged(mySection);
633   updateUndoRedo();
634   onCancelSection();
635 }
636
637 void CurveCreator_Widget::onJoin()
638 {
639   if( !myCurve )
640     return;
641   QList<int> aSections = mySectionView->getSelectedSections();
642   if( aSections.size() == 0 ){
643     return;
644   }
645   stopActionMode();
646
647   std::list<int> aSectionsToJoin;
648   for( int i = 0; i < aSections.size() ; i++ ){
649     aSectionsToJoin.push_back( aSections[i] );
650   }
651   //int aMainSect = aSectionsToJoin.front();
652   //int aMainSectSize = myCurve->getNbPoints(aMainSect);
653   if ( myCurve->join( aSectionsToJoin ) )
654   {
655     std::list<int>::const_iterator anIt = aSectionsToJoin.begin(),
656                                    aLast = aSectionsToJoin.end();
657     // the first section should be skipped. It is not removed, but is modified
658     anIt++;
659     for ( ; anIt != aLast; anIt++ )
660       mySectionView->sectionsRemoved( *anIt );
661   }
662
663   /* The update for the points of the main section
664   int aNewSectSize = myCurve->getNbPoints(aMainSect);
665   if( aNewSectSize != aMainSectSize )
666     mySectionView->pointsAdded( aMainSect, aMainSectSize, aNewSectSize-aMainSectSize );*/
667   updateUndoRedo();
668 }
669
670 void CurveCreator_Widget::onRemove()
671 {
672   if( !myCurve )
673     return;
674
675   switch( getActionMode() ) {
676     case NoneMode:
677       removeSection();
678     break;
679     case ModificationMode:
680       removePoint();
681     break;
682     default:
683       break;
684   }
685 }
686
687 void CurveCreator_Widget::onClearAll()
688 {
689   if( !myCurve )
690     return;
691   stopActionMode();
692   myCurve->clear();
693   mySectionView->reset();
694   updateActionsStates();
695   updateUndoRedo();
696 }
697
698 void CurveCreator_Widget::onJoinAll()
699 {
700   if( !myCurve )
701     return;
702   stopActionMode();
703
704   std::list<int> aSectionsToJoin;
705   for( int i = 0, aNb = myCurve->getNbSections(); i < aNb ; i++ ){
706     aSectionsToJoin.push_back( i );
707   }
708   bool aRes = myCurve->join( aSectionsToJoin );
709
710   mySectionView->reset();
711   updateActionsStates();
712   updateUndoRedo();
713 }
714
715 void CurveCreator_Widget::onUndoSettings()
716 {
717
718 }
719
720 void CurveCreator_Widget::onSetSpline()
721 {
722   if( !myCurve )
723     return;
724   stopActionMode();
725   QList<int> aSelSections = mySectionView->getSelectedSections();
726   for( int i = 0 ; i < aSelSections.size() ; i++ ){
727     myCurve->setSectionType(aSelSections[i], CurveCreator::Spline );
728     mySectionView->sectionChanged(aSelSections[i]);
729   }
730   updateUndoRedo();
731 }
732
733 void CurveCreator_Widget::onSetPolyline()
734 {
735   if( !myCurve )
736     return;
737   stopActionMode();
738   QList<int> aSelSections = mySectionView->getSelectedSections();
739   for( int i = 0 ; i < aSelSections.size() ; i++ ){
740     myCurve->setSectionType( aSelSections[i], CurveCreator::Polyline );
741     mySectionView->sectionChanged( aSelSections[i] );
742   }
743   updateUndoRedo();
744 }
745
746 void CurveCreator_Widget::onCloseSections()
747 {
748   if( !myCurve )
749     return;
750   stopActionMode();
751   QList<int> aSelSections = mySectionView->getSelectedSections();
752   for( int i = 0 ; i < aSelSections.size() ; i++ ){
753     myCurve->setClosed(aSelSections[i], true);
754     mySectionView->sectionChanged(aSelSections[i]);
755   }
756   updateUndoRedo();
757 }
758
759 void CurveCreator_Widget::onUncloseSections()
760 {
761   if( !myCurve )
762     return;
763   stopActionMode();
764   QList<int> aSelSections = mySectionView->getSelectedSections();
765   for( int i = 0 ; i < aSelSections.size() ; i++ ){
766     myCurve->setClosed(aSelSections[i], false);
767     mySectionView->sectionChanged(aSelSections[i]);
768   }
769   updateUndoRedo();
770 }
771
772 void CurveCreator_Widget::onUndo()
773 {
774   if( !myCurve )
775     return;
776
777   CurveCreator_ICurve::SectionToPointList aPoints;
778   startCurveModification( aPoints, false );
779   myCurve->undo();
780   finishCurveModification();
781   mySectionView->reset();
782 }
783
784 void CurveCreator_Widget::onRedo()
785 {
786   if( !myCurve )
787     return;
788   CurveCreator_ICurve::SectionToPointList aPoints;
789   startCurveModification( aPoints, false );
790   myCurve->redo();
791   finishCurveModification();
792   mySectionView->reset();
793 }
794
795 void CurveCreator_Widget::updateUndoRedo()
796 {
797   if( !myCurve )
798     return;
799   QAction* anAct = myActionMap[UNDO_ID];
800   if( anAct != 0 ){
801     if( myCurve->getNbUndo() != 0 ){
802       anAct->setEnabled(true);
803     }
804     else{
805       anAct->setDisabled(true);
806     }
807   }
808   anAct = myActionMap[REDO_ID];
809   if( anAct != 0 ){
810     if( myCurve->getNbRedo() != 0 ){
811       anAct->setEnabled(true);
812     }
813     else{
814       anAct->setDisabled(true);
815     }
816   }
817 }
818
819 void CurveCreator_Widget::onContextMenu( QPoint thePoint )
820 {
821   QList<ActionId> aContextActions;
822   aContextActions << CLEAR_ALL_ID << JOIN_ID << JOIN_ALL_ID << SEPARATOR_ID <<
823                      CLOSE_SECTIONS_ID << UNCLOSE_SECTIONS_ID << SET_SECTIONS_POLYLINE_ID <<
824                      SET_SECTIONS_SPLINE_ID;
825   QPoint aGlPoint = mySectionView->mapToGlobal(thePoint);
826   bool isVis = false;
827   QList<ActionId> aResAct;
828   for( int i = 0 ; i < aContextActions.size() ; i++ ){
829     if( aContextActions[i] != SEPARATOR_ID ){
830       if( myActionMap.contains(aContextActions[i]) ){
831         QAction* anAct = myActionMap[aContextActions[i]];
832         if( anAct->isEnabled() ){
833           aResAct << aContextActions[i];
834           isVis = true;
835         }
836       }
837     }
838     else{
839       aResAct << SEPARATOR_ID;
840     }
841   }
842   if( !isVis )
843     return;
844
845   QMenu* aMenu = new QMenu(this);
846   for( int i = 0 ; i < aResAct.size() ; i++ ){
847     if( aResAct[i] == SEPARATOR_ID ){
848       aMenu->addSeparator();
849     }
850     else{
851       QAction* anAct = myActionMap[aResAct[i]];
852       aMenu->insertAction(NULL, anAct);
853     }
854   }
855   aMenu->exec(aGlPoint);
856 }
857
858 QList<int> CurveCreator_Widget::getSelectedSections()
859 {
860   return mySectionView->getSelectedSections();
861 }
862
863 void CurveCreator_Widget::setSelectedSections( const QList<int>& theSections )
864 {
865   mySectionView->setSelectedSections( theSections );
866   updateActionsStates();
867   updateUndoRedo();
868 }
869
870 /**
871  * According to the widget state, performs the remove action
872  */
873 void CurveCreator_Widget::removeSelected()
874 {
875   onRemove();
876 }
877
878 /**
879  * Checks whether there are some selection to be removed
880  */
881 bool CurveCreator_Widget::removeEnabled()
882 {
883   bool isEnabled = getActionMode() == ModificationMode;
884   if ( !isEnabled ) {
885     QList<int> aSelSections = mySectionView->getSelectedSections();
886     CurveCreator_TreeView::SelectionType aSelType = mySectionView->getSelectionType();
887     isEnabled = aSelType == CurveCreator_TreeView::ST_SECTIONS &&
888                 aSelSections.size() == 1;
889   }
890   return isEnabled;
891 }
892
893 void CurveCreator_Widget::setActionMode( const ActionMode& theMode )
894 {
895   ActionMode aPrevMode = getActionMode();
896   QAction* aPrevAction = getAction( aPrevMode );
897   QAction* anAction = getAction( theMode );
898   switch ( theMode ) {
899     case NoneMode:
900     case AdditionMode: {
901       if ( aPrevAction ) {
902         if ( aPrevAction->isChecked() ) {
903           aPrevAction->setChecked( false );
904         }
905       }
906       if ( aPrevMode == ModificationMode )
907         onModificationMode( false );
908       if ( aPrevMode == AdditionMode )
909         onAdditionMode( false );
910
911       if ( theMode == AdditionMode )
912       {
913         anAction->setChecked( true );
914         onModeChanged( true );
915       }
916     }
917     break;
918     break;
919     case ModificationMode:
920     {
921       //TODO
922     }
923     break;
924     case DetectionMode:
925       break;
926   }
927 }
928
929 CurveCreator_Widget::ActionMode CurveCreator_Widget::getActionMode() const
930 {
931   ActionMode aMode = NoneMode;
932
933   if ( myActionMap[ADDITION_MODE_ID]->isChecked() )
934     aMode = AdditionMode;
935   else if ( myActionMap[MODIFICATION_MODE_ID]->isChecked() )
936     aMode = ModificationMode;
937   else if ( myActionMap[DETECTION_MODE_ID]->isChecked() )
938     aMode = DetectionMode;
939
940   return aMode;
941 }
942
943 void CurveCreator_Widget::SetViewer2DMode(const bool To2D)
944 {
945   if (myOCCViewer) {
946     if (To2D) {
947       myOld2DMode = OCCViewer_Utilities::setViewer2DMode
948                     (myOCCViewer, OCCViewer_ViewWindow::XYPlane);
949     } else {
950       OCCViewer_Utilities::setViewer2DMode(myOCCViewer, myOld2DMode);
951     }
952   }
953 }
954
955 //=================================================================================
956 // function : GeometryGUI::addCoordsByClick()
957 // purpose  : Manage mouse press events in Additon mode
958 //=================================================================================
959 void CurveCreator_Widget::addCoordsByClick( QMouseEvent* pe )
960 {
961   if (pe->button() != Qt::LeftButton)
962     return;
963
964   if ( pe->modifiers() != Qt::ControlModifier ) {
965     Handle(AIS_InteractiveContext) ic = getAISContext();
966     if ( ic.IsNull() )
967       return;
968
969     gp_Pnt aPnt;    
970     OCCViewer_ViewPort3d* vp = getViewPort();
971
972     aPnt = CurveCreator_Utils::ConvertClickToPoint( pe->x(), pe->y(), vp->getView() );
973
974     // set the coordinates into dialog
975     CurveCreator::Coordinates aCoords;
976     aCoords.push_back( aPnt.X() );
977     aCoords.push_back( aPnt.Y() );
978     if ( myCurve->getDimension() == 3 ) {
979       aCoords.push_back( aPnt.Z() );
980     }
981     addNewPoint(aCoords);
982   }
983 }
984
985 /**
986  * Set the same coordinates on two section extremities.
987  * Usage: build a closed contour with several sections.
988  * Works with two points selected, at the extremities of different sections.
989  * The second point gets the coordinates of the first.
990  */
991 void CurveCreator_Widget::onBringTogether()
992 {
993   MESSAGE("onBringTogether");
994   ActionMode aMode = getActionMode();
995   if ( aMode != ModificationMode )
996     return;
997   int nbPoints = myLocalPoints.size();
998   MESSAGE("number of selected points: " << nbPoints);
999   if (nbPoints != 2)
1000     {
1001       MESSAGE("works only with two points taken at the extremities of different sections, nothing done");
1002       return;
1003     }
1004
1005   CurveCreator_ICurve::SectionToPointList::const_iterator anIt = myLocalPoints.begin(),
1006                                                           aLast = myLocalPoints.end();
1007   std::vector<int> sections(nbPoints);
1008   std::vector<int> iPoints(nbPoints);
1009   std::vector<int> nbPtsSection(nbPoints);
1010   std::vector<double> x(nbPoints);
1011   std::vector<double> y(nbPoints);
1012   int i = 0;
1013   for ( ; anIt != aLast; anIt++, i++ )
1014     {
1015       CurveCreator_ICurve::SectionToPoint aSPoint = *anIt;
1016       sections[i] = aSPoint.first;
1017       iPoints[i] = aSPoint.second;
1018       nbPtsSection[i] = myCurve->getNbPoints(sections[i]);
1019       if ((iPoints[i] != 0) && (iPoints[i] != nbPtsSection[i]-1))
1020         {
1021           MESSAGE("a point is not on a section extremity, nothing done");
1022           return;
1023         }
1024       gp_Pnt aPoint;
1025       CurveCreator_UtilsICurve::getPoint( myCurve, sections[i], iPoints[i], aPoint );
1026       x[i] = aPoint.X();
1027       y[i] = aPoint.Y();
1028       MESSAGE("point: " << sections[i] << " " << iPoints[i] << " " << x[i] << " " << y[i]);
1029     }
1030   if (sections[1] == sections[0])
1031     {
1032       MESSAGE("the two points must be at the extremities of different sections, nothing done");
1033       return;
1034     }
1035
1036   CurveCreator_ICurve::SectionToPointList aSelPoints;
1037   startCurveModification( aSelPoints );
1038
1039   CurveCreator::Coordinates aChangedPos;
1040   aChangedPos.push_back( x[0] ); // apply the first point coordinates to the second point.
1041   aChangedPos.push_back( y[0] );
1042   myCurve->setPoint( sections[1], iPoints[1], aChangedPos );
1043
1044   finishCurveModification( aSelPoints );
1045 }
1046
1047 /**
1048  * Manage mouse press events
1049  * \param theWindow an owner of the signal
1050  * \param theEvent a mouse event
1051  */
1052 void CurveCreator_Widget::onMousePress( SUIT_ViewWindow*, QMouseEvent* theEvent )
1053 {
1054   if ( theEvent->button() != Qt::LeftButton )
1055     return;
1056
1057   // Initialize the starting point
1058   myStartPoint.setX( theEvent->x() );
1059   myStartPoint.setY( theEvent->y() );
1060
1061   switch( getActionMode() ) {
1062     case ModificationMode: {
1063       //store initial cursor position for Drag&Drop
1064       setDragStarted( true, theEvent->pos() );
1065       break;
1066     }
1067     case AdditionMode: {
1068       addCoordsByClick( theEvent );
1069       break;
1070     }
1071     default:
1072       break;
1073   }
1074 }
1075
1076 /**
1077  * Manage mouse release events in Modification mode
1078  * \param theWindow an owner of the signal
1079  * \param theEvent a mouse event
1080  */
1081 void CurveCreator_Widget::onMouseRelease( SUIT_ViewWindow* theWindow, QMouseEvent* theEvent )
1082 {
1083   ActionMode aMode = getActionMode();
1084   if ( aMode != ModificationMode )
1085   {
1086     // Emit selectionChanged() signal
1087     getOCCViewer()->performSelectionChanged();
1088
1089     if ( aMode == AdditionMode )
1090     {
1091       Handle(AIS_InteractiveContext) aCtx = getAISContext();
1092       if ( !aCtx.IsNull() )
1093         aCtx->ClearSelected( Standard_True );
1094     }
1095     return;
1096   } 
1097   if (theEvent->button() != Qt::LeftButton) return;
1098   if (!theWindow->inherits("OCCViewer_ViewWindow")) return;
1099
1100   // Initialize the ending point
1101   myEndPoint.setX( theEvent->x() );
1102   myEndPoint.setY( theEvent->y() );
1103
1104   bool aHasShift = ( theEvent->modifiers() & Qt::ShiftModifier );
1105
1106   // Highlight detected objects
1107   Handle(AIS_InteractiveContext) aCtx = getAISContext();
1108   if ( !aCtx.IsNull() )
1109   {
1110     OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*) theWindow;
1111     if (!aView)
1112       return;
1113
1114     if (!aHasShift)
1115       aCtx->ClearCurrents( false );
1116
1117     Handle(V3d_View) aView3d = aView->getViewPort()->getView();
1118     if ( !aView3d.IsNull() )
1119     {
1120       // Initialize the single selection if start and end points are equal,
1121       // otherwise a rectangular selection.
1122       if ( myStartPoint == myEndPoint )
1123       {
1124         aCtx->MoveTo( myEndPoint.x(), myEndPoint.y(), aView3d, Standard_True );
1125         if ( aHasShift )
1126           aCtx->ShiftSelect( Standard_True );
1127         else
1128           aCtx->Select( Standard_True );
1129       }
1130       else
1131       {
1132         if ( aHasShift )
1133           aCtx->ShiftSelect( myStartPoint.x(), myStartPoint.y(), myEndPoint.x(), myEndPoint.y(),
1134                              aView3d, Standard_False );
1135         else
1136           aCtx->Select( myStartPoint.x(), myStartPoint.y(), myEndPoint.x(), myEndPoint.y(),
1137                         aView3d, Standard_False );
1138       }
1139     }
1140   }
1141
1142   if ( myDragStarted ) {
1143     bool isDragged = myDragged;
1144     CurveCreator_ICurve::SectionToPointList aDraggedPoints;
1145     QMap<CurveCreator_ICurve::SectionToPoint, CurveCreator::Coordinates > anInitialDragPointsCoords;
1146     if ( myDragged ) {
1147       aDraggedPoints = myDragPoints;
1148       anInitialDragPointsCoords = myInitialDragPointsCoords;
1149     }
1150
1151     setDragStarted( false );
1152
1153     if ( aDraggedPoints.size() > 0 ) {
1154       // Collect old coordinates of the dragged points
1155       CurveCreator_ICurve::SectionToPointCoordsList anOldPoints;
1156       foreach ( const CurveCreator_ICurve::SectionToPoint aSectionToPoint, anInitialDragPointsCoords.keys() ) {
1157         CurveCreator::Coordinates aCoords = anInitialDragPointsCoords.value( aSectionToPoint );
1158         anOldPoints.push_back( std::make_pair( aSectionToPoint, aCoords ) );
1159       }
1160
1161       if ( myCurve->canPointsBeSorted() ) {
1162         // Add old coordinates of the curve points (except the dragged points) to the list
1163         for( int aSectionId = 0 ; aSectionId < myCurve->getNbSections() ; aSectionId++ ) {
1164           CurveCreator::Coordinates aCoords;
1165           for ( int aPointId = 0, aNb = myCurve->getNbPoints( aSectionId ); aPointId < aNb; aPointId++ ) {
1166             aCoords = myCurve->getPoint( aSectionId, aPointId );
1167             if ( aCoords.size() < 2 ) {
1168               continue;
1169             }
1170             
1171             CurveCreator_ICurve::SectionToPoint aSectionToPoint = std::make_pair( aSectionId, aPointId );
1172
1173             if ( !anInitialDragPointsCoords.contains( aSectionToPoint ) ) {
1174               anOldPoints.push_back( std::make_pair( aSectionToPoint, aCoords ) );
1175             }
1176           }
1177         }
1178         
1179         // Apply points sorting
1180         CurveCreator_ICurve::SectionToPointList aPoints;
1181         startCurveModification( aPoints, false );
1182
1183         myCurve->setSkipSorting( false );
1184
1185         CurveCreator_ICurve::SectionToPointCoordsList aCoordList;
1186         CurveCreator_ICurve::SectionToPointList::const_iterator anIt = aDraggedPoints.begin(),
1187                                                                 aLast = aDraggedPoints.end();
1188         for ( ; anIt != aLast; anIt++ ) {
1189           int aSectionId = anIt->first;
1190           int aPointId = anIt->second;
1191           CurveCreator::Coordinates aPos = myCurve->getPoint( aSectionId, aPointId );
1192
1193           aCoordList.push_back(
1194             std::make_pair( std::make_pair( aSectionId, aPointId ), aPos ) );
1195         }
1196
1197         myCurve->setSeveralPoints( aCoordList, false );
1198     
1199         finishCurveModification( aDraggedPoints );
1200       } else {
1201         // if the drag of some points has happened, restore the drag selection
1202         START_MEASURE_TIME;
1203         setSelectedPoints( aDraggedPoints );
1204         END_MEASURE_TIME( "drop" );
1205       }
1206
1207       // Save drag difference
1208       myCurve->saveCoordDiff( anOldPoints );
1209     }
1210   }
1211   else // check whether the segment is clicked an a new point should be added to the segment
1212   {
1213     if ( myStartPoint.x() == myEndPoint.x() && myStartPoint.y() == myEndPoint.y() )
1214       insertPointToSelectedSegment( myEndPoint.x(), myStartPoint.y() );
1215   }
1216
1217   // updates the input panel table to show the selected point coordinates
1218   updateLocalPointView();
1219   updateUndoRedo();
1220 }
1221
1222 /**
1223  * Manage mouse move events in Modification mode
1224  * \param theWindow an owner of the signal
1225  * \param theEvent a mouse event
1226  */
1227 void CurveCreator_Widget::onMouseMove( SUIT_ViewWindow*, QMouseEvent* theEvent )
1228 {
1229   if ( getActionMode() != ModificationMode || !myDragStarted )
1230     return;
1231
1232   QPoint aPos = theEvent->pos();
1233   if ( (aPos - myDragStartPosition).manhattanLength() < QApplication::startDragDistance() )
1234     return;
1235
1236   START_MEASURE_TIME;
1237
1238   moveSelectedPoints( aPos.x(), aPos.y() );
1239   myDragStartPosition = aPos;
1240
1241   END_MEASURE_TIME( "drag" );
1242 }
1243
1244 /**
1245  * Set zero viewer by the last view closed in
1246  * \param theManager a viewer manager
1247  */
1248 void CurveCreator_Widget::onLastViewClosed( SUIT_ViewManager* theManager )
1249 {
1250   myOCCViewer = 0;
1251 }
1252
1253 void CurveCreator_Widget::onMousePress( QMouseEvent* theEvent )
1254 {
1255   onMousePress( 0, theEvent );
1256 }
1257
1258 void CurveCreator_Widget::onMouseRelease( QMouseEvent* theEvent )
1259 {
1260   onMouseRelease( 0, theEvent );
1261 }
1262
1263 void CurveCreator_Widget::onMouseMove( QMouseEvent* theEvent )
1264 {
1265   onMouseMove( 0, theEvent );
1266 }
1267
1268 void CurveCreator_Widget::onCellChanged( int theRow, int theColumn )
1269 {
1270   int aCurrSect = myLocalPointView->getSectionId( theRow );
1271   int aPntIndex = myLocalPointView->getPointId( theRow );
1272
1273   if ( aPntIndex < 0 )
1274     return;
1275
1276   CurveCreator_ICurve::SectionToPointList aSelPoints;
1277   startCurveModification( aSelPoints );
1278
1279   double aX  = myLocalPointView->item( theRow, 2 )->data( Qt::UserRole ).toDouble();
1280   double anY = myLocalPointView->item( theRow, 3 )->data( Qt::UserRole ).toDouble();
1281   CurveCreator::Coordinates aChangedPos;
1282   aChangedPos.push_back( aX );
1283   aChangedPos.push_back( anY );
1284   myCurve->setPoint( aCurrSect, aPntIndex, aChangedPos );
1285
1286   finishCurveModification( aSelPoints );
1287 }
1288
1289 /**
1290  * Removes a selected section from the curve. Updates undo/redo status
1291  */
1292 void CurveCreator_Widget::removeSection()
1293 {
1294   stopActionMode();
1295
1296   QList<int> aSections = mySectionView->getSelectedSections();
1297   for( int i = 0 ; i < aSections.size() ; i++ ){
1298     int aSectNum = aSections[i] - (i);
1299     myCurve->removeSection( aSectNum );
1300     mySectionView->sectionsRemoved( aSectNum );
1301   }
1302   mySectionView->clearSelection();
1303   updateUndoRedo();
1304 }
1305
1306 /**
1307  * Removes a selected points from the curve. Updates undo/redo status
1308  */
1309 void CurveCreator_Widget::removePoint()
1310 {
1311   CurveCreator_ICurve::SectionToPointList aPoints;
1312   getSelectedPoints( aPoints );
1313   if ( aPoints.size() == 0 )
1314     return;
1315
1316   CurveCreator_ICurve::SectionToPointList aSelPoints;
1317   startCurveModification( aSelPoints, false );
1318
1319   myCurve->removeSeveralPoints( aPoints );
1320   finishCurveModification( CurveCreator_ICurve::SectionToPointList() );
1321   mySectionView->reset();
1322 }
1323
1324 void CurveCreator_Widget::addNewPoint(const CurveCreator::Coordinates& theCoords)
1325 {
1326   if( !myCurve )
1327     return;
1328   QList<int> aSections = mySectionView->getSelectedSections();
1329   if( aSections.size() == 0 ){
1330     return;
1331   }
1332   int aSection = aSections[0];
1333   myCurve->addPoints(theCoords, aSection); // add to the end of section
1334   mySectionView->pointsAdded( aSection, myCurve->getNbPoints( aSection ) );
1335   updateActionsStates();
1336   updateUndoRedo();
1337 }
1338
1339 void CurveCreator_Widget::insertPointToSelectedSegment( const int theX,
1340                                                         const int theY )
1341 {
1342   Handle(AIS_InteractiveContext) aContext = getAISContext();
1343
1344   OCCViewer_ViewPort3d* aViewPort = getViewPort();
1345   Handle(V3d_View) aView;
1346   if ( aViewPort )
1347     aView = aViewPort->getView();
1348
1349   if ( aContext.IsNull() || aView.IsNull() )
1350     return;
1351   gp_Pnt aPoint;
1352   gp_Pnt aPoint1, aPoint2;
1353   Handle(AIS_InteractiveObject) anAISObject = myCurve->getAISObject();
1354   bool isFoundPoint = CurveCreator_Utils::pointOnObject( aView, anAISObject, theX, theY,
1355                                                          aPoint, aPoint1, aPoint2 );
1356   if ( !isFoundPoint )
1357     return;
1358
1359   // insert the point to the model curve
1360   CurveCreator_ICurve::SectionToPointList aSelPoints;
1361   startCurveModification( aSelPoints );
1362
1363   CurveCreator::Coordinates aCoords;
1364   aCoords.push_back( aPoint.X() );
1365   aCoords.push_back( aPoint.Y() );
1366
1367   CurveCreator_ICurve::SectionToPointList aPoints1, aPoints2;
1368   findSectionsToPoints( aPoint1.X(), aPoint1.Y(), aPoints1 );
1369   findSectionsToPoints( aPoint2.X(), aPoint2.Y(), aPoints2 );
1370   CurveCreator_ICurve::SectionToPointList::const_iterator anIt = aPoints1.begin(),
1371                                                           aLast = aPoints1.end();
1372   int aSectionId = -1;
1373   // find the indices of the neighbour point
1374   // there can be a case when a new point is added into two sections
1375   int aPoint1Id = -1, aPoint2Id = -1;
1376   for ( ; anIt != aLast && aSectionId < 0; anIt++ ) {
1377     int aSectionCur = anIt->first;
1378     CurveCreator_ICurve::SectionToPointList::const_iterator anIt2 = aPoints2.begin(),
1379                                                             aLast2 = aPoints2.end();
1380     for ( ; anIt2 != aLast2 && aSectionId < 0; anIt2++ ) {
1381       if ( anIt2->first == aSectionCur ) {
1382         aSectionId = aSectionCur;
1383         aPoint1Id = anIt->second;
1384         aPoint2Id = anIt2->second;
1385       }
1386     }
1387   }
1388
1389   int anInsertPos = -1;
1390   int aLastPoint = myCurve->getNbPoints( aSectionId )-1; 
1391   if ( ( aPoint1Id == aLastPoint && aPoint2Id == 0 ) ||
1392        ( aPoint2Id == aLastPoint && aPoint1Id == 0 ) )
1393     anInsertPos = -1; // if the section happens between first and last points
1394   else
1395     anInsertPos = aPoint1Id < aPoint2Id ? aPoint1Id + 1 : aPoint2Id + 1;
1396
1397   myCurve->addPoints( aCoords, aSectionId, anInsertPos );
1398   mySectionView->pointsAdded( aSectionId, myCurve->getNbPoints( aSectionId ) );
1399
1400   finishCurveModification( aSelPoints );
1401
1402   setSelectedPoints();
1403 }
1404
1405 void CurveCreator_Widget::moveSelectedPoints( const int theXPosition,
1406                                               const int theYPosition )
1407 {
1408   OCCViewer_ViewPort3d* aViewPort = getViewPort();
1409   if ( !aViewPort )
1410     return;
1411
1412   CurveCreator_ICurve::SectionToPointList aPoints;
1413   startCurveModification( aPoints, false );
1414
1415   gp_Pnt aStartPnt = CurveCreator_Utils::ConvertClickToPoint( myDragStartPosition.x(),
1416                                                               myDragStartPosition.y(),
1417                                                               aViewPort->getView() );
1418   gp_Pnt anEndPnt = CurveCreator_Utils::ConvertClickToPoint( theXPosition, theYPosition,
1419                                                              aViewPort->getView() );
1420   double aXDelta = aStartPnt.X() - anEndPnt.X();
1421   double anYDelta = aStartPnt.Y() - anEndPnt.Y();
1422
1423   CurveCreator_ICurve::SectionToPointCoordsList aCoordList;
1424   CurveCreator::Coordinates aChangedPos;
1425   CurveCreator_ICurve::SectionToPointList::const_iterator anIt = myDragPoints.begin(),
1426                                                           aLast = myDragPoints.end();
1427   for ( ; anIt != aLast; anIt++ ) {
1428     int aSectionId = anIt->first;
1429     int aPointId = anIt->second;
1430     aChangedPos = myCurve->getPoint( aSectionId, aPointId );
1431     if ( aChangedPos.size() < 2 )
1432       continue;
1433
1434     // Remember drag points coordinates
1435     if ( !myDragged ) {
1436       myInitialDragPointsCoords.insert( std::make_pair( aSectionId, aPointId ), aChangedPos );
1437     }
1438
1439     aChangedPos[0] = aChangedPos[0] - aXDelta;
1440     aChangedPos[1] = aChangedPos[1] - anYDelta;
1441     
1442     aCoordList.push_back(
1443       std::make_pair(std::make_pair( aSectionId, aPointId ), 
1444                      aChangedPos ));
1445   }
1446   myCurve->setSeveralPoints( aCoordList, false );
1447
1448   myDragged = true;
1449   finishCurveModification( myDragPoints );
1450 }
1451
1452 void CurveCreator_Widget::updateLocalPointView()
1453 {
1454   if ( myDragStarted )
1455     return;
1456   Handle(AIS_InteractiveContext) aContext = getAISContext();
1457   if ( aContext.IsNull() )
1458     return;
1459
1460   CurveCreator_Utils::getSelectedPoints( aContext, myCurve, myLocalPoints );
1461   int aNbPoints = myLocalPoints.size();
1462
1463   bool isRowLimit = aNbPoints > myLocalPointRowLimit;
1464   myLocalPointView->setVisible( getActionMode() == ModificationMode && !isRowLimit );
1465
1466   if ( !isRowLimit ) {
1467     bool isBlocked = myLocalPointView->blockSignals(true);
1468
1469     myLocalPointView->setLocalPointsToTable( myLocalPoints );
1470
1471     myLocalPointView->blockSignals( isBlocked );
1472   }
1473 }
1474
1475 /**
1476  * 
1477  */
1478 void CurveCreator_Widget::setLocalPointContext( const bool theOpen, const bool isUpdateTable )
1479 {
1480   CurveCreator_Utils::setLocalPointContext( myCurve, getAISContext(), theOpen );
1481   if ( !theOpen && isUpdateTable )
1482     updateLocalPointView();
1483 }
1484
1485 /**
1486  * Set drag operation started. Save the position and a list of dragged points
1487  * \param theState the drag operation state: started/finished
1488  * \param thePoint the start drag position
1489  */
1490 void CurveCreator_Widget::setDragStarted( const bool theState, const QPoint& thePoint )
1491 {
1492   if ( theState ) {
1493     getSelectedPoints( myDragPoints );
1494
1495     myDragStarted = myDragPoints.size();
1496     myDragStartPosition = thePoint;
1497     if ( myDragStarted ) {
1498       // change a viewer interaction style in order to avoid a select rectangle build
1499       myDragInteractionStyle = changeInteractionStyle( SUIT_ViewModel::KEY_FREE );
1500       myCurve->setSkipSorting( true );
1501     }
1502   }
1503   else {
1504     if ( myDragStarted )
1505       changeInteractionStyle( myDragInteractionStyle );
1506     myDragStarted = false;
1507     myDragPoints.clear();
1508     myInitialDragPointsCoords.clear();
1509   }
1510   myDragged = false;
1511 }
1512
1513 void CurveCreator_Widget::getSelectedPoints( CurveCreator_ICurve::SectionToPointList& thePoints )
1514 {
1515   thePoints.clear();
1516   thePoints = myLocalPoints;
1517 }
1518
1519 void CurveCreator_Widget::setSelectedPoints( const CurveCreator_ICurve::SectionToPointList& thePoints )
1520 {
1521   if ( myDragStarted )
1522     return;
1523   Handle(AIS_InteractiveContext) aContext = getAISContext();
1524   if ( aContext.IsNull() || !aContext->HasOpenedContext() )
1525     return;
1526
1527   CurveCreator_Utils::setSelectedPoints( aContext, myCurve, thePoints );
1528
1529   updateLocalPointView();
1530 }
1531
1532 void CurveCreator_Widget::stopActionMode()
1533 {
1534   setActionMode( NoneMode );
1535 }
1536
1537 /**
1538  * Get viewer information before perform the curve modification.
1539  * Take a list of selected cuve points an close local context.
1540  * The context should be closed because the curve presentation is
1541  * redisplayed and if it is not closed, when we close the local context
1542  * later, the presentation shown in the local context is disappeared.
1543  * \param thePoints an output list of curve selected points
1544  * \param theFillPoints a flag whether the selection list should be filled
1545  */
1546 void CurveCreator_Widget::startCurveModification(
1547                            CurveCreator_ICurve::SectionToPointList& thePoints,
1548                            const bool theFillPoints )
1549 {
1550   if ( theFillPoints ) {
1551     thePoints.clear();
1552     getSelectedPoints( thePoints );
1553   }
1554   setLocalPointContext( false );
1555 }
1556
1557 /**
1558  * Restore the viewer state after the curve modification is done.
1559  * Open local context and select given points inside it.
1560  * \param thePoints a list of curve selected points
1561  */
1562 void CurveCreator_Widget::finishCurveModification(
1563                            const CurveCreator_ICurve::SectionToPointList& thePoints )
1564 {
1565   if ( getActionMode() == ModificationMode )
1566     setLocalPointContext( true );
1567   setSelectedPoints( thePoints );
1568   updateUndoRedo();
1569 }
1570
1571 /**
1572  * Returns a point index in the model curve by the point coordinates in the viewer
1573  * \param theX the X coordinate of the point
1574  * \param theY the Y coordinate of the point
1575  */
1576 int CurveCreator_Widget::findLocalPointIndex( int theSectionId, double theX, double theY )
1577 {
1578   return CurveCreator_UtilsICurve::findLocalPointIndex( myCurve, theSectionId, theX, theY );
1579 }
1580
1581 void CurveCreator_Widget::findSectionsToPoints( const double theX, const double theY,
1582                                  CurveCreator_ICurve::SectionToPointList& thePoints )
1583 {
1584   return CurveCreator_UtilsICurve::findSectionsToPoints( myCurve, theX, theY, thePoints );
1585 }
1586
1587 void CurveCreator_Widget::convert( const CurveCreator_ICurve::SectionToPointList& thePoints,
1588                                    QMap<int, QList<int> >& theConvPoints )
1589 {
1590   return CurveCreator_UtilsICurve::convert( thePoints, theConvPoints );
1591 }
1592
1593 /**
1594  * Returns whethe the container has the value
1595  * \param theList a container of values
1596  * \param theValue a value
1597  */
1598 bool CurveCreator_Widget::contains( const CurveCreator_ICurve::SectionToPointList& theList,
1599                                     const CurveCreator_ICurve::SectionToPoint& theValue ) const
1600 {
1601   return CurveCreator_UtilsICurve::contains( theList, theValue );
1602 }