Salome HOME
bug fixes/improvements (678, 681, 679, etc..)
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_LandCoverMapOp.cxx
index 96655be197d5f11dbf5b83091812536e003adea8..a04f5a1ca1267a996e1a13c46627899fc7415722 100644 (file)
 #include "HYDROGUI_Tool.h"
 #include "HYDROGUI_UpdateFlags.h"
 #include "HYDROGUI_DataObject.h"
+#include "HYDROGUI_ShapeLandCoverMap.h"
 
 #include <HYDROData_Iterator.h>
 #include <HYDROData_StricklerTable.h>
 #include <HYDROData_PolylineXY.h>
 #include <HYDROData_Object.h>
 
+#include <OCCViewer_ViewManager.h>
+#include <OCCViewer_ViewModel.h>
+
+#include <LightApp_Application.h>
+
+#include <TopoDS.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <AIS_Shape.hxx>
+
+#include <QApplication>
+
 HYDROGUI_LandCoverMapOp::HYDROGUI_LandCoverMapOp( HYDROGUI_Module* theModule, const int theOperationId )
 : HYDROGUI_Operation( theModule ),
   myOperationId( theOperationId ),
@@ -53,6 +67,9 @@ HYDROGUI_LandCoverMapOp::HYDROGUI_LandCoverMapOp( HYDROGUI_Module* theModule, co
     case MergeLandCoverId:
       setName( tr( "MERGE_LAND_COVER" ) );
       break;
+    case ChangeLandCoverTypeId:
+      setName( tr( "CHANGE_LAND_COVER_TYPE" ) );
+      break;
   }  
 }
 
@@ -99,8 +116,14 @@ void HYDROGUI_LandCoverMapOp::startOperation()
     }
   }  
   aPanel->setObjectName( anObjectName );
-  
+
+  closePreview();
+  if ( myOperationId != CreateLandCoverMapId )
+    onCreatePreview();
+
   aPanel->blockSignals( false );
+
+  module()->update( UF_OCCViewer | UF_FitAll );
 }
 
 void HYDROGUI_LandCoverMapOp::abortOperation()
@@ -108,6 +131,8 @@ void HYDROGUI_LandCoverMapOp::abortOperation()
   closePreview();
 
   HYDROGUI_Operation::abortOperation();
+
+  module()->update( UF_OCCViewer | UF_FitAll );
 }
 
 void HYDROGUI_LandCoverMapOp::commitOperation()
@@ -115,17 +140,15 @@ void HYDROGUI_LandCoverMapOp::commitOperation()
   closePreview();
 
   HYDROGUI_Operation::commitOperation();
+
+  module()->update( UF_OCCViewer | UF_FitAll );
 }
 
 HYDROGUI_InputPanel* HYDROGUI_LandCoverMapOp::createInputPanel() const
 {
   HYDROGUI_LandCoverMapDlg* aPanel = new HYDROGUI_LandCoverMapDlg( module(), getName(), myOperationId );
-  /*
-  connect( aPanel, SIGNAL( CreatePreview( const QStringList& ) ),
-           this,   SLOT( onCreatePreview( const QStringList& ) ) );
-  connect( aPanel, SIGNAL( addPolylines() ), SLOT( onAddPolylines() ) );
-  connect( aPanel, SIGNAL( removePolylines() ), SLOT( onRemovePolylines() ) );
-  */
+  connect( aPanel, SIGNAL( landCoverMapChanged( const QString& ) ),
+           this, SLOT( onLandCoverMapChanged( const QString& ) ) );
   return aPanel;
 }
 
@@ -156,9 +179,12 @@ bool HYDROGUI_LandCoverMapOp::processApply( int& theUpdateFlags,
     }
   }
 
-  // Get selected polyline/face
   Handle(HYDROData_PolylineXY) aPolyline;
   Handle(HYDROData_Object) aFace;
+
+  TopTools_ListOfShape aFacesSelectedInViewer;
+
+  // Get polyline/face selected in combo-box
   if ( myOperationId == CreateLandCoverMapId || myOperationId == AddLandCoverId || myOperationId == SplitLandCoverId )
   {
     Handle(HYDROData_Entity) aPolylineFace = aPanel->getPolylineFace();
@@ -170,10 +196,25 @@ bool HYDROGUI_LandCoverMapOp::processApply( int& theUpdateFlags,
       return false;
     }
   }
+  // Get face(s) selected in the 3d viewer
+  else if ( myOperationId == RemoveLandCoverId || 
+            myOperationId == MergeLandCoverId || 
+            myOperationId == ChangeLandCoverTypeId )
+  {
+    if ( myPreviewPrs )
+    {
+      // Fill in aFacesSelectedInViewer list
+      Handle(AIS_InteractiveContext) aCtx;
+      getSelectedShapes( aFacesSelectedInViewer, aCtx );
+    }
+  }
 
   // Get selected Strickler type
   QString aSelectedStricklerType;
-  if ( myOperationId == CreateLandCoverMapId || myOperationId == AddLandCoverId || myOperationId == MergeLandCoverId )
+  if ( myOperationId == CreateLandCoverMapId || 
+       myOperationId == AddLandCoverId || 
+       myOperationId == MergeLandCoverId ||
+       myOperationId == ChangeLandCoverTypeId )
   {
     aSelectedStricklerType = aPanel->getSelectedStricklerTypeName();
     if ( aSelectedStricklerType.isEmpty() )
@@ -190,6 +231,7 @@ bool HYDROGUI_LandCoverMapOp::processApply( int& theUpdateFlags,
   // Set land cover map name
   aLandCoverMapObj->SetName( anObjectName );
   
+  // Add land cover to new / edited land cover map
   if ( myOperationId == CreateLandCoverMapId || myOperationId == AddLandCoverId )
   {
     bool aLandCoverAdded = false;
@@ -203,30 +245,88 @@ bool HYDROGUI_LandCoverMapOp::processApply( int& theUpdateFlags,
       return false;
     }
   }
-    
-  /*TCollection_AsciiString anError;
-  if ( HYDROData_LandCover::buildShape( aZonePolylines, anError ).IsNull() )
+
+  // Remove land cover from edited land cover map
+  if ( myOperationId == RemoveLandCoverId )
   {
-    if ( !anError.IsEmpty() ) {
-      theErrorMsg = HYDROGUI_Tool::ToQString( anError );
-    } else {
-      theErrorMsg = tr( "LAND_COVER_OBJECT_CANNOT_BE_CREATED" );
+    bool aLandCoverRemoved = false;
+    if ( !aFacesSelectedInViewer.IsEmpty() )
+    {
+      aLandCoverRemoved = aLandCoverMapObj->Remove( aFacesSelectedInViewer );
+      if ( !aLandCoverRemoved )
+      {
+        theErrorMsg = tr( "LAND_COVER_NOT_REMOVED" );
+        return false;
+      }
     }
-    return false;
-  }*/  
+  }
+
+  // Split land cover(s) inside edited land cover map
+  if ( myOperationId == SplitLandCoverId )
+  {
+    bool aLandCoverSplitted = false;
+    if ( !aPolyline.IsNull() )
+      aLandCoverSplitted = aLandCoverMapObj->Split( aPolyline );
+    else if ( !aFace.IsNull() )
+    {
+      // Get the complete boundary of the object face as the splitting polyline
+      QList<TopoDS_Shape> aBoundShapes;
+      QStringList aBoundNames;
+      aFace->GetBoundaries( aBoundShapes, aBoundNames );
 
-  /*if ( myOperationId == CreateLandCoverMapId )
-  {    
-    aLandCoverMapObj->SetFillingColor( aLandCoverMapObj->DefaultFillingColor() );
-    aLandCoverMapObj->SetBorderColor( aLandCoverMapObj->DefaultBorderColor() );
-  }*/
+      for( int i=0, n=aBoundShapes.size(); i<n; i++ )
+      {
+        TopoDS_Shape aShape = aBoundShapes[i];
+        if( aShape.IsNull() )
+          continue;
+
+        bool aSplitResult = aLandCoverMapObj->Split( aShape );
+        aLandCoverSplitted = ( i==0 ? aSplitResult : aLandCoverSplitted && aSplitResult );
+      }
+    }
+    if ( !aLandCoverSplitted )
+    {
+      theErrorMsg = tr( "LAND_COVER_NOT_SPLITTED" );
+      return false;
+    }
+  }
 
-  //aLandCoverMapObj->SetPolylines( aZonePolylines );
-  //aLandCoverMapObj->SetStricklerType( aSelectedStricklerType );
+  // Merge land covers inside edited land cover map
+  if ( myOperationId == MergeLandCoverId )
+  {
+    bool aLandCoverMerged = false;
+    if ( !aFacesSelectedInViewer.IsEmpty() )
+    {
+      aLandCoverMerged = aLandCoverMapObj->Merge( aFacesSelectedInViewer, aSelectedStricklerType );
+      if ( !aLandCoverMerged )
+      {
+        theErrorMsg = tr( "LAND_COVER_NOT_MERGED" );
+        return false;
+      }
+    }
+  }
+
+  // Change Strickler type for land cover(s) inside edited land cover map
+  if ( myOperationId == ChangeLandCoverTypeId )
+  {
+    bool aLandCoverChangeType = false;
+    if ( !aFacesSelectedInViewer.IsEmpty() )
+    {
+      aLandCoverChangeType = aLandCoverMapObj->ChangeType( aFacesSelectedInViewer, aSelectedStricklerType );
+      if ( !aLandCoverChangeType )
+      {
+        theErrorMsg = tr( "LAND_COVER_TYPE_NOT_CHANGED" );
+        return false;
+      }
+    }
+  }
+    
+  // Update land cover map object and close preview
   aLandCoverMapObj->Update();
 
   closePreview();
 
+  // Publish the newly created land cover map in the Object Browser
   module()->setObjectVisible( HYDROGUI_Tool::GetActiveOCCViewId( module() ), aLandCoverMapObj, true );
   if ( myOperationId == CreateLandCoverMapId )
   {
@@ -234,6 +334,7 @@ bool HYDROGUI_LandCoverMapOp::processApply( int& theUpdateFlags,
     theBrowseObjectsEntries.append( anEntry );
   }
 
+  // Update presentation of land cover object in the 3d viewer
   module()->setIsToUpdate( aLandCoverMapObj );
   module()->getOCCDisplayer()->SetToUpdateColorScale();
 
@@ -242,29 +343,29 @@ bool HYDROGUI_LandCoverMapOp::processApply( int& theUpdateFlags,
   return true;
 }
 
-void HYDROGUI_LandCoverMapOp::onCreatePreview( const QStringList& thePolylineNames )
+void HYDROGUI_LandCoverMapOp::onLandCoverMapChanged( const QString& theName )
 {
-  /*
-  HYDROGUI_LandCoverDlg* aPanel = ::qobject_cast<HYDROGUI_LandCoverDlg*>( inputPanel() );
+  // If the edited land cover map was changed in the combo-box, update myEditedObject
+  if ( myOperationId != CreateLandCoverMapId )
+  {
+    myEditedObject = Handle(HYDROData_LandCoverMap)::DownCast( HYDROGUI_Tool::FindObjectByName( module(), theName ) );
+    if ( !myEditedObject.IsNull() )
+    {
+      // Show preview of the newly selected land cover map
+      closePreview();
+      onCreatePreview();
+    }
+  }
+}
+
+void HYDROGUI_LandCoverMapOp::onCreatePreview()
+{
+  HYDROGUI_LandCoverMapDlg* aPanel = ::qobject_cast<HYDROGUI_LandCoverMapDlg*>( inputPanel() );
   if ( !aPanel )
     return;
 
   QApplication::setOverrideCursor( Qt::WaitCursor );  
 
-  HYDROData_SequenceOfObjects aZonePolylines;
-  QStringList::const_iterator anIt = thePolylineNames.begin(), aLast = thePolylineNames.end();
-  for( ; anIt!=aLast; anIt++ )
-  {
-    QString aPolylineName = *anIt;
-    Handle(HYDROData_PolylineXY) aPolyline = Handle(HYDROData_PolylineXY)::DownCast(
-      HYDROGUI_Tool::FindObjectByName( module(), aPolylineName, KIND_POLYLINEXY ) );
-    if ( !aPolyline.IsNull() )
-      aZonePolylines.Append( aPolyline );
-  }
-  
-  TCollection_AsciiString anError;
-  TopoDS_Shape aZoneShape = HYDROData_LandCover::buildShape( aZonePolylines, anError );  
-
   LightApp_Application* anApp = module()->getApp();
   if ( !getPreviewManager() )
     setPreviewManager( ::qobject_cast<OCCViewer_ViewManager*>( 
@@ -276,28 +377,64 @@ void HYDROGUI_LandCoverMapOp::onCreatePreview( const QStringList& thePolylineNam
     {
       Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
       if ( !aCtx.IsNull() )
-        myPreviewPrs = new HYDROGUI_Shape( aCtx, NULL, getPreviewZLayer() );
+      {
+        connect( aViewer, SIGNAL( selectionChanged() ), this, SLOT( onViewerSelectionChanged() ) );
+        myPreviewPrs = new HYDROGUI_ShapeLandCoverMap( module()->getOCCDisplayer(), aCtx, myEditedObject, getPreviewZLayer()/*, theIsScalarMapMode*/ );
+      }
     }
   }
 
   if ( aViewManager && myPreviewPrs )
   {
-    QColor aFillingColor = Qt::magenta;
-    QColor aBorderColor = Qt::transparent;
-    if ( !myEditedObject.IsNull() ) {
-      aFillingColor = myEditedObject->GetFillingColor();
-      aBorderColor = myEditedObject->GetBorderColor();
+    TopoDS_Shape aLandCoverMapShape = myEditedObject->GetShape();
+    if( !aLandCoverMapShape.IsNull() )
+    {
+      if ( myOperationId == RemoveLandCoverId ||
+           myOperationId == MergeLandCoverId ||
+           myOperationId == ChangeLandCoverTypeId )
+        myPreviewPrs->setSelectionMode( AIS_Shape::SelectionMode( TopAbs_FACE ) ); 
+      myPreviewPrs->setShape( aLandCoverMapShape );      
     }
+  }
+  
+  module()->update( UF_OCCViewer | UF_FitAll );
 
-    myPreviewPrs->setFillingColor( aFillingColor, false, false );
-    myPreviewPrs->setBorderColor( aBorderColor, false, false );
+  QApplication::restoreOverrideCursor();  
+}
 
-    if( !aZoneShape.IsNull() )
-      myPreviewPrs->setShape( aZoneShape );
-  }
+void HYDROGUI_LandCoverMapOp::onViewerSelectionChanged()
+{
+  HYDROGUI_LandCoverMapDlg* aPanel = ::qobject_cast<HYDROGUI_LandCoverMapDlg*>( inputPanel() );
+  if ( !aPanel )
+    return;
+
+  Handle(AIS_InteractiveContext) aCtx = getInteractiveContext();
+  if ( !aCtx.IsNull() )
+  {
+    int aNbSelected = aCtx->NbSelected();
 
-  QApplication::restoreOverrideCursor();
-  */
+    if ( myOperationId == RemoveLandCoverId || myOperationId == ChangeLandCoverTypeId )
+      // Enable Apply, Apply and Close buttons only if at least one face (land cover) is selected in the 3d viewer
+      aPanel->setApplyEnabled( aNbSelected > 0 );
+    else if ( myOperationId == MergeLandCoverId )
+      // Enable Apply, Apply and Close buttons only if at least two faces (land covers) are selected in the 3d viewer
+      aPanel->setApplyEnabled( aNbSelected > 1 );
+
+    if ( myOperationId == MergeLandCoverId || myOperationId == ChangeLandCoverTypeId )
+    {
+      if ( aNbSelected == 1 && !myEditedObject.IsNull() )
+      {
+        TopTools_ListOfShape aFacesSelectedInViewer;
+        getSelectedShapes( aFacesSelectedInViewer, aCtx );
+        if ( aFacesSelectedInViewer.Extent() == 1 )
+        {
+          QString aType = myEditedObject->StricklerType( TopoDS::Face( aFacesSelectedInViewer.First() ) );
+          if ( !aType.isEmpty() )
+            aPanel->setSelectedStricklerTypeName( aType );
+        }
+      }
+    }
+  }
 }
 
 void HYDROGUI_LandCoverMapOp::closePreview()
@@ -307,4 +444,42 @@ void HYDROGUI_LandCoverMapOp::closePreview()
     delete myPreviewPrs;
     myPreviewPrs = 0;
   }
+
+  HYDROGUI_LandCoverMapDlg* aPanel = ::qobject_cast<HYDROGUI_LandCoverMapDlg*>( inputPanel() );
+  if ( !aPanel )
+    return;
+
+  if ( myOperationId == RemoveLandCoverId || myOperationId == MergeLandCoverId || myOperationId == ChangeLandCoverTypeId )
+    aPanel->setApplyEnabled( false );
+}
+
+Handle(AIS_InteractiveContext) HYDROGUI_LandCoverMapOp::getInteractiveContext()
+{
+  OCCViewer_ViewManager* aViewManager = getPreviewManager();
+  Handle(AIS_InteractiveContext) aCtx = NULL;
+  if ( aViewManager ) {
+    if ( OCCViewer_Viewer* aViewer = aViewManager->getOCCViewer() ) {
+      aCtx = aViewer->getAISContext();
+    }
+  }
+  return aCtx;
+}
+
+void HYDROGUI_LandCoverMapOp::getSelectedShapes( TopTools_ListOfShape& theSelectedShapes,
+                                                 Handle(AIS_InteractiveContext)& theCtx )
+{
+  if ( theCtx.IsNull() )
+    theCtx = getInteractiveContext();
+
+  if ( !theCtx.IsNull() && theCtx->NbSelected() > 0 )
+  {
+    for ( theCtx->InitSelected(); theCtx->MoreSelected(); theCtx->NextSelected() )
+    {
+      TopoDS_Shape aSelectedShape = theCtx->SelectedShape();
+      if ( aSelectedShape.IsNull() )
+        continue;
+
+      theSelectedShapes.Append( aSelectedShape );
+    }
+  }
 }