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