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