Salome HOME
94f41248773476f7ddaa35ab4782afb0d6bccc93
[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   qSort( aPoints );
997   SectionToPointList::const_iterator anIt = aPoints.end(), aFirst = aPoints.begin();
998   anIt--;
999   for ( ; anIt != aFirst; anIt-- ) {
1000     int aSectionId = anIt->first;
1001     int aPointId = anIt->second;
1002     myCurve->removePoint( aSectionId, aPointId );
1003     mySectionView->pointsRemoved( aSectionId, aPointId );
1004   }
1005   finishCurveModification( SectionToPointList() );
1006 }
1007
1008 void CurveCreator_Widget::insertPointToSelectedSegment( const int theX,
1009                                                         const int theY )
1010 {
1011   OCCViewer_Viewer* aViewer = getOCCViewer();
1012   if ( !aViewer )
1013     return;
1014
1015   gp_Pnt aPoint;
1016   gp_Pnt aPoint1, aPoint2;
1017   bool isFoundPoint = false;
1018   Handle(AIS_InteractiveContext) aContext = aViewer->getAISContext();
1019   for ( aContext->InitSelected(); aContext->MoreSelected() && !isFoundPoint;
1020         aContext->NextSelected() ) {
1021     TopoDS_Shape aTShape = aContext->SelectedShape();
1022     if ( !aTShape.IsNull() && aTShape.ShapeType() == TopAbs_VERTEX )
1023       continue;
1024     else {
1025       Handle(SelectMgr_EntityOwner) anOwner = aContext->SelectedOwner();
1026       if ( anOwner.IsNull() )
1027         continue;
1028       const TopLoc_Location& aLocation = anOwner->Location();
1029       Handle(AIS_InteractiveObject) anAIS = Handle(AIS_InteractiveObject)::DownCast( anOwner->Selectable() );
1030       isFoundPoint = pointOnObject( anAIS, theX, theY, aPoint, aPoint1, aPoint2 );
1031     }
1032   }
1033   if ( !isFoundPoint )
1034     return;
1035
1036   // insert the point to the model curve
1037   SectionToPointList aSelPoints;
1038   startCurveModification( aSelPoints );
1039
1040   CurveCreator::Coordinates aCoords;
1041   aCoords.push_back( aPoint.X() );
1042   aCoords.push_back( aPoint.Y() );
1043
1044   SectionToPointList aPoints1, aPoints2;
1045   findSectionsToPoints( aPoint1.X(), aPoint1.Y(), aPoints1 );
1046   findSectionsToPoints( aPoint2.X(), aPoint2.Y(), aPoints2 );
1047   SectionToPointList::const_iterator anIt = aPoints1.begin(), aLast = aPoints1.end();
1048   int aSectionId = -1;
1049   // there can be a case when a new point is added into two sections
1050   int aPoint1Id = -1, aPoint2Id = -1;
1051   for ( ; anIt != aLast && aSectionId < 0; anIt++ ) {
1052     int aSectionCur = anIt->first;
1053     SectionToPointList::const_iterator anIt2 = aPoints2.begin(), aLast2 = aPoints2.end();
1054     for ( ; anIt2 != aLast2 && aSectionId < 0; anIt2++ ) {
1055       if ( anIt2->first == aSectionCur ) {
1056         aSectionId = aSectionCur;
1057         aPoint1Id = anIt->second;
1058         aPoint2Id = anIt2->second;
1059       }
1060     }
1061   }
1062
1063   int anInsertPos = -1;
1064   int aLastPoint = myCurve->getNbPoints( aSectionId )-1; 
1065   if ( ( aPoint1Id == aLastPoint && aPoint2Id == 0 ) ||
1066        ( aPoint2Id == aLastPoint && aPoint1Id == 0 ) )
1067     anInsertPos = -1; // if the section happens between first and last points
1068   else
1069     anInsertPos = aPoint1Id < aPoint2Id ? aPoint1Id + 1 : aPoint2Id + 1;
1070
1071   myCurve->addPoints( aCoords, aSectionId, anInsertPos );
1072   mySectionView->pointsAdded( aSectionId, myCurve->getNbPoints( aSectionId ) );
1073
1074   finishCurveModification( aSelPoints );
1075
1076   setSelectedPonts();
1077   updateUndoRedo();
1078 }
1079
1080 void CurveCreator_Widget::moveSelectedPoints( const int theXPosition,
1081                                               const int theYPosition )
1082 {
1083   OCCViewer_Viewer* aViewer = getOCCViewer();
1084   if ( !aViewer )
1085     return;
1086
1087   SectionToPointList aPoints;
1088   startCurveModification( aPoints, false );
1089
1090   OCCViewer_ViewWindow* aWindow =
1091            (OCCViewer_ViewWindow*)aViewer->getViewManager()->getActiveView();
1092   gp_Pnt aStartPnt = CurveCreator_Utils::ConvertClickToPoint( myDragStartPosition.x(),
1093                                                      myDragStartPosition.y(),
1094                                                      aWindow->getViewPort()->getView() );
1095   gp_Pnt anEndPnt = CurveCreator_Utils::ConvertClickToPoint( theXPosition, theYPosition,
1096                                                      aWindow->getViewPort()->getView() );
1097   double aXDelta = aStartPnt.X() - anEndPnt.X();
1098   double anYDelta = aStartPnt.Y() - anEndPnt.Y();
1099
1100   int aSectionId;
1101   int aPointId;
1102   std::deque<float> aChangedPos;
1103   SectionToPointList::const_iterator anIt = myDragPoints.begin(), aLast = myDragPoints.end();
1104   for ( ; anIt != aLast; anIt++ ) {
1105     aSectionId = anIt->first;
1106     aPointId = anIt->second;
1107     aChangedPos = myCurve->getPoint( aSectionId, aPointId );
1108     if ( aChangedPos.size() < 2 )
1109       continue;
1110     aChangedPos[0] = aChangedPos[0] - aXDelta;
1111     aChangedPos[1] = aChangedPos[1] - anYDelta;
1112     myCurve->setPoint( aSectionId, aPointId, aChangedPos );
1113   }
1114   myDragged = true;
1115   finishCurveModification( myDragPoints );
1116 }
1117
1118 void CurveCreator_Widget::updateLocalPointView()
1119 {
1120   OCCViewer_Viewer* aViewer = getOCCViewer();
1121   if ( !aViewer )
1122     return;
1123   Handle(AIS_InteractiveContext) aContext = aViewer->getAISContext();
1124
1125   bool isBlocked = myLocalPointView->blockSignals(true);
1126   gp_Pnt aPnt;
1127   myLocalPointView->setRowCount( 0 );
1128   for ( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() ) {
1129     TopoDS_Vertex aVertex;
1130     TopoDS_Shape aShape = aContext->SelectedShape();
1131     if ( !aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX )
1132       aVertex = TopoDS::Vertex( aContext->SelectedShape() );
1133     else {
1134       Handle(SelectMgr_EntityOwner) anOwner = aContext->SelectedOwner();
1135       if ( !anOwner.IsNull() ) {
1136         Handle(AIS_InteractiveObject) anAIS = Handle(AIS_InteractiveObject)::DownCast( anOwner->Selectable() );
1137         if ( !anAIS.IsNull() ) {
1138           Handle(AIS_Point) aPoint = Handle(AIS_Point)::DownCast( anAIS);
1139           if ( !aPoint.IsNull() )
1140             aVertex = TopoDS::Vertex( aPoint->Vertex() );
1141         }
1142         if ( aVertex.IsNull() ) {
1143           // the following happens if there are no points in the current curve, there is only a shape
1144           /*Handle(StdSelect_BRepOwner) aBrepOwner = Handle(StdSelect_BRepOwner)::DownCast(anOwner);
1145           if ( aBrepOwner.IsNull() )
1146             continue;
1147           if ( aBrepOwner->HasShape() ) {
1148             const TopoDS_Shape& aShape = aBrepOwner->Shape();
1149             if ( !aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX )
1150             {
1151               aVertex = TopoDS::Vertex( aShape );
1152             }
1153           }*/
1154         }
1155       }
1156       if ( aVertex.IsNull() )
1157         continue;
1158       aPnt = BRep_Tool::Pnt( aVertex );
1159       addLocalPointToTable( aPnt.X(), aPnt.Y() );
1160     }
1161   }
1162   myLocalPointView->blockSignals(isBlocked);
1163 }
1164
1165 /**
1166  * 
1167  */
1168 void CurveCreator_Widget::setLocalPointContext( const bool theOpen, const bool isUpdateTable )
1169 {
1170   OCCViewer_Viewer* aViewer = getOCCViewer();
1171   if ( !aViewer )
1172     return;
1173   Handle(AIS_InteractiveContext) ic = aViewer->getAISContext();
1174
1175   if ( theOpen ) {
1176     // Open local context if there is no one
1177     if ( !ic->HasOpenedContext() ) {
1178       ic->ClearCurrents( false );
1179       ic->OpenLocalContext( false/*use displayed objects*/, true/*allow shape decomposition*/ );
1180     }
1181     AIS_ListOfInteractive aList;
1182     ic->DisplayedObjects( aList );
1183     int aLSize = 0;
1184     for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() )
1185       aLSize++;
1186
1187     for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() )
1188     {
1189       Handle(AIS_InteractiveObject) anAIS = it.Value();
1190       if ( !anAIS.IsNull() )
1191       {
1192         if ( anAIS->IsKind( STANDARD_TYPE( AIS_Shape ) ) )
1193         {
1194           ic->Load( anAIS, -1/*selection mode*/, true/*allow decomposition*/ );
1195           ic->Activate( anAIS, AIS_Shape::SelectionMode( (TopAbs_ShapeEnum)TopAbs_WIRE ) );
1196         }
1197         else if ( anAIS->DynamicType() != STANDARD_TYPE(AIS_Trihedron) )
1198         {
1199           ic->Load( anAIS, -1/*selection mode*/, false/*allow decomposition*/ );
1200           ic->Activate( anAIS, TopAbs_VERTEX );
1201         }
1202       }
1203       continue;
1204     }
1205   }
1206   else {
1207     if ( ic->HasOpenedContext() )
1208       ic->CloseAllContexts();
1209     if ( isUpdateTable )
1210       updateLocalPointView();
1211   }
1212 }
1213
1214 void CurveCreator_Widget::addLocalPointToTable( const double theX, const double theY )
1215 {
1216   SectionToPointList aPoints;
1217   findSectionsToPoints( theX, theY, aPoints );
1218
1219   SectionToPointList aSkipList;
1220   // table could not contain two equal value rows
1221   int aRowId = myLocalPointView->rowCount();
1222   double aCurrentX, aCurrentY;
1223   int aSectionId, aPointId;
1224   SectionToPoint aPoint;
1225   for ( int i = 0; i < aRowId; i++ ) {
1226     aCurrentX = myLocalPointView->item( i, 2 )->data( Qt::UserRole ).toDouble();
1227     aCurrentY = myLocalPointView->item( i, 3 )->data( Qt::UserRole ).toDouble();
1228     if ( fabs( aCurrentX - theX ) < LOCAL_SELECTION_TOLERANCE &&
1229          fabs( aCurrentY - theY ) < LOCAL_SELECTION_TOLERANCE ) {
1230       aPoint = qMakePair( getSectionId( i ), getPointId( i ) );
1231       if ( !aSkipList.contains( aPoint ) )
1232         aSkipList.append( aPoint );
1233     }
1234   }
1235   if ( aSkipList.size() == aPoints.size() )
1236     return;
1237
1238   QTableWidgetItem* anItem;
1239   SectionToPointList::const_iterator anIt = aPoints.begin(), aLast = aPoints.end();
1240   for ( ; anIt != aLast; anIt++ ) {
1241     aPoint = *anIt;
1242     if ( aSkipList.contains( aPoint ) )
1243       continue;
1244
1245     myLocalPointView->setRowCount( aRowId+1 );
1246     aSectionId = aPoint.first;
1247     aPointId = aPoint.second;
1248
1249     anItem = new QTableWidgetItem( myCurve->getSectionName( aSectionId ).c_str() );
1250     anItem->setFlags( anItem->flags() & ~Qt::ItemIsEnabled );
1251     anItem->setData( Qt::UserRole, aSectionId );
1252     myLocalPointView->setItem( aRowId, 0, anItem );
1253
1254     anItem = new QTableWidgetItem( QString::number( aPointId + 1 ) );
1255     anItem->setFlags( anItem->flags() & ~Qt::ItemIsEnabled );
1256     anItem->setData( Qt::UserRole, aPointId );
1257     myLocalPointView->setItem( aRowId, 1, anItem );
1258
1259     anItem = new QTableWidgetItem( QString::number( theX ) );
1260     anItem->setData( Qt::UserRole, theX );
1261     myLocalPointView->setItem( aRowId, 2, anItem );
1262
1263     anItem = new QTableWidgetItem( QString::number( theY ) );
1264     anItem->setData( Qt::UserRole, theY );
1265     myLocalPointView->setItem( aRowId, 3, anItem );
1266   }
1267 }
1268
1269 /**
1270  * Set drag operation started. Save the position and a list of dragged points
1271  * \param theState the drag operation state: started/finished
1272  * \param thePoint the start drag position
1273  */
1274 void CurveCreator_Widget::setDragStarted( const bool theState, const QPoint& thePoint )
1275 {
1276   OCCViewer_Viewer* aViewer = getOCCViewer();
1277   if ( theState ) {
1278     getSelectedPonts( myDragPoints );
1279     myDragStarted = myDragPoints.size();
1280     myDragStartPosition = thePoint;
1281     if ( aViewer && myDragStarted ) {
1282       // change a viewer interaction style in order to avoid a select rectangle build
1283       myDragInteractionStyle = aViewer->interactionStyle();
1284       aViewer->setInteractionStyle(SUIT_ViewModel::KEY_FREE);
1285     }
1286   }
1287   else {
1288     if ( aViewer && myDragStarted )
1289       aViewer->setInteractionStyle( myDragInteractionStyle );
1290     myDragStarted = false;
1291     myDragPoints.clear();
1292   }
1293   myDragged = false;
1294 }
1295
1296 void CurveCreator_Widget::getSelectedPonts( CurveCreator_Widget::SectionToPointList& thePoints )
1297 {
1298   thePoints.clear();
1299   for ( int i = 0, aNb = myLocalPointView->rowCount(); i < aNb; i++ )
1300     thePoints.append( qMakePair( getSectionId( i ), getPointId( i ) ) );
1301 }
1302
1303 void CurveCreator_Widget::setSelectedPonts( const CurveCreator_Widget::SectionToPointList& thePoints )
1304 {
1305   OCCViewer_Viewer* aViewer = getOCCViewer();
1306   if ( !aViewer )
1307     return;
1308
1309   AIS_ListOfInteractive aListToSelect;
1310
1311   Handle(AIS_InteractiveContext) ic = aViewer->getAISContext();
1312   if ( !ic->HasOpenedContext() )
1313     return;
1314
1315   AIS_ListOfInteractive aDisplayedList;
1316   ic->DisplayedObjects( aDisplayedList );
1317   for ( AIS_ListIteratorOfListOfInteractive it( aDisplayedList ); it.More(); it.Next() )
1318   {
1319     Handle(AIS_InteractiveObject) anAIS = it.Value();
1320     if ( anAIS.IsNull() )
1321       continue;
1322     Handle(AIS_Point) anAISPoint = Handle(AIS_Point)::DownCast( anAIS );
1323     if ( anAISPoint.IsNull() )
1324       continue;
1325
1326     TopoDS_Vertex aVertex = TopoDS::Vertex( anAISPoint->Vertex() );
1327
1328     if ( aVertex.IsNull() )
1329       continue;
1330
1331     gp_Pnt aPnt = BRep_Tool::Pnt( aVertex );
1332
1333     SectionToPointList aPoints;
1334     findSectionsToPoints( aPnt.X(), aPnt.Y(), aPoints );
1335
1336     SectionToPointList::const_iterator anIt = aPoints.begin(), aLast = aPoints.end();
1337     SectionToPoint aPoint;
1338     for ( ; anIt != aLast; anIt++ ) {
1339       aPoint = *anIt;
1340       if ( thePoints.contains( aPoint ) )
1341         aListToSelect.Append( anAIS );
1342     }
1343   }
1344
1345   ic->ClearSelected( Standard_False );
1346   aViewer->setObjectsSelected( aListToSelect );
1347   updateLocalPointView();
1348 }
1349
1350 /**
1351  * Get viewer information before perform the curve modification.
1352  * Take a list of selected cuve points an close local context.
1353  * The context should be closed because the curve presentation is
1354  * redisplayed and if it is not closed, when we close the local context
1355  * later, the presentation shown in the local context is disappeared.
1356  * \param thePoints an output list of curve selected points
1357  * \param theFillPoints a flag whether the selection list should be filled
1358  */
1359 void CurveCreator_Widget::startCurveModification(
1360                            CurveCreator_Widget::SectionToPointList& thePoints,
1361                            const bool theFillPoints )
1362 {
1363   if ( theFillPoints ) {
1364     thePoints.clear();
1365     getSelectedPonts( thePoints );
1366   }
1367   setLocalPointContext( false );
1368 }
1369
1370 /**
1371  * Restore the viewer state after the curve modification is done.
1372  * Open local context and select given points inside it.
1373  * \param thePoints a list of curve selected points
1374  */
1375 void CurveCreator_Widget::finishCurveModification(
1376                            const CurveCreator_Widget::SectionToPointList& thePoints )
1377 {
1378   setLocalPointContext( true );
1379   int aSectionId = 0;
1380   setSelectedPonts( thePoints );
1381 }
1382
1383 /**
1384  * Returns a point index in the model curve by the point coordinates in the viewer
1385  * \param theX the X coordinate of the point
1386  * \param theY the Y coordinate of the point
1387  */
1388 int CurveCreator_Widget::findLocalPointIndex( int theSectionId, float theX, float theY )
1389 {
1390   int aPntIndex = -1;
1391
1392   CurveCreator::Coordinates aCoords;
1393   for ( int i = 0, aNb = myCurve->getNbPoints( theSectionId ); i < aNb && aPntIndex < 0; i++ ) {
1394     aCoords = myCurve->getPoint( theSectionId, i );
1395     if ( aCoords.size() < 2 )
1396       continue;
1397     if ( fabs( aCoords[0] - theX ) < LOCAL_SELECTION_TOLERANCE &&
1398          fabs( aCoords[1] - theY ) < LOCAL_SELECTION_TOLERANCE )
1399       aPntIndex = i;
1400   }
1401
1402   return aPntIndex;
1403 }
1404
1405 void CurveCreator_Widget::findSectionsToPoints( const double theX, const double theY,
1406                                  CurveCreator_Widget::SectionToPointList& thePoints )
1407 {
1408   thePoints.clear();
1409
1410   int aPointId = -1;
1411   for ( int i = 0, aNb = myCurve->getNbSections(); i < aNb; i++ ) {
1412     aPointId = findLocalPointIndex( i, theX, theY );
1413     if ( aPointId < 0 )
1414       continue;
1415     SectionToPoint aPoint = qMakePair( i, aPointId );
1416     if ( !thePoints.contains( aPoint ) )
1417      thePoints.append( aPoint );
1418   }
1419 }
1420
1421 /**
1422  * Checks whether the point belongs to the OCC object
1423  * \param theObject a line or shape with a bspline inside
1424  * \param theX the X coordinate in the view.
1425  * \param theY the Y coordinate in the view.
1426  * \param thePoint the output point to be append to the model curve
1427  * \param thePoint1 the output point to bound the line where a new point should be inserted
1428  * \param thePoint2 the output point to bound the line where a new point should be inserted
1429  */
1430 bool CurveCreator_Widget::pointOnObject( Handle(AIS_InteractiveObject) theObject,
1431                                          const int theX, const int theY,
1432                                          gp_Pnt& thePoint,
1433                                          gp_Pnt& thePoint1, gp_Pnt& thePoint2 )
1434 {
1435   bool isFound = false;
1436
1437   OCCViewer_Viewer* aViewer = getOCCViewer();
1438   if ( theObject.IsNull() || !aViewer )
1439     return isFound;
1440
1441   gp_Pnt aPoint;
1442   Standard_Real aParameter;
1443   gp_Pnt aPnt1, aPnt2;
1444   Handle(AIS_Line) aLine = Handle(AIS_Line)::DownCast( theObject );
1445   if ( !aLine.IsNull() ) {
1446     const Handle(Geom_Line) aGLine = aLine->Line();
1447     isFound = hasProjectPointOnCurve( theX, theY, aGLine, aParameter );
1448     if ( isFound ) {
1449       aPoint = aGLine->Value( aParameter );
1450
1451       Handle(Geom_Point) aPStart;
1452       Handle(Geom_Point) aPEnd;
1453       aLine->Points( aPStart, aPEnd );
1454       aPnt1 = aPStart->Pnt();
1455       aPnt2 = aPEnd->Pnt();
1456
1457       // in case of Geom line a projection is performed to the infinite line,
1458       // so it is necessary to bound it by the line size
1459       Bnd_Box aLineBox;
1460       aLineBox.Set( aPnt1, gp_Vec( aPnt1, aPnt2 ) );
1461       isFound = !aLineBox.IsOut( aPoint );
1462     }
1463   }
1464   else {
1465     Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast( theObject );
1466     if ( !aShape.IsNull() ) {
1467       const TopoDS_Wire& aWire = TopoDS::Wire( aShape->Shape() );
1468       if ( !aWire.IsNull() ) {
1469         TopExp_Explorer anExp( aWire, TopAbs_EDGE );
1470         for ( ; anExp.More(); anExp.Next())
1471         {
1472           const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current());
1473           if ( !anEdge.IsNull() ) {
1474             Standard_Real aFirst, aLast;
1475             Handle(Geom_Curve) aCurve = BRep_Tool::Curve( anEdge, aFirst, aLast );
1476
1477             if ( aCurve->IsKind( STANDARD_TYPE(Geom_BSplineCurve) ) ) {
1478               Handle(Geom_BSplineCurve) aBSplineCurve = Handle(Geom_BSplineCurve)::DownCast( aCurve );
1479               if ( !aBSplineCurve.IsNull() ) {
1480                 isFound = hasProjectPointOnCurve( theX, theY, aCurve, aParameter );
1481                 if ( isFound ) {
1482                   aPoint = aBSplineCurve->Value( aParameter );
1483                   Standard_Integer anI1, anI2;
1484                   aBSplineCurve->LocateU( aParameter, LOCAL_SELECTION_TOLERANCE, anI1, anI2 );
1485
1486                   aPnt1 = aBSplineCurve->Value( aBSplineCurve->Knot( anI1 ) );
1487                   aPnt2 = aBSplineCurve->Value( aBSplineCurve->Knot( anI2 ) );
1488                 }
1489               }
1490             }
1491           }
1492         }
1493       }
1494     }
1495   }
1496   if ( isFound ) {
1497     thePoint = aPoint;
1498
1499     thePoint1 = aPnt1;
1500     thePoint2 = aPnt2;
1501     //thePoint1 = findLocalPointIndex( 0, aPnt1.X(), aPnt1.Y() );
1502     //thePoint2 = findLocalPointIndex( 0, aPnt2.X(), aPnt2.Y() );
1503     //isFound = thePoint1 >= 0 && thePoint2 >= 0;
1504   }
1505   return isFound;
1506 }
1507
1508 /**
1509  * Returns whether the clicked point belong to the curve or has a very near projection
1510  * \param theX the X coordinate of a point clicked in the OCC viewer
1511  * \param theY the Y coordinate of a point clicked in the OCC viewer
1512  * \param theCurve a geometry curve
1513  * \param theOutPoint a found projected point on the curve
1514  */
1515 bool CurveCreator_Widget::hasProjectPointOnCurve( const int theX, const int theY,
1516                                                   const Handle(Geom_Curve)& theCurve,
1517                                                   Standard_Real& theParameter )
1518 {
1519   bool isFound = false;
1520   OCCViewer_Viewer* aViewer = getOCCViewer();
1521   if ( !aViewer )
1522     return isFound;
1523
1524   OCCViewer_ViewWindow* aWindow =
1525            (OCCViewer_ViewWindow*)aViewer->getViewManager()->getActiveView();
1526   Handle(V3d_View) aView = aWindow->getViewPort()->getView();
1527   gp_Pnt aPoint = CurveCreator_Utils::ConvertClickToPoint( theX, theY, aView );
1528
1529   GeomAPI_ProjectPointOnCurve aProj( aPoint, theCurve );
1530   Standard_Integer aNbPoint = aProj.NbPoints();
1531   if (aNbPoint > 0) {
1532     for (Standard_Integer j = 1; j <= aNbPoint && !isFound; j++) {
1533       gp_Pnt aNewPoint = aProj.Point( j );
1534       theParameter = aProj.Parameter( j );
1535
1536       int aX, anY;
1537       CurveCreator_Utils::ConvertPointToClick( aNewPoint, aView, aX, anY );
1538
1539       int aXDelta = abs( aX - theX );
1540       int anYDelta = abs( anY - theY );
1541       isFound = aXDelta < SCENE_PIXEL_TOLERANCE && anYDelta < SCENE_PIXEL_TOLERANCE;
1542     }
1543   }
1544   return isFound;
1545 }
1546
1547 /**
1548  * Returns a section index from the table
1549  * \param theRowId a table row
1550  */
1551 int CurveCreator_Widget::getSectionId( const int theRowId ) const
1552 {
1553   return myLocalPointView->item( theRowId, 0 )->data( Qt::UserRole ).toInt();
1554 }
1555
1556 /**
1557  * Returns a point index from the table
1558  * \param theRowId a table row
1559  */
1560 int CurveCreator_Widget::getPointId( const int theRowId ) const
1561 {
1562   return myLocalPointView->item( theRowId, 1 )->data( Qt::UserRole ).toInt();
1563 }