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