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