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