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