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