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