+
+ // Initialize the starting point
+ myStartPoint.setX( theEvent->x() );
+ myStartPoint.setY( theEvent->y() );
+
+ switch( getActionMode() ) {
+ case ModificationMode: {
+ //store initial cursor position for Drag&Drop
+ setDragStarted( true, theEvent->pos() );
+ break;
+ }
+ case AdditionMode: {
+ addCoordsByClick( theEvent );
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+/**
+ * Manage mouse release events in Modification mode
+ * \param theWindow an owner of the signal
+ * \param theEvent a mouse event
+ */
+void CurveCreator_Widget::onMouseRelease( SUIT_ViewWindow* theWindow, QMouseEvent* theEvent )
+{
+ ActionMode aMode = getActionMode();
+ if ( aMode != ModificationMode )
+ {
+ // Emit selectionChanged() signal
+ getOCCViewer()->performSelectionChanged();
+
+ if ( aMode == AdditionMode )
+ {
+ Handle(AIS_InteractiveContext) aCtx = getAISContext();
+ if ( !aCtx.IsNull() )
+ aCtx->ClearSelected( Standard_True );
+ }
+ return;
+ }
+ if (theEvent->button() != Qt::LeftButton) return;
+ if (!theWindow->inherits("OCCViewer_ViewWindow")) return;
+
+ // Initialize the ending point
+ myEndPoint.setX( theEvent->x() );
+ myEndPoint.setY( theEvent->y() );
+
+ bool aHasShift = ( theEvent->modifiers() & Qt::ShiftModifier );
+
+ // Highlight detected objects
+ Handle(AIS_InteractiveContext) aCtx = getAISContext();
+ if ( !aCtx.IsNull() )
+ {
+ OCCViewer_ViewWindow* aView = (OCCViewer_ViewWindow*) theWindow;
+ if (!aView)
+ return;
+
+ if (!aHasShift)
+ aCtx->ClearCurrents( false );
+
+ Handle(V3d_View) aView3d = aView->getViewPort()->getView();
+ if ( !aView3d.IsNull() )
+ {
+ // Initialize the single selection if start and end points are equal,
+ // otherwise a rectangular selection.
+ if ( myStartPoint == myEndPoint )
+ {
+ aCtx->MoveTo( myEndPoint.x(), myEndPoint.y(), aView3d, Standard_True );
+ if ( aHasShift )
+ aCtx->ShiftSelect( Standard_True );
+ else
+ aCtx->Select( Standard_True );
+ }
+ else
+ {
+ if ( aHasShift )
+ aCtx->ShiftSelect( myStartPoint.x(), myStartPoint.y(), myEndPoint.x(), myEndPoint.y(),
+ aView3d, Standard_False );
+ else
+ aCtx->Select( myStartPoint.x(), myStartPoint.y(), myEndPoint.x(), myEndPoint.y(),
+ aView3d, Standard_False );
+ }
+ }
+ }
+
+ if ( myDragStarted ) {
+ bool isDragged = myDragged;
+ CurveCreator_ICurve::SectionToPointList aDraggedPoints;
+ QMap<CurveCreator_ICurve::SectionToPoint, CurveCreator::Coordinates > anInitialDragPointsCoords;
+ if ( myDragged ) {
+ aDraggedPoints = myDragPoints;
+ anInitialDragPointsCoords = myInitialDragPointsCoords;
+ }
+
+ setDragStarted( false );
+
+ if ( aDraggedPoints.size() > 0 ) {
+ // Collect old coordinates of the dragged points
+ CurveCreator_ICurve::SectionToPointCoordsList anOldPoints;
+ foreach ( const CurveCreator_ICurve::SectionToPoint aSectionToPoint, anInitialDragPointsCoords.keys() ) {
+ CurveCreator::Coordinates aCoords = anInitialDragPointsCoords.value( aSectionToPoint );
+ anOldPoints.push_back( std::make_pair( aSectionToPoint, aCoords ) );
+ }
+
+ if ( myCurve->canPointsBeSorted() ) {
+ // Add old coordinates of the curve points (except the dragged points) to the list
+ for( int aSectionId = 0 ; aSectionId < myCurve->getNbSections() ; aSectionId++ ) {
+ CurveCreator::Coordinates aCoords;
+ for ( int aPointId = 0, aNb = myCurve->getNbPoints( aSectionId ); aPointId < aNb; aPointId++ ) {
+ aCoords = myCurve->getPoint( aSectionId, aPointId );
+ if ( aCoords.size() < 2 ) {
+ continue;
+ }
+
+ CurveCreator_ICurve::SectionToPoint aSectionToPoint = std::make_pair( aSectionId, aPointId );
+
+ if ( !anInitialDragPointsCoords.contains( aSectionToPoint ) ) {
+ anOldPoints.push_back( std::make_pair( aSectionToPoint, aCoords ) );
+ }
+ }
+ }
+
+ // Apply points sorting
+ CurveCreator_ICurve::SectionToPointList aPoints;
+ startCurveModification( aPoints, false );
+
+ myCurve->setSkipSorting( false );
+
+ CurveCreator_ICurve::SectionToPointCoordsList aCoordList;
+ CurveCreator_ICurve::SectionToPointList::const_iterator anIt = aDraggedPoints.begin(),
+ aLast = aDraggedPoints.end();
+ for ( ; anIt != aLast; anIt++ ) {
+ int aSectionId = anIt->first;
+ int aPointId = anIt->second;
+ CurveCreator::Coordinates aPos = myCurve->getPoint( aSectionId, aPointId );
+
+ aCoordList.push_back(
+ std::make_pair( std::make_pair( aSectionId, aPointId ), aPos ) );
+ }
+
+ myCurve->setSeveralPoints( aCoordList, false );
+
+ finishCurveModification( aDraggedPoints );
+ } else {
+ // if the drag of some points has happened, restore the drag selection
+ START_MEASURE_TIME;
+ setSelectedPoints( aDraggedPoints );
+ END_MEASURE_TIME( "drop" );
+ }
+
+ // Save drag difference
+ myCurve->saveCoordDiff( anOldPoints );
+ }
+ }
+ else // check whether the segment is clicked an a new point should be added to the segment
+ {
+ if ( myStartPoint.x() == myEndPoint.x() && myStartPoint.y() == myEndPoint.y() )
+ insertPointToSelectedSegment( myEndPoint.x(), myStartPoint.y() );
+ }
+
+ // updates the input panel table to show the selected point coordinates
+ updateLocalPointView();
+ updateUndoRedo();
+}
+
+/**
+ * Manage mouse move events in Modification mode
+ * \param theWindow an owner of the signal
+ * \param theEvent a mouse event
+ */
+void CurveCreator_Widget::onMouseMove( SUIT_ViewWindow*, QMouseEvent* theEvent )
+{
+ if ( getActionMode() != ModificationMode || !myDragStarted )
+ return;
+
+ QPoint aPos = theEvent->pos();
+ if ( (aPos - myDragStartPosition).manhattanLength() < QApplication::startDragDistance() )
+ return;
+
+ START_MEASURE_TIME;
+
+ moveSelectedPoints( aPos.x(), aPos.y() );
+ myDragStartPosition = aPos;
+
+ END_MEASURE_TIME( "drag" );
+}
+
+/**
+ * Set zero viewer by the last view closed in
+ * \param theManager a viewer manager
+ */
+void CurveCreator_Widget::onLastViewClosed( SUIT_ViewManager* theManager )
+{
+ myOCCViewer = 0;
+}
+
+void CurveCreator_Widget::onMousePress( QMouseEvent* theEvent )
+{
+ onMousePress( 0, theEvent );
+}
+
+void CurveCreator_Widget::onMouseRelease( QMouseEvent* theEvent )
+{
+ onMouseRelease( 0, theEvent );
+}
+
+void CurveCreator_Widget::onMouseMove( QMouseEvent* theEvent )
+{
+ onMouseMove( 0, theEvent );
+}
+
+void CurveCreator_Widget::onCellChanged( int theRow, int theColumn )
+{
+ int aCurrSect = myLocalPointView->getSectionId( theRow );
+ int aPntIndex = myLocalPointView->getPointId( theRow );
+
+ if ( aPntIndex < 0 )
+ return;
+
+ CurveCreator_ICurve::SectionToPointList aSelPoints;
+ startCurveModification( aSelPoints );
+
+ double aX = myLocalPointView->item( theRow, 2 )->data( Qt::UserRole ).toDouble();
+ double anY = myLocalPointView->item( theRow, 3 )->data( Qt::UserRole ).toDouble();
+ CurveCreator::Coordinates aChangedPos;
+ aChangedPos.push_back( aX );
+ aChangedPos.push_back( anY );
+ myCurve->setPoint( aCurrSect, aPntIndex, aChangedPos );
+
+ finishCurveModification( aSelPoints );
+}
+
+/**
+ * Removes a selected section from the curve. Updates undo/redo status
+ */
+void CurveCreator_Widget::removeSection()
+{
+ stopActionMode();
+
+ QList<int> aSections = mySectionView->getSelectedSections();
+ for( int i = 0 ; i < aSections.size() ; i++ ){
+ int aSectNum = aSections[i] - (i);
+ myCurve->removeSection( aSectNum );
+ mySectionView->sectionsRemoved( aSectNum );
+ }
+ mySectionView->clearSelection();
+ updateUndoRedo();
+}
+
+/**
+ * Removes a selected points from the curve. Updates undo/redo status
+ */
+void CurveCreator_Widget::removePoint()
+{
+ CurveCreator_ICurve::SectionToPointList aPoints;
+ getSelectedPoints( aPoints );
+ if ( aPoints.size() == 0 )
+ return;
+
+ CurveCreator_ICurve::SectionToPointList aSelPoints;
+ startCurveModification( aSelPoints, false );
+
+ myCurve->removeSeveralPoints( aPoints );
+ finishCurveModification( CurveCreator_ICurve::SectionToPointList() );
+ mySectionView->reset();
+}
+
+void CurveCreator_Widget::addNewPoint(const CurveCreator::Coordinates& theCoords)
+{
+ if( !myCurve )
+ return;
+ QList<int> aSections = mySectionView->getSelectedSections();
+ if( aSections.size() == 0 ){
+ return;
+ }
+ int aSection = aSections[0];
+ myCurve->addPoints(theCoords, aSection); // add to the end of section
+ mySectionView->pointsAdded( aSection, myCurve->getNbPoints( aSection ) );
+ updateActionsStates();
+ updateUndoRedo();
+}
+
+void CurveCreator_Widget::insertPointToSelectedSegment( const int theX,
+ const int theY )
+{
+ Handle(AIS_InteractiveContext) aContext = getAISContext();
+
+ OCCViewer_ViewPort3d* aViewPort = getViewPort();
+ Handle(V3d_View) aView;
+ if ( aViewPort )
+ aView = aViewPort->getView();
+
+ if ( aContext.IsNull() || aView.IsNull() )
+ return;
+ gp_Pnt aPoint;
+ gp_Pnt aPoint1, aPoint2;
+ Handle(AIS_InteractiveObject) anAISObject = myCurve->getAISObject();
+ bool isFoundPoint = CurveCreator_Utils::pointOnObject( aView, anAISObject, theX, theY,
+ aPoint, aPoint1, aPoint2 );
+ if ( !isFoundPoint )
+ return;
+
+ // insert the point to the model curve
+ CurveCreator_ICurve::SectionToPointList aSelPoints;
+ startCurveModification( aSelPoints );
+
+ CurveCreator::Coordinates aCoords;
+ aCoords.push_back( aPoint.X() );
+ aCoords.push_back( aPoint.Y() );
+
+ CurveCreator_ICurve::SectionToPointList aPoints1, aPoints2;
+ findSectionsToPoints( aPoint1.X(), aPoint1.Y(), aPoints1 );
+ findSectionsToPoints( aPoint2.X(), aPoint2.Y(), aPoints2 );
+ CurveCreator_ICurve::SectionToPointList::const_iterator anIt = aPoints1.begin(),
+ aLast = aPoints1.end();
+ int aSectionId = -1;
+ // find the indices of the neighbour point
+ // there can be a case when a new point is added into two sections
+ int aPoint1Id = -1, aPoint2Id = -1;
+ for ( ; anIt != aLast && aSectionId < 0; anIt++ ) {
+ int aSectionCur = anIt->first;
+ CurveCreator_ICurve::SectionToPointList::const_iterator anIt2 = aPoints2.begin(),
+ aLast2 = aPoints2.end();
+ for ( ; anIt2 != aLast2 && aSectionId < 0; anIt2++ ) {
+ if ( anIt2->first == aSectionCur ) {
+ aSectionId = aSectionCur;
+ aPoint1Id = anIt->second;
+ aPoint2Id = anIt2->second;
+ }
+ }
+ }
+
+ int anInsertPos = -1;
+ int aLastPoint = myCurve->getNbPoints( aSectionId )-1;
+ if ( ( aPoint1Id == aLastPoint && aPoint2Id == 0 ) ||
+ ( aPoint2Id == aLastPoint && aPoint1Id == 0 ) )
+ anInsertPos = -1; // if the section happens between first and last points
+ else
+ anInsertPos = aPoint1Id < aPoint2Id ? aPoint1Id + 1 : aPoint2Id + 1;
+
+ myCurve->addPoints( aCoords, aSectionId, anInsertPos );
+ mySectionView->pointsAdded( aSectionId, myCurve->getNbPoints( aSectionId ) );
+
+ finishCurveModification( aSelPoints );
+
+ setSelectedPoints();
+}
+
+void CurveCreator_Widget::moveSelectedPoints( const int theXPosition,
+ const int theYPosition )
+{
+ OCCViewer_ViewPort3d* aViewPort = getViewPort();
+ if ( !aViewPort )
+ return;
+
+ CurveCreator_ICurve::SectionToPointList aPoints;
+ startCurveModification( aPoints, false );
+
+ gp_Pnt aStartPnt = CurveCreator_Utils::ConvertClickToPoint( myDragStartPosition.x(),
+ myDragStartPosition.y(),
+ aViewPort->getView() );
+ gp_Pnt anEndPnt = CurveCreator_Utils::ConvertClickToPoint( theXPosition, theYPosition,
+ aViewPort->getView() );
+ double aXDelta = aStartPnt.X() - anEndPnt.X();
+ double anYDelta = aStartPnt.Y() - anEndPnt.Y();
+
+ CurveCreator_ICurve::SectionToPointCoordsList aCoordList;
+ CurveCreator::Coordinates aChangedPos;
+ CurveCreator_ICurve::SectionToPointList::const_iterator anIt = myDragPoints.begin(),
+ aLast = myDragPoints.end();
+ for ( ; anIt != aLast; anIt++ ) {
+ int aSectionId = anIt->first;
+ int aPointId = anIt->second;
+ aChangedPos = myCurve->getPoint( aSectionId, aPointId );
+ if ( aChangedPos.size() < 2 )
+ continue;
+
+ // Remember drag points coordinates
+ if ( !myDragged ) {
+ myInitialDragPointsCoords.insert( std::make_pair( aSectionId, aPointId ), aChangedPos );
+ }
+
+ aChangedPos[0] = aChangedPos[0] - aXDelta;
+ aChangedPos[1] = aChangedPos[1] - anYDelta;
+
+ aCoordList.push_back(
+ std::make_pair(std::make_pair( aSectionId, aPointId ),
+ aChangedPos ));
+ }
+ myCurve->setSeveralPoints( aCoordList, false );
+
+ myDragged = true;
+ finishCurveModification( myDragPoints );
+}
+
+void CurveCreator_Widget::updateLocalPointView()
+{
+ if ( myDragStarted )
+ return;
+ Handle(AIS_InteractiveContext) aContext = getAISContext();
+ if ( aContext.IsNull() )
+ return;
+
+ CurveCreator_Utils::getSelectedPoints( aContext, myCurve, myLocalPoints );
+ int aNbPoints = myLocalPoints.size();
+
+ bool isRowLimit = aNbPoints > myLocalPointRowLimit;
+ myLocalPointView->setVisible( getActionMode() == ModificationMode && !isRowLimit );
+
+ if ( !isRowLimit ) {
+ bool isBlocked = myLocalPointView->blockSignals(true);
+
+ myLocalPointView->setLocalPointsToTable( myLocalPoints );
+
+ myLocalPointView->blockSignals( isBlocked );
+ }
+}
+
+/**
+ *
+ */
+void CurveCreator_Widget::setLocalPointContext( const bool theOpen, const bool isUpdateTable )
+{
+ CurveCreator_Utils::setLocalPointContext( myCurve, getAISContext(), theOpen );
+ if ( !theOpen && isUpdateTable )
+ updateLocalPointView();
+}
+
+/**
+ * Set drag operation started. Save the position and a list of dragged points
+ * \param theState the drag operation state: started/finished
+ * \param thePoint the start drag position
+ */
+void CurveCreator_Widget::setDragStarted( const bool theState, const QPoint& thePoint )
+{
+ if ( theState ) {
+ getSelectedPoints( myDragPoints );
+
+ myDragStarted = myDragPoints.size();
+ myDragStartPosition = thePoint;
+ if ( myDragStarted ) {
+ // change a viewer interaction style in order to avoid a select rectangle build
+ myDragInteractionStyle = changeInteractionStyle( SUIT_ViewModel::KEY_FREE );
+ myCurve->setSkipSorting( true );
+ }
+ }
+ else {
+ if ( myDragStarted )
+ changeInteractionStyle( myDragInteractionStyle );
+ myDragStarted = false;
+ myDragPoints.clear();
+ myInitialDragPointsCoords.clear();
+ }
+ myDragged = false;
+}
+
+void CurveCreator_Widget::getSelectedPoints( CurveCreator_ICurve::SectionToPointList& thePoints )
+{
+ thePoints.clear();
+ thePoints = myLocalPoints;
+}
+
+void CurveCreator_Widget::setSelectedPoints( const CurveCreator_ICurve::SectionToPointList& thePoints )
+{
+ if ( myDragStarted )
+ return;
+ Handle(AIS_InteractiveContext) aContext = getAISContext();
+ if ( aContext.IsNull() || !aContext->HasOpenedContext() )
+ return;
+
+ CurveCreator_Utils::setSelectedPoints( aContext, myCurve, thePoints );
+
+ updateLocalPointView();
+}
+
+void CurveCreator_Widget::stopActionMode()
+{
+ setActionMode( NoneMode );
+}
+
+/**
+ * Get viewer information before perform the curve modification.
+ * Take a list of selected cuve points an close local context.
+ * The context should be closed because the curve presentation is
+ * redisplayed and if it is not closed, when we close the local context
+ * later, the presentation shown in the local context is disappeared.
+ * \param thePoints an output list of curve selected points
+ * \param theFillPoints a flag whether the selection list should be filled
+ */
+void CurveCreator_Widget::startCurveModification(
+ CurveCreator_ICurve::SectionToPointList& thePoints,
+ const bool theFillPoints )
+{
+ if ( theFillPoints ) {
+ thePoints.clear();
+ getSelectedPoints( thePoints );
+ }
+ setLocalPointContext( false );
+}
+
+/**
+ * Restore the viewer state after the curve modification is done.
+ * Open local context and select given points inside it.
+ * \param thePoints a list of curve selected points
+ */
+void CurveCreator_Widget::finishCurveModification(
+ const CurveCreator_ICurve::SectionToPointList& thePoints )
+{
+ if ( getActionMode() == ModificationMode )
+ setLocalPointContext( true );
+ setSelectedPoints( thePoints );
+ updateUndoRedo();
+}
+
+/**
+ * Returns a point index in the model curve by the point coordinates in the viewer
+ * \param theX the X coordinate of the point
+ * \param theY the Y coordinate of the point
+ */
+int CurveCreator_Widget::findLocalPointIndex( int theSectionId, double theX, double theY )
+{
+ return CurveCreator_UtilsICurve::findLocalPointIndex( myCurve, theSectionId, theX, theY );
+}
+
+void CurveCreator_Widget::findSectionsToPoints( const double theX, const double theY,
+ CurveCreator_ICurve::SectionToPointList& thePoints )
+{
+ return CurveCreator_UtilsICurve::findSectionsToPoints( myCurve, theX, theY, thePoints );
+}
+
+void CurveCreator_Widget::convert( const CurveCreator_ICurve::SectionToPointList& thePoints,
+ QMap<int, QList<int> >& theConvPoints )
+{
+ return CurveCreator_UtilsICurve::convert( thePoints, theConvPoints );
+}
+
+/**
+ * Returns whethe the container has the value
+ * \param theList a container of values
+ * \param theValue a value
+ */
+bool CurveCreator_Widget::contains( const CurveCreator_ICurve::SectionToPointList& theList,
+ const CurveCreator_ICurve::SectionToPoint& theValue ) const
+{
+ return CurveCreator_UtilsICurve::contains( theList, theValue );