]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Merge branch 'Dev_1.1.1' of newgeom:newgeom into Dev_1.2.0
authorSergey POKHODENKO <sergey.pokhodenko@opencascade.com>
Fri, 22 May 2015 13:08:41 +0000 (16:08 +0300)
committerSergey POKHODENKO <sergey.pokhodenko@opencascade.com>
Fri, 22 May 2015 13:08:41 +0000 (16:08 +0300)
268 files changed:
CMakeCommon/FindCAS.cmake
eclipse_centos.sh [new file with mode: 0755]
eclipse_debian.sh [new file with mode: 0755]
make_centos.sh [new file with mode: 0755]
make_debian.sh [new file with mode: 0755]
src/Config/Config_Keywords.h
src/ConstructionPlugin/ConstructionPlugin_Axis.cpp
src/ConstructionPlugin/ConstructionPlugin_Plane.h
src/ExchangePlugin/CMakeLists.txt
src/ExchangePlugin/ExchangePlugin.h
src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp [new file with mode: 0644]
src/ExchangePlugin/ExchangePlugin_ExportFeature.h [new file with mode: 0644]
src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp
src/ExchangePlugin/ExchangePlugin_ImportFeature.h
src/ExchangePlugin/ExchangePlugin_Plugin.cpp
src/ExchangePlugin/ExchangePlugin_Tools.cpp [new file with mode: 0644]
src/ExchangePlugin/ExchangePlugin_Tools.h [new file with mode: 0644]
src/ExchangePlugin/ExchangePlugin_Validators.cpp
src/ExchangePlugin/ExchangePlugin_Validators.h
src/ExchangePlugin/plugin-Exchange.xml
src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp
src/FeaturesPlugin/FeaturesPlugin_Boolean.h
src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp
src/FeaturesPlugin/FeaturesPlugin_Extrusion.h
src/FeaturesPlugin/Test/TestBoolean.py
src/FeaturesPlugin/Test/TestExtrusion.py
src/FeaturesPlugin/Test/TestGroup.py
src/FeaturesPlugin/Test/TestMultiBoolean.py
src/FeaturesPlugin/boolean_widget.xml
src/FeaturesPlugin/extrusion_widget.xml
src/GeomAPI/GeomAPI_Dir.cpp
src/GeomAPI/GeomAPI_Dir.h
src/GeomAPI/GeomAPI_Dir2d.cpp
src/GeomAPI/GeomAPI_Dir2d.h
src/GeomAPI/GeomAPI_Face.cpp
src/GeomAlgoAPI/CMakeLists.txt
src/GeomAlgoAPI/GeomAlgoAPI.i
src/GeomAlgoAPI/GeomAlgoAPI_BREPExport.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_BREPExport.h [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_BREPImport.cpp
src/GeomAlgoAPI/GeomAlgoAPI_BREPImport.h
src/GeomAlgoAPI/GeomAlgoAPI_FaceBuilder.cpp
src/GeomAlgoAPI/GeomAlgoAPI_FaceBuilder.h
src/GeomAlgoAPI/GeomAlgoAPI_IGESExport.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_IGESExport.h [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_IGESImport.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_IGESImport.h [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Prism.h [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_STEPExport.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_STEPExport.h [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_STEPImport.cpp
src/GeomAlgoAPI/GeomAlgoAPI_STEPImport.h
src/GeomAlgoAPI/GeomAlgoAPI_ShapeProps.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_ShapeProps.h [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Tools.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Tools.h [new file with mode: 0644]
src/GeomValidators/CMakeLists.txt
src/GeomValidators/GeomValidators_Edge.cpp [deleted file]
src/GeomValidators/GeomValidators_Edge.h [deleted file]
src/GeomValidators/GeomValidators_EdgeOrVertex.cpp [deleted file]
src/GeomValidators/GeomValidators_EdgeOrVertex.h [deleted file]
src/GeomValidators/GeomValidators_Positive.cpp
src/GeomValidators/GeomValidators_ShapeType.cpp [new file with mode: 0644]
src/GeomValidators/GeomValidators_ShapeType.h [new file with mode: 0644]
src/InitializationPlugin/InitializationPlugin_Plugin.cpp
src/Model/CMakeLists.txt
src/Model/Model_Application.cpp
src/Model/Model_AttributeRefAttr.cpp
src/Model/Model_AttributeRefAttr.h
src/Model/Model_AttributeRefList.cpp
src/Model/Model_AttributeReference.cpp
src/Model/Model_AttributeReference.h
src/Model/Model_AttributeSelection.cpp
src/Model/Model_AttributeSelection.h
src/Model/Model_Data.cpp
src/Model/Model_Data.h
src/Model/Model_Document.cpp
src/Model/Model_Document.h
src/Model/Model_Objects.cpp [new file with mode: 0644]
src/Model/Model_Objects.h [new file with mode: 0644]
src/Model/Model_ResultBody.cpp
src/Model/Model_ResultBody.h
src/Model/Model_ResultConstruction.h
src/Model/Model_ResultGroup.h
src/Model/Model_ResultParameter.h
src/Model/Model_ResultPart.h
src/Model/Model_Session.cpp
src/Model/Model_Session.h
src/Model/Model_Update.cpp
src/Model/Model_Update.h
src/ModelAPI/ModelAPI.i
src/ModelAPI/ModelAPI_AttributeSelection.h
src/ModelAPI/ModelAPI_CompositeFeature.cpp
src/ModelAPI/ModelAPI_Data.h
src/ModelAPI/ModelAPI_Document.h
src/ModelAPI/ModelAPI_Events.cpp
src/ModelAPI/ModelAPI_Events.h
src/ModelAPI/ModelAPI_Feature.cpp
src/ModelAPI/ModelAPI_Feature.h
src/ModelAPI/ModelAPI_Object.cpp
src/ModelAPI/ModelAPI_Object.h
src/ModelAPI/ModelAPI_Result.cpp
src/ModelAPI/ModelAPI_Result.h
src/ModelAPI/ModelAPI_Session.h
src/ModelAPI/ModelAPI_Tools.cpp
src/ModelAPI/ModelAPI_Tools.h
src/ModuleBase/CMakeLists.txt
src/ModuleBase/ModuleBase_IDocumentDataModel.h [new file with mode: 0644]
src/ModuleBase/ModuleBase_IModule.h
src/ModuleBase/ModuleBase_IPropertyPanel.h
src/ModuleBase/ModuleBase_ISelection.cpp [new file with mode: 0644]
src/ModuleBase/ModuleBase_ISelection.h
src/ModuleBase/ModuleBase_IWorkshop.h
src/ModuleBase/ModuleBase_ModelWidget.h
src/ModuleBase/ModuleBase_Operation.cpp
src/ModuleBase/ModuleBase_Operation.h
src/ModuleBase/ModuleBase_PageGroupBox.cpp
src/ModuleBase/ModuleBase_ParamSpinBox.cpp
src/ModuleBase/ModuleBase_Preferences.cpp
src/ModuleBase/ModuleBase_ResultPrs.cpp
src/ModuleBase/ModuleBase_Tools.cpp
src/ModuleBase/ModuleBase_Tools.h
src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp
src/ModuleBase/ModuleBase_WidgetEditor.cpp
src/ModuleBase/ModuleBase_WidgetEditor.h
src/ModuleBase/ModuleBase_WidgetFactory.cpp
src/ModuleBase/ModuleBase_WidgetFileSelector.cpp
src/ModuleBase/ModuleBase_WidgetFileSelector.h
src/ModuleBase/ModuleBase_WidgetIntValue.cpp [new file with mode: 0644]
src/ModuleBase/ModuleBase_WidgetIntValue.h [new file with mode: 0644]
src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp
src/ModuleBase/ModuleBase_WidgetMultiSelector.h
src/ModuleBase/ModuleBase_WidgetShapeSelector.cpp
src/ModuleBase/ModuleBase_WidgetShapeSelector.h
src/ModuleBase/ModuleBase_WidgetValidated.cpp
src/ModuleBase/ModuleBase_WidgetValidated.h
src/NewGeom/NewGeom_Module.cpp
src/NewGeom/NewGeom_NestedButton.cpp
src/NewGeom/NewGeom_SalomeViewer.cpp
src/NewGeom/NewGeom_SalomeViewer.h
src/ParametersPlugin/CMakeLists.txt
src/ParametersPlugin/ParametersPlugin_EvalListener.cpp [new file with mode: 0644]
src/ParametersPlugin/ParametersPlugin_EvalListener.h [new file with mode: 0644]
src/ParametersPlugin/ParametersPlugin_Parameter.cpp
src/ParametersPlugin/ParametersPlugin_Parameter.h
src/ParametersPlugin/ParametersPlugin_Plugin.cpp
src/ParametersPlugin/ParametersPlugin_Plugin.h
src/ParametersPlugin/ParametersPlugin_PyInterp.cpp
src/ParametersPlugin/ParametersPlugin_PyInterp.h
src/ParametersPlugin/Test/TestParameterCreation.py [new file with mode: 0644]
src/PartSet/CMakeLists.txt
src/PartSet/PartSet_DataTreeModel.h [new file with mode: 0644]
src/PartSet/PartSet_DocumentDataModel.cpp [new file with mode: 0644]
src/PartSet/PartSet_DocumentDataModel.h [new file with mode: 0644]
src/PartSet/PartSet_MenuMgr.cpp
src/PartSet/PartSet_MenuMgr.h
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_Module.h
src/PartSet/PartSet_PartDataModel.cpp [new file with mode: 0644]
src/PartSet/PartSet_PartDataModel.h [new file with mode: 0644]
src/PartSet/PartSet_SketcherMgr.cpp
src/PartSet/PartSet_SketcherMgr.h
src/PartSet/PartSet_WidgetFileSelector.cpp [new file with mode: 0644]
src/PartSet/PartSet_WidgetFileSelector.h [new file with mode: 0644]
src/PartSet/PartSet_WidgetMultiSelector.h
src/PartSet/PartSet_WidgetPoint2d.cpp
src/PartSet/PartSet_WidgetPoint2d.h
src/PartSet/PartSet_WidgetPoint2dAngle.cpp [new file with mode: 0644]
src/PartSet/PartSet_WidgetPoint2dAngle.h [new file with mode: 0644]
src/PartSet/PartSet_WidgetPoint2dDistance.cpp
src/PartSet/PartSet_WidgetPoint2dDistance.h
src/PartSet/PartSet_WidgetShapeSelector.cpp
src/PartSet/PartSet_WidgetShapeSelector.h
src/PartSet/PartSet_WidgetSketchLabel.cpp
src/PartSet/PartSet_WidgetSketchLabel.h
src/PartSet/PartSet_icons.qrc
src/PartSet/icons/activate.png [new file with mode: 0644]
src/PartSet/icons/angle.png [new file with mode: 0644]
src/PartSet/icons/angle_down.png [new file with mode: 0644]
src/PartSet/icons/angle_up.png [new file with mode: 0644]
src/PartSet/icons/deactivate.png [new file with mode: 0644]
src/PartSet/icons/dimension_down.png [new file with mode: 0644]
src/PartSet/icons/dimension_up.png [new file with mode: 0644]
src/PartSet/icons/edit.png [new file with mode: 0644]
src/PartSet/icons/exec_state_failed.png [new file with mode: 0644]
src/PartSet/icons/exec_state_invalid_parameters.png [new file with mode: 0644]
src/PartSet/icons/export.png [new file with mode: 0644]
src/PartSet/icons/plane_inverted.png [new file with mode: 0644]
src/PartSet/icons/rotate.png [new file with mode: 0644]
src/PartSet/icons/translate.png [new file with mode: 0644]
src/PartSetPlugin/PartSetPlugin_Part.cpp
src/PartSetPlugin/PartSetPlugin_Part.h
src/PythonAPI/modeler/extrusion.py
src/PythonAddons/macros/box/feature.py
src/SketchPlugin/CMakeLists.txt
src/SketchPlugin/SketchPlugin_Circle.cpp
src/SketchPlugin/SketchPlugin_ConstraintBase.h
src/SketchPlugin/SketchPlugin_ConstraintCoincidence.cpp
src/SketchPlugin/SketchPlugin_MultiRotation.cpp [new file with mode: 0644]
src/SketchPlugin/SketchPlugin_MultiRotation.h [new file with mode: 0644]
src/SketchPlugin/SketchPlugin_MultiTranslation.cpp [new file with mode: 0644]
src/SketchPlugin/SketchPlugin_MultiTranslation.h [new file with mode: 0644]
src/SketchPlugin/SketchPlugin_Plugin.cpp
src/SketchPlugin/SketchPlugin_Sketch.cpp
src/SketchPlugin/SketchPlugin_Sketch.h
src/SketchPlugin/SketchPlugin_SketchEntity.h
src/SketchPlugin/SketchPlugin_Validators.cpp
src/SketchPlugin/SketchPlugin_Validators.h
src/SketchPlugin/plugin-Sketch.xml
src/SketchSolver/CMakeLists.txt
src/SketchSolver/SketchSolver.h
src/SketchSolver/SketchSolver_Builder.cpp
src/SketchSolver/SketchSolver_Constraint.cpp
src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp
src/SketchSolver/SketchSolver_ConstraintCoincidence.h
src/SketchSolver/SketchSolver_ConstraintMirror.cpp
src/SketchSolver/SketchSolver_ConstraintMirror.h
src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintMultiRotation.h [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintMultiTranslation.h [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintRigid.cpp
src/SketchSolver/SketchSolver_Group.cpp
src/SketchSolver/SketchSolver_Solver.h
src/SketcherPrs/CMakeLists.txt
src/SketcherPrs/SketcherPrs_Coincident.cpp
src/SketcherPrs/SketcherPrs_Factory.cpp
src/SketcherPrs/SketcherPrs_Factory.h
src/SketcherPrs/SketcherPrs_Mirror.cpp
src/SketcherPrs/SketcherPrs_Rigid.cpp
src/SketcherPrs/SketcherPrs_SymbolPrs.cpp
src/SketcherPrs/SketcherPrs_SymbolPrs.h
src/SketcherPrs/SketcherPrs_Tools.cpp
src/SketcherPrs/SketcherPrs_Transformation.cpp [new file with mode: 0644]
src/SketcherPrs/SketcherPrs_Transformation.h [new file with mode: 0644]
src/SketcherPrs/icons/rotate.png [new file with mode: 0644]
src/SketcherPrs/icons/translate.png [new file with mode: 0644]
src/XGUI/CMakeLists.txt
src/XGUI/XGUI_ColorDialog.cpp [new file with mode: 0644]
src/XGUI/XGUI_ColorDialog.h [new file with mode: 0644]
src/XGUI/XGUI_ContextMenuMgr.cpp
src/XGUI/XGUI_ContextMenuMgr.h
src/XGUI/XGUI_CustomPrs.cpp
src/XGUI/XGUI_DataTreeModel.h [deleted file]
src/XGUI/XGUI_Displayer.cpp
src/XGUI/XGUI_Displayer.h
src/XGUI/XGUI_DocumentDataModel.cpp [deleted file]
src/XGUI/XGUI_DocumentDataModel.h [deleted file]
src/XGUI/XGUI_ModuleConnector.cpp
src/XGUI/XGUI_ModuleConnector.h
src/XGUI/XGUI_ObjectsBrowser.cpp
src/XGUI/XGUI_ObjectsBrowser.h
src/XGUI/XGUI_PartDataModel.cpp [deleted file]
src/XGUI/XGUI_PartDataModel.h [deleted file]
src/XGUI/XGUI_PropertyPanel.h
src/XGUI/XGUI_SelectionMgr.cpp
src/XGUI/XGUI_Tools.cpp
src/XGUI/XGUI_Tools.h
src/XGUI/XGUI_ViewerProxy.cpp
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_Workshop.h
src/XGUI/XGUI_pictures.qrc
src/XGUI/pictures/activate.png [deleted file]
src/XGUI/pictures/arrow.png [new file with mode: 0644]
src/XGUI/pictures/edit.png [deleted file]
src/XGUI/pictures/exec_state_failed.png [deleted file]
src/XGUI/pictures/exec_state_invalid_parameters.png [deleted file]

index b610c2915d5f027ec9b77f77fec29cd393daf9bf..3abac49ee64b1845bd4ae8c45a7c66c1985f907f 100644 (file)
@@ -152,7 +152,7 @@ SET(CAS_KERNEL ${CAS_TKernel} ${CAS_TKMath})
 SET(CAS_OCAF ${CAS_TKernel} ${CAS_TKMath} ${CAS_TKCDF} ${CAS_TKLCAF})
 SET(CAS_VIEWER ${CAS_TKService} ${CAS_TKV3d} ${CAS_TKG3d} ${CAS_TKGeomBase} ${CAS_TKBRep})
 SET(CAS_OCAFVIS ${CAS_TKCAF} ${CAS_TKBRep} ${CAS_TKG2d})
-SET(CAS_MODELER ${CAS_TKG3d} ${CAS_TKGeomBase} ${CAS_TKGeomAlgo} ${CAS_TKBRep} ${CAS_TKTopAlgo} ${CAS_TKG2d})
+SET(CAS_MODELER ${CAS_TKG3d} ${CAS_TKGeomBase} ${CAS_TKGeomAlgo} ${CAS_TKBRep} ${CAS_TKTopAlgo} ${CAS_TKG2d} ${CAS_TKFeat})
 # TODO(mpv, vsv) Give a proper name for the following variable
 SET(CAS_SHAPE ${CAS_TKShHealing} ${CAS_TKMesh} ${CAS_TKHLR})
 
diff --git a/eclipse_centos.sh b/eclipse_centos.sh
new file mode 100755 (executable)
index 0000000..ea5e02a
--- /dev/null
@@ -0,0 +1,25 @@
+
+# Find absolute path to ROOT_DIR
+export ROOT_DIR=$(pwd)/..
+export ROOT_DIR=`cd "${ROOT_DIR}";pwd`
+
+SRC_DIR=${ROOT_DIR}/sources
+
+source ${SRC_DIR}/linux_env.sh
+mkdir -p ${ROOT_DIR}/build-centos
+cd ${ROOT_DIR}/build-centos
+
+export LD_LIBRARY_PATH=${KERNEL_ROOT_DIR}/lib/salome:${LD_LIBRARY_PATH}
+export LightAppConfig=${ROOT_DIR}/install/share/salome/resources/newgeom:${GUI_ROOT_DIR}/share/salome/resources/gui
+
+CMAKE_ARGS="-D_ECLIPSE_VERSION=4.3"
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_BUILD_TYPE=Debug"
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT=ON"
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=${ROOT_DIR}/install"
+CMAKE_ARGS="${CMAKE_ARGS} -DPYTHON_EXECUTABLE=${PYTHONHOME}/bin/python"
+CMAKE_ARGS="${CMAKE_ARGS} -DUSE_TEST_COVERAGE=OFF"
+CMAKE_ARGS="${CMAKE_ARGS} ${SRC_DIR}"
+
+cmake -G "Eclipse CDT4 - Unix Makefiles" ${CMAKE_ARGS}
+
+/misc/dn48/newgeom/common/eclipse-4.4.0/eclipse&
diff --git a/eclipse_debian.sh b/eclipse_debian.sh
new file mode 100755 (executable)
index 0000000..f7d456a
--- /dev/null
@@ -0,0 +1,26 @@
+
+# Find absolute path to ROOT_DIR
+export ROOT_DIR=$(pwd)/..
+export ROOT_DIR=`cd "${ROOT_DIR}";pwd`
+
+SRC_DIR=${ROOT_DIR}/sources
+
+export INST_ROOT=/misc/dn48/newgeom/common/SALOME-7.5.1_Debian-6.0
+source ${SRC_DIR}/linux_env.sh
+mkdir -p ${ROOT_DIR}/build-debian
+cd ${ROOT_DIR}/build-debian
+
+export LD_LIBRARY_PATH=${KERNEL_ROOT_DIR}/lib/salome:${LD_LIBRARY_PATH}
+export LightAppConfig=${ROOT_DIR}/install/share/salome/resources/newgeom:${GUI_ROOT_DIR}/share/salome/resources/gui
+
+CMAKE_ARGS="-D_ECLIPSE_VERSION=4.3"
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_BUILD_TYPE=Debug"
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT=ON"
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=${ROOT_DIR}/install"
+CMAKE_ARGS="${CMAKE_ARGS} -DPYTHON_EXECUTABLE=${PYTHONHOME}/bin/python"
+CMAKE_ARGS="${CMAKE_ARGS} -DUSE_TEST_COVERAGE=OFF"
+CMAKE_ARGS="${CMAKE_ARGS} ${SRC_DIR}"
+
+cmake -G "Eclipse CDT4 - Unix Makefiles" ${CMAKE_ARGS}
+
+/misc/dn48/newgeom/common/eclipse-4.4.0/eclipse&
diff --git a/make_centos.sh b/make_centos.sh
new file mode 100755 (executable)
index 0000000..ef61abc
--- /dev/null
@@ -0,0 +1,18 @@
+
+# Find absolute path to ROOT_DIR
+export ROOT_DIR=$(pwd)/..
+export ROOT_DIR=`cd "${ROOT_DIR}";pwd`
+
+SRC_DIR=${ROOT_DIR}/sources
+
+source ${SRC_DIR}/linux_env.sh
+mkdir -p ${ROOT_DIR}/build
+cd ${ROOT_DIR}/build
+
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_BUILD_TYPE=Release"
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=${ROOT_DIR}/install"
+CMAKE_ARGS="${CMAKE_ARGS} ${SRC_DIR}"
+
+cmake -G "Unix Makefiles" ${CMAKE_ARGS}
+make
+make install
diff --git a/make_debian.sh b/make_debian.sh
new file mode 100755 (executable)
index 0000000..e2ce3a0
--- /dev/null
@@ -0,0 +1,19 @@
+
+# Find absolute path to ROOT_DIR
+export ROOT_DIR=$(pwd)/..
+export ROOT_DIR=`cd "${ROOT_DIR}";pwd`
+
+SRC_DIR=${ROOT_DIR}/sources
+
+export INST_ROOT=/misc/dn48/newgeom/common/SALOME-7.5.1_Debian-6.0
+source ${SRC_DIR}/linux_env.sh
+mkdir -p ${ROOT_DIR}/build-debian
+cd ${ROOT_DIR}/build-debian
+
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_BUILD_TYPE=Release"
+CMAKE_ARGS="${CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=${ROOT_DIR}/install"
+CMAKE_ARGS="${CMAKE_ARGS} ${SRC_DIR}"
+
+cmake -G "Unix Makefiles" ${CMAKE_ARGS}
+make
+make install
index a9f44bf63b4a5adc2a7b79184d03b00e5e0031db..2827d269c6bc4f29dd28e4d0fa9573b33b357978 100644 (file)
@@ -24,6 +24,7 @@ const static char* NODE_XMLPARENT = "libxml_parent";
 // Widgets
 const static char* WDG_INFO = "label";
 const static char* WDG_DOUBLEVALUE = "doublevalue";
+const static char* WDG_INTEGERVALUE = "integervalue";
 const static char* WDG_BOOLVALUE = "boolvalue";
 const static char* WDG_STRINGVALUE = "stringvalue";
 const static char* WDG_MULTISELECTOR = "multi_selector";
index ae24aaf3c7916561f9de78cd36f8dfdbc6dcbf69..280da1e7fd28869a24c27f8e23cc3189db3f5af1 100644 (file)
@@ -89,7 +89,8 @@ bool ConstructionPlugin_Axis::customisePresentation(ResultPtr theResult, AISObje
   bool isCustomized = theDefaultPrs.get() != NULL &&
                       theDefaultPrs->customisePresentation(theResult, thePrs, theDefaultPrs);
 
-  isCustomized = thePrs->setLineStyle(3);
+  isCustomized = thePrs->setLineStyle(3) || isCustomized;
+  isCustomized = thePrs->setWidth(2) || isCustomized;
 
   return isCustomized;
 }
index 317d6f348232239c1b4c3c5037c5f3085d23d183..546577b44ea5d35a31fe8df7881b2ab083b5ea47 100644 (file)
@@ -31,7 +31,7 @@ class ConstructionPlugin_Plane : public ModelAPI_Feature, public GeomAPI_ICustom
   /// default color for a plane
   inline static const std::string& DEFAULT_COLOR()
   {
-    static const std::string CONSTRUCTION_PLANE_COLOR("#32FF32");
+    static const std::string CONSTRUCTION_PLANE_COLOR("150,150,180");
     return CONSTRUCTION_PLANE_COLOR;
   }
 
index 6ed972b2bad265f1509011fc48b0be64f20c586c..c31364d8f094bd016fd2d706f573f57368277fb1 100644 (file)
@@ -8,19 +8,23 @@ INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Events
                     ${PROJECT_SOURCE_DIR}/src/GeomAPI
                     ${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI
                     ${CAS_INCLUDE_DIRS}
-) 
+)
 
 SET(PROJECT_HEADERS
     ExchangePlugin.h
     ExchangePlugin_Plugin.h
     ExchangePlugin_ImportFeature.h
+    ExchangePlugin_ExportFeature.h
     ExchangePlugin_Validators.h
+    ExchangePlugin_Tools.h
 )
+
 SET(PROJECT_SOURCES
     ExchangePlugin_Plugin.cpp
     ExchangePlugin_ImportFeature.cpp
+    ExchangePlugin_ExportFeature.cpp
     ExchangePlugin_Validators.cpp
+    ExchangePlugin_Tools.cpp
 )
 
 SET(XML_RESOURCES
index 0c8f80b9577120adceb9f21eef3e24848be5f4a9..a6152af3ea0ac9d700f080086ff90981ff1a3dbd 100644 (file)
@@ -4,17 +4,17 @@
 #define EXCHANGEPLUGIN_H
 
 #if defined EXCHANGEPLUGIN_EXPORTS
-#if defined WIN32
-#define EXCHANGEPLUGIN_EXPORT              __declspec( dllexport )
+# if defined WIN32
+#  define EXCHANGEPLUGIN_EXPORT              __declspec( dllexport )
+# else
+#  define EXCHANGEPLUGIN_EXPORT
+# endif
 #else
-#define EXCHANGEPLUGIN_EXPORT
-#endif
-#else
-#if defined WIN32
-#define EXCHANGEPLUGIN_EXPORT              __declspec( dllimport )
-#else
-#define EXCHANGEPLUGIN_EXPORT
-#endif
+# if defined WIN32
+#  define EXCHANGEPLUGIN_EXPORT              __declspec( dllimport )
+# else
+#  define EXCHANGEPLUGIN_EXPORT
+# endif
 #endif
 
 #endif
diff --git a/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp b/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp
new file mode 100644 (file)
index 0000000..a67b57b
--- /dev/null
@@ -0,0 +1,131 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+/*
+ * ExchangePlugin_ExportFeature.cpp
+ *
+ *  Created on: May 14, 2015
+ *      Author: spo
+ */
+
+#include <ExchangePlugin_ExportFeature.h>
+
+#include <ExchangePlugin_Tools.h>
+
+#include <GeomAlgoAPI_BREPExport.h>
+#include <GeomAlgoAPI_STEPExport.h>
+#include <GeomAlgoAPI_IGESExport.h>
+
+#include <Config_Common.h>
+#include <Config_PropManager.h>
+
+#include <GeomAlgoAPI_CompoundBuilder.h>
+
+#include <GeomAPI_Shape.h>
+
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Object.h>
+#include <ModelAPI_ResultBody.h>
+
+#include <TCollection_AsciiString.hxx>
+#include <TDF_Label.hxx>
+#include <TopoDS_Shape.hxx>
+#include <OSD_Path.hxx>
+
+#include <algorithm>
+#include <iterator>
+#include <string>
+#ifdef _DEBUG
+#include <iostream>
+#include <ostream>
+#endif
+
+ExchangePlugin_ExportFeature::ExchangePlugin_ExportFeature()
+{
+}
+
+ExchangePlugin_ExportFeature::~ExchangePlugin_ExportFeature()
+{
+  // TODO Auto-generated destructor stub
+}
+
+/*
+ * Returns the unique kind of a feature
+ */
+const std::string& ExchangePlugin_ExportFeature::getKind()
+{
+  return ExchangePlugin_ExportFeature::ID();
+}
+
+/*
+ * Request for initialization of data model of the feature: adding all attributes
+ */
+void ExchangePlugin_ExportFeature::initAttributes()
+{
+  data()->addAttribute(ExchangePlugin_ExportFeature::FILE_FORMAT_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(ExchangePlugin_ExportFeature::FILE_PATH_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(ExchangePlugin_ExportFeature::SELECTION_LIST_ID(), ModelAPI_AttributeSelectionList::typeId());
+}
+
+/*
+ * Computes or recomputes the results
+ */
+void ExchangePlugin_ExportFeature::execute()
+{
+  AttributeStringPtr aFormatAttr =
+      this->string(ExchangePlugin_ExportFeature::FILE_FORMAT_ID());
+  std::string aFormat = aFormatAttr->value();
+  if (aFormat.empty())
+    return;
+
+  AttributeStringPtr aFilePathAttr =
+      this->string(ExchangePlugin_ExportFeature::FILE_PATH_ID());
+  std::string aFilePath = aFilePathAttr->value();
+  if (aFilePath.empty())
+    return;
+
+  AttributeSelectionListPtr aSelectionListAttr =
+      this->selectionList(ExchangePlugin_ExportFeature::SELECTION_LIST_ID());
+  std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
+  for (int i = 0, aSize = aSelectionListAttr->size(); i < aSize; ++i) {
+    aShapes.push_back(aSelectionListAttr->value(i)->value());
+  }
+  std::shared_ptr<GeomAPI_Shape> aShape =
+      GeomAlgoAPI_CompoundBuilder::compound(aShapes);
+
+  exportFile(aFilePath, aFormat, aShape);
+}
+
+bool ExchangePlugin_ExportFeature::exportFile(const std::string& theFileName,
+                                              const std::string& theFormat,
+                                              std::shared_ptr<GeomAPI_Shape> theShape)
+{
+  // retrieve the file and plugin library names
+  TCollection_AsciiString aFileName(theFileName.c_str());
+  TCollection_AsciiString aFormatName(theFormat.c_str());
+
+  // Perform the export
+  TCollection_AsciiString anError;
+  TopoDS_Shape aShape(theShape->impl<TopoDS_Shape>());
+  bool aResult = false;
+  if (aFormatName == "BREP") {
+    aResult = BREPExport::Export(aFileName, aFormatName, aShape, anError);
+  } else if (aFormatName == "STEP") {
+    aResult = STEPExport::Export(aFileName, aFormatName, aShape, anError);
+  } else if (aFormatName.SubString(1, 4) == "IGES") {
+    aResult = IGESExport::Export(aFileName, aFormatName, aShape, anError);
+  } else {
+    anError = TCollection_AsciiString("Unsupported format ") + aFormatName;
+  }
+
+  if (!aResult) {
+    std::string aShapeError =
+        "An error occurred while exporting " + theFileName + ": " + anError.ToCString();
+    setError(aShapeError);
+    return false;
+  }
+
+  return true;
+}
diff --git a/src/ExchangePlugin/ExchangePlugin_ExportFeature.h b/src/ExchangePlugin/ExchangePlugin_ExportFeature.h
new file mode 100644 (file)
index 0000000..774cbad
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#ifndef EXCHANGEPLUGIN_EXPORTFEATURE_H_
+#define EXCHANGEPLUGIN_EXPORTFEATURE_H_
+
+#include <ExchangePlugin.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Result.h>
+
+#include <map>
+
+/**\class ExchangePlugin_ExportFeature
+ * \ingroup Plugins
+ * \brief Feature for export shapes to the external files in CAD formats.
+ *
+ * The set of supported formats is defined in the configuration file.
+ */
+class ExchangePlugin_ExportFeature : public ModelAPI_Feature
+{
+public:
+  inline static const std::string& ID()
+  {
+    static const std::string MY_EXPORT_ID("Export");
+    return MY_EXPORT_ID;
+  }
+  /// attribute name of file format
+  inline static const std::string& FILE_FORMAT_ID()
+  {
+    static const std::string MY_FILE_FORMAT_ID("export_file_format");
+    return MY_FILE_FORMAT_ID;
+  }
+  /// attribute name of file path
+  inline static const std::string& FILE_PATH_ID()
+  {
+    static const std::string MY_FILE_PATH_ID("export_file_selector");
+    return MY_FILE_PATH_ID;
+  }
+  /// attribute name of selection list
+  inline static const std::string& SELECTION_LIST_ID()
+  {
+    static const std::string MY_SELECTION_LIST_ID("selection_list");
+    return MY_SELECTION_LIST_ID;
+  }
+  /// default constructor
+  EXCHANGEPLUGIN_EXPORT ExchangePlugin_ExportFeature();
+  /// default destructor
+  EXCHANGEPLUGIN_EXPORT virtual ~ExchangePlugin_ExportFeature();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  EXCHANGEPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Returns the unique kind of a feature
+  EXCHANGEPLUGIN_EXPORT virtual const std::string& getKind();
+
+  /// Computes or recomputes the results
+  EXCHANGEPLUGIN_EXPORT virtual void execute();
+
+  /// Reimplemented from ModelAPI_Feature::isMacro(). Returns true.
+  EXCHANGEPLUGIN_EXPORT virtual bool isMacro() const { return true; }
+
+  /// Reimplemented from ModelAPI_Feature::isPreviewNeeded(). Returns false.
+  EXCHANGEPLUGIN_EXPORT virtual bool isPreviewNeeded() const { return false; }
+
+protected:
+  /// Performs the export of the file
+  EXCHANGEPLUGIN_EXPORT bool exportFile(const std::string& theFileName,
+                                        const std::string& theFormat,
+                                        std::shared_ptr<GeomAPI_Shape> theShape);
+};
+
+#endif /* EXPORT_EXPORTFEATURE_H_ */
index f3f53a273e26fe136ecae73b051a9fdb9531c797..ea085c13f9c4673f540d9889dc854f080f991d63 100644 (file)
@@ -10,6 +10,7 @@
 #include <ExchangePlugin_ImportFeature.h>
 #include <GeomAlgoAPI_BREPImport.h>
 #include <GeomAlgoAPI_STEPImport.h>
+#include <GeomAlgoAPI_IGESImport.h>
 
 #include <GeomAPI_Shape.h>
 #include <Config_Common.h>
@@ -62,37 +63,39 @@ void ExchangePlugin_ImportFeature::initAttributes()
  */
 void ExchangePlugin_ImportFeature::execute()
 {
-  AttributeStringPtr aFilePathAttr = std::dynamic_pointer_cast<ModelAPI_AttributeString>(
-      data()->attribute(ExchangePlugin_ImportFeature::FILE_PATH_ID()));
+  AttributeStringPtr aFilePathAttr =
+      this->string(ExchangePlugin_ImportFeature::FILE_PATH_ID());
   std::string aFilePath = aFilePathAttr->value();
-  if(aFilePath.empty())
+  if (aFilePath.empty())
     return;
+
   importFile(aFilePath);
 }
 
 bool ExchangePlugin_ImportFeature::importFile(const std::string& theFileName)
 {
   // retrieve the file and plugin library names
-  TCollection_AsciiString aFileName (theFileName.c_str());
+  TCollection_AsciiString aFileName(theFileName.c_str());
   OSD_Path aPath(aFileName);
-  TCollection_AsciiString aFormatName = aPath.Extension();
+  TCollection_AsciiString anExtension = aPath.Extension();
   // ".brep" -> "BREP", TCollection_AsciiString are numbered from 1
-  aFormatName = aFormatName.SubString(2, aFormatName.Length());
-  aFormatName.UpperCase();
+  anExtension = anExtension.SubString(2, anExtension.Length());
+  anExtension.UpperCase();
 
   // Perform the import
   TCollection_AsciiString anError;
-  TDF_Label anUnknownLabel = TDF_Label();
 
   TopoDS_Shape aShape;
-  if (aFormatName == "BREP") {
-    aShape = BREPImport::Import(aFileName, aFormatName, anError, anUnknownLabel);
-  } else if (aFormatName == "STEP") {
-    aShape = STEPImport::Import(aFileName, aFormatName, anError, anUnknownLabel);
+  if (anExtension == "BREP") {
+    aShape = BREPImport::Import(aFileName, anExtension, anError);
+  } else if (anExtension == "STEP" || anExtension == "STP") {
+    aShape = STEPImport::Import(aFileName, anExtension, anError);
+  } else if (anExtension == "IGES") {
+    aShape = IGESImport::Import(aFileName, anExtension, anError);
   }
    // Check if shape is valid
   if ( aShape.IsNull() ) {
-     const static std::string aShapeError = 
+     const static std::string aShapeError =
        "An error occurred while importing " + theFileName + ": " + anError.ToCString();
      setError(aShapeError);
      return false;
@@ -115,17 +118,13 @@ bool ExchangePlugin_ImportFeature::importFile(const std::string& theFileName)
 
 //============================================================================
 void ExchangePlugin_ImportFeature::loadNamingDS(
-                                   std::shared_ptr<GeomAPI_Shape> theGeomShape, 
-                                            std::shared_ptr<ModelAPI_ResultBody> theResultBody)
-{  
+    std::shared_ptr<GeomAPI_Shape> theGeomShape,
+    std::shared_ptr<ModelAPI_ResultBody> theResultBody)
+{
   //load result
   theResultBody->store(theGeomShape);
+
   int aTag(1);
   std::string aNameMS = "Shape";
   theResultBody->loadFirstLevel(theGeomShape, aNameMS, aTag);
-  //std::string aNameDE = "DiscEdges";
-  //theResultBody->loadDisconnectedEdges(theGeomShape, aNameDE, aTag);
-  //std::string aNameDV = "DiscVertexes";
-  //theResultBody->loadDisconnectedVertexes(theGeomShape, aNameDV, aTag); 
 }
index 673a6d9509955ac69ccd9298798b1ea936a7f8a7..b1fc310add5dbbae09f14ab85d9955e69fd972e1 100644 (file)
@@ -50,13 +50,13 @@ class ExchangePlugin_ImportFeature : public ModelAPI_Feature
   }
 
  protected:
-  /// POerforms the import of the file
+  /// Performs the import of the file
   EXCHANGEPLUGIN_EXPORT bool importFile(const std::string& theFileName);
 
 private:
   /// Loads Naming data structure to the document
   void loadNamingDS(std::shared_ptr<GeomAPI_Shape> theGeomShape, 
-                                       std::shared_ptr<ModelAPI_ResultBody> theResultBody);
+                    std::shared_ptr<ModelAPI_ResultBody> theResultBody);
 };
 
 #endif /* IMPORT_IMPORTFEATURE_H_ */
index 58b214b47c96522dcfcf5df123e5f27b7e1251fe..2b8cb8b484f3e46221f6f6588f602d6b3d0e1b31 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <ExchangePlugin_Plugin.h>
 #include <ExchangePlugin_ImportFeature.h>
+#include <ExchangePlugin_ExportFeature.h>
 #include <ExchangePlugin_Validators.h>
 
 #include <Config_PropManager.h>
@@ -28,16 +29,17 @@ ExchangePlugin_Plugin::ExchangePlugin_Plugin()
   ModelAPI_ValidatorsFactory* aFactory = aSession->validators();
   aFactory->registerValidator("ExchangePlugin_ImportFormat",
                               new ExchangePlugin_ImportFormatValidator);
-
-  // register construction properties
-  //Config_PropManager::registerProp("Visualization", "import_feature_color", "Imported feature color",
-  //                                 Config_Prop::Color, ExchangePlugin_ImportFeature::DEFAULT_COLOR());
+  aFactory->registerValidator("ExchangePlugin_ExportFormat",
+                              new ExchangePlugin_ExportFormatValidator);
 }
 
 FeaturePtr ExchangePlugin_Plugin::createFeature(string theFeatureID)
 {
   if (theFeatureID == ExchangePlugin_ImportFeature::ID()) {
     return FeaturePtr(new ExchangePlugin_ImportFeature);
+  } else
+  if (theFeatureID == ExchangePlugin_ExportFeature::ID()) {
+    return FeaturePtr(new ExchangePlugin_ExportFeature);
   }
   // feature of such kind is not found
   return FeaturePtr();
diff --git a/src/ExchangePlugin/ExchangePlugin_Tools.cpp b/src/ExchangePlugin/ExchangePlugin_Tools.cpp
new file mode 100644 (file)
index 0000000..c55689e
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * ExchangePlugin_Tools.cpp
+ *
+ *  Created on: May 15, 2015
+ *      Author: spo
+ */
+
+#include <ExchangePlugin_Tools.h>
+
+#include <sstream>
+
+std::list<std::string> ExchangePlugin_Tools::split(const std::string& theString, char theDelimiter)
+{
+  std::list<std::string> theResult;
+  std::istringstream aStream(theString);
+  std::string aSection;
+  while (std::getline(aStream, aSection, theDelimiter))
+    theResult.push_back(aSection);
+  return theResult;
+}
diff --git a/src/ExchangePlugin/ExchangePlugin_Tools.h b/src/ExchangePlugin/ExchangePlugin_Tools.h
new file mode 100644 (file)
index 0000000..b855207
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * ExchangePlugin_Tools.h
+ *
+ *  Created on: May 15, 2015
+ *      Author: spo
+ */
+
+#ifndef EXCHANGEPLUGIN_TOOLS_H_
+#define EXCHANGEPLUGIN_TOOLS_H_
+
+#include <ExchangePlugin.h>
+
+#include <list>
+#include <string>
+
+/**\class ExchangePlugin_Tools
+ * \ingroup Plugins
+ * \brief Internal tools for the plugin.
+ */
+class EXCHANGEPLUGIN_EXPORT ExchangePlugin_Tools {
+public:
+  /// Splits theString using theDelimiter.
+  static std::list<std::string> split(const std::string& theString,
+                                      char theDelimiter);
+
+};
+
+#endif /* EXCHANGEPLUGIN_TOOLS_H_ */
index c001a0c3f41585bd42416e2b7ca68ec4822807d3..16df0a1fe6b5946f4940f14cf3cad44b350882dd 100644 (file)
@@ -5,6 +5,9 @@
 // Author:      Vitaly SMETANNIKOV
 
 #include <ExchangePlugin_Validators.h>
+
+#include <ExchangePlugin_Tools.h>
+
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Object.h>
 #include <ModelAPI_Session.h>
@@ -14,8 +17,8 @@
 #include <string>
 #include <algorithm>
 
-bool ExchangePlugin_ImportFormatValidator::parseFormats(const std::list<std::string>& theArguments,
-                                                        std::list<std::string>& outFormats)
+bool ExchangePlugin_FormatValidator::parseFormats(const std::list<std::string>& theArguments,
+                                                  std::list<std::string>& outFormats)
 {
   std::list<std::string>::const_iterator it = theArguments.begin();
   bool result = true;
@@ -26,39 +29,40 @@ bool ExchangePlugin_ImportFormatValidator::parseFormats(const std::list<std::str
       result = false;
       continue;
     }
-    std::string aFormat = anArg.substr(0, aSepPos);
-    std::transform(aFormat.begin(), aFormat.end(), aFormat.begin(), toupper);
-    outFormats.push_back(aFormat);
+    std::string aFormats = anArg.substr(0, aSepPos);
+    std::transform(aFormats.begin(), aFormats.end(), aFormats.begin(), toupper);
+    std::list<std::string> aFormatList = ExchangePlugin_Tools::split(aFormats, '|');
+    outFormats.insert(outFormats.end(), aFormatList.begin(), aFormatList.end());
   }
   return result;
 }
 
-bool ExchangePlugin_ImportFormatValidator::isValid(const AttributePtr& theAttribute,
-                                                   const std::list<std::string>& theArguments) const
+bool ExchangePlugin_FormatValidator::isValid(const AttributePtr& theAttribute,
+                                             const std::list<std::string>& theArguments) const
 {
-  SessionPtr aMgr = ModelAPI_Session::get();
-  ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
-  if (theAttribute->isInitialized()) {
-    const AttributeStringPtr aStrAttr =
-        std::dynamic_pointer_cast<ModelAPI_AttributeString>(theAttribute);
-    if(!aStrAttr)
-      return false;
-    std::string aFileName = aStrAttr->value();
-    if (!aFileName.empty()) {
-      std::list<std::string> aFormats;
-      ExchangePlugin_ImportFormatValidator::parseFormats(theArguments, aFormats);
-      std::list<std::string>::const_iterator itFormats = aFormats.begin();
-      size_t aFileNameLen = aFileName.length();
-      std::transform(aFileName.begin(), aFileName.end(), aFileName.begin(), toupper);
-      // Is file name ends with the format
-      for (; itFormats != aFormats.end(); ++itFormats) {
-        size_t aFormatBeginPos = aFileNameLen - (*itFormats).length();
-        if (aFileName.compare(aFormatBeginPos, std::string::npos, *itFormats) == 0) {
-          return true;
-        }
-      }
+  if (!theAttribute->isInitialized())
+    return false;
+
+  const AttributeStringPtr aStrAttr =
+      std::dynamic_pointer_cast<ModelAPI_AttributeString>(theAttribute);
+  if (!aStrAttr)
+    return false;
+
+  std::string aFileName = aStrAttr->value();
+  if (aFileName.empty())
+    return false;
+
+  std::list<std::string> aFormats;
+  ExchangePlugin_FormatValidator::parseFormats(theArguments, aFormats);
+  std::list<std::string>::const_iterator itFormats = aFormats.begin();
+  size_t aFileNameLen = aFileName.length();
+  std::transform(aFileName.begin(), aFileName.end(), aFileName.begin(), toupper);
+  // Is file name ends with the format
+  for (; itFormats != aFormats.end(); ++itFormats) {
+    size_t aFormatBeginPos = aFileNameLen - (*itFormats).length();
+    if (aFileName.compare(aFormatBeginPos, std::string::npos, *itFormats) == 0) {
+      return true;
     }
   }
   return false;
 }
-
index f8db19fc21857ae0e17ecea369e868b4340d7b93..3e9ebb912383932058df32c67792741fd40a1062 100644 (file)
  * about which formats are supported and the extension of the associated files.
  * This validator filters out files that are out of this description.
  */
-class ExchangePlugin_ImportFormatValidator : public ModelAPI_AttributeValidator
+class ExchangePlugin_FormatValidator : public ModelAPI_AttributeValidator
 {
   /**
-   * Parses input arguments "BREP:BREPImport", "STEP:STEPImport"
-   * into list of file formats "BREP","STEP"
+   * Parses input arguments "BREP:BREPImport", "STEP|STP:STEPImport"
+   * into list of file formats "BREP","STEP","STP"
    * and list of corresponding plugins: "BREPImport", "STEPImport"
    */
   static bool parseFormats(const std::list<std::string>& theArguments,
-                             std::list<std::string>& outFormats);
+                           std::list<std::string>& outFormats);
 public:
   /**
    * Returns true is the file-name attribute correctly corresponds to the set of
@@ -34,8 +34,15 @@ public:
    */
   virtual bool isValid(const AttributePtr& theAttribute,
                        const std::list<std::string>& theArguments) const;
+};
 
+class ExchangePlugin_ImportFormatValidator : public ExchangePlugin_FormatValidator
+{
 
+};
+
+class ExchangePlugin_ExportFormatValidator : public ExchangePlugin_FormatValidator
+{
 
 };
 
index 76a107e8230d67d755e1c65764a5234881cb0d59..f478491fed0f0406b29dafb904437cdbd3fb1143 100644 (file)
@@ -4,13 +4,16 @@
   <workbench id="Features" document="Part">
     <group id="Exchange">
       <feature id="Import" title="Import" tooltip="Import a file" icon=":icons/import.png">
-        <file_selector
-          id="import_file_selector"
-          title="Import file"
-          path="">
-          <validator id="ExchangePlugin_ImportFormat" parameters="BREP:BREPImport,STEP:STEPImport" />
+        <file_selector id="import_file_selector" title="Import file" path="">
+          <validator id="ExchangePlugin_ImportFormat" parameters="BREP:BREP,STEP|STP:STEP,IGES:IGES" />
         </file_selector>
       </feature>
+      <feature id="Export" title="Export" tooltip="Export to file" icon=":icons/export.png">
+        <export_file_selector id="export_file_selector" type="save" title="Export file" path="">
+          <validator id="ExchangePlugin_ExportFormat" parameters="BREP:BREP,STEP|STP:STEP,IGES:IGES-5.1,IGES:IGES-5.3" />
+        </export_file_selector>
+        <multi_selector id="selection_list" tooltip="Select a set of objects" type_choice="Vertices Edges Faces Solids" /> 
+      </feature>
     </group>
   </workbench>
 </plugin>
\ No newline at end of file
index 2932d5e5cce410fa963f068e5579554a3dcfc13c..f52353397cd33038c352ef1a98cbcfb3280e55ff 100644 (file)
 #include <ModelAPI_AttributeReference.h>
 #include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_ResultBody.h>
+#include <ModelAPI_AttributeSelectionList.h>
 #include <GeomAlgoAPI_Boolean.h>
 using namespace std;
 
+//#define DEBUG_ONE_OBJECT
+
 #define FACE 4
 #define _MODIFY_TAG 1
 #define _DELETED_TAG 2
@@ -24,8 +27,25 @@ FeaturesPlugin_Boolean::FeaturesPlugin_Boolean()
 void FeaturesPlugin_Boolean::initAttributes()
 {
   data()->addAttribute(FeaturesPlugin_Boolean::TYPE_ID(), ModelAPI_AttributeInteger::typeId());
+
+#ifdef DEBUG_ONE_OBJECT
   data()->addAttribute(FeaturesPlugin_Boolean::OBJECT_ID(), ModelAPI_AttributeReference::typeId());
+#else
+  AttributeSelectionListPtr aSelection = 
+    std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
+    FeaturesPlugin_Boolean::OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
+  // extrusion works with faces always
+  aSelection->setSelectionType("SOLID");
+#endif
+
+#ifdef DEBUG_ONE_OBJECT
   data()->addAttribute(FeaturesPlugin_Boolean::TOOL_ID(), ModelAPI_AttributeReference::typeId());
+#else
+  aSelection = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
+    FeaturesPlugin_Boolean::TOOL_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
+  // extrusion works with faces always
+  aSelection->setSelectionType("SOLID");
+#endif
 }
 
 std::shared_ptr<GeomAPI_Shape> FeaturesPlugin_Boolean::getShape(const std::string& theAttrName)
@@ -49,12 +69,41 @@ void FeaturesPlugin_Boolean::execute()
   if (!aTypeAttr)
     return;
   int aType = aTypeAttr->value();
-
+#ifdef DEBUG_ONE_OBJECT
   std::shared_ptr<GeomAPI_Shape> anObject = this->getShape(FeaturesPlugin_Boolean::OBJECT_ID());
+#else
+  std::shared_ptr<GeomAPI_Shape> anObject;
+  {
+    AttributeSelectionListPtr anObjects = selectionList(FeaturesPlugin_Boolean::OBJECT_LIST_ID());
+    if (anObjects->size() == 0)
+      return;
+
+    // Getting bounding planes.
+    std::shared_ptr<ModelAPI_AttributeSelection> anObjRef = anObjects->value(0);
+    if (!anObjRef.get())
+      return;
+    anObject = std::dynamic_pointer_cast<GeomAPI_Shape>(anObjRef->value());
+  }
+#endif
   if (!anObject)
     return;
 
+#ifdef DEBUG_ONE_OBJECT
   std::shared_ptr<GeomAPI_Shape> aTool = this->getShape(FeaturesPlugin_Boolean::TOOL_ID());
+#else
+  std::shared_ptr<GeomAPI_Shape> aTool;
+  {
+    AttributeSelectionListPtr anObjects = selectionList(FeaturesPlugin_Boolean::TOOL_LIST_ID());
+    if (anObjects->size() == 0)
+      return;
+
+    // Getting bounding planes.
+    std::shared_ptr<ModelAPI_AttributeSelection> anObjRef = anObjects->value(0);
+    if (!anObjRef.get())
+      return;
+    aTool = std::dynamic_pointer_cast<GeomAPI_Shape>(anObjRef->value());
+  }
+#endif
   if (!aTool)
     return;
 
index 65ad15d2e99f2ba424a3ebb50e75681d613d8713..53023300a90359148b8fccf7df6fde8152739e7f 100644 (file)
@@ -29,6 +29,12 @@ public:
     return MY_ID;
   }
   /// attribute name of referenced object
+  inline static const std::string& OBJECT_LIST_ID()
+  {
+    static const std::string MY_OBJECT_LIST_ID("main_objects");
+    return MY_OBJECT_LIST_ID;
+  }
+  /// attribute name of referenced object
   inline static const std::string& OBJECT_ID()
   {
     static const std::string MY_OBJECT_ID("main_object");
@@ -40,6 +46,12 @@ public:
     static const std::string MY_TOOL_ID("tool_object");
     return MY_TOOL_ID;
   }
+  /// attribute name of tool object
+  inline static const std::string& TOOL_LIST_ID()
+  {
+    static const std::string MY_TOOL_LIST_ID("tool_objects");
+    return MY_TOOL_LIST_ID;
+  }
   /// attribute name of operation type
   inline static const std::string& TYPE_ID()
   {
index 3056c26826725267bb419994850fb66990db52ff..f8a6bfc55e0c7388efc47f4f94a3b43c1e3ebdbb 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "FeaturesPlugin_Extrusion.h"
 #include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
 #include <ModelAPI_Document.h>
 #include <ModelAPI_Data.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_AttributeSelection.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeReference.h>
+#include <GeomAPI_Pln.h>
+#include <GeomAPI_XYZ.h>
 #include <GeomAlgoAPI_Extrusion.h>
+#include <GeomAlgoAPI_FaceBuilder.h>
+#include <GeomAlgoAPI_Prism.h>
 
 using namespace std;
 #define _LATERAL_TAG 1
@@ -33,14 +40,40 @@ void FeaturesPlugin_Extrusion::initAttributes()
     FeaturesPlugin_Extrusion::LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
   // extrusion works with faces always
   aSelection->setSelectionType("FACE");
-  data()->addAttribute(FeaturesPlugin_Extrusion::SIZE_ID(), ModelAPI_AttributeDouble::typeId());
-  data()->addAttribute(FeaturesPlugin_Extrusion::REVERSE_ID(), ModelAPI_AttributeBoolean::typeId());
+
+  data()->addAttribute(FeaturesPlugin_Extrusion::TO_SIZE_ID(), ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(FeaturesPlugin_Extrusion::FROM_SIZE_ID(), ModelAPI_AttributeDouble::typeId());
+
+  //data()->addAttribute(FeaturesPlugin_Extrusion::AXIS_OBJECT_ID(), ModelAPI_AttributeReference::typeId());
+
+  data()->addAttribute(FeaturesPlugin_Extrusion::FROM_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
+  data()->addAttribute(FeaturesPlugin_Extrusion::TO_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
+
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FeaturesPlugin_Extrusion::FROM_OBJECT_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FeaturesPlugin_Extrusion::TO_OBJECT_ID());
 }
 
 void FeaturesPlugin_Extrusion::execute()
 {
   AttributeSelectionListPtr aFaceRefs = selectionList(FeaturesPlugin_Extrusion::LIST_ID());
 
+  std::shared_ptr<GeomAPI_Shape> aFromShape(new GeomAPI_Shape);
+  std::shared_ptr<GeomAPI_Shape> aToShape(new GeomAPI_Shape);
+
+  // Getting bounding planes.
+  std::shared_ptr<ModelAPI_AttributeSelection> anObjRef = selection(FeaturesPlugin_Extrusion::FROM_OBJECT_ID());
+  if (anObjRef) {
+    aFromShape = std::dynamic_pointer_cast<GeomAPI_Shape>(anObjRef->value());
+  }
+  anObjRef = selection(FeaturesPlugin_Extrusion::TO_OBJECT_ID());
+  if (anObjRef) {
+    aToShape = std::dynamic_pointer_cast<GeomAPI_Shape>(anObjRef->value());
+  }
+
+  // Getting sizes.
+  double aFromSize = real(FeaturesPlugin_Extrusion::FROM_SIZE_ID())->value();
+  double aToSize = real(FeaturesPlugin_Extrusion::TO_SIZE_ID())->value();
+
   // for each selected face generate a result
   int anIndex = 0, aResultIndex = 0;
   for(; anIndex < aFaceRefs->size(); anIndex++) {
@@ -52,9 +85,6 @@ void FeaturesPlugin_Extrusion::execute()
       setError(aContextError);
       break;
     }
-    double aSize = real(FeaturesPlugin_Extrusion::SIZE_ID())->value();
-    if (boolean(FeaturesPlugin_Extrusion::REVERSE_ID())->value())
-      aSize = -aSize;
 
     std::shared_ptr<GeomAPI_Shape> aValueFace = aFaceRef->value();
     int aFacesNum = -1; // this mean that "aFace" is used
@@ -72,32 +102,66 @@ void FeaturesPlugin_Extrusion::execute()
 
     for(int aFaceIndex = 0; aFaceIndex < aFacesNum || aFacesNum == -1; aFaceIndex++) {
       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
-      std::shared_ptr<GeomAPI_Shape> aFace;
+      std::shared_ptr<GeomAPI_Shape> aBaseShape;
       if (aFacesNum == -1) {
-        aFace = aValueFace;
+        aBaseShape = aValueFace;
       } else {
-        aFace = std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
+        aBaseShape = std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
+      }
+
+      // If bounding faces was not set creating them.
+      std::shared_ptr<GeomAPI_Face> aBaseFace(new GeomAPI_Face(aBaseShape));
+      std::shared_ptr<GeomAPI_Pln> aBasePlane = aBaseFace->getPlane();
+      std::shared_ptr<GeomAPI_Dir> aBaseDir = aBasePlane->direction();
+      std::shared_ptr<GeomAPI_Pnt> aBaseLoc = aBasePlane->location();
+
+      if(!aFromShape) {
+        aFromShape = GeomAlgoAPI_FaceBuilder::plane(aBaseLoc, aBaseDir);
+      }
+      if(!aToShape) {
+        aToShape = GeomAlgoAPI_FaceBuilder::plane(aBaseLoc, aBaseDir);
       }
-      GeomAlgoAPI_Extrusion aFeature(aFace, aSize);
+
+      // Moving bounding faces according to "from" and "to" sizes.
+      std::shared_ptr<GeomAPI_Face> aFromFace(new GeomAPI_Face(aFromShape));
+      std::shared_ptr<GeomAPI_Pln> aFromPlane = aFromFace->getPlane();
+      std::shared_ptr<GeomAPI_Pnt> aFromLoc = aFromPlane->location();
+      std::shared_ptr<GeomAPI_Dir> aFromDir = aFromPlane->direction();
+
+      std::shared_ptr<GeomAPI_Face> aToFace(new GeomAPI_Face(aToShape));
+      std::shared_ptr<GeomAPI_Pln> aToPlane = aToFace->getPlane();
+      std::shared_ptr<GeomAPI_Pnt> aToLoc = aToPlane->location();
+      std::shared_ptr<GeomAPI_Dir> aToDir = aToPlane->direction();
+
+      bool aSign = aFromLoc->xyz()->dot(aBaseDir->xyz()) > aToLoc->xyz()->dot(aBaseDir->xyz());
+
+      std::shared_ptr<GeomAPI_Pnt> aFromPnt(new GeomAPI_Pnt(aFromLoc->xyz()->added(aBaseDir->xyz()->multiplied(aSign ? aFromSize : -aFromSize))));
+      aFromShape = GeomAlgoAPI_FaceBuilder::plane(aFromPnt, aFromDir);
+
+      std::shared_ptr<GeomAPI_Pnt> aToPnt(new GeomAPI_Pnt(aToLoc->xyz()->added(aBaseDir->xyz()->multiplied(aSign ? -aToSize : aToSize))));
+      aToShape = GeomAlgoAPI_FaceBuilder::plane(aToPnt, aToDir);
+
+      //GeomAlgoAPI_Extrusion aFeature(aFace, aFromSize);
+      GeomAlgoAPI_Prism aFeature(aBaseShape, aFromShape, aToShape);
       if(!aFeature.isDone()) {
-        static const std::string aFeatureError = "Extrusion algorithm failed";  
+        static const std::string aFeatureError = "Extrusion algorithm failed";
         setError(aFeatureError);
         break;
       }
 
       // Check if shape is valid
-      if (aFeature.shape()->isNull()) {
-        static const std::string aShapeError = "Resulting shape is Null";     
+      if(aFeature.shape()->isNull()) {
+        static const std::string aShapeError = "Resulting shape is Null";
         setError(aShapeError);
         break;
       }
       if(!aFeature.isValid()) {
-        std::string aFeatureError = "Warning: resulting shape is not valid";  
+        std::string aFeatureError = "Warning: resulting shape is not valid";
         setError(aFeatureError);
         break;
-      }  
+      }
       //LoadNamingDS
-      LoadNamingDS(aFeature, aResultBody, aFace, aContext);
+      LoadNamingDS(aFeature, aResultBody, aBaseShape, aContext);
 
       setResult(aResultBody, aResultIndex);
       aResultIndex++;
@@ -111,18 +175,16 @@ void FeaturesPlugin_Extrusion::execute()
 }
 
 //============================================================================
-void FeaturesPlugin_Extrusion::LoadNamingDS(GeomAlgoAPI_Extrusion& theFeature, 
-  std::shared_ptr<ModelAPI_ResultBody> theResultBody, 
-  std::shared_ptr<GeomAPI_Shape> theBasis,
-  std::shared_ptr<GeomAPI_Shape> theContext)
-{  
-
-
+void FeaturesPlugin_Extrusion::LoadNamingDS(GeomAlgoAPI_Prism& theFeature,
+                                            std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+                                            std::shared_ptr<GeomAPI_Shape> theBasis,
+                                            std::shared_ptr<GeomAPI_Shape> theContext)
+{
   //load result
   if(theBasis->isEqual(theContext))
     theResultBody->store(theFeature.shape());
   else
-    theResultBody->storeGenerated(theContext, theFeature.shape()); 
+    theResultBody->storeGenerated(theContext, theFeature.shape());
 
   GeomAPI_DataMapOfShapeShape* aSubShapes = new GeomAPI_DataMapOfShapeShape();
   theFeature.mapOfShapes(*aSubShapes);
@@ -133,26 +195,23 @@ void FeaturesPlugin_Extrusion::LoadNamingDS(GeomAlgoAPI_Extrusion& theFeature,
 
   //Insert bottom face
   std::string aBotName = "BottomFace";
-  std::shared_ptr<GeomAPI_Shape> aBottomFace = theFeature.firstShape();  
-  if (!aBottomFace->isNull()) {
-       if (aSubShapes->isBound(aBottomFace)) {  
-               aBottomFace = aSubShapes->find(aBottomFace);            
-    }     
+  std::shared_ptr<GeomAPI_Shape> aBottomFace = theFeature.firstShape();
+  if(!aBottomFace->isNull()) {
+    if(aSubShapes->isBound(aBottomFace)) {
+      aBottomFace = aSubShapes->find(aBottomFace);
+    }
     theResultBody->generated(aBottomFace, aBotName, _FIRST_TAG);
   }
 
-
-
   //Insert top face
   std::string aTopName = "TopFace";
   std::shared_ptr<GeomAPI_Shape> aTopFace = theFeature.lastShape();
   if (!aTopFace->isNull()) {
-    if (aSubShapes->isBound(aTopFace)) {        
-      aTopFace = aSubShapes->find(aTopFace);   
+    if (aSubShapes->isBound(aTopFace)) {
+      aTopFace = aSubShapes->find(aTopFace);
     }
     theResultBody->generated(aTopFace, aTopName, _LAST_TAG);
   }
-  
 }
 
 //============================================================================
index 2150ce72023c8a72023a77e4775e6b52b0387122..42c0dc1d67b2fef738bc4b95569e7cdda38eb02a 100644 (file)
@@ -11,6 +11,7 @@
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_ResultBody.h>
 #include <GeomAlgoAPI_Extrusion.h>
+#include <GeomAlgoAPI_Prism.h>
 #include <GeomAPI_Shape.h>
 
 /**\class FeaturesPlugin_Extrusion
@@ -18,8 +19,9 @@
  * \brief Feature for creation of extrusion from the planar face.
  *
  * Extrusion creates the lateral faces based on edges of the base face and
- * the top face equal to the base face. Direction of extrusion is taken from the face
- * plane, but can be corrected by the "reverse" flag.
+ * the top and bottom faces equal to the base face or this faces can be projection on the
+ * bounding planes if they were set. Direction of extrusion is taken from the face
+ * plane or if the bounding faces were set then it will be from the bottom to the top plane.
  */
 class FeaturesPlugin_Extrusion : public ModelAPI_Feature
 {
@@ -38,17 +40,39 @@ class FeaturesPlugin_Extrusion : public ModelAPI_Feature
     return MY_GROUP_LIST_ID;
   }
 
+  /// attribute name of an object to which the extrusion grows
+  inline static const std::string& AXIS_OBJECT_ID()
+  {
+    static const std::string MY_TO_OBJECT_ID("axis_object");
+    return MY_TO_OBJECT_ID;
+  }
+
   /// attribute name of extrusion size
-  inline static const std::string& SIZE_ID()
+  inline static const std::string& TO_SIZE_ID()
   {
-    static const std::string MY_SIZE_ID("size");
-    return MY_SIZE_ID;
+    static const std::string MY_TO_SIZE_ID("to_size");
+    return MY_TO_SIZE_ID;
   }
-  /// attribute name of reverse direction
-  inline static const std::string& REVERSE_ID()
+
+  /// attribute name of extrusion size
+  inline static const std::string& FROM_SIZE_ID()
+  {
+    static const std::string MY_FROM_SIZE_ID("from_size");
+    return MY_FROM_SIZE_ID;
+  }
+
+  /// attribute name of an object to which the extrusion grows
+  inline static const std::string& TO_OBJECT_ID()
+  {
+    static const std::string MY_TO_OBJECT_ID("to_object");
+    return MY_TO_OBJECT_ID;
+  }
+
+  /// attribute name of tool object
+  inline static const std::string& FROM_OBJECT_ID()
   {
-    static const std::string MY_REVERSE_ID("reverse");
-    return MY_REVERSE_ID;
+    static const std::string MY_FROM_OBJECT_ID("from_object");
+    return MY_FROM_OBJECT_ID;
   }
 
   /// Returns the kind of a feature
@@ -68,9 +92,9 @@ class FeaturesPlugin_Extrusion : public ModelAPI_Feature
   FeaturesPlugin_Extrusion();
 private:
   /// Load Naming data structure of the feature to the document
-  void LoadNamingDS(GeomAlgoAPI_Extrusion& theFeature, std::shared_ptr<ModelAPI_ResultBody> theResultBody,
-                       std::shared_ptr<GeomAPI_Shape> theBasis,
-                       std::shared_ptr<GeomAPI_Shape> theContext);
+  void LoadNamingDS(GeomAlgoAPI_Prism& theFeature, std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+                    std::shared_ptr<GeomAPI_Shape> theBasis,
+                    std::shared_ptr<GeomAPI_Shape> theContext);
 
   /// Set an empty shape to the result of extrusion
   void clearResult();
index 767e51e15240ceac23d78b21f3e77d74e58e72c4..657a504d242938211ad83b347b4f81ff95689e08 100644 (file)
@@ -92,8 +92,8 @@ for eachSketchFeature in [aCircleSketchFeature, aTriangleSketchFeature]:
     anExtrusionFt = aPart.addFeature("Extrusion")
     anExtrusionFt.selectionList("base").append(
         aSketchResult, aSketchFaces[0])
-    anExtrusionFt.real("size").setValue(50)
-    anExtrusionFt.boolean("reverse").setValue(False)
+    anExtrusionFt.real("from_size").setValue(0)
+    anExtrusionFt.real("to_size").setValue(50)
     anExtrusionFt.execute()
     extrudedObjects.append(modelAPI_ResultBody(anExtrusionFt.firstResult()))
 aSession.finishOperation()
index bf5a2c0825e0a519747531c03e55b298fd1f8943..b74979c8bec7e4196c115598e93908905591623d 100644 (file)
@@ -4,13 +4,17 @@
       
       class FeaturesPlugin_Extrusion : public ModelAPI_Feature
         static const std::string MY_EXTRUSION_ID("Extrusion");
-        static const std::string MY_FACE_ID("base");
-        static const std::string MY_SIZE_ID("size");
-        static const std::string MY_REVERSE_ID("reverse");
-          
-        data()->addAttribute(FeaturesPlugin_Extrusion::FACE_ID(), ModelAPI_AttributeSelection::typeId());
-        data()->addAttribute(FeaturesPlugin_Extrusion::SIZE_ID(), ModelAPI_AttributeDouble::typeId());
-        data()->addAttribute(FeaturesPlugin_Extrusion::REVERSE_ID(), ModelAPI_AttributeBoolean::typeId());
+        static const std::string LIST_ID("base");
+        static const std::string MY_TO_SIZE_ID("to_size");
+        static const std::string MY_FROM_SIZE_ID("from_size");
+        static const std::string MY_TO_OBJECT_ID("to_object");
+        static const std::string MY_FROM_OBJECT_ID("from_object");
+
+        data()->addAttribute(FeaturesPlugin_Extrusion::LIST_ID(), ModelAPI_AttributeSelection::typeId());
+        data()->addAttribute(FeaturesPlugin_Extrusion::FROM_SIZE_ID(), ModelAPI_AttributeDouble::typeId());
+        data()->addAttribute(FeaturesPlugin_Extrusion::TO_SIZE_ID(), ModelAPI_AttributeDouble::typeId());
+        data()->addAttribute(FeaturesPlugin_Extrusion::FROM_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
+        data()->addAttribute(FeaturesPlugin_Extrusion::TO_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
 """
 #=========================================================================
 # Initialization of the test
@@ -19,6 +23,7 @@ from ModelAPI import *
 from GeomDataAPI import *
 from GeomAlgoAPI import *
 from GeomAPI import *
+import math
 
 __updated__ = "2014-12-16"
 
@@ -37,15 +42,15 @@ aPart = aPartResult.partDoc()
 # Create a sketch circle to extrude
 #=========================================================================
 aSession.startOperation()
-aSketchFeature = featureToCompositeFeature(aPart.addFeature("Sketch"))
-origin = geomDataAPI_Point(aSketchFeature.attribute("Origin"))
+aCircleSketchFeature = featureToCompositeFeature(aPart.addFeature("Sketch"))
+origin = geomDataAPI_Point(aCircleSketchFeature.attribute("Origin"))
 origin.setValue(0, 0, 0)
-dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX"))
+dirx = geomDataAPI_Dir(aCircleSketchFeature.attribute("DirX"))
 dirx.setValue(1, 0, 0)
-norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
+norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 # Create circle
-aSketchCircle = aSketchFeature.addFeature("SketchCircle")
+aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle")
 anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
 aCircleRadius = aSketchCircle.real("CircleRadius")
 anCircleCentr.setValue(50., 50)
@@ -55,34 +60,169 @@ aSession.finishOperation()
 # Make extrusion on circle
 #=========================================================================
 # Build shape from sketcher results
-aSketchResult = aSketchFeature.firstResult()
-aSketchEdges = modelAPI_ResultConstruction(aSketchResult).shape()
-origin = geomDataAPI_Point(aSketchFeature.attribute("Origin")).pnt()
-dirX = geomDataAPI_Dir(aSketchFeature.attribute("DirX")).dir()
-norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm")).dir()
-aSketchFaces = ShapeList()
+aCircleSketchResult = aCircleSketchFeature.firstResult()
+aCircleSketchEdges = modelAPI_ResultConstruction(aCircleSketchResult).shape()
+origin = geomDataAPI_Point(aCircleSketchFeature.attribute("Origin")).pnt()
+dirX = geomDataAPI_Dir(aCircleSketchFeature.attribute("DirX")).dir()
+norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm")).dir()
+aCircleSketchFaces = ShapeList()
 GeomAlgoAPI_SketchBuilder.createFaces(
-    origin, dirX, norm, aSketchEdges, aSketchFaces)
-assert (len(aSketchFaces) > 0)
-assert (aSketchFaces[0] is not None)
+    origin, dirX, norm, aCircleSketchEdges, aCircleSketchFaces)
+assert (len(aCircleSketchFaces) > 0)
+assert (aCircleSketchFaces[0] is not None)
 # Create extrusion
 aSession.startOperation()
 anExtrusionFt = aPart.addFeature("Extrusion")
 assert (anExtrusionFt.getKind() == "Extrusion")
 # selection type FACE=4
 anExtrusionFt.selectionList("base").append(
-    aSketchResult, aSketchFaces[0])
-anExtrusionFt.real("size").setValue(50)
-anExtrusionFt.boolean("reverse").setValue(False)
+    aCircleSketchResult, aCircleSketchFaces[0])
+anExtrusionFt.real("from_size").setValue(0)
+anExtrusionFt.real("to_size").setValue(50)
 anExtrusionFt.execute()
 aSession.finishOperation()
-assert (anExtrusionFt.real("size").value() == 50.0)
-assert (anExtrusionFt.boolean("reverse").value() == False)
+assert (anExtrusionFt.real("to_size").value() == 50.0)
 
 # Check extrusion results
 assert (len(anExtrusionFt.results()) > 0)
 anExtrusionResult = modelAPI_ResultBody(anExtrusionFt.firstResult())
 assert (anExtrusionResult is not None)
+
+#=========================================================================
+# Test extrusion between bounding planes
+#=========================================================================
+# Create from plane
+aSession.startOperation()
+aFromPlaneFeature = aPart.addFeature("Plane")
+aFromPlaneFeature.string("CreationMethod").setValue("PlaneByGeneralEquation")
+aFromPlaneFeature.real("A").setValue(0.)
+aFromPlaneFeature.real("B").setValue(0.)
+aFromPlaneFeature.real("C").setValue(1.)
+aFromPlaneFeature.real("D").setValue(30.)
+aSession.finishOperation()
+
+# Create to plane
+aSession.startOperation()
+aToPlaneFeature = aPart.addFeature("Plane")
+aToPlaneFeature.string("CreationMethod").setValue("PlaneByGeneralEquation")
+aToPlaneFeature.real("A").setValue(0.)
+aToPlaneFeature.real("B").setValue(0.)
+aToPlaneFeature.real("C").setValue(1.)
+aToPlaneFeature.real("D").setValue(-30.)
+aSession.finishOperation()
+
+# Create extrusion
+aSession.startOperation()
+anExtrusionFt = aPart.addFeature("Extrusion")
+assert (anExtrusionFt.getKind() == "Extrusion")
+# selection type FACE=4
+anExtrusionFt.selectionList("base").append(
+    aCircleSketchResult, aCircleSketchFaces[0])
+aFromResult = aFromPlaneFeature.firstResult()
+aFromShape = modelAPI_ResultConstruction(aFromResult).shape()
+anExtrusionFt.selection("from_object").setValue(aFromResult, aFromShape)
+anExtrusionFt.real("from_size").setValue(10)
+aToResult = aToPlaneFeature.firstResult()
+aToShape = modelAPI_ResultConstruction(aToResult).shape()
+anExtrusionFt.selection("to_object").setValue(aToResult, aToShape)
+anExtrusionFt.real("to_size").setValue(10)
+anExtrusionFt.execute()
+aSession.finishOperation()
+
+# Check extrusion results
+assert (len(anExtrusionFt.results()) > 0)
+anExtrusionResult = modelAPI_ResultBody(anExtrusionFt.firstResult())
+assert (anExtrusionResult is not None)
+
+# Check extrusion volume
+aRefVolume = 100530.96491487337
+aResVolume = GeomAlgoAPI_ShapeProps_volume(anExtrusionResult.shape())
+assert (math.fabs(aResVolume - aRefVolume) < 10 ** -5)
+
+#=========================================================================
+# Test extrusion between bounding faces from other sketch result
+#=========================================================================
+aSession.startOperation()
+aClampSketchFeature = featureToCompositeFeature(aPart.addFeature("Sketch"))
+origin = geomDataAPI_Point(aClampSketchFeature.attribute("Origin"))
+origin.setValue(0, 0, 0)
+dirx = geomDataAPI_Dir(aClampSketchFeature.attribute("DirX"))
+dirx.setValue(1, 0, 0)
+norm = geomDataAPI_Dir(aClampSketchFeature.attribute("Norm"))
+norm.setValue(0, 1, 0)
+# Create clamp
+aSketchLineA = aClampSketchFeature.addFeature("SketchLine")
+aSketchLineB = aClampSketchFeature.addFeature("SketchLine")
+aSketchLineC = aClampSketchFeature.addFeature("SketchLine")
+aSketchLineD = aClampSketchFeature.addFeature("SketchLine")
+aSketchLineE = aClampSketchFeature.addFeature("SketchLine")
+aLineAStartPoint = geomDataAPI_Point2D(aSketchLineA.attribute("StartPoint"))
+aLineAEndPoint = geomDataAPI_Point2D(aSketchLineA.attribute("EndPoint"))
+aLineBStartPoint = geomDataAPI_Point2D(aSketchLineB.attribute("StartPoint"))
+aLineBEndPoint = geomDataAPI_Point2D(aSketchLineB.attribute("EndPoint"))
+aLineCStartPoint = geomDataAPI_Point2D(aSketchLineC.attribute("StartPoint"))
+aLineCEndPoint = geomDataAPI_Point2D(aSketchLineC.attribute("EndPoint"))
+aLineDStartPoint = geomDataAPI_Point2D(aSketchLineD.attribute("StartPoint"))
+aLineDEndPoint = geomDataAPI_Point2D(aSketchLineD.attribute("EndPoint"))
+aLineEStartPoint = geomDataAPI_Point2D(aSketchLineE.attribute("StartPoint"))
+aLineEEndPoint = geomDataAPI_Point2D(aSketchLineE.attribute("EndPoint"))
+aLineAStartPoint.setValue(0., -50.)
+aLineAEndPoint.setValue(0., 50.)
+aLineBStartPoint.setValue(0., 50.)
+aLineBEndPoint.setValue(100., 50.)
+aLineCStartPoint.setValue(100., 50.)
+aLineCEndPoint.setValue(10., 0.)
+aLineDStartPoint.setValue(10., 0.)
+aLineDEndPoint.setValue(100., -50.)
+aLineEStartPoint.setValue(100., -50.)
+aLineEEndPoint.setValue(0., -50.)
+aSession.finishOperation()
+
+# Extrude clamp
+aClampSketchResult = aClampSketchFeature.firstResult()
+aClampSketchEdges = modelAPI_ResultConstruction(aClampSketchResult).shape()
+origin = geomDataAPI_Point(aClampSketchFeature.attribute("Origin")).pnt()
+dirX = geomDataAPI_Dir(aClampSketchFeature.attribute("DirX")).dir()
+norm = geomDataAPI_Dir(aClampSketchFeature.attribute("Norm")).dir()
+aClampSketchFaces = ShapeList()
+GeomAlgoAPI_SketchBuilder.createFaces(
+    origin, dirX, norm, aClampSketchEdges, aClampSketchFaces)
+aSession.startOperation()
+aClampExtrusionFt = aPart.addFeature("Extrusion")
+assert (aClampExtrusionFt.getKind() == "Extrusion")
+# selection type FACE=4
+aClampExtrusionFt.selectionList("base").append(
+    aClampSketchResult, aClampSketchFaces[0])
+aClampExtrusionFt.real("from_size").setValue(0)
+aClampExtrusionFt.real("to_size").setValue(70)
+aClampExtrusionFt.execute()
+aSession.finishOperation()
+
+# Check extrusion results
+assert (len(aClampExtrusionFt.results()) > 0)
+anExtrusionResult = modelAPI_ResultBody(aClampExtrusionFt.firstResult())
+assert (anExtrusionResult is not None)
+
+# Extrude circle
+aSession.startOperation()
+anExtrusionFt = aPart.addFeature("Extrusion")
+assert (anExtrusionFt.getKind() == "Extrusion")
+# selection type FACE=4
+anExtrusionFt.selectionList("base").append(
+    aCircleSketchResult, aCircleSketchFaces[0])
+aClampResult = aClampExtrusionFt.firstResult()
+anExtrusionFt.selection("from_object").selectSubShape("face", "Extrusion_3/LateralFace_1")
+anExtrusionFt.real("from_size").setValue(0)
+anExtrusionFt.selection("to_object").selectSubShape("face", "Extrusion_3/LateralFace_2")
+anExtrusionFt.real("to_size").setValue(0)
+anExtrusionFt.execute()
+aSession.finishOperation()
+
+# Check extrusion results
+assert (len(anExtrusionFt.results()) > 0)
+anExtrusionResult = modelAPI_ResultBody(anExtrusionFt.firstResult())
+assert (anExtrusionResult is not None)
+
 #=========================================================================
 # End of test
 #=========================================================================
index 4fda808d6fa172fc378358cef1e42547c218872e..2307a16a52c16b1d658336b1f9ab2f5a98b7342e 100644 (file)
@@ -65,8 +65,8 @@ GeomAlgoAPI_SketchBuilder.createFaces(
 anExtrusionFt = aPart.addFeature("Extrusion")
 anExtrusionFt.selectionList("base").append(
     aSketchResult, aSketchFaces[0])
-anExtrusionFt.real("size").setValue(50)
-anExtrusionFt.boolean("reverse").setValue(False)
+anExtrusionFt.real("from_size").setValue(50)
+anExtrusionFt.real("to_size").setValue(50)
 anExtrusionFt.execute()
 aSession.finishOperation()
 anExtrusionBody = modelAPI_ResultBody(anExtrusionFt.firstResult())
index 8ff8dabb1273db26bf3c726c8ad0440c43a14077..eb15549c14591f97e273d4e5b9a7875c2f5e2fdb 100644 (file)
@@ -90,8 +90,8 @@ for i in xrange(0, N * N):
 
     anExtrusionFt.selectionList("base").append(
         aSketchResult, aSketchFaces[0])
-    anExtrusionFt.real("size").setValue(10)
-    anExtrusionFt.boolean("reverse").setValue(False)
+    anExtrusionFt.real("from_size").setValue(0)
+    anExtrusionFt.real("to_size").setValue(10)
     # v1.0.2 from master
     # anExtrusionFt.selection("extrusion_face").setValue(
     #    aSketchResult, aSketchFaces[0])
@@ -151,8 +151,8 @@ GeomAlgoAPI_SketchBuilder.createFaces(
 aBox = aPart.addFeature("Extrusion")
 aBox.selectionList("base").append(
     aSketchResult, aSketchFaces[0])
-aBox.real("size").setValue(10)
-aBox.boolean("reverse").setValue(False)
+aBox.real("from_size").setValue(0)
+aBox.real("to_size").setValue(10)
 # v 1.0.2 from master
 # aBox.selection("extrusion_face").setValue(
 #     aSketchResult, aSketchFaces[0])
index 9a6e83da90e1e76fd50c922146d840aaacaf55dc..e1443e531c8ff456970a73001450b6e18f90a8bd 100644 (file)
@@ -1,24 +1,40 @@
 <!-- Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
 
 <source>
-  <shape_selector id="main_object" 
+  <!--<shape_selector id="main_object" 
     label="Main object" 
     icon=":icons/cut_shape.png" 
     tooltip="Select an object solid"
     shape_types="solid shell"
     concealment="true"
+  />-->
+  <multi_selector id="main_objects" 
+    label="Main object" 
+    icon=":icons/cut_shape.png" 
+    tooltip="Select an object solid"
+    type_choice="Solids"
+    concealment="true"
   />
-  <shape_selector id="tool_object" 
+  <multi_selector id="tool_objects" 
+    label="Tool object" 
+    icon=":icons/cut_tool.png" 
+    tooltip="Select a tool solid"
+    type_choice="Solids"
+    concealment="true" >
+       <validator id="PartSet_DifferentObjects"/>
+  </multi_selector>
+  <!--<shape_selector id="tool_object" 
     label="Tool object" 
     icon=":icons/cut_tool.png" 
     tooltip="Select a tool solid"
     shape_types="solid"
     concealment="true" >
        <validator id="PartSet_DifferentObjects"/>
-  </shape_selector>
+  </shape_selector>-->
   <choice id="bool_type" 
     label="Type" 
     tooltip="Type of boolean operation"
     string_list="Cut Fuse Common"
+    default="0"
   />
 </source>
index adbe17b11541e5971ca8a5724a65584af036ddc2..5783d542c91d650034452da3bccba393a648ea67 100644 (file)
@@ -8,15 +8,96 @@
     type_choice="Faces">
     <validator id="PartSet_SketchEntityValidator" parameters="Sketch"/>
   </multi_selector>
-  <doublevalue
-    id="size"
-    label="Size"
-    min="0"
-    step="1.0"
-    default="1"
-    icon=":icons/dimension_v.png"
-    tooltip="Height">
-    <validator id="GeomValidators_Positive"/>
-  </doublevalue>
-  <boolvalue id="reverse" label="Reverse" default="false" tooltip="Reverse default direction"/>
+  <groupbox title="From">
+    <shape_selector id="from_object"
+                    icon=":icons/plane.png"
+                    label="Plane face"
+                    tooltip="Select a planar face"
+                    shape_types="face"
+                    default="&lt;sketch&gt;">
+      <validator id="GeomValidators_Face" parameters="plane"/>
+    </shape_selector>
+    <doublevalue
+      id="from_size"
+      label="Size"
+      min="0"
+      step="1.0"
+      default="0"
+      icon=":icons/dimension_down.png"
+      tooltip="Height">
+      <validator id="GeomValidators_Positive"/>
+    </doublevalue>
+  </groupbox>
+  <groupbox title="To">
+    <shape_selector id="to_object"
+                    icon=":icons/plane_inverted.png"
+                    label="Plane face"
+                    tooltip="Select a planar face"
+                    shape_types="face"
+                    default="&lt;sketch&gt;">
+      <validator id="GeomValidators_Face" parameters="plane"/>
+    </shape_selector>
+    <doublevalue
+      id="to_size"
+      label="Size"
+      min="0"
+      step="1.0"
+      default="10"
+      icon=":icons/dimension_up.png"
+      tooltip="Height">
+      <validator id="GeomValidators_Positive"/>
+    </doublevalue>
+  </groupbox>
+<!--XML definition of the revolution:-->
+<!--  <multi_selector id="base"
+    label="Select a sketch face"
+    icon=":icons/sketch.png"
+    tooltip="Select a sketch face"
+    type_choice="Faces">
+    <validator id="PartSet_SketchEntityValidator" parameters="Sketch"/>
+  </multi_selector>
+  <shape_selector id="axis_object"
+                  icon=":icons/axis.png"
+                  label="Plane face"
+                  tooltip="Select a planar face"
+                  shape_types="edge">
+  </shape_selector>
+  <groupbox title="From">
+    <shape_selector id="from_object"
+                    icon=":icons/plane.png"
+                    label="Plane face"
+                    tooltip="Select a planar face"
+                    shape_types="face">
+      <validator id="GeomValidators_Face" parameters="plane"/>
+    </shape_selector>
+    <doublevalue
+      id="from_size"
+      label="Size"
+      min="0"
+      step="1.0"
+      default="0"
+      icon=":icons/angle_down.png"
+      tooltip="Height">
+      <validator id="GeomValidators_Positive"/>
+    </doublevalue>
+  </groupbox>
+  <groupbox title="To">
+    <shape_selector id="to_object"
+                    icon=":icons/plane_inverted.png"
+                    label="Plane face"
+                    tooltip="Select a planar face"
+                    shape_types="face">
+      <validator id="GeomValidators_Face" parameters="plane"/>
+    </shape_selector>
+    <doublevalue
+      id="to_size"
+      label="Size"
+      min="0"
+      step="1.0"
+      default="10"
+      icon=":icons/angle_up.png"
+      tooltip="Height">
+      <validator id="GeomValidators_Positive"/>
+    </doublevalue>
+  </groupbox>-->
 </source>
index 858d8f877bca48b78b968e536a4eaa214a746e48..5c42d68a0d9e6afc35664479468a23ca8701ee89 100644 (file)
@@ -53,3 +53,8 @@ const std::shared_ptr<GeomAPI_XYZ> GeomAPI_Dir::cross(
   return std::shared_ptr<GeomAPI_XYZ>(new GeomAPI_XYZ(aResult.X(), aResult.Y(), aResult.Z()));
 }
 
+double GeomAPI_Dir::angle(const std::shared_ptr<GeomAPI_Dir>& theArg) const
+{
+  return MY_DIR->Angle(theArg->impl<gp_Dir>());
+}
+
index c713019f92267f6d7a9f46fce67fa605b98b5e1d..fa0cdcb6bcce408a43dcd90038f15b1b687eaab5 100644 (file)
@@ -39,6 +39,9 @@ class GEOMAPI_EXPORT GeomAPI_Dir : public GeomAPI_Interface
   double dot(const std::shared_ptr<GeomAPI_Dir>& theArg) const;
   /// result is a cross product of two directions
   const std::shared_ptr<GeomAPI_XYZ> cross(const std::shared_ptr<GeomAPI_Dir>& theArg) const;
+
+  /// calculates angle between two directions
+  double angle(const std::shared_ptr<GeomAPI_Dir>& theArg) const;
 };
 
 #endif
index e9131f992d6b2782d32d73d895eabcd6b83ab92e..abb954f294e260c54d789982eb52f361cf7a9bf5 100644 (file)
@@ -46,3 +46,7 @@ double GeomAPI_Dir2d::cross(const std::shared_ptr<GeomAPI_Dir2d>& theArg) const
   return MY_DIR->XY().Crossed(theArg->impl<gp_Dir2d>().XY());
 }
 
+double GeomAPI_Dir2d::angle(const std::shared_ptr<GeomAPI_Dir2d>& theArg) const
+{
+  return MY_DIR->Angle(theArg->impl<gp_Dir2d>());
+}
index ec558769392d7b1f91a370edaa9ea172a8526d1d..afea837238ee4077bef285278ae8c76ee91e2dab 100644 (file)
@@ -37,6 +37,9 @@ class GEOMAPI_EXPORT GeomAPI_Dir2d : public GeomAPI_Interface
   double dot(const std::shared_ptr<GeomAPI_Dir2d>& theArg) const;
   /// result is a cross product of two directions
   double cross(const std::shared_ptr<GeomAPI_Dir2d>& theArg) const;
+
+  /// calculates angle between two directions
+  double angle(const std::shared_ptr<GeomAPI_Dir2d>& theArg) const;
 };
 
 #endif
index 2055bdc6dac6951b35fb2e822c1eb46b5eee628b..b9dbd45df2f45bf8127e0b0d8f18a20ff43d9dfa 100644 (file)
@@ -16,6 +16,7 @@
 #include <BRepAdaptor_Surface.hxx>
 #include <Geom_Surface.hxx>
 #include <Geom_Plane.hxx>
+#include <GeomLib_IsPlanarSurface.hxx>
 
 GeomAPI_Face::GeomAPI_Face()
   : GeomAPI_Shape()
@@ -64,9 +65,8 @@ bool GeomAPI_Face::isPlanar() const
 {
   const TopoDS_Shape& aShape = const_cast<GeomAPI_Face*>(this)->impl<TopoDS_Shape>();
   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aShape));
-  if (aSurf->IsKind(STANDARD_TYPE(Geom_Plane)))
-    return true;
-  return false;
+  GeomLib_IsPlanarSurface isPlanar(aSurf);
+  return isPlanar.IsPlanar();
 }
 
 std::shared_ptr<GeomAPI_Pln> GeomAPI_Face::getPlane() const
index de7f2da3e7b1826fc96fbaf9ab4113c81b5aa191..83a668987dc3824de0e2c3674b65aa1ae50a2814 100644 (file)
@@ -7,33 +7,47 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
 
 SET(PROJECT_HEADERS
     GeomAlgoAPI.h
+    GeomAlgoAPI_Tools.h
     GeomAlgoAPI_CompoundBuilder.h
     GeomAlgoAPI_FaceBuilder.h
     GeomAlgoAPI_EdgeBuilder.h
     GeomAlgoAPI_PointBuilder.h
     GeomAlgoAPI_SketchBuilder.h
     GeomAlgoAPI_Extrusion.h
+    GeomAlgoAPI_Prism.h
     GeomAlgoAPI_Boolean.h
     GeomAlgoAPI_MakeShape.h
+    GeomAlgoAPI_ShapeProps.h
     GeomAlgoAPI_DFLoader.h
     GeomAlgoAPI_Placement.h
     GeomAlgoAPI_BREPImport.h
     GeomAlgoAPI_STEPImport.h
+    GeomAlgoAPI_IGESImport.h
+    GeomAlgoAPI_BREPExport.h
+    GeomAlgoAPI_STEPExport.h
+    GeomAlgoAPI_IGESExport.h
 )
 
 SET(PROJECT_SOURCES
+    GeomAlgoAPI_Tools.cpp
     GeomAlgoAPI_CompoundBuilder.cpp
     GeomAlgoAPI_FaceBuilder.cpp
     GeomAlgoAPI_EdgeBuilder.cpp
     GeomAlgoAPI_PointBuilder.cpp
     GeomAlgoAPI_SketchBuilder.cpp
     GeomAlgoAPI_Extrusion.cpp
+    GeomAlgoAPI_Prism.cpp
     GeomAlgoAPI_Boolean.cpp
     GeomAlgoAPI_MakeShape.cpp
+    GeomAlgoAPI_ShapeProps.cpp
     GeomAlgoAPI_DFLoader.cpp
     GeomAlgoAPI_Placement.cpp
     GeomAlgoAPI_BREPImport.cpp
     GeomAlgoAPI_STEPImport.cpp
+    GeomAlgoAPI_IGESImport.cpp
+    GeomAlgoAPI_BREPExport.cpp
+    GeomAlgoAPI_STEPExport.cpp
+    GeomAlgoAPI_IGESExport.cpp
 )
 
 SET(PROJECT_LIBRARIES
@@ -50,6 +64,7 @@ SET(PROJECT_LIBRARIES
     ${CAS_TKPrim}
     ${CAS_TKSTEP}
     ${CAS_TKSTEPBase}
+    ${CAS_TKIGES}
     ${CAS_TKTopAlgo}
     ${CAS_TKXSBase} 
 )
index 18d82cbcf25771b9270fbd65d9183f49b08ff4bc..f53434b4cd31a7f7ba6364589be72b606fccc8ca 100644 (file)
@@ -10,6 +10,8 @@
   #include "GeomAlgoAPI_FaceBuilder.h"
   #include "GeomAlgoAPI_MakeShape.h"
   #include "GeomAlgoAPI_PointBuilder.h"
+  #include "GeomAlgoAPI_Prism.h"
+  #include "GeomAlgoAPI_ShapeProps.h"
   #include "GeomAlgoAPI_SketchBuilder.h"
 
   #include <memory>
@@ -35,6 +37,8 @@
 %include "GeomAlgoAPI_FaceBuilder.h"
 %include "GeomAlgoAPI_MakeShape.h"
 %include "GeomAlgoAPI_PointBuilder.h"
+%include "GeomAlgoAPI_Prism.h"
+%include "GeomAlgoAPI_ShapeProps.h"
 %include "GeomAlgoAPI_SketchBuilder.h"
 
 %template(ShapeList) std::list<std::shared_ptr<GeomAPI_Shape> >;
\ No newline at end of file
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_BREPExport.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_BREPExport.cpp
new file mode 100644 (file)
index 0000000..c57b274
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#include <GeomAlgoAPI_BREPExport.h>
+
+#include "GeomAlgoAPI_Tools.h"
+
+#include <BRepTools.hxx>
+#include <BRep_Builder.hxx>
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+//extern "C" {
+namespace BREPExport {
+bool Export(const TCollection_AsciiString& theFileName,
+            const TCollection_AsciiString&,
+            const TopoDS_Shape& theShape,
+            TCollection_AsciiString& theError)
+{
+  #ifdef _DEBUG
+  std::cout << "Export BREP into file " << theFileName << std::endl;
+  #endif
+
+  // Set "C" numeric locale to save numbers correctly
+  GeomAlgoAPI_Tools::Localizer loc;
+
+  if ( !BRepTools::Write( theShape, theFileName.ToCString() ) ) {
+    theError = "BREP Export failed";
+    return false;
+  }
+  return true;
+}
+
+}
+//}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_BREPExport.h b/src/GeomAlgoAPI/GeomAlgoAPI_BREPExport.h
new file mode 100644 (file)
index 0000000..88acbf5
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+/*
+ * GEOMALGOAPI_BREPExport.h
+ *
+ *  Created on: May 14, 2015
+ *      Author: spo
+ */
+
+#ifndef GEOMALGOAPI_BREPEXPORT_H_
+#define GEOMALGOAPI_BREPEXPORT_H_
+
+#include <GeomAlgoAPI.h>
+
+#include <TCollection_AsciiString.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TDF_Label.hxx>
+
+namespace BREPExport {
+
+/// Implementation of the export BREP files algorithms
+GEOMALGOAPI_EXPORT
+bool Export(const TCollection_AsciiString& theFileName,
+            const TCollection_AsciiString& theFormatName,
+            const TopoDS_Shape& theShape,
+            TCollection_AsciiString& theError);
+
+}
+
+#endif /* GEOMALGOAPI_BREPEXPORT_H_ */
index 2df29ebc080dedf4445d8563d8b6b54616c14d78..32cb7c95a67c461068f2ff681051729acfac2513 100644 (file)
@@ -14,7 +14,7 @@
 namespace BREPImport {
 TopoDS_Shape Import(const TCollection_AsciiString& theFileName,
                     const TCollection_AsciiString&,
-                    TCollection_AsciiString& theError, const TDF_Label&)
+                    TCollection_AsciiString& theError)
 {
   #ifdef _DEBUG
   std::cout << "Import BREP from file " << theFileName << std::endl;
index aa0c7202dd8fc62a6de4fadaa696db6ff74fbc62..6afbdf0cad1d1c830fe72af945630c70723455a9 100644 (file)
@@ -22,7 +22,7 @@ namespace BREPImport {
 GEOMALGOAPI_EXPORT
 TopoDS_Shape Import(const TCollection_AsciiString& theFileName,
                     const TCollection_AsciiString& theFormatName,
-                    TCollection_AsciiString& theError, const TDF_Label&);
+                    TCollection_AsciiString& theError);
 
 }
 
index a00f8d8c0972a2b00a6dd60c83e5a451071df0db..d03b76169da3c224762f41fcdb5057e3885333cb 100644 (file)
@@ -11,6 +11,7 @@
 #include <TopoDS.hxx>
 #include <BRep_Tool.hxx>
 #include <Geom_Plane.hxx>
+#include <GeomLib_IsPlanarSurface.hxx>
 
 
 std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_FaceBuilder::square(
@@ -41,6 +42,18 @@ std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_FaceBuilder::square(
   return aRes;
 }
 
+std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_FaceBuilder::plane(std::shared_ptr<GeomAPI_Pnt> theCenter,
+                                                              std::shared_ptr<GeomAPI_Dir> theNormal)
+{
+  const gp_Pnt& aCenter = theCenter->impl<gp_Pnt>();
+  const gp_Dir& aDir = theNormal->impl<gp_Dir>();
+  gp_Pln aPlane(aCenter, aDir);
+  BRepBuilderAPI_MakeFace aFaceBuilder(aPlane);
+  std::shared_ptr<GeomAPI_Shape> aRes(new GeomAPI_Shape);
+  aRes->setImpl(new TopoDS_Shape(aFaceBuilder.Face()));
+  return aRes;
+}
+
 std::shared_ptr<GeomAPI_Pln> GeomAlgoAPI_FaceBuilder::plane(
     std::shared_ptr<GeomAPI_Shape> theFace)
 {
@@ -58,11 +71,13 @@ std::shared_ptr<GeomAPI_Pln> GeomAlgoAPI_FaceBuilder::plane(
   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
   if (aSurf.IsNull())
     return aResult;  // no surface
-  Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(aSurf);
-  if (aPlane.IsNull())
-    return aResult;  // not planar
+  GeomLib_IsPlanarSurface isPlanar(aSurf);
+  if(!isPlanar.IsPlanar()) {
+    return aResult;
+  }
+  gp_Pln aPln = isPlanar.Plan();
   double aA, aB, aC, aD;
-  aPlane->Coefficients(aA, aB, aC, aD);
+  aPln.Coefficients(aA, aB, aC, aD);
   aResult = std::shared_ptr<GeomAPI_Pln>(new GeomAPI_Pln(aA, aB, aC, aD));
   return aResult;
 }
index d71ec0b9cff9c7c8eb3794bbc7c0cbe38e067d16..9f15bb5c090b3da652499945e128a3636ab65094 100644 (file)
@@ -32,6 +32,10 @@ class GEOMALGOAPI_EXPORT GeomAlgoAPI_FaceBuilder
   static std::shared_ptr<GeomAPI_Shape> square(std::shared_ptr<GeomAPI_Pln> thePlane,
                                                const double theSize);
 
+  /// Creates the plane by given point of the center and normal to the plane.
+  static std::shared_ptr<GeomAPI_Shape> plane(std::shared_ptr<GeomAPI_Pnt> theCenter,
+                                            std::shared_ptr<GeomAPI_Dir> theNormal);
+
   /// Returns the plane of the planar face. If it is not planar, returns empty ptr.
   static std::shared_ptr<GeomAPI_Pln> plane(std::shared_ptr<GeomAPI_Shape> theFace);
 
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_IGESExport.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_IGESExport.cpp
new file mode 100644 (file)
index 0000000..936dfd6
--- /dev/null
@@ -0,0 +1,138 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#include <GeomAlgoAPI_IGESExport.h>
+
+#include "GeomAlgoAPI_Tools.h"
+
+// OOCT includes
+#include <IGESControl_Controller.hxx>
+#include <IGESControl_Writer.hxx>
+#include <Interface_Static.hxx>
+
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Iterator.hxx>
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+/*!
+ *  KindOfBRep
+ *  \return 0 if theShape contains only simple entities (wires, edges and vertices),
+ *          1 if theShape contains only complex entities (shells, solids and compsolids)
+ *          2 if theShape contains only indifferent entities (faces)
+ *         -1 if theShape contains both simple and complex entities (and in this case it
+ *            cannot be saved without any loss neither in BRepMode == 0 nor in BRepMode == 1)
+ */
+//=============================================================================
+int KindOfBRep (const TopoDS_Shape& theShape)
+{
+  int aKind = 2;
+
+  switch (theShape.ShapeType())
+  {
+  case TopAbs_COMPOUND:
+    {
+      bool isSimple = false;
+      bool isComplex = false;
+      TopoDS_Iterator anIt (theShape, Standard_True, Standard_True);
+      for (; anIt.More(); anIt.Next()) {
+        TopoDS_Shape aS = anIt.Value();
+        int aKindSub = KindOfBRep(aS);
+        if (aKindSub == 0)
+          isSimple = true;
+        else if (aKindSub == 1)
+          isComplex = true;
+        else if (aKindSub == -1) {
+          return -1; // heterogeneous
+        }
+      }
+      if (isSimple && isComplex)
+        aKind = -1; // heterogeneous
+      else if (isSimple)
+        aKind = 0;
+      else if (isComplex)
+        aKind = 1;
+    }
+    break;
+  case TopAbs_COMPSOLID:
+  case TopAbs_SOLID:
+  case TopAbs_SHELL:
+    aKind = 1;
+    break;
+  case TopAbs_WIRE:
+  case TopAbs_EDGE:
+  case TopAbs_VERTEX:
+    aKind = 0;
+    break;
+  default:
+    aKind = 2;
+  }
+
+  return aKind;
+}
+
+//=============================================================================
+//extern "C" {
+
+namespace IGESExport {
+
+bool Export(const TCollection_AsciiString& theFileName,
+            const TCollection_AsciiString& theFormatName,
+            const TopoDS_Shape& theShape,
+            TCollection_AsciiString& theError)
+{
+  // theFormatName expected "IGES-5.1", "IGES-5.3"...
+  TCollection_AsciiString aVersion = theFormatName.Token("-", 2);
+  #ifdef _DEBUG
+  if (!aVersion.IsEqual("5.1") || !aVersion.IsEqual("5.3"))
+    std::cout << "Warning: unrecognized version " << aVersion.ToCString()
+              << ". Default version: 5.1." << std::endl;
+  #endif
+  // define, whether to write only faces (5.1 IGES format)
+  // or shells and solids also (5.3 IGES format)
+  int aBrepMode = 0;
+  if( aVersion.IsEqual( "5.3" ) )
+    aBrepMode = 1;
+
+  #ifdef _DEBUG
+  std::cout << "Export IGES into file " << theFileName.ToCString() << std::endl;
+  #endif
+
+  // Mantis issue 0021350: check being exported shape, as some stand-alone
+  // entities (edges, wires and vertices) cannot be saved in BRepMode
+  if( aBrepMode == 1 ) {
+    int aKind = KindOfBRep( theShape );
+    if( aKind == -1 ) {
+      theError = "EXPORT_IGES_HETEROGENEOUS_COMPOUND";
+      return false;
+    } else if( aKind == 2 )
+      aBrepMode = 1;
+    else
+      aBrepMode = aKind;
+  }
+
+  // Set "C" numeric locale to save numbers correctly
+  GeomAlgoAPI_Tools::Localizer loc;
+
+  // initialize writer
+  IGESControl_Controller::Init();
+  IGESControl_Writer ICW( "M", aBrepMode ); // export explicitly in meters
+  Interface_Static::SetCVal( "xstep.cascade.unit", "M" );
+
+  // 09.03.2010 skl for bug 0020726
+  // change default value "Average" to "Max"
+  Interface_Static::SetCVal( "write.precision.mode", "Max" );
+
+  // perform shape writing
+  if( ICW.AddShape( theShape ) ) {
+    ICW.ComputeModel();
+    return ICW.Write( theFileName.ToCString() );
+  }
+  return false;
+}
+
+}
+
+//}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_IGESExport.h b/src/GeomAlgoAPI/GeomAlgoAPI_IGESExport.h
new file mode 100644 (file)
index 0000000..4f0f3cc
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+/*
+ * GEOMALGOAPI_IGESExport.h
+ *
+ *  Created on: Dec 24, 2014
+ *      Author: sbh
+ */
+
+#ifndef GEOMALGOAPI_IGESEXPORT_H_
+#define GEOMALGOAPI_IGESEXPORT_H_
+
+#include <GeomAlgoAPI.h>
+
+#include <TCollection_AsciiString.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TDF_Label.hxx>
+
+namespace IGESExport {
+
+/// Implementation of the export IGES files algorithms
+GEOMALGOAPI_EXPORT
+bool Export(const TCollection_AsciiString& theFileName,
+            const TCollection_AsciiString& theFormatName,
+            const TopoDS_Shape& theShape,
+            TCollection_AsciiString& theError);
+
+}
+
+#endif /* GEOMALGOAPI_IGESEXPORT_H_ */
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_IGESImport.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_IGESImport.cpp
new file mode 100644 (file)
index 0000000..8e20cb3
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#include <GeomAlgoAPI_IGESImport.h>
+
+// OOCT includes
+#include <IGESControl_Reader.hxx>
+#include <IGESData_IGESModel.hxx>
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+//extern "C" {
+namespace IGESImport {
+TopoDS_Shape Import(const TCollection_AsciiString& theFileName,
+                    const TCollection_AsciiString&,
+                    TCollection_AsciiString& theError)
+{
+  #ifdef _DEBUG
+  std::cout << "Import IGES from file " << theFileName << std::endl;
+  #endif
+  TopoDS_Shape aResShape;
+  IGESControl_Reader aReader;
+  try {
+    IFSelect_ReturnStatus status = aReader.ReadFile( theFileName.ToCString() );
+
+    if (status == IFSelect_RetDone) {
+      #ifdef _DEBUG
+      std::cout << "ImportIGES : all Geometry Transfer" << std::endl;
+      #endif
+      aReader.ClearShapes();
+      aReader.TransferRoots();
+
+      #ifdef _DEBUG
+      std::cout << "ImportIGES : count of shapes produced = " << aReader.NbShapes() << std::endl;
+      #endif
+      aResShape = aReader.OneShape();
+    }
+    else {
+      switch (status) {
+        case IFSelect_RetVoid:
+          theError = "Nothing created or No data to process";
+          break;
+        case IFSelect_RetError:
+          theError = "Error in command or input data";
+          break;
+        case IFSelect_RetFail:
+          theError = "Execution was run, but has failed";
+          break;
+        case IFSelect_RetStop:
+          theError = "Execution has been stopped. Quite possible, an exception was raised";
+          break;
+        default:
+          theError = "Wrong format of the imported file. Can't import file.";
+          break;
+      }
+      aResShape.Nullify();
+    }
+  }
+  catch( Standard_Failure ) {
+    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+    theError = aFail->GetMessageString();
+    aResShape.Nullify();
+  }
+
+  return aResShape;
+}
+
+}
+//}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_IGESImport.h b/src/GeomAlgoAPI/GeomAlgoAPI_IGESImport.h
new file mode 100644 (file)
index 0000000..9bdb3ad
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+/*
+ * GEOMALGOAPI_IGESImport.h
+ *
+ *  Created on: May 14, 2015
+ *      Author: spo
+ */
+
+#ifndef GEOMALGOAPI_IGESIMPORT_H_
+#define GEOMALGOAPI_IGESIMPORT_H_
+
+#include <GeomAlgoAPI.h>
+
+#include <TCollection_AsciiString.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TDF_Label.hxx>
+
+namespace IGESImport {
+
+/// Implementation of the import IGES files algorithms
+GEOMALGOAPI_EXPORT
+TopoDS_Shape Import(const TCollection_AsciiString& theFileName,
+                    const TCollection_AsciiString& theFormatName,
+                    TCollection_AsciiString& theError);
+
+}
+
+#endif /* GEOMALGOAPI_IGESIMPORT_H_ */
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp
new file mode 100644 (file)
index 0000000..f800657
--- /dev/null
@@ -0,0 +1,144 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomAlgoAPI_Prism.h
+// Created:     5 May 2015
+// Author:      Dmitry Bobylev
+
+#include <GeomAlgoAPI_Prism.h>
+
+#include <GeomAlgoAPI_DFLoader.h>
+
+#include <BRep_Tool.hxx>
+#include <BRepCheck_Analyzer.hxx>
+#include <BRepFeat_MakePrism.hxx>
+#include <BRepGProp.hxx>
+#include <Geom_CylindricalSurface.hxx>
+#include <Geom_Plane.hxx>
+#include <Geom_RectangularTrimmedSurface.hxx>
+#include <gp_Cylinder.hxx>
+#include <gp_Pln.hxx>
+#include <GProp_GProps.hxx>
+#include <LocOpe_FindEdgesInFace.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+
+GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(std::shared_ptr<GeomAPI_Shape> theBasis,
+                                     std::shared_ptr<GeomAPI_Shape> theFromShape,
+                                     std::shared_ptr<GeomAPI_Shape> theToShape)
+: myFromShape(theFromShape),
+  myToShape(theToShape),
+  myShape(new GeomAPI_Shape()),
+  myFirst(new GeomAPI_Shape()),myLast(new GeomAPI_Shape())
+{
+  build(theBasis);
+}
+
+//============================================================================
+void GeomAlgoAPI_Prism::build(const std::shared_ptr<GeomAPI_Shape>& theBasis)
+{
+  TopoDS_Face aBasis = TopoDS::Face(theBasis->impl<TopoDS_Shape>());
+  Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(
+    BRep_Tool::Surface(aBasis));
+  if(aPlane.IsNull()) { // non-planar shapes is not supported for extrusion yet
+    return;
+  }
+
+  const gp_Dir& aNormal = aPlane->Pln().Axis().Direction();
+  BRepFeat_MakePrism* aBuilder = new BRepFeat_MakePrism(aBasis, aBasis, aBasis, aNormal, 2, Standard_True);
+
+  if(aBuilder) {
+    setImpl(aBuilder);
+    TopoDS_Shape aFromShape = myFromShape->impl<TopoDS_Shape>();
+    TopoDS_Shape aToShape   = myToShape->impl<TopoDS_Shape>();
+    aBuilder->Perform(myFromShape->impl<TopoDS_Shape>(), myToShape->impl<TopoDS_Shape>());
+    myDone = aBuilder->IsDone();
+    if (myDone) {
+      TopoDS_Shape aResult;
+      if(aBuilder->Shape().ShapeType() == TopAbs_COMPOUND) {
+        aResult = GeomAlgoAPI_DFLoader::refineResult(aBuilder->Shape());
+      }
+      else {
+        aResult = aBuilder->Shape();
+      }
+      TopExp_Explorer anExp(aResult, TopAbs_SOLID);
+      if(!anExp.More()) {
+        return;
+      }
+      // fill data map to keep correct orientation of sub-shapes
+      for (TopExp_Explorer Exp(aResult,TopAbs_FACE); Exp.More(); Exp.Next()) {
+        std::shared_ptr<GeomAPI_Shape> aCurrentShape(new GeomAPI_Shape());
+        aCurrentShape->setImpl(new TopoDS_Shape(Exp.Current()));
+        myMap.bind(aCurrentShape, aCurrentShape);
+      }
+      myShape->setImpl(new TopoDS_Shape(aResult));
+      myFirst->setImpl(new TopoDS_Shape(aBuilder->Modified(aFromShape).First()));
+      myLast->setImpl(new TopoDS_Shape(aBuilder->Modified(aToShape).First()));
+      myMkShape = new GeomAlgoAPI_MakeShape (aBuilder);
+    }
+  }
+}
+
+//============================================================================
+const bool GeomAlgoAPI_Prism::isDone() const
+{
+  return myDone;
+}
+
+//============================================================================
+const bool GeomAlgoAPI_Prism::isValid() const
+{
+  BRepCheck_Analyzer aChecker(myShape->impl<TopoDS_Shape>());
+  return (aChecker.IsValid() == Standard_True);
+}
+
+//============================================================================
+const bool GeomAlgoAPI_Prism::hasVolume() const
+{
+  bool hasVolume(false);
+  if(isValid()) {
+    const TopoDS_Shape& aRShape = myShape->impl<TopoDS_Shape>();
+    GProp_GProps aGProp;
+    BRepGProp::VolumeProperties(aRShape, aGProp);
+    if(aGProp.Mass() > Precision::Confusion())
+      hasVolume = true;
+  }
+  return hasVolume;
+}
+
+//============================================================================
+const std::shared_ptr<GeomAPI_Shape>& GeomAlgoAPI_Prism::shape () const
+{
+  return myShape;
+}
+
+//============================================================================
+const std::shared_ptr<GeomAPI_Shape>& GeomAlgoAPI_Prism::firstShape()
+{
+  return myFirst;
+}
+
+//============================================================================
+const std::shared_ptr<GeomAPI_Shape>& GeomAlgoAPI_Prism::lastShape()
+{
+  return myLast;
+}
+
+//============================================================================
+void GeomAlgoAPI_Prism::mapOfShapes (GeomAPI_DataMapOfShapeShape& theMap) const
+{
+  theMap = myMap;
+}
+
+//============================================================================
+GeomAlgoAPI_MakeShape* GeomAlgoAPI_Prism::makeShape() const
+{
+  return myMkShape;
+}
+
+//============================================================================
+GeomAlgoAPI_Prism::~GeomAlgoAPI_Prism()
+{
+  if (myImpl) {
+    myMap.clear();
+  }
+}
\ No newline at end of file
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Prism.h b/src/GeomAlgoAPI/GeomAlgoAPI_Prism.h
new file mode 100644 (file)
index 0000000..a795e90
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomAlgoAPI_Prism.h
+// Created:     5 May 2015
+// Author:      Dmitry Bobylev
+
+#ifndef GeomAlgoAPI_Prism_H_
+#define GeomAlgoAPI_Prism_H_
+
+#include <GeomAlgoAPI.h>
+#include <GeomAPI_Shape.h>
+#include <GeomAlgoAPI_MakeShape.h>
+#include <GeomAPI_DataMapOfShapeShape.h>
+#include <memory>
+
+/**\class GeomAlgoAPI_Prism
+ * \ingroup DataAlgo
+ * \brief Allows to create the prism based on a given face and bounding planes
+ */
+
+class GeomAlgoAPI_Prism : public GeomAPI_Interface
+{
+public:
+  /* \brief Creates extrusion for the given shape along the normal for this shape
+   * \param[in] theBasis face or wire to be extruded
+   * \param[in] theFromShape bottom bounding shape
+   * \param[in] theToShape top bounding shape
+   * \return a solid or a face/shell which is obtained from specified one
+   */
+  /// Constructor
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Prism(std::shared_ptr<GeomAPI_Shape> theBasis,
+                                       std::shared_ptr<GeomAPI_Shape> theFromShape,
+                                       std::shared_ptr<GeomAPI_Shape> theToShape);
+
+  /// Returns True if algorithm succeed
+  GEOMALGOAPI_EXPORT const bool isDone() const;
+
+  ///  Returns True if resulting shape is valid
+  GEOMALGOAPI_EXPORT const bool isValid() const;
+
+  /// Returns True if resulting shape has volume
+  GEOMALGOAPI_EXPORT const bool hasVolume() const;
+
+  /// Returns result of the Prism algorithm which may be a Solid or a Face
+  GEOMALGOAPI_EXPORT const std::shared_ptr<GeomAPI_Shape>& shape() const;
+
+  /// Returns the first shape 
+  GEOMALGOAPI_EXPORT const std::shared_ptr<GeomAPI_Shape>& firstShape();
+
+  /// returns last shape
+  GEOMALGOAPI_EXPORT const std::shared_ptr<GeomAPI_Shape>& lastShape();
+  /// Returns map of sub-shapes of the result. To be used for History keeping
+  GEOMALGOAPI_EXPORT void  mapOfShapes(GeomAPI_DataMapOfShapeShape& theMap) const;
+
+  /// Return interface for for History processing
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_MakeShape* makeShape() const;
+
+  /// Destructor
+  GEOMALGOAPI_EXPORT  ~GeomAlgoAPI_Prism();
+private:
+  /// builds resulting shape
+  void build(const std::shared_ptr<GeomAPI_Shape>& theBasis);
+  /// fields
+  std::shared_ptr<GeomAPI_Shape> myFromShape;
+  std::shared_ptr<GeomAPI_Shape> myToShape;
+  bool myDone;
+  std::shared_ptr<GeomAPI_Shape> myShape;
+  std::shared_ptr<GeomAPI_Shape> myFirst;
+  std::shared_ptr<GeomAPI_Shape> myLast;
+  GeomAPI_DataMapOfShapeShape myMap;
+  GeomAlgoAPI_MakeShape* myMkShape;
+};
+
+#endif
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_STEPExport.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_STEPExport.cpp
new file mode 100644 (file)
index 0000000..ab2ac79
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#include <GeomAlgoAPI_STEPExport.h>
+
+#include "GeomAlgoAPI_Tools.h"
+
+// OOCT includes
+#include <IFSelect_ReturnStatus.hxx>
+#include <STEPControl_Writer.hxx>
+#include <Interface_Static.hxx>
+
+namespace STEPExport {
+
+bool Export(const TCollection_AsciiString& theFileName,
+            const TCollection_AsciiString& theFormatName,
+            const TopoDS_Shape& theShape,
+            TCollection_AsciiString& theError)
+{
+  #ifdef _DEBUG
+  std::cout << "Export STEP into file " << theFileName.ToCString() << std::endl;
+  #endif
+
+  try
+  {
+    // Set "C" numeric locale to save numbers correctly
+    GeomAlgoAPI_Tools::Localizer loc;
+
+    IFSelect_ReturnStatus status ;
+    //VRV: OCC 4.0 migration
+    STEPControl_Writer aWriter;
+    Interface_Static::SetCVal("xstep.cascade.unit","M");
+    Interface_Static::SetCVal("write.step.unit", "M");
+    Interface_Static::SetIVal("write.step.nonmanifold", 1);
+    status = aWriter.Transfer( theShape, STEPControl_AsIs );
+    //VRV: OCC 4.0 migration
+    if( status == IFSelect_RetDone )
+      status = aWriter.Write( theFileName.ToCString() );
+
+    // Return previous locale
+    if( status == IFSelect_RetDone )
+      return true;
+  }
+  catch (Standard_Failure)
+  {
+    theError = "Exception catched in STEPExport";
+  }
+  return false;
+}
+
+} // namespace STEPExport
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_STEPExport.h b/src/GeomAlgoAPI/GeomAlgoAPI_STEPExport.h
new file mode 100644 (file)
index 0000000..e05a59f
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+/*
+ * GEOMALGOAPI_STEPExport.h
+ *
+ *  Created on: May 14, 2015
+ *      Author: spo
+ */
+
+#ifndef GEOMALGOAPI_STEPEXPORT_H_
+#define GEOMALGOAPI_STEPEXPORT_H_
+
+#include <GeomAlgoAPI.h>
+
+#include <TCollection_AsciiString.hxx>
+#include <TCollection_HAsciiString.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TDF_Label.hxx>
+
+namespace STEPExport {
+
+/// Implementation of the export parameter from the STEP file
+GEOMALGOAPI_EXPORT
+Handle(TCollection_HAsciiString) GetValue(const TCollection_AsciiString& theFileName,
+                                          const TCollection_AsciiString& theParameterName,
+                                          TCollection_AsciiString& theError);
+
+/// Implementation of the export STEP files algorithms
+GEOMALGOAPI_EXPORT
+bool Export(const TCollection_AsciiString& theFileName,
+            const TCollection_AsciiString& theFormatName,
+            const TopoDS_Shape& theShape,
+            TCollection_AsciiString& theError);
+}
+
+#endif /* GEOMALGOAPI_STEPEXPORT_H_ */
index 8ed138604b6ebfea7cf7d14f52b1fbe35e2feb3c..4bc7f2f6488b334be9f229440f06679317eb8700 100644 (file)
@@ -366,8 +366,7 @@ Handle(TCollection_HAsciiString) GetValue (const TCollection_AsciiString& theFil
 
 TopoDS_Shape Import (const TCollection_AsciiString& theFileName,
                      const TCollection_AsciiString& theFormatName,
-                     TCollection_AsciiString&       theError,
-                     const TDF_Label&               theShapeLabel)
+                     TCollection_AsciiString&       theError)
 {
   TopoDS_Shape aResShape;
 
index 232f28dced00e767cc03b4f1edb4ea9de4805985..5955ddbf11a13792b62f84379e769d476fd06cda 100644 (file)
@@ -7,6 +7,9 @@
  *      Author: sbh
  */
 
+#ifndef GEOMALGOAPI_STEPIMPORT_H_
+#define GEOMALGOAPI_STEPIMPORT_H_
+
 #include <GeomAlgoAPI.h>
 
 #include <TCollection_AsciiString.hxx>
@@ -25,6 +28,8 @@ Handle(TCollection_HAsciiString) GetValue(const TCollection_AsciiString& theFile
 /// Implementation of the import STEP files algorithms
 GEOMALGOAPI_EXPORT
 TopoDS_Shape Import(const TCollection_AsciiString& theFileName,
-                    const TCollection_AsciiString& theFormatName, TCollection_AsciiString& theError,
-                    const TDF_Label& theShapeLabel);
+                    const TCollection_AsciiString& theFormatName,
+                    TCollection_AsciiString& theError);
 }
+
+#endif /* GEOMALGOAPI_STEPIMPORT_H_ */
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeProps.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeProps.cpp
new file mode 100644 (file)
index 0000000..00ef55c
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomAlgoAPI_ShapeProps.cpp
+// Created:     8 May 2015
+// Author:      Dmitry Bobylev
+
+#include <GeomAlgoAPI_ShapeProps.h>
+
+#include <BRepGProp.hxx>
+#include <GProp_GProps.hxx>
+#include <TopoDS_Shape.hxx>
+
+
+double GeomAlgoAPI_ShapeProps::volume(std::shared_ptr<GeomAPI_Shape> theShape)
+{
+  GProp_GProps aGProps;
+  TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
+  BRepGProp::VolumeProperties(aShape, aGProps);
+  return aGProps.Mass();
+}
\ No newline at end of file
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeProps.h b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeProps.h
new file mode 100644 (file)
index 0000000..636b43d
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomAlgoAPI_ShapeProps.h
+// Created:     8 May 2015
+// Author:      Dmitry Bobylev
+
+#ifndef GeomAlgoAPI_ShapeProps_H_
+#define GeomAlgoAPI_ShapeProps_H_
+
+/**\class GeomAlgoAPI_ShapeProps
+ * \ingroup DataAlgo
+ * \brief Allows to compute different shape props
+ */
+
+#include <GeomAlgoAPI.h>
+#include <GeomAPI_Shape.h>
+
+class GEOMALGOAPI_EXPORT GeomAlgoAPI_ShapeProps
+{
+public:
+  /// Returns the total volume of the solids of the current shape
+  static double volume(std::shared_ptr<GeomAPI_Shape> theShape);
+};
+
+#endif
+
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Tools.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Tools.cpp
new file mode 100644 (file)
index 0000000..50a3907
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * GeomAlgoAPI_Tools.cpp
+ *
+ *  Created on: May 18, 2015
+ *      Author: spo
+ */
+
+#include "GeomAlgoAPI_Tools.h"
+
+#include <clocale>
+
+using namespace GeomAlgoAPI_Tools;
+
+Localizer::Localizer()
+{
+  myCurLocale = std::setlocale(LC_NUMERIC, 0);
+  std::setlocale(LC_NUMERIC, "C");
+}
+
+Localizer::~Localizer()
+{
+  std::setlocale(LC_NUMERIC, myCurLocale.c_str());
+}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Tools.h b/src/GeomAlgoAPI/GeomAlgoAPI_Tools.h
new file mode 100644 (file)
index 0000000..2f1e0eb
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * GeomAlgoAPI_Tools.h
+ *
+ *  Created on: May 18, 2015
+ *      Author: spo
+ */
+
+#ifndef GEOMALGOAPI_TOOLS_H_
+#define GEOMALGOAPI_TOOLS_H_
+
+#include <GeomAlgoAPI.h>
+
+#include <string>
+
+namespace GeomAlgoAPI_Tools {
+
+class GEOMALGOAPI_EXPORT Localizer
+{
+public:
+  Localizer();
+  ~Localizer();
+private:
+  std::string myCurLocale;
+};
+
+} // GeomAlgoAPI_Tools
+
+#endif /* GEOMALGOAPI_TOOLS_H_ */
index 3a07a17cbbf265f6c6f072ceb97ada89bbcfea0c..fda2411f42b9727627719ea32702dd588a28a6bd 100644 (file)
@@ -5,19 +5,17 @@ INCLUDE(Common)
 SET(PROJECT_HEADERS
     GeomValidators.h
     GeomValidators_ConstructionComposite.h
-    GeomValidators_Edge.h
-    GeomValidators_EdgeOrVertex.h
     GeomValidators_Face.h
     GeomValidators_Positive.h
+    GeomValidators_ShapeType.h
     GeomValidators_Tools.h
 )
 
 SET(PROJECT_SOURCES
     GeomValidators_ConstructionComposite.cpp
-    GeomValidators_Edge.cpp
-    GeomValidators_EdgeOrVertex.cpp
     GeomValidators_Face.cpp
     GeomValidators_Positive.cpp
+    GeomValidators_ShapeType.cpp
     GeomValidators_Tools.cpp
 )
 
diff --git a/src/GeomValidators/GeomValidators_Edge.cpp b/src/GeomValidators/GeomValidators_Edge.cpp
deleted file mode 100644 (file)
index 0518f4a..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-
-#include "GeomValidators_Edge.h"
-#include "GeomValidators_Tools.h"
-
-#include <GeomAPI_Curve.h>
-#include <Events_Error.h>
-#include <ModelAPI_Result.h>
-
-#include <StdSelect_TypeOfEdge.hxx>
-
-#include <string>
-#include <map>
-
-
-typedef std::map<std::string, GeomValidators_Edge::TypeOfEdge> EdgeTypes;
-static EdgeTypes MyEdgeTypes;
-
-GeomValidators_Edge::TypeOfEdge GeomValidators_Edge::edgeType(const std::string& theType)
-{
-  if (MyEdgeTypes.size() == 0) {
-    MyEdgeTypes["line"] = Line;
-    MyEdgeTypes["circle"] = Circle;
-  }
-  std::string aType = std::string(theType.c_str());
-  if (MyEdgeTypes.find(aType) != MyEdgeTypes.end())
-    return MyEdgeTypes[aType];
-  
-  Events_Error::send("Edge type defined in XML is not implemented!");
-  return AnyEdge;
-}
-
-bool GeomValidators_Edge::isValid(const AttributePtr& theAttribute,
-                                  const std::list<std::string>& theArguments) const
-{
-  bool aValid = false;
-
-  TypeOfEdge anEdgeType = AnyEdge;
-  if (theArguments.size() == 1) {
-    std::string anArgument = theArguments.front();
-    anEdgeType = edgeType(anArgument);
-  }
-
-  ObjectPtr anObject = GeomValidators_Tools::getObject(theAttribute);
-  if (anObject.get() != NULL) {
-    FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
-    ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
-    if (aResult.get() != NULL) {
-      GeomShapePtr aShape = aResult->shape();
-      if (aShape.get() != NULL && aShape->isEdge()) {
-        aValid = anEdgeType == AnyEdge;
-        if (!aValid) {
-          bool isCircle = GeomAPI_Curve(aShape).isCircle();
-          aValid = (isCircle && anEdgeType == Circle) ||
-                   (!isCircle && anEdgeType == Line);
-        }
-      }
-    }
-  }
-  else {
-    //AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
-  }
-  return aValid;
-}
diff --git a/src/GeomValidators/GeomValidators_Edge.h b/src/GeomValidators/GeomValidators_Edge.h
deleted file mode 100644 (file)
index 5b29a82..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:        GeomValidators_Edge.h
-// Created:     19 Mar 2015
-// Author:      Natalia ERMOLAEVA
-
-#ifndef GeomValidators_Edge_H
-#define GeomValidators_Edge_H
-
-#include "GeomValidators.h"
-#include "ModelAPI_AttributeValidator.h"
-
-#include <string>
-
-/**
-* \ingroup Validators
-* A validator of selection
-*/
-class GeomValidators_Edge : public ModelAPI_AttributeValidator
-{
- public:
-  //  the edge type
-  enum TypeOfEdge
-  {
-    AnyEdge,
-    Line,
-    Circle
-  };
-
- public:
-   GEOMVALIDATORS_EXPORT GeomValidators_Edge() {}
-  //! returns true if attribute is valid
-  //! \param theAttribute the checked attribute
-  //! \param theArguments arguments of the attribute
-  GEOMVALIDATORS_EXPORT virtual bool isValid(const AttributePtr& theAttribute,
-                                             const std::list<std::string>& theArguments) const;
-protected:
-  /// Convert string to TypeOfEdge value
-  /// \param theType a string value
-  static TypeOfEdge edgeType(const std::string& theType);
-};
-
-#endif
diff --git a/src/GeomValidators/GeomValidators_EdgeOrVertex.cpp b/src/GeomValidators/GeomValidators_EdgeOrVertex.cpp
deleted file mode 100644 (file)
index cfd78c9..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-
-#include "GeomValidators_EdgeOrVertex.h"
-#include "GeomValidators_Tools.h"
-#include "GeomValidators_Edge.h"
-
-#include "ModelAPI_AttributeRefAttr.h"
-#include "ModelAPI_Result.h"
-
-#include <ModelAPI_Session.h>
-
-#include <GeomAPI_Curve.h>
-#include <GeomDataAPI_Point2D.h>
-
-#include <Events_Error.h>
-
-#include <StdSelect_TypeOfEdge.hxx>
-
-#include <QString>
-#include <QMap>
-
-
-bool GeomValidators_EdgeOrVertex::isValid(const AttributePtr& theAttribute,
-                                          const std::list<std::string>& theArguments) const
-{
-  bool aValid = false;
-
-  // 1. check whether the attribute is a linear edge
-    // there is a check whether the feature contains a point and a linear edge or two point values
-  SessionPtr aMgr = ModelAPI_Session::get();
-  ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
-
-  const GeomValidators_Edge* aLinearEdgeValidator =
-    dynamic_cast<const GeomValidators_Edge*>(aFactory->validator("GeomValidators_Edge"));
-
-  std::list<std::string> anArguments;
-  anArguments.push_back("line");
-  aValid = aLinearEdgeValidator->isValid(theAttribute, anArguments);
-  if (!aValid) {
-    //2. check whether the attribute is a vertex
-    ObjectPtr anObject = GeomValidators_Tools::getObject(theAttribute);
-    if (anObject.get() != NULL) {
-      FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
-      ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
-      if (aResult.get() != NULL) {
-        GeomShapePtr aShape = aResult->shape();
-        if (aShape.get() != NULL) {
-          aValid = aShape->isVertex();
-        }
-      }
-    }
-    else {
-      AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
-      if (anAttr.get() != NULL) {
-        AttributePtr aRefAttr = anAttr->attr();
-        aValid = aRefAttr.get() != NULL && aRefAttr->attributeType() == GeomDataAPI_Point2D::typeId();
-      }
-    }
-  }
-  return aValid;
-}
diff --git a/src/GeomValidators/GeomValidators_EdgeOrVertex.h b/src/GeomValidators/GeomValidators_EdgeOrVertex.h
deleted file mode 100644 (file)
index 52b7add..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File:        GeomValidators_EdgeOrVertex.h
-// Created:     19 Mar 2015
-// Author:      Natalia ERMOLAEVA
-
-#ifndef GeomValidators_EdgeOrVertex_H
-#define GeomValidators_EdgeOrVertex_H
-
-#include "GeomValidators.h"
-#include "ModelAPI_AttributeValidator.h"
-
-#include <StdSelect_TypeOfEdge.hxx>
-
-/**
-* \ingroup Validators
-* A validator of selection
-*/
-class GeomValidators_EdgeOrVertex : public ModelAPI_AttributeValidator
-{
- public:
-   GEOMVALIDATORS_EXPORT GeomValidators_EdgeOrVertex() {}
-  //! returns true if attribute is valid
-  //! \param theAttribute the checked attribute
-  //! \param theArguments arguments of the attribute
-  GEOMVALIDATORS_EXPORT virtual bool isValid(const AttributePtr& theAttribute,
-                                             const std::list<std::string>& theArguments) const;
-};
-
-#endif
index 58964c04f985a1ce4f9afc8bedd3c83f8ebc6926..9d3fbf983cbb233da6fbd89d8ee71c3aae325a99 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "GeomValidators_Positive.h"
 #include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
 
@@ -23,7 +24,11 @@ GeomValidators_Positive::GeomValidators_Positive()
 bool GeomValidators_Positive::isValid(
     const AttributePtr& theAttribute, const std::list<std::string>& theArguments) const
 {
-  std::shared_ptr<ModelAPI_AttributeDouble> aDouble = 
+  AttributeDoublePtr aDouble = 
     std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
-  return aDouble->isInitialized() && aDouble->value() > 1.e-5;
+  if (aDouble.get())
+    return aDouble->isInitialized() && aDouble->value() > 1.e-5;
+  AttributeIntegerPtr aInteger = 
+    std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(theAttribute);
+  return aInteger->isInitialized() && aInteger->value() > 0;
 }
diff --git a/src/GeomValidators/GeomValidators_ShapeType.cpp b/src/GeomValidators/GeomValidators_ShapeType.cpp
new file mode 100644 (file)
index 0000000..f5ce2fd
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+
+#include "GeomValidators_ShapeType.h"
+#include "GeomValidators_Tools.h"
+
+#include <GeomAPI_Curve.h>
+#include <GeomDataAPI_Point2D.h>
+
+#include <ModelAPI_Result.h>
+#include "ModelAPI_AttributeRefAttr.h"
+
+#include <Events_Error.h>
+
+#include <string>
+#include <map>
+
+
+typedef std::map<std::string, GeomValidators_ShapeType::TypeOfShape> EdgeTypes;
+static EdgeTypes MyEdgeTypes;
+
+GeomValidators_ShapeType::TypeOfShape GeomValidators_ShapeType::shapeType(const std::string& theType)
+{
+  if (MyEdgeTypes.size() == 0) {
+    MyEdgeTypes["vertex"] = Vertex;
+    MyEdgeTypes["line"]   = Line;
+    MyEdgeTypes["circle"] = Circle;
+  }
+  std::string aType = std::string(theType.c_str());
+  if (MyEdgeTypes.find(aType) != MyEdgeTypes.end())
+    return MyEdgeTypes[aType];
+  
+  Events_Error::send("Edge type defined in XML is not implemented!");
+  return AnyShape;
+}
+
+bool GeomValidators_ShapeType::isValid(const AttributePtr& theAttribute,
+                                       const std::list<std::string>& theArguments) const
+{
+  bool aValid = false;
+
+  std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
+  for (; anIt != aLast && !aValid; anIt++) {
+    aValid = isValidArgument(theAttribute, *anIt);
+  }
+
+  return aValid;
+}
+
+bool GeomValidators_ShapeType::isValidArgument(const AttributePtr& theAttribute,
+                                               const std::string& theArgument) const
+{
+  bool aValid = false;
+  TypeOfShape aShapeType = shapeType(theArgument);
+  if (aShapeType == AnyShape)
+    return true;
+
+  ObjectPtr anObject = GeomValidators_Tools::getObject(theAttribute);
+  if (anObject.get() != NULL) {
+    FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
+    ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
+    if (aResult.get() != NULL) {
+      GeomShapePtr aShape = aResult->shape();
+      if (aShape.get() != NULL) {
+        switch (aShapeType) {
+          case Line:
+            aValid = aShape->isEdge() && !GeomAPI_Curve(aShape).isCircle();
+          break;
+          case Circle:
+            aValid = aShape->isEdge() && GeomAPI_Curve(aShape).isCircle();
+          break;
+          case Vertex:
+            aValid = aShape->isVertex();
+          break;
+          default: break;
+        }
+      }
+    }
+  }
+  else {
+    AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
+    if (anAttr.get() != NULL) {
+      if (aShapeType == Vertex) {
+        AttributePtr aRefAttr = anAttr->attr();
+        aValid = aRefAttr.get() != NULL && aRefAttr->attributeType() == GeomDataAPI_Point2D::typeId();
+      }
+    }
+  }
+  return aValid;
+}
diff --git a/src/GeomValidators/GeomValidators_ShapeType.h b/src/GeomValidators/GeomValidators_ShapeType.h
new file mode 100644 (file)
index 0000000..ce3232d
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        GeomValidators_ShapeType.h
+// Created:     19 Mar 2015
+// Author:      Natalia ERMOLAEVA
+
+#ifndef GeomValidators_ShapeType_H
+#define GeomValidators_ShapeType_H
+
+#include "GeomValidators.h"
+#include "ModelAPI_AttributeValidator.h"
+
+#include <string>
+
+/**
+* \ingroup Validators
+* A validator for shape types, such as vertex, line, circe or arc.
+* If there are some argument parameters, this validator returns true if the attribute satisfied
+* at least one argument (OR combination of arguments).
+*/
+class GeomValidators_ShapeType : public ModelAPI_AttributeValidator
+{
+ public:
+  //  the edge type
+  enum TypeOfShape
+  {
+    AnyShape,
+    Vertex,
+    Line,
+    Circle
+  };
+
+ public:
+   GEOMVALIDATORS_EXPORT GeomValidators_ShapeType() {}
+  //! returns true if attribute is valid
+  //! \param theAttribute the checked attribute
+  //! \param theArguments arguments of the attribute
+  GEOMVALIDATORS_EXPORT virtual bool isValid(const AttributePtr& theAttribute,
+                                             const std::list<std::string>& theArguments) const;
+protected:
+  /// Convert string to TypeOfShape value
+  /// \param theType a string value
+  static TypeOfShape shapeType(const std::string& theType);
+
+  bool isValidArgument(const AttributePtr& theAttribute,
+                       const std::string& theArgument) const;
+
+};
+
+#endif
index b2ced2b57b3ef5372fa45dbaf9ddcb9a3b316240..f3ef02d96f74386779af970e047e0496363f9433 100644 (file)
@@ -55,17 +55,16 @@ void InitializationPlugin_Plugin::processEvent(const std::shared_ptr<Events_Mess
 
     // hides the created features, the precondition is that the feature's results have been
     // already built, so the createPlane/Points method calls the execute function for the planes
-    static Events_ID HIDE_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TOHIDE);
     std::list<FeaturePtr >::const_iterator aFIter = aFeatures.begin();
     for (; aFIter != aFeatures.cend(); aFIter++) {
       FeaturePtr aPlane = *aFIter;
       const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aPlane->results();
       std::list<ResultPtr >::const_iterator aRIter = aResults.begin();
       for (; aRIter != aResults.cend(); aRIter++) {
-        ModelAPI_EventCreator::get()->sendUpdated(*aRIter, HIDE_DISP);
+        (*aRIter)->setDisplayed(false);
       }
     }
-    Events_Loop::loop()->flush(HIDE_DISP);
+    Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
 
     // the viewer update should be unblocked in order to avoid the features blinking before they are
     // hidden
index eef87c35f0ab499310e9e2537fa811087cd2ddce..46c9881a214e6cf2b214b441128f256b31690fdb 100644 (file)
@@ -6,6 +6,7 @@ SET(PROJECT_HEADERS
     Model.h
     Model_Application.h
     Model_Document.h
+    Model_Objects.h
     Model_Session.h
     Model_Data.h
     Model_AttributeDouble.h
@@ -33,6 +34,7 @@ SET(PROJECT_HEADERS
 SET(PROJECT_SOURCES
     Model_Application.cpp
     Model_Document.cpp
+    Model_Objects.cpp
     Model_Session.cpp
     Model_Data.cpp
     Model_AttributeDouble.cpp
index 212fd4c9cab1ec924a6fe9fd14d2ced24b7a74ec..4a77ae9ef42f7afc79e077acbe72349aacfef8a9 100644 (file)
@@ -37,9 +37,10 @@ const std::shared_ptr<Model_Document>& Model_Application::getDocument(string the
 
   // load it if it must be loaded by demand
   if (myLoadedByDemand.find(theDocID) != myLoadedByDemand.end() && !myPath.empty()) {
-    aNew->load(myPath.c_str());
+    aNew->load(myPath.c_str(), aNew);
     myLoadedByDemand.erase(theDocID);  // done, don't do it anymore
   } else {
+    aNew->setThis(aNew);
     static Events_ID anId = ModelAPI_DocumentCreatedMessage::eventId();
     std::shared_ptr<ModelAPI_DocumentCreatedMessage> aMessage = std::shared_ptr
       <ModelAPI_DocumentCreatedMessage>(new ModelAPI_DocumentCreatedMessage(anId, this));
index 38e989e047ca7f10928df123f79e44117b43d02a..0c24fe3e1b762cfa047e634473aca9408b288c2c 100644 (file)
@@ -7,6 +7,7 @@
 #include "Model_AttributeRefAttr.h"
 #include "Model_Application.h"
 #include "Model_Data.h"
+#include "Model_Objects.h"
 #include <ModelAPI_Feature.h>
 
 using namespace std;
@@ -45,7 +46,7 @@ void Model_AttributeRefAttr::setObject(ObjectPtr theObject)
 {
   // the back reference from the previous object to the attribute should be removed
   ObjectPtr anObject = object();
-  if (theObject && (!myIsInitialized || myID->Get().Length() != 0 || object() != theObject)) {
+  if (theObject.get() && (!myIsInitialized || myID->Get().Length() != 0 || object() != theObject)) {
     REMOVE_BACK_REF(anObject);
 
     std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(
@@ -76,13 +77,21 @@ ObjectPtr Model_AttributeRefAttr::object()
         owner()->document());
     if (aDoc) {
       TDF_Label aRefLab = myRef->Get();
-      return aDoc->object(aRefLab);
+      return aDoc->objects()->object(aRefLab);
     }
   }
   // not initialized
   return ObjectPtr();
 }
 
+bool Model_AttributeRefAttr::isInitialized()
+{
+  if (myRef->Get() == myRef->Label()) { // empty is not initialized: sketch parallelity
+    return false;
+  }
+  return ModelAPI_AttributeRefAttr::isInitialized();
+}
+
 Model_AttributeRefAttr::Model_AttributeRefAttr(TDF_Label& theLabel)
 {
   myIsInitialized = theLabel.FindAttribute(TDataStd_Comment::GetID(), myID) == Standard_True;
index 94609a8f5f37e5e9390638844764f3d177d5b775..66c0870e696a2fc035b2b0b736bd03d496df77c9 100644 (file)
@@ -40,6 +40,10 @@ class Model_AttributeRefAttr : public ModelAPI_AttributeRefAttr
   /// Returns object referenced from this attribute
   MODEL_EXPORT virtual ObjectPtr object();
 
+  /// Returns true if attribute was  initialized by some value
+  MODEL_EXPORT virtual bool isInitialized();
+
+
  protected:
   /// Objects are created for features automatically
   MODEL_EXPORT Model_AttributeRefAttr(TDF_Label& theLabel);
index b1fcda04632516822a6a4ae3c9abdbd4d95320dd..3e4f5a21dadb9f9bdce28065578f85e1f863f158 100644 (file)
@@ -7,6 +7,7 @@
 #include "Model_AttributeRefList.h"
 #include "Model_Application.h"
 #include "Model_Data.h"
+#include "Model_Objects.h"
 #include <ModelAPI_Feature.h>
 #include <TDF_ListIteratorOfLabelList.hxx>
 
@@ -37,7 +38,7 @@ void Model_AttributeRefList::remove(ObjectPtr theObject)
     if (aDoc) {
       const TDF_LabelList& aList = myRef->List();
       for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
-        ObjectPtr anObj = aDoc->object(aLIter.Value());
+        ObjectPtr anObj = aDoc->objects()->object(aLIter.Value());
         if (anObj.get() == NULL) {
           myRef->Remove(aLIter.Value());
           REMOVE_BACK_REF(theObject);
@@ -70,7 +71,7 @@ list<ObjectPtr> Model_AttributeRefList::list()
   if (aDoc) {
     const TDF_LabelList& aList = myRef->List();
     for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
-      ObjectPtr anObj = aDoc->object(aLIter.Value());
+      ObjectPtr anObj = aDoc->objects()->object(aLIter.Value());
       aResult.push_back(anObj);
     }
   }
@@ -86,7 +87,7 @@ ObjectPtr Model_AttributeRefList::object(const int theIndex) const
     int anIndex = 0;
     for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next(), anIndex++) {
       if (anIndex == theIndex)
-        return aDoc->object(aLIter.Value());
+        return aDoc->objects()->object(aLIter.Value());
     }
   }
   return ObjectPtr();
index 9c51e545b66ee0983cfcb17eb8747ce7dfe96654..a6ac5e31acfff3927684c76b6d2b792bbaee3723 100644 (file)
@@ -8,6 +8,7 @@
 #include "Model_Application.h"
 #include "Model_Events.h"
 #include "Model_Data.h"
+#include "Model_Objects.h"
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Session.h>
 
@@ -19,21 +20,29 @@ using namespace std;
 
 void Model_AttributeReference::setValue(ObjectPtr theObject)
 {
-  if(!theObject)
-    return;
+  // now allow to deselect in this attribute: extrusion from/to
+  //if(!theObject)
+  //  return;
   ObjectPtr aValue = value();
   if (!myIsInitialized || aValue != theObject) {
     REMOVE_BACK_REF(aValue);
 
-    std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(
-      theObject->data());
-    TDF_Label anObjLab = aData->label().Father(); // object label
-
-    if (owner()->document() == theObject->document()) { // same document, use reference attribute
+    TDF_Label anObjLab;
+    if (theObject.get() && theObject->data().get() && theObject->data()->isValid()) {
+      std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(
+        theObject->data());
+      anObjLab = aData->label().Father(); // object label
+    }
+    // same document, use reference attribute
+    if (anObjLab.IsNull() || owner()->document() == theObject->document()) {
 
       std::shared_ptr<Model_Document> aDoc =
         std::dynamic_pointer_cast<Model_Document>(owner()->document());
-      myRef->Set(anObjLab);  // references to the object label
+      if (anObjLab.IsNull()) {
+        myRef->Set(myRef->Label());
+      } else {
+        myRef->Set(anObjLab);  // references to the object label
+      }
        // remove external link attributes (if any)
       myRef->Label().ForgetAttribute(TDataStd_Comment::GetID());
       myRef->Label().ForgetAttribute(TDataStd_AsciiString::GetID());
@@ -54,7 +63,7 @@ void Model_AttributeReference::setValue(ObjectPtr theObject)
 
 ObjectPtr Model_AttributeReference::value()
 {
-  if (myIsInitialized) {
+  if (isInitialized()) {
     Handle(TDataStd_Comment) aDocID;
     if (myRef->Label().FindAttribute(TDataStd_Comment::GetID(), aDocID)) { // external ref
       DocumentPtr aRefDoc =
@@ -64,9 +73,9 @@ ObjectPtr Model_AttributeReference::value()
         if (myRef->Label().FindAttribute(TDataStd_AsciiString::GetID(), anEntry)) {
           std::shared_ptr<Model_Document> aDR = std::dynamic_pointer_cast<Model_Document>(aRefDoc);
           TDF_Label aRefLab;
-          TDF_Tool::Label(aDR->featuresLabel().Data(), anEntry->Get().ToCString(), aRefLab);
+          TDF_Tool::Label(aDR->objects()->featuresLabel().Data(), anEntry->Get().ToCString(), aRefLab);
           if (!aRefLab.IsNull()) {
-            return aDR->object(aRefLab);
+            return aDR->objects()->object(aRefLab);
           }
         }
       }
@@ -76,7 +85,7 @@ ObjectPtr Model_AttributeReference::value()
       if (aDoc) {
         TDF_Label aRefLab = myRef->Get();
         if (!aRefLab.IsNull()) {  // it may happen with old document, issue #285
-          return aDoc->object(aRefLab);
+          return aDoc->objects()->object(aRefLab);
         }
       }
     }
@@ -85,6 +94,15 @@ ObjectPtr Model_AttributeReference::value()
   return FeaturePtr();
 }
 
+bool Model_AttributeReference::isInitialized()
+{
+  if (myRef->Label() == myRef->Get() && !myRef->Label().IsAttribute(TDataStd_Comment::GetID())) {
+    // empty reference is not initialized
+    return false;
+  }
+  return ModelAPI_AttributeReference::isInitialized();
+}
+
 Model_AttributeReference::Model_AttributeReference(TDF_Label& theLabel)
 {
   myIsInitialized = theLabel.FindAttribute(TDF_Reference::GetID(), myRef) == Standard_True;
index 991f4e725544ae90283cad4ecd618c58bbeba063..7ea779b6ce656afa2da6a068d4e2c5aca4e83ee7 100644 (file)
@@ -32,6 +32,10 @@ class Model_AttributeReference : public ModelAPI_AttributeReference
 
   MODEL_EXPORT virtual void setObject(const std::shared_ptr<ModelAPI_Object>& theObject);
 
+  /// Returns true if attribute was  initialized by some value
+  MODEL_EXPORT virtual bool isInitialized();
+
+
 protected:
   /// Objects are created for features automatically
   MODEL_EXPORT Model_AttributeReference(TDF_Label& theLabel);
index d6f9f869eb5fdf184b293bcd64e754a05bf03006..6ff60d02e363dde45d66a62466e116f72c006518 100644 (file)
@@ -649,10 +649,11 @@ bool isTrivial (const TopTools_ListOfShape& theAncestors, TopTools_IndexedMapOfS
   if(aNumber > 1) return false;
   return true;
 }
-std::string Model_AttributeSelection::namingName()
+std::string Model_AttributeSelection::namingName(const std::string& theDefaultName)
 {
   std::string aName("");
-  if(!this->isInitialized()) return aName;
+  if(!this->isInitialized())
+    return !theDefaultName.empty() ? theDefaultName : aName;
   Handle(TDataStd_Name) anAtt;
   if(selectionLabel().FindAttribute(TDataStd_Name::GetID(), anAtt)) {
     aName = TCollection_AsciiString(anAtt->Get()).ToCString();
@@ -663,7 +664,7 @@ std::string Model_AttributeSelection::namingName()
   ResultPtr aCont = context();
   aName = "Undefined name";
   if(!aCont.get() || aCont->shape()->isNull()) 
-    return aName;
+    return !theDefaultName.empty() ? theDefaultName : aName;
   if (!aSubSh.get() || aSubSh->isNull()) { // no subshape, so just the whole feature name
     return aCont->data()->name();
   }
index b900299de1b8f16fc8e3b22e3e64c68d89e222e8..19c1a151490126d014cc4931642f3d492bebbe08 100644 (file)
@@ -40,7 +40,8 @@ public:
   MODEL_EXPORT virtual bool update();
 
   /// Returns a textual string of the selection
-  MODEL_EXPORT virtual std::string namingName();
+  /// \param theDefaultValue a name, which is returned if the naming name can not be obtained
+  MODEL_EXPORT virtual std::string namingName(const std::string& theDefaultValue = "");
   
   /// Returns an Id of the selection
   /// NOTE: This method has been added for temporary export of groups towards old GEOM
index e2ef4c7477e1357cfae8ae05164661d08040f092..b6c27518e4fe1a9bc8c84d4bfc516a418d769c34 100644 (file)
 // myLab contains:
 // TDataStd_Name - name of the object
 // TDataStd_Integer - state of the object execution
+// TDataStd_BooleanArray - array of flags of this data:
+//                             0 - is in history or not
+static const int kFlagInHistory = 0;
+//                             1 - is displayed or not
+static const int kFlagDisplayed = 1;
 
 Model_Data::Model_Data() : mySendAttributeUpdated(true)
 {
@@ -47,6 +52,13 @@ Model_Data::Model_Data() : mySendAttributeUpdated(true)
 void Model_Data::setLabel(TDF_Label theLab)
 {
   myLab = theLab;
+  // set or get the default flags
+  if (!myLab.FindAttribute(TDataStd_BooleanArray::GetID(), myFlags)) {
+    // set default values if not found
+    myFlags = TDataStd_BooleanArray::Set(myLab, 0, 1);
+    myFlags->SetValue(kFlagInHistory, Standard_True); // is in history by default is true
+    myFlags->SetValue(kFlagDisplayed, Standard_True); // is displayed by default is true
+  }
 }
 
 std::string Model_Data::name()
@@ -369,3 +381,29 @@ void Model_Data::copyTo(std::shared_ptr<ModelAPI_Data> theTarget)
     }
   }
 }
+
+bool Model_Data::isInHistory()
+{
+  return myFlags->Value(kFlagInHistory) == Standard_True;
+}
+
+void Model_Data::setIsInHistory(const bool theFlag)
+{
+  return myFlags->SetValue(kFlagInHistory, theFlag);
+}
+
+bool Model_Data::isDisplayed()
+{
+  return myFlags->Value(kFlagDisplayed) == Standard_True;
+}
+
+void Model_Data::setDisplayed(const bool theDisplay)
+{
+  if (theDisplay != isDisplayed()) {
+    myFlags->SetValue(kFlagDisplayed, theDisplay);
+    static Events_Loop* aLoop = Events_Loop::loop();
+    static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+    static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
+    aECreator->sendUpdated(myObject, EVENT_DISP);
+  }
+}
index 4e96a5be5c65e126cc2352ca2fc2f07e72904e44..10464cabdba9c7b620c0197f3c91a4186d1773cf 100644 (file)
@@ -23,6 +23,7 @@
 #include <ModelAPI_Object.h>
 
 #include <TDF_Label.hxx>
+#include <TDataStd_BooleanArray.hxx>
 
 #include <memory>
 
@@ -44,6 +45,8 @@ class Model_Data : public ModelAPI_Data
   TDF_Label myLab;  ///< label of the feature in the document
   /// All attributes of the object identified by the attribute ID
   std::map<std::string, std::shared_ptr<ModelAPI_Attribute> > myAttrs;
+  /// Array of flags of this data
+  Handle(TDataStd_BooleanArray) myFlags;
 
   /// needed here to emit signal that object changed on change of the attribute
   ObjectPtr myObject;
@@ -62,6 +65,7 @@ class Model_Data : public ModelAPI_Data
   }
 
   friend class Model_Document;
+  friend class Model_Objects;
   friend class Model_Update;
   friend class Model_AttributeReference;
   friend class Model_AttributeRefAttr;
@@ -182,6 +186,13 @@ class Model_Data : public ModelAPI_Data
   /// Copies all atributes content into theTarget data
   MODEL_EXPORT virtual void copyTo(std::shared_ptr<ModelAPI_Data> theTarget);
 
+protected:
+  /// Returns true if "is in history" custom behaviors is defined for the feature
+  MODEL_EXPORT virtual bool isInHistory();
+
+  /// Defines the custom "is in history" behavior
+  MODEL_EXPORT virtual void setIsInHistory(const bool theFlag);
+
 private:
   /// Removes all information about back references
   void eraseBackReferences();
@@ -196,6 +207,15 @@ private:
   /// \param theApplyConcealment applies consealment flag changes
   void addBackReference(FeaturePtr theFeature, std::string theAttrID, 
     const bool theApplyConcealment = true);
+
+  /// Returns true if object must be displayed in the viewer: flag is stored in the
+  /// data model, so on undo/redo, open/save or recreation of object by history-playing it keeps
+  /// the original state i nthe current transaction.
+  MODEL_EXPORT virtual bool isDisplayed();
+
+  /// Sets the displayed/hidden state of the object. If it is changed, sends the "redisplay"
+  /// signal.
+  MODEL_EXPORT virtual void setDisplayed(const bool theDisplay);
 };
 
 /// Generic method to register back reference, used in referencing attributes.
index 836e289b2433e06499cf6ebd4b2a7b7da8dce0b1..df85c6e4b7ad3bc2c45cd6b72ec77b4b4660e945 100644 (file)
@@ -6,14 +6,11 @@
 
 #include <Model_Document.h>
 #include <Model_Data.h>
+#include <Model_Objects.h>
 #include <Model_Application.h>
 #include <Model_Session.h>
 #include <Model_Events.h>
-#include <Model_ResultPart.h>
-#include <Model_ResultConstruction.h>
-#include <Model_ResultBody.h>
-#include <Model_ResultGroup.h>
-#include <Model_ResultParameter.h>
+#include <ModelAPI_ResultPart.h>
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_CompositeFeature.h>
 
 static const int UNDO_LIMIT = 1000;  // number of possible undo operations (big for sketcher)
 
 static const int TAG_GENERAL = 1;  // general properties tag
-static const int TAG_OBJECTS = 2;  // tag of the objects sub-tree (features, results)
-static const int TAG_HISTORY = 3;  // tag of the history sub-tree (python dump)
 
-// feature sub-labels
-static const int TAG_FEATURE_ARGUMENTS = 1;  ///< where the arguments are located
-static const int TAG_FEATURE_RESULTS = 2;  ///< where the results are located
-
-///
-/// 0:1:2 - where features are located
-/// 0:1:2:N:1 - data of the feature N
-/// 0:1:2:N:2:K:1 - data of the K result of the feature N
+// general sub-labels
+static const int TAG_CURRENT_FEATURE = 1; ///< where the reference to the current feature label is located (or no attribute if null feature)
 
 Model_Document::Model_Document(const std::string theID, const std::string theKind)
     : myID(theID), myKind(theKind),
       myDoc(new TDocStd_Document("BinOcaf"))  // binary OCAF format
 {
+  myObjs = new Model_Objects(myDoc->Main());
   myDoc->SetUndoLimit(UNDO_LIMIT);  
   myTransactionSave = 0;
   myExecuteFeatures = true;
@@ -72,6 +62,11 @@ Model_Document::Model_Document(const std::string theID, const std::string theKin
   myDoc->CommitCommand();
 }
 
+void Model_Document::setThis(DocumentPtr theDoc)
+{
+  myObjs->setOwner(theDoc);
+}
+
 /// Returns the file name of this document by the nameof directory and identifuer of a document
 static TCollection_ExtendedString DocFileName(const char* theFileName, const std::string& theID)
 {
@@ -91,7 +86,7 @@ bool Model_Document::isRoot() const
   return this == Model_Session::get()->moduleDocument().get();
 }
 
-bool Model_Document::load(const char* theFileName)
+bool Model_Document::load(const char* theFileName, DocumentPtr theThis)
 {
   Handle(Model_Application) anApp = Model_Application::getApplication();
   if (isRoot()) {
@@ -168,7 +163,12 @@ bool Model_Document::load(const char* theFileName)
       std::dynamic_pointer_cast<Model_Session>(Model_Session::get());
     aSession->setActiveDocument(anApp->getDocument(myID), false);
     aSession->setCheckTransactions(false);
-    synchronizeFeatures(false, true, true);
+    if (myObjs)
+      delete myObjs;
+    myObjs = new Model_Objects(myDoc->Main()); // synchronisation is inside
+    myObjs->setOwner(theThis);
+    // update the current features status
+    setCurrentFeature(currentFeature(false), false);
     aSession->setCheckTransactions(true);
     aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false);
     aSession->setActiveDocument(anApp->getDocument(myID), true);
@@ -263,33 +263,14 @@ void Model_Document::close(const bool theForever)
   // close for thid document needs no transaction in this document
   std::static_pointer_cast<Model_Session>(Model_Session::get())->setCheckTransactions(false);
 
-  // delete all features of this document
-  std::shared_ptr<ModelAPI_Document> aThis = 
-    Model_Application::getApplication()->getDocument(myID);
-  Events_Loop* aLoop = Events_Loop::loop();
-  NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFeaturesIter(myObjs);
-  for(; aFeaturesIter.More(); aFeaturesIter.Next()) {
-    FeaturePtr aFeature = aFeaturesIter.Value();
-    static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-    ModelAPI_EventCreator::get()->sendDeleted(aThis, ModelAPI_Feature::group());
-    ModelAPI_EventCreator::get()->sendUpdated(aFeature, EVENT_DISP);
-    aFeature->eraseResults();
-    if (theForever) { // issue #294: do not delete content of the document until it can be redone
-      aFeature->erase();
-    } else {
-      aFeature->data()->execState(ModelAPI_StateMustBeUpdated);
-    }
-  }
-  if (theForever) {
-    myObjs.Clear();
-  }
-  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
-  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
-
   // close all only if it is really asked, otherwise it can be undoed/redoed
   if (theForever) {
+    delete myObjs;
+    myObjs = 0;
     if (myDoc->CanClose() == CDM_CCS_OK)
       myDoc->Close();
+  } else {
+    setCurrentFeature(FeaturePtr(), false); // disables all features
   }
 
   std::static_pointer_cast<Model_Session>(Model_Session::get())->setCheckTransactions(true);
@@ -338,12 +319,11 @@ bool Model_Document::finishOperation()
   bool isNestedClosed = !myDoc->HasOpenCommand() && !myNestedNum.empty();
   static std::shared_ptr<Model_Session> aSession = 
     std::static_pointer_cast<Model_Session>(Model_Session::get());
-  synchronizeBackRefs();
+  myObjs->synchronizeBackRefs();
   Events_Loop* aLoop = Events_Loop::loop();
   aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
   aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
   aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
-  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TOHIDE));
   aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
   // this must be here just after everything is finished but before real transaction stop
   // to avoid messages about modifications outside of the transaction
@@ -417,7 +397,7 @@ void Model_Document::abortOperation()
   for (; aSubIter != aSubs.end(); aSubIter++)
     subDoc(*aSubIter)->abortOperation();
   // references may be changed because they are set in attributes on the fly
-  synchronizeFeatures(true, true, isRoot());
+  myObjs->synchronizeFeatures(true, true, isRoot());
 }
 
 bool Model_Document::isOperation() const
@@ -468,8 +448,11 @@ void Model_Document::undoInternal(const bool theWithSubs, const bool theSynchron
       subDoc(*aSubIter)->undoInternal(theWithSubs, theSynchronize);
   }
   // after redo of all sub-documents to avoid updates on not-modified data (issue 370)
-  if (theSynchronize)
-    synchronizeFeatures(true, true, isRoot());
+  if (theSynchronize) {
+    myObjs->synchronizeFeatures(true, true, isRoot());
+    // update the current features status
+    setCurrentFeature(currentFeature(false), false);
+  }
 }
 
 void Model_Document::undo()
@@ -507,7 +490,9 @@ void Model_Document::redo()
     subDoc(*aSubIter)->redo();
 
   // after redo of all sub-documents to avoid updates on not-modified data (issue 370)
-  synchronizeFeatures(true, true, isRoot());
+  myObjs->synchronizeFeatures(true, true, isRoot());
+  // update the current features status
+  setCurrentFeature(currentFeature(false), false);
 }
 
 std::list<std::string> Model_Document::undoList() const
@@ -541,28 +526,8 @@ void Model_Document::operationId(const std::string& theId)
   myTransactions.rbegin()->myId = theId;
 }
 
-/// Append to the array of references a new referenced label
-static void AddToRefArray(TDF_Label& theArrayLab, TDF_Label& theReferenced)
-{
-  Handle(TDataStd_ReferenceArray) aRefs;
-  if (!theArrayLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
-    aRefs = TDataStd_ReferenceArray::Set(theArrayLab, 0, 0);
-    aRefs->SetValue(0, theReferenced);
-  } else {  // extend array by one more element
-    Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(),
-                                                                        aRefs->Upper() + 1);
-    for (int a = aRefs->Lower(); a <= aRefs->Upper(); a++) {
-      aNewArray->SetValue(a, aRefs->Value(a));
-    }
-    aNewArray->SetValue(aRefs->Upper() + 1, theReferenced);
-    aRefs->SetInternalArray(aNewArray);
-  }
-}
-
-FeaturePtr Model_Document::addFeature(std::string theID)
+FeaturePtr Model_Document::addFeature(std::string theID, const bool theMakeCurrent)
 {
-  TDF_Label anEmptyLab;
-  FeaturePtr anEmptyFeature;
   std::shared_ptr<Model_Session> aSession = 
     std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get());
   FeaturePtr aFeature = aSession->createFeature(theID, this);
@@ -579,23 +544,10 @@ FeaturePtr Model_Document::addFeature(std::string theID)
     aDocToAdd = this;
   }
   if (aFeature) {
-    TDF_Label aFeatureLab;
+    aDocToAdd->myObjs->addFeature(aFeature, currentFeature(false));
     if (!aFeature->isAction()) {  // do not add action to the data model
-      TDF_Label aFeaturesLab = aDocToAdd->featuresLabel();
-      aFeatureLab = aFeaturesLab.NewChild();
-      aDocToAdd->initData(aFeature, aFeatureLab, TAG_FEATURE_ARGUMENTS);
-      // keep the feature ID to restore document later correctly
-      TDataStd_Comment::Set(aFeatureLab, aFeature->getKind().c_str());
-      aDocToAdd->myObjs.Bind(aFeatureLab, aFeature);
-      // store feature in the history of features array
-      if (aFeature->isInHistory()) {
-        AddToRefArray(aFeaturesLab, aFeatureLab);
-      }
-    }
-    if (!aFeature->isAction()) {  // do not add action to the data model
-      // event: feature is added
-      static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
-      ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent);
+      if (theMakeCurrent)  // after all this feature stays in the document, so make it current
+        setCurrentFeature(aFeature, false);
     } else { // feature must be executed
        // no creation event => updater not working, problem with remove part
       aFeature->execute();
@@ -604,159 +556,31 @@ FeaturePtr Model_Document::addFeature(std::string theID)
   return aFeature;
 }
 
-/// Appenad to the array of references a new referenced label.
-/// If theIndex is not -1, removes element at this index, not theReferenced.
-/// \returns the index of removed element
-static int RemoveFromRefArray(TDF_Label theArrayLab, TDF_Label theReferenced, 
-  const int theIndex = -1)
-{
-  int aResult = -1;  // no returned
-  Handle(TDataStd_ReferenceArray) aRefs;
-  if (theArrayLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
-    if (aRefs->Length() == 1) {  // just erase an array
-      if ((theIndex == -1 && aRefs->Value(0) == theReferenced) || theIndex == 0) {
-        theArrayLab.ForgetAttribute(TDataStd_ReferenceArray::GetID());
-      }
-      aResult = 0;
-    } else {  // reduce the array
-      Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(),
-                                                                          aRefs->Upper() - 1);
-      int aCount = aRefs->Lower();
-      for (int a = aCount; a <= aRefs->Upper(); a++, aCount++) {
-        if ((theIndex == -1 && aRefs->Value(a) == theReferenced) || theIndex == a) {
-          aCount--;
-          aResult = a;
-        } else {
-          aNewArray->SetValue(aCount, aRefs->Value(a));
-        }
-      }
-      aRefs->SetInternalArray(aNewArray);
-    }
-  }
-  return aResult;
-}
 
 void Model_Document::refsToFeature(FeaturePtr theFeature,
-                                   std::set<std::shared_ptr<ModelAPI_Feature> >& theRefs,
-                                   const bool isSendError)
-{
-  // check the feature: it must have no depended objects on it
-  // the dependencies can be in the feature results
-  std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
-  for(; aResIter != theFeature->results().cend(); aResIter++) {
-    ResultPtr aResult = (*aResIter);
-    std::shared_ptr<Model_Data> aData = 
-      std::dynamic_pointer_cast<Model_Data>(aResult->data());
-    if (aData.get() != NULL) {
-      const std::set<AttributePtr>& aRefs = aData->refsToMe();
-      std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin(), aRefLast = aRefs.end();
-      for(; aRefIt != aRefLast; aRefIt++) {
-        FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIt)->owner());
-        if (aFeature.get() != NULL)
-          theRefs.insert(aFeature);
-      }
-    }
-  }
-  // the dependencies can be in the feature itself
-  std::shared_ptr<Model_Data> aData = 
-      std::dynamic_pointer_cast<Model_Data>(theFeature->data());
-  if (aData && !aData->refsToMe().empty()) {
-    const std::set<AttributePtr>& aRefs = aData->refsToMe();
-    std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin(), aRefLast = aRefs.end();
-    for(; aRefIt != aRefLast; aRefIt++) {
-      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIt)->owner());
-      if (aFeature.get() != NULL)
-        theRefs.insert(aFeature);
-    }
-  }
-
-  if (!theRefs.empty() && isSendError) {
-    Events_Error::send(
-      "Feature '" + theFeature->data()->name() + "' is used and can not be deleted");
-  }
-}
-
-void Model_Document::removeFeature(FeaturePtr theFeature/*, const bool theCheck*/)
+  std::set<std::shared_ptr<ModelAPI_Feature> >& theRefs, const bool isSendError)
 {
-  std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theFeature->data());
-  if (aData) {
-    TDF_Label aFeatureLabel = aData->label().Father();
-    if (myObjs.IsBound(aFeatureLabel))
-      myObjs.UnBind(aFeatureLabel);
-    else
-      return;  // not found feature => do not remove
-
-    // checking that the sub-element of composite feature is removed: if yes, inform the owner
-    std::set<std::shared_ptr<ModelAPI_Feature> > aRefs;
-    refsToFeature(theFeature, aRefs, false);
-    std::set<std::shared_ptr<ModelAPI_Feature> >::iterator aRefIter = aRefs.begin();
-    for(; aRefIter != aRefs.end(); aRefIter++) {
-      std::shared_ptr<ModelAPI_CompositeFeature> aComposite = 
-        std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aRefIter);
-      if (aComposite.get()) {
-        aComposite->removeFeature(theFeature);
-      }
-    }
-
-    // erase fields
-    theFeature->erase();
-    static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-    ModelAPI_EventCreator::get()->sendUpdated(theFeature, EVENT_DISP);
-    // erase all attributes under the label of feature
-    aFeatureLabel.ForgetAllAttributes();
-    // remove it from the references array
-    if (theFeature->isInHistory()) {
-      RemoveFromRefArray(featuresLabel(), aFeatureLabel);
-    }
-    // event: feature is deleted
-    ModelAPI_EventCreator::get()->sendDeleted(theFeature->document(), ModelAPI_Feature::group());
-    // the redisplay signal should be flushed in order to erase the feature presentation in the viewer
-    Events_Loop::loop()->flush(EVENT_DISP);
-  }
+  myObjs->refsToFeature(theFeature, theRefs, isSendError);
 }
 
-void Model_Document::addToHistory(const std::shared_ptr<ModelAPI_Object> theObject)
+void Model_Document::removeFeature(FeaturePtr theFeature)
 {
-  TDF_Label aFeaturesLab = featuresLabel();
-  std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theObject->data());
-  if (!aData) {
-      return;  // not found feature => do not remove
-  }
-  TDF_Label aFeatureLabel = aData->label().Father();
-  // store feature in the history of features array
-  if (theObject->isInHistory()) {
-    AddToRefArray(aFeaturesLab, aFeatureLabel);
-  } else {
-    RemoveFromRefArray(aFeaturesLab, aFeatureLabel);
+  // if this feature is current, make the current the previous feature
+  if (theFeature == currentFeature(false)) {
+    FeaturePtr aPrev = myObjs->nextFeature(theFeature, true);
+    setCurrentFeature(aPrev, false);
   }
+  myObjs->removeFeature(theFeature);
 }
 
-FeaturePtr Model_Document::feature(TDF_Label& theLabel) const
+void Model_Document::updateHistory(const std::shared_ptr<ModelAPI_Object> theObject)
 {
-  if (myObjs.IsBound(theLabel))
-    return myObjs.Find(theLabel);
-  return FeaturePtr();  // not found
+  myObjs->updateHistory(theObject);
 }
 
-ObjectPtr Model_Document::object(TDF_Label theLabel)
+void Model_Document::updateHistory(const std::string theGroup)
 {
-  // try feature by label
-  FeaturePtr aFeature = feature(theLabel);
-  if (aFeature)
-    return feature(theLabel);
-  TDF_Label aFeatureLabel = theLabel.Father().Father();  // let's suppose it is result
-  aFeature = feature(aFeatureLabel);
-  if (aFeature) {
-    const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
-    std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.cbegin();
-    for (; aRIter != aResults.cend(); aRIter++) {
-      std::shared_ptr<Model_Data> aResData = std::dynamic_pointer_cast<Model_Data>(
-          (*aRIter)->data());
-      if (aResData->label().Father().IsEqual(theLabel))
-        return *aRIter;
-    }
-  }
-  return FeaturePtr();  // not found
+  myObjs->updateHistory(theGroup);
 }
 
 std::shared_ptr<ModelAPI_Document> Model_Document::subDocument(std::string theDocID)
@@ -767,24 +591,13 @@ std::shared_ptr<ModelAPI_Document> Model_Document::subDocument(std::string theDo
 const std::set<std::string> Model_Document::subDocuments(const bool theActivatedOnly) const
 {
   std::set<std::string> aResult;
-  // comment must be in any feature: it is kind
-  int anIndex = 0;
-  TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
-  for (; aLabIter.More(); aLabIter.Next()) {
-    TDF_Label aFLabel = aLabIter.Value()->Label();
-    FeaturePtr aFeature = feature(aFLabel);
-    if (aFeature.get()) { // if document is closed the feature may be not in myObjs map
-      const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
-      std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
-      for (; aRIter != aResults.cend(); aRIter++) {
-        if ((*aRIter)->groupName() != ModelAPI_ResultPart::group()) continue;
-        if ((*aRIter)->isInHistory()) {
-          ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aRIter);
-          if (aPart && (!theActivatedOnly || aPart->isActivated()))
-            aResult.insert(aPart->data()->name());
-        }
-      }
-    }
+  std::list<ResultPtr> aPartResults;
+  myObjs->allResults(ModelAPI_ResultPart::group(), aPartResults);
+  std::list<ResultPtr>::iterator aPartRes = aPartResults.begin();
+  for(; aPartRes != aPartResults.end(); aPartRes++) {
+    ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aPartRes);
+    if (aPart && (!theActivatedOnly || aPart->isActivated()))
+      aResult.insert(aPart->data()->name());
   }
   return aResult;
 }
@@ -796,461 +609,146 @@ std::shared_ptr<Model_Document> Model_Document::subDoc(std::string theDocID)
     Model_Application::getApplication()->getDocument(theDocID));
 }
 
-ObjectPtr Model_Document::object(const std::string& theGroupID, const int theIndex,
-                                 const bool theHidden)
+ObjectPtr Model_Document::object(const std::string& theGroupID, const int theIndex)
 {
-  if (theGroupID == ModelAPI_Feature::group()) {
-    if (theHidden) {
-      int anIndex = 0;
-      TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
-      for (; aLabIter.More(); aLabIter.Next()) {
-        if (theIndex == anIndex) {
-          TDF_Label aFLabel = aLabIter.Value()->Label();
-          return feature(aFLabel);
-        }
-        anIndex++;
-      }
-    } else {
-      Handle(TDataStd_ReferenceArray) aRefs;
-      if (!featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
-        return ObjectPtr();
-      if (aRefs->Lower() > theIndex || aRefs->Upper() < theIndex)
-        return ObjectPtr();
-      TDF_Label aFeatureLabel = aRefs->Value(theIndex);
-      return feature(aFeatureLabel);
-    }
-  } else {
-    // comment must be in any feature: it is kind
-    int anIndex = 0;
-    TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
-    for (; aLabIter.More(); aLabIter.Next()) {
-      TDF_Label aFLabel = aLabIter.Value()->Label();
-      FeaturePtr aFeature = feature(aFLabel);
-      const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
-      std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
-      for (; aRIter != aResults.cend(); aRIter++) {
-        if ((*aRIter)->groupName() != theGroupID) continue;
-        bool isIn = theHidden && (*aRIter)->isInHistory();
-        if (!isIn && (*aRIter)->isInHistory()) { // check that there is nobody references this result
-          isIn = !(*aRIter)->isConcealed();
-        }
-        if (isIn) {
-          if (anIndex == theIndex)
-            return *aRIter;
-          anIndex++;
-        }
-      }
-    }
-  }
-  // not found
-  return ObjectPtr();
+  return myObjs->object(theGroupID, theIndex);
 }
 
 std::shared_ptr<ModelAPI_Object> Model_Document::objectByName(
     const std::string& theGroupID, const std::string& theName)
 {
-  if (theGroupID == ModelAPI_Feature::group()) {
-    int anIndex = 0;
-    TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
-    for (; aLabIter.More(); aLabIter.Next()) {
-      TDF_Label aFLabel = aLabIter.Value()->Label();
-      FeaturePtr aFeature = feature(aFLabel);
-      if (aFeature && aFeature->name() == theName)
-        return aFeature;
-    }
-  } else {
-    // comment must be in any feature: it is kind
-    int anIndex = 0;
-    TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
-    for (; aLabIter.More(); aLabIter.Next()) {
-      TDF_Label aFLabel = aLabIter.Value()->Label();
-      FeaturePtr aFeature = feature(aFLabel);
-      const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
-      std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
-      for (; aRIter != aResults.cend(); aRIter++) {
-        if ((*aRIter)->groupName() == theGroupID && (*aRIter)->data()->name() == theName)
-          return *aRIter;
-      }
-    }
-  }
-  // not found
-  return ObjectPtr();
+  return myObjs->objectByName(theGroupID, theName);
 }
 
-int Model_Document::size(const std::string& theGroupID, const bool theHidden)
+const int Model_Document::index(std::shared_ptr<ModelAPI_Object> theObject)
 {
-  int aResult = 0;
-  if (theGroupID == ModelAPI_Feature::group()) {
-    if (theHidden) {
-      return myObjs.Size();
-    } else {
-      Handle(TDataStd_ReferenceArray) aRefs;
-      if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
-        return aRefs->Length();
-    }
-  } else {
-    // comment must be in any feature: it is kind
-    TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
-    for (; aLabIter.More(); aLabIter.Next()) {
-      TDF_Label aFLabel = aLabIter.Value()->Label();
-      FeaturePtr aFeature = feature(aFLabel);
-      if (!aFeature) // may be on close
-        continue;
-      const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
-      std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
-      for (; aRIter != aResults.cend(); aRIter++) {
-        if ((*aRIter)->groupName() != theGroupID) continue;
-        bool isIn = theHidden;
-        if (!isIn && (*aRIter)->isInHistory()) { // check that there is nobody references this result
-          isIn = !(*aRIter)->isConcealed();
-        }
-        if (isIn)
-          aResult++;
-      }
-    }
-  }
-  // group is not found
-  return aResult;
+  return myObjs->index(theObject);
 }
 
-TDF_Label Model_Document::featuresLabel() const
+int Model_Document::size(const std::string& theGroupID)
 {
-  return myDoc->Main().FindChild(TAG_OBJECTS);
+  return myObjs->size(theGroupID);
 }
 
-void Model_Document::setUniqueName(FeaturePtr theFeature)
+std::shared_ptr<ModelAPI_Feature> Model_Document::currentFeature(const bool theVisible)
 {
-  if (!theFeature->data()->name().empty())
-    return;  // not needed, name is already defined
-  std::string aName;  // result
-  // first count all objects of such kind to start with index = count + 1
-  int aNumObjects = 0;
-  NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myObjs);
-  for (; aFIter.More(); aFIter.Next()) {
-    if (aFIter.Value()->getKind() == theFeature->getKind())
-      aNumObjects++;
-  }
-  // generate candidate name
-  std::stringstream aNameStream;
-  aNameStream << theFeature->getKind() << "_" << aNumObjects + 1;
-  aName = aNameStream.str();
-  // check this is unique, if not, increase index by 1
-  for (aFIter.Initialize(myObjs); aFIter.More();) {
-    FeaturePtr aFeature = aFIter.Value();
-    bool isSameName = aFeature->data()->name() == aName;
-    if (!isSameName) {  // check also results to avoid same results names (actual for Parts)
-      const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
-      std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
-      for (; aRIter != aResults.cend(); aRIter++) {
-        isSameName = (*aRIter)->data()->name() == aName;
+  TDF_Label aRefLab = generalLabel().FindChild(TAG_CURRENT_FEATURE);
+  Handle(TDF_Reference) aRef;
+  if (aRefLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
+    TDF_Label aLab = aRef->Get();
+    FeaturePtr aResult = myObjs->feature(aLab);
+    if (theVisible) { // get nearest visible (in history) going up
+      while(aResult.get() && !aResult->isInHistory()) {
+        aResult = myObjs->nextFeature(aResult, true);
       }
     }
-    if (isSameName) {
-      aNumObjects++;
-      std::stringstream aNameStream;
-      aNameStream << theFeature->getKind() << "_" << aNumObjects + 1;
-      aName = aNameStream.str();
-      // reinitialize iterator to make sure a new name is unique
-      aFIter.Initialize(myObjs);
-    } else
-      aFIter.Next();
-  }
-  theFeature->data()->setName(aName);
-}
-
-void Model_Document::initData(ObjectPtr theObj, TDF_Label theLab, const int theTag)
-{
-  std::shared_ptr<ModelAPI_Document> aThis = Model_Application::getApplication()->getDocument(
-      myID);
-  std::shared_ptr<Model_Data> aData(new Model_Data);
-  aData->setLabel(theLab.FindChild(theTag));
-  aData->setObject(theObj);
-  theObj->setDoc(aThis);
-  theObj->setData(aData);
-  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
-  if (aFeature) {
-    setUniqueName(aFeature);  // must be before "initAttributes" because duplicate part uses name
+    return aResult;
   }
-  theObj->initAttributes();
+  return std::shared_ptr<ModelAPI_Feature>(); // null feature means the higher than first
 }
 
-void Model_Document::synchronizeFeatures(
-  const bool theMarkUpdated, const bool theUpdateReferences, const bool theFlush)
+void Model_Document::setCurrentFeature(std::shared_ptr<ModelAPI_Feature> theCurrent,
+  const bool theVisible)
 {
-  std::shared_ptr<ModelAPI_Document> aThis = 
-    Model_Application::getApplication()->getDocument(myID);
-  // after all updates, sends a message that groups of features were created or updated
-  Events_Loop* aLoop = Events_Loop::loop();
-  static Events_ID aDispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-  static Events_ID aCreateEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
-  static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
-  static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-  static Events_ID aDeleteEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
-  static Events_ID aToHideEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-  aLoop->activateFlushes(false);
-
-  // update all objects by checking are they on labels or not
-  std::set<FeaturePtr> aNewFeatures, aKeptFeatures;
-  TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
-  for (; aLabIter.More(); aLabIter.Next()) {
-    TDF_Label aFeatureLabel = aLabIter.Value()->Label();
-    FeaturePtr aFeature;
-    if (!myObjs.IsBound(aFeatureLabel)) {  // a new feature is inserted
-      // create a feature
-      aFeature = std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get())->createFeature(
-        TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(aLabIter.Value())->Get())
-        .ToCString(), this);
-      if (!aFeature) {  // somethig is wrong, most probably, the opened document has invalid structure
-        Events_Error::send("Invalid type of object in the document");
-        aLabIter.Value()->Label().ForgetAllAttributes();
-        continue;
+  TDF_Label aRefLab = generalLabel().FindChild(TAG_CURRENT_FEATURE);
+  CompositeFeaturePtr aMain; // main feature that may nest the new current
+  if (theCurrent.get()) {
+    /*
+    if (theVisible) { // make features below which are not in history also enabled: sketch subs
+      FeaturePtr aNext = myObjs->nextFeature(theCurrent);
+      for (; aNext.get(); aNext = myObjs->nextFeature(theCurrent)) {
+        if (aNext->isInHistory()) {
+          break; // next in history is not needed
+        } else { // next not in history is good for making current
+          theCurrent = aNext;
+        }
       }
-      // this must be before "setData" to redo the sketch line correctly
-      myObjs.Bind(aFeatureLabel, aFeature);
-      aNewFeatures.insert(aFeature);
-      initData(aFeature, aFeatureLabel, TAG_FEATURE_ARGUMENTS);
-
-      // event: model is updated
-      ModelAPI_EventCreator::get()->sendUpdated(aFeature, aCreateEvent);
-    } else {  // nothing is changed, both iterators are incremented
-      aFeature = myObjs.Find(aFeatureLabel);
-      aKeptFeatures.insert(aFeature);
-      if (theMarkUpdated) {
-        ModelAPI_EventCreator::get()->sendUpdated(aFeature, anUpdateEvent);
+    }*/
+    aMain = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theCurrent);
+    if (!aMain.get()) {
+      // if feature nests into compisite feature, make the composite feature as current
+      const std::set<AttributePtr>& aRefsToMe = theCurrent->data()->refsToMe();
+      std::set<AttributePtr>::const_iterator aRefToMe = aRefsToMe.begin();
+      for(; aRefToMe != aRefsToMe.end(); aRefToMe++) {
+        CompositeFeaturePtr aComposite = 
+          std::dynamic_pointer_cast<ModelAPI_CompositeFeature>((*aRefToMe)->owner());
+        if (aComposite.get() && aComposite->isSub(theCurrent)) {
+          aMain = aComposite;
+          break;
+        }
       }
     }
-  }
-  // update results of the features (after features created because they may be connected, like sketch and sub elements)
-  std::list<FeaturePtr> aComposites; // composites must be updated after their subs (issue 360)
-  TDF_ChildIDIterator aLabIter2(featuresLabel(), TDataStd_Comment::GetID());
-  for (; aLabIter2.More(); aLabIter2.Next()) {
-    TDF_Label aFeatureLabel = aLabIter2.Value()->Label();
-    if (myObjs.IsBound(aFeatureLabel)) {  // a new feature is inserted
-      FeaturePtr aFeature = myObjs.Find(aFeatureLabel);
-      if (std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeature).get())
-        aComposites.push_back(aFeature);
-      updateResults(aFeature);
-    }
-  }
-  std::list<FeaturePtr>::iterator aComposite = aComposites.begin();
-  for(; aComposite != aComposites.end(); aComposite++) {
-    updateResults(*aComposite);
-  }
 
-  // check all features are checked: if not => it was removed
-  NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myObjs);
-  while (aFIter.More()) {
-    if (aKeptFeatures.find(aFIter.Value()) == aKeptFeatures.end()
-      && aNewFeatures.find(aFIter.Value()) == aNewFeatures.end()) {
-        FeaturePtr aFeature = aFIter.Value();
-        // event: model is updated
-        //if (aFeature->isInHistory()) {
-        ModelAPI_EventCreator::get()->sendDeleted(aThis, ModelAPI_Feature::group());
-        //}
-        // results of this feature must be redisplayed (hided)
-        // redisplay also removed feature (used for sketch and AISObject)
-        ModelAPI_EventCreator::get()->sendUpdated(aFeature, aRedispEvent);
-        aFeature->erase();
-        // unbind after the "erase" call: on abort sketch is removes sub-objects that corrupts aFIter
-        myObjs.UnBind(aFIter.Key());
-        // reinitialize iterator because unbind may corrupt the previous order in the map
-        aFIter.Initialize(myObjs);
-    } else
-      aFIter.Next();
-  }
-
-  if (theUpdateReferences) {
-    synchronizeBackRefs();
-  }
-
-  myExecuteFeatures = false;
-  aLoop->activateFlushes(true);
-
-  if (theFlush) {
-    aLoop->flush(aCreateEvent);
-    aLoop->flush(aDeleteEvent);
-    aLoop->flush(anUpdateEvent);
-    aLoop->flush(aRedispEvent);
-    aLoop->flush(aToHideEvent);
-  }
-  myExecuteFeatures = true;
-}
+    std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theCurrent->data());
+    if (!aData.get()) return; // unknown case
+    TDF_Label aFeatureLabel = aData->label().Father();
 
-void Model_Document::synchronizeBackRefs()
-{
-  std::shared_ptr<ModelAPI_Document> aThis = 
-    Model_Application::getApplication()->getDocument(myID);
-  // keeps the concealed flags of result to catch the change and create created/deleted events
-  std::list<std::pair<ResultPtr, bool> > aConcealed;
-  // first cycle: erase all data about back-references
-  NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFeatures(myObjs);
-  for(; aFeatures.More(); aFeatures.Next()) {
-    FeaturePtr aFeature = aFeatures.Value();
-    std::shared_ptr<Model_Data> aFData = 
-      std::dynamic_pointer_cast<Model_Data>(aFeature->data());
-    if (aFData) {
-      aFData->eraseBackReferences();
-    }
-    const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
-    std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
-    for (; aRIter != aResults.cend(); aRIter++) {
-      std::shared_ptr<Model_Data> aResData = 
-        std::dynamic_pointer_cast<Model_Data>((*aRIter)->data());
-      if (aResData) {
-        aConcealed.push_back(std::pair<ResultPtr, bool>(*aRIter, (*aRIter)->isConcealed()));
-        aResData->eraseBackReferences();
-      }
+    Handle(TDF_Reference) aRef;
+    if (aRefLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
+      aRef->Set(aFeatureLabel);
+    } else {
+      aRef = TDF_Reference::Set(aRefLab, aFeatureLabel);
     }
+  } else { // remove reference for the null feature
+    aRefLab.ForgetAttribute(TDF_Reference::GetID());
   }
+  // make all features after this feature disabled in reversed order (to remove results without deps)
+  static Events_Loop* aLoop = Events_Loop::loop();
+  static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
 
-  // second cycle: set new back-references: only features may have reference, iterate only them
-  ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
-  for(aFeatures.Initialize(myObjs); aFeatures.More(); aFeatures.Next()) {
-    FeaturePtr aFeature = aFeatures.Value();
-    std::shared_ptr<Model_Data> aFData = 
-      std::dynamic_pointer_cast<Model_Data>(aFeature->data());
-    if (aFData) {
-      std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
-      aFData->referencesToObjects(aRefs);
-      std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator 
-        aRefsIter = aRefs.begin();
-      for(; aRefsIter != aRefs.end(); aRefsIter++) {
-        std::list<ObjectPtr>::iterator aRefTo = aRefsIter->second.begin();
-        for(; aRefTo != aRefsIter->second.end(); aRefTo++) {
-          if (*aRefTo) {
-            std::shared_ptr<Model_Data> aRefData = 
-              std::dynamic_pointer_cast<Model_Data>((*aRefTo)->data());
-            aRefData->addBackReference(aFeature, aRefsIter->first); // here the Concealed flag is updated
-          }
-        }
-      }
-    }
-  }
-  std::list<std::pair<ResultPtr, bool> >::iterator aCIter = aConcealed.begin();
-  for(; aCIter != aConcealed.end(); aCIter++) {
-    if (aCIter->first->isConcealed() != aCIter->second) { // somethign is changed => produce event
-      if (aCIter->second) { // was concealed become not => creation event
-        static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
-        ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, anEvent);
-      } else { // was not concealed become concealed => delete event
-        ModelAPI_EventCreator::get()->sendDeleted(aThis, aCIter->first->groupName());
-        // redisplay for the viewer (it must be disappeared also)
-        static Events_ID EVENT_DISP = 
-          Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-        ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, EVENT_DISP);
-      }
+  bool aPassed = false; // flag that the current object is already passed in cycle
+  FeaturePtr anIter = myObjs->lastFeature();
+  for(; anIter.get(); anIter = myObjs->nextFeature(anIter, true)) {
+    // check this before passed become enabled: the current feature is enabled!
+    if (anIter == theCurrent) aPassed = true;
+
+    bool aDisabledFlag = !aPassed;
+    if (aMain.get() && aMain->isSub(anIter))
+      aDisabledFlag = false;
+    if (anIter->setDisabled(aDisabledFlag)) {
+      // state of feature is changed => so feature become updated
+      static Events_ID anUpdateEvent = aLoop->eventByName(EVENT_OBJECT_UPDATED);
+      ModelAPI_EventCreator::get()->sendUpdated(anIter, anUpdateEvent);
+      // flush is in the end of this method
+      ModelAPI_EventCreator::get()->sendUpdated(anIter, aRedispEvent /*, false*/);
     }
   }
+  aLoop->flush(aRedispEvent);
 }
 
-TDF_Label Model_Document::resultLabel(
-  const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theResultIndex) 
-{
-  const std::shared_ptr<Model_Data>& aData = 
-    std::dynamic_pointer_cast<Model_Data>(theFeatureData);
-  return aData->label().Father().FindChild(TAG_FEATURE_RESULTS).FindChild(theResultIndex + 1);
-}
-
-void Model_Document::storeResult(std::shared_ptr<ModelAPI_Data> theFeatureData,
-                                 std::shared_ptr<ModelAPI_Result> theResult,
-                                 const int theResultIndex)
+TDF_Label Model_Document::generalLabel() const
 {
-  std::shared_ptr<ModelAPI_Document> aThis = 
-    Model_Application::getApplication()->getDocument(myID);
-  theResult->setDoc(aThis);
-  initData(theResult, resultLabel(theFeatureData, theResultIndex), TAG_FEATURE_ARGUMENTS);
-  if (theResult->data()->name().empty()) {  // if was not initialized, generate event and set a name
-    std::stringstream aNewName;
-    aNewName<<theFeatureData->name();
-    if (theResultIndex > 0) // if there are several results, add unique prefix starting from second
-      aNewName<<"_"<<theResultIndex + 1;
-    theResult->data()->setName(aNewName.str());
-  }
+  return myDoc->Main().FindChild(TAG_GENERAL);
 }
 
 std::shared_ptr<ModelAPI_ResultConstruction> Model_Document::createConstruction(
     const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
 {
-  TDF_Label aLab = resultLabel(theFeatureData, theIndex);
-  TDataStd_Comment::Set(aLab, ModelAPI_ResultConstruction::group().c_str());
-  ObjectPtr anOldObject = object(aLab);
-  std::shared_ptr<ModelAPI_ResultConstruction> aResult;
-  if (anOldObject) {
-    aResult = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(anOldObject);
-  }
-  if (!aResult) {
-    aResult = std::shared_ptr<ModelAPI_ResultConstruction>(new Model_ResultConstruction);
-    storeResult(theFeatureData, aResult, theIndex);
-  }
-  return aResult;
+  return myObjs->createConstruction(theFeatureData, theIndex);
 }
 
 std::shared_ptr<ModelAPI_ResultBody> Model_Document::createBody(
     const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
 {
-  TDF_Label aLab = resultLabel(theFeatureData, theIndex);
-  TDataStd_Comment::Set(aLab, ModelAPI_ResultBody::group().c_str());
-  ObjectPtr anOldObject = object(aLab);
-  std::shared_ptr<ModelAPI_ResultBody> aResult;
-  if (anOldObject) {
-    aResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(anOldObject);
-  }
-  if (!aResult) {
-    aResult = std::shared_ptr<ModelAPI_ResultBody>(new Model_ResultBody);
-    storeResult(theFeatureData, aResult, theIndex);
-  }
-  return aResult;
+  return myObjs->createBody(theFeatureData, theIndex);
 }
 
 std::shared_ptr<ModelAPI_ResultPart> Model_Document::createPart(
     const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
 {
-  TDF_Label aLab = resultLabel(theFeatureData, theIndex);
-  TDataStd_Comment::Set(aLab, ModelAPI_ResultPart::group().c_str());
-  ObjectPtr anOldObject = object(aLab);
-  std::shared_ptr<ModelAPI_ResultPart> aResult;
-  if (anOldObject) {
-    aResult = std::dynamic_pointer_cast<ModelAPI_ResultPart>(anOldObject);
-  }
-  if (!aResult) {
-    aResult = std::shared_ptr<ModelAPI_ResultPart>(new Model_ResultPart);
-    storeResult(theFeatureData, aResult, theIndex);
-  }
-  return aResult;
+  return myObjs->createPart(theFeatureData, theIndex);
 }
 
 std::shared_ptr<ModelAPI_ResultGroup> Model_Document::createGroup(
     const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
 {
-  TDF_Label aLab = resultLabel(theFeatureData, theIndex);
-  TDataStd_Comment::Set(aLab, ModelAPI_ResultGroup::group().c_str());
-  ObjectPtr anOldObject = object(aLab);
-  std::shared_ptr<ModelAPI_ResultGroup> aResult;
-  if (anOldObject) {
-    aResult = std::dynamic_pointer_cast<ModelAPI_ResultGroup>(anOldObject);
-  }
-  if (!aResult) {
-    aResult = std::shared_ptr<ModelAPI_ResultGroup>(new Model_ResultGroup(theFeatureData));
-    storeResult(theFeatureData, aResult, theIndex);
-  }
-  return aResult;
+  return myObjs->createGroup(theFeatureData, theIndex);
 }
 
 std::shared_ptr<ModelAPI_ResultParameter> Model_Document::createParameter(
       const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
 {
-  TDF_Label aLab = resultLabel(theFeatureData, theIndex);
-  TDataStd_Comment::Set(aLab, ModelAPI_ResultParameter::group().c_str());
-  ObjectPtr anOldObject = object(aLab);
-  std::shared_ptr<ModelAPI_ResultParameter> aResult;
-  if (anOldObject) {
-    aResult = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(anOldObject);
-  }
-  if (!aResult) {
-    aResult = std::shared_ptr<ModelAPI_ResultParameter>(new Model_ResultParameter);
-    storeResult(theFeatureData, aResult, theIndex);
-  }
-  return aResult;
+  return myObjs->createParameter(theFeatureData, theIndex);
 }
 
 std::shared_ptr<ModelAPI_Feature> Model_Document::feature(
@@ -1259,68 +757,11 @@ std::shared_ptr<ModelAPI_Feature> Model_Document::feature(
   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theResult->data());
   if (aData) {
     TDF_Label aFeatureLab = aData->label().Father().Father().Father();
-    return feature(aFeatureLab);
+    return myObjs->feature(aFeatureLab);
   }
   return FeaturePtr();
 }
 
-void Model_Document::updateResults(FeaturePtr theFeature)
-{
-  // for not persistent is will be done by parametric updater automatically
-  //if (!theFeature->isPersistentResult()) return;
-  // check the existing results and remove them if there is nothing on the label
-  std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
-  while(aResIter != theFeature->results().cend()) {
-    ResultPtr aBody = std::dynamic_pointer_cast<ModelAPI_Result>(*aResIter);
-    if (aBody) {
-      if (!aBody->data()->isValid()) { 
-        // found a disappeared result => remove it
-        theFeature->removeResult(aBody);
-        // start iterate from beginning because iterator is corrupted by removing
-        aResIter = theFeature->results().cbegin();
-        continue;
-      }
-    }
-    aResIter++;
-  }
-  // it may be on undo
-  if (!theFeature->data() || !theFeature->data()->isValid())
-    return;
-  // check that results are presented on all labels
-  int aResSize = theFeature->results().size();
-  TDF_ChildIterator aLabIter(resultLabel(theFeature->data(), 0).Father());
-  for(; aLabIter.More(); aLabIter.Next()) {
-    // here must be GUID of the feature
-    int aResIndex = aLabIter.Value().Tag() - 1;
-    ResultPtr aNewBody;
-    if (aResSize <= aResIndex) {
-      TDF_Label anArgLab = aLabIter.Value();
-      Handle(TDataStd_Comment) aGroup;
-      if (anArgLab.FindAttribute(TDataStd_Comment::GetID(), aGroup)) {
-        if (aGroup->Get() == ModelAPI_ResultBody::group().c_str()) {
-          aNewBody = createBody(theFeature->data(), aResIndex);
-        } else if (aGroup->Get() == ModelAPI_ResultPart::group().c_str()) {
-          aNewBody = createPart(theFeature->data(), aResIndex);
-        } else if (aGroup->Get() == ModelAPI_ResultConstruction::group().c_str()) {
-          theFeature->execute(); // construction shapes are needed for sketch solver
-          break;
-        } else if (aGroup->Get() == ModelAPI_ResultGroup::group().c_str()) {
-          aNewBody = createGroup(theFeature->data(), aResIndex);
-        } else if (aGroup->Get() == ModelAPI_ResultParameter::group().c_str()) {
-          theFeature->attributeChanged("expression"); // just produce a value
-          break;
-        } else {
-          Events_Error::send(std::string("Unknown type of result is found in the document:") +
-            TCollection_AsciiString(aGroup->Get()).ToCString());
-        }
-      }
-      if (aNewBody) {
-        theFeature->setResult(aNewBody, aResIndex);
-      }
-    }
-  }
-}
-
 Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper)
 {
   return TDF_LabelMapHasher::HashCode(theLab, theUpper);
@@ -1346,20 +787,5 @@ TDF_Label Model_Document::findNamingName(std::string theName)
 
 ResultPtr Model_Document::findByName(const std::string theName)
 {
-  NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator anObjIter(myObjs);
-  for(; anObjIter.More(); anObjIter.Next()) {
-    FeaturePtr& aFeature = anObjIter.ChangeValue();
-    if (!aFeature) // may be on close
-      continue;
-    const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
-    std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
-    for (; aRIter != aResults.cend(); aRIter++) {
-      if (aRIter->get() && (*aRIter)->data() && (*aRIter)->data()->isValid() &&
-          (*aRIter)->data()->name() == theName) {
-        return *aRIter;
-      }
-    }
-  }
-  // not found
-  return ResultPtr();
+  return myObjs->findByName(theName);
 }
index 453422ffcf9900e7f3cf846c1dd3ece339a3f5e8..127934e03f201519a994a428b089d96876634b1b 100644 (file)
 #include <ModelAPI_ResultParameter.h>
 
 #include <TDocStd_Document.hxx>
-#include <NCollection_DataMap.hxx>
-#include <TDF_Label.hxx>
 #include <map>
 #include <set>
 
 class Handle_Model_Document;
-
-// for TDF_Label map usage
-static Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper);
-static Standard_Boolean IsEqual(const TDF_Label& theLab1, const TDF_Label& theLab2);
+class Model_Objects;
 
 /**\class Model_Document
  * \ingroup DataModel
@@ -41,8 +36,9 @@ class Model_Document : public ModelAPI_Document
 
   //! Loads the OCAF document from the file.
   //! \param theFileName full name of the file to load
+  //! \param theThis the common shared pointer to the document to manage with it later
   //! \returns true if file was loaded successfully
-  MODEL_EXPORT virtual bool load(const char* theFileName);
+  MODEL_EXPORT virtual bool load(const char* theFileName, DocumentPtr theThis);
 
   //! Saves the OCAF document to the file.
   //! \param theFileName full name of the file to store
@@ -77,7 +73,8 @@ class Model_Document : public ModelAPI_Document
 
   //! Adds to the document the new feature of the given feature id
   //! \param theID creates feature and puts it in the document
-  MODEL_EXPORT virtual FeaturePtr addFeature(std::string theID);
+  //! \param theMakeCurrent to make current this new feature in this document
+  MODEL_EXPORT virtual FeaturePtr addFeature(std::string theID, const bool theMakeCurrent = true);
 
   //! Return a list of features, which refers to the feature
   //! \param theFeature a feature
@@ -91,14 +88,6 @@ class Model_Document : public ModelAPI_Document
   //! \param theFeature a removed feature
   MODEL_EXPORT virtual void removeFeature(FeaturePtr theFeature);
 
-  //! Returns the existing feature by the label
-  //! \param theLabel base label of the feature
-  MODEL_EXPORT virtual FeaturePtr feature(TDF_Label& theLabel) const;
-
-  //! Returns the existing object: result or feature
-  //! \param theLabel base label of the object
-  MODEL_EXPORT virtual ObjectPtr object(TDF_Label theLabel);
-
   //! Returns the first found object in the group by the object name
   //! \param theGroupID group that contains an object
   //! \param theName name of the object to search
@@ -106,6 +95,10 @@ class Model_Document : public ModelAPI_Document
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Object> objectByName(
     const std::string& theGroupID, const std::string& theName);
 
+  //! Returns the object index in the group. Object must be visible. Otherwise returns -1.
+  //! \param theObject object of this document
+  //! \returns index started from zero, or -1 if object is invisible or belongs to another document
+  MODEL_EXPORT virtual const int index(std::shared_ptr<ModelAPI_Object> theObject);
 
   //! Adds a new sub-document by the identifier, or returns existing one if it is already exist
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Document> subDocument(std::string theDocID);
@@ -122,13 +115,23 @@ class Model_Document : public ModelAPI_Document
   //! Returns the feature in the group by the index (started from zero)
   //! \param theGroupID group that contains a feature
   //! \param theIndex zero-based index of feature in the group
-  //! \param theHidden if it is true, it counts also the features that are not in tree
-  MODEL_EXPORT virtual ObjectPtr object(const std::string& theGroupID, const int theIndex,
-                                        const bool theHidden = false);
+  MODEL_EXPORT virtual ObjectPtr object(const std::string& theGroupID, const int theIndex);
 
   //! Returns the number of features in the group
-  //! If theHidden is true, it counts also the features that are not in tree
-  MODEL_EXPORT virtual int size(const std::string& theGroupID, const bool theHidden = false);
+  MODEL_EXPORT virtual int size(const std::string& theGroupID);
+
+  //! Returns the feature that is currently edited in this document, normally
+  //! this is the latest created feature
+  //! \param theVisible use visible features only: flag is true for Object Browser functionality
+  //! \returns null if next created feature must be the first
+  MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Feature> currentFeature(const bool theVisible);
+
+  //! Sets the current feature: all features below will be disabled, new features
+  //! will be appended after this one.
+  //! \param theCurrent the selected feature as current: blow it everythin become disabled
+  //! \param theVisible use visible features only: flag is true for Object Browser functionality
+  MODEL_EXPORT virtual void setCurrentFeature(std::shared_ptr<ModelAPI_Feature> theCurrent,
+    const bool theVisible);
 
   /// Creates a construction cresults
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_ResultConstruction> createConstruction(
@@ -152,7 +155,7 @@ class Model_Document : public ModelAPI_Document
 
   ///! Returns true if parametric updater need to execute feature on recomputartion
   ///! On abort, undo or redo it is not necessary: results in document are updated automatically
-  bool executeFeatures() {return myExecuteFeatures;}
+  bool& executeFeatures() {return myExecuteFeatures;}
 
   //! Registers the name of the shape for the topological naming needs
   void addNamingName(const TDF_Label theLabel, std::string theName);
@@ -163,22 +166,8 @@ class Model_Document : public ModelAPI_Document
   ResultPtr findByName(const std::string theName);
 
  protected:
-
-  //! Returns (creates if needed) the features label
-  TDF_Label featuresLabel() const;
-
-  //! Initializes feature with a unique name in this group (unique name is generated as 
-  //! feature type + "_" + index
-  void setUniqueName(FeaturePtr theFeature);
-
-  //! Synchronizes myFeatures list with the updated document
-  //! \param theMarkUpdated causes the "update" event for all features
-  //! \param theUpdateReferences causes the update of back-references
-  //! \param theFlush makes flush all events in the end of all modifications of this method
-  void synchronizeFeatures(const bool theMarkUpdated, const bool theUpdateReferences,
-    const bool theFlush);
-  //! Synchronizes the BackReferences list in Data of Features and Results
-  void synchronizeBackRefs();
+  //! Returns (creates if needed) the general label
+  TDF_Label generalLabel() const;
 
   //! Creates new document with binary file format
   Model_Document(const std::string theID, const std::string theKind);
@@ -193,20 +182,6 @@ class Model_Document : public ModelAPI_Document
   //! \returns true if resulting transaction is not empty and can be undoed
   void compactNested();
 
-  //! Initializes the data fields of the feature
-  void initData(ObjectPtr theObj, TDF_Label theLab, const int theTag);
-
-  //! Allows to store the result in the data tree of the document (attaches 'data' of result to tree)
-  MODEL_EXPORT virtual void storeResult(std::shared_ptr<ModelAPI_Data> theFeatureData,
-                                        std::shared_ptr<ModelAPI_Result> theResult,
-                                        const int theResultIndex = 0);
-
-  //! returns the label of result by index; creates this label if it was not created before
-  TDF_Label resultLabel(const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theResultIndex);
-
-  //! Updates the results list of the feature basing on the current data tree
-  void updateResults(FeaturePtr theFeature);
-
   //! Returns all sub documents
   const std::set<std::string> subDocuments(const bool theActivatedOnly) const;
 
@@ -223,15 +198,25 @@ class Model_Document : public ModelAPI_Document
   std::list<std::string> redoList() const;
 
   /// Internally makes document know that feature was removed or added in history after creation
-  MODEL_EXPORT virtual void addToHistory(const std::shared_ptr<ModelAPI_Object> theObject);
+  virtual void updateHistory(const std::shared_ptr<ModelAPI_Object> theObject);
+  /// Internally makes document know that feature was removed or added in history after creation
+  virtual void updateHistory(const std::string theGroup);
 
   /// Returns true if the document is root module document
   bool isRoot() const;
 
+  /// Sets shared pointer to this
+  void setThis(DocumentPtr theDoc);
+
+  /// Returns the objects manager
+  Model_Objects* objects() {return myObjs;}
+
   friend class Model_Application;
   friend class Model_Session;
   friend class Model_Update;
   friend class Model_AttributeReference;
+  friend class Model_AttributeRefAttr;
+  friend class Model_AttributeRefList;
   friend class DFBrowser;
 
  private:
@@ -239,6 +224,8 @@ class Model_Document : public ModelAPI_Document
   std::string myKind;  ///< kind of the document in the application
   Handle_TDocStd_Document myDoc;  ///< OCAF document
 
+  Model_Objects *myObjs; ///< data manager of this document
+
   /// counter value of transaction on the last "save" call, used for "IsModified" method
   int myTransactionSave;
   /// number of nested transactions performed (list becasue may be nested inside of nested)
@@ -258,9 +245,7 @@ class Model_Document : public ModelAPI_Document
   std::list<Transaction> myTransactions;
   /// list of info about transactions undone (first is oldest undone)
   std::list<Transaction> myRedos;
-  /// All features managed by this document (not only in history of OB)
-  /// For optimization mapped by labels
-  NCollection_DataMap<TDF_Label, FeaturePtr> myObjs;
+
   /// Optimization for finding the shape-label by topological naming names
   std::map<std::string, TDF_Label> myNamingNames;
   /// If it is true, features are not executed on update (on abort, undo, redo)
diff --git a/src/Model/Model_Objects.cpp b/src/Model/Model_Objects.cpp
new file mode 100644 (file)
index 0000000..98ead6c
--- /dev/null
@@ -0,0 +1,878 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        Model_Objects.cxx
+// Created:     15 May 2015
+// Author:      Mikhail PONIKAROV
+
+#include <Model_Objects.h>
+#include <Model_Data.h>
+#include <Model_Document.h>
+#include <Model_Events.h>
+#include <Model_Session.h>
+#include <Model_ResultPart.h>
+#include <Model_ResultConstruction.h>
+#include <Model_ResultBody.h>
+#include <Model_ResultGroup.h>
+#include <Model_ResultParameter.h>
+#include <ModelAPI_Validator.h>
+#include <ModelAPI_CompositeFeature.h>
+
+#include <Events_Loop.h>
+#include <Events_Error.h>
+
+#include <TDataStd_Integer.hxx>
+#include <TDataStd_Comment.hxx>
+#include <TDF_ChildIDIterator.hxx>
+#include <TDataStd_ReferenceArray.hxx>
+#include <TDataStd_HLabelArray1.hxx>
+#include <TDataStd_Name.hxx>
+#include <TDF_Reference.hxx>
+#include <TDF_ChildIDIterator.hxx>
+#include <TDF_LabelMapHasher.hxx>
+
+static const int TAG_OBJECTS = 2;  // tag of the objects sub-tree (features, results)
+
+// feature sub-labels
+static const int TAG_FEATURE_ARGUMENTS = 1;  ///< where the arguments are located
+static const int TAG_FEATURE_RESULTS = 2;  ///< where the results are located
+
+///
+/// 0:1:2 - where features are located
+/// 0:1:2:N:1 - data of the feature N
+/// 0:1:2:N:2:K:1 - data of the K result of the feature N
+
+Model_Objects::Model_Objects(TDF_Label theMainLab) : myMain(theMainLab)
+{
+}
+
+void Model_Objects::setOwner(DocumentPtr theDoc)
+{
+  myDoc = theDoc;
+  // update all fields and recreate features and result objects if needed
+  synchronizeFeatures(false, true, true);
+  myHistory.clear();
+}
+
+Model_Objects::~Model_Objects()
+{
+  // delete all features of this document
+  Events_Loop* aLoop = Events_Loop::loop();
+  NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFeaturesIter(myFeatures);
+  for(; aFeaturesIter.More(); aFeaturesIter.Next()) {
+    FeaturePtr aFeature = aFeaturesIter.Value();
+    static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+    ModelAPI_EventCreator::get()->sendDeleted(myDoc, ModelAPI_Feature::group());
+    ModelAPI_EventCreator::get()->sendUpdated(aFeature, EVENT_DISP);
+    aFeature->eraseResults();
+    aFeature->erase();
+  }
+  myFeatures.Clear();
+  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
+  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+
+}
+
+/// Appends to the array of references a new referenced label
+static void AddToRefArray(TDF_Label& theArrayLab, TDF_Label& theReferenced, TDF_Label& thePrevLab)
+{
+  Handle(TDataStd_ReferenceArray) aRefs;
+  if (!theArrayLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+    aRefs = TDataStd_ReferenceArray::Set(theArrayLab, 0, 0);
+    aRefs->SetValue(0, theReferenced);
+  } else {  // extend array by one more element
+    Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(),
+                                                                        aRefs->Upper() + 1);
+    int aPassedPrev = 0; // prev feature is found and passed
+    if (thePrevLab.IsNull()) { // null means that inserted feature must be the first
+      aNewArray->SetValue(aRefs->Lower(), theReferenced);
+      aPassedPrev = 1;
+    }
+    for (int a = aRefs->Lower(); a <= aRefs->Upper(); a++) {
+      aNewArray->SetValue(a + aPassedPrev, aRefs->Value(a));
+      if (!aPassedPrev && aRefs->Value(a).IsEqual(thePrevLab)) {
+        aPassedPrev = 1;
+        aNewArray->SetValue(a + 1, theReferenced);
+      }
+    }
+    if (!aPassedPrev) // not found: unknown situation
+      aNewArray->SetValue(aRefs->Upper() + 1, theReferenced);
+    aRefs->SetInternalArray(aNewArray);
+  }
+}
+
+void Model_Objects::addFeature(FeaturePtr theFeature, const FeaturePtr theAfterThis)
+{
+  if (!theFeature->isAction()) {  // do not add action to the data model
+    TDF_Label aFeaturesLab = featuresLabel();
+    TDF_Label aFeatureLab = aFeaturesLab.NewChild();
+    initData(theFeature, aFeatureLab, TAG_FEATURE_ARGUMENTS);
+    // keep the feature ID to restore document later correctly
+    TDataStd_Comment::Set(aFeatureLab, theFeature->getKind().c_str());
+    myFeatures.Bind(aFeatureLab, theFeature);
+    // store feature in the features array
+    TDF_Label aPrevFeateureLab;
+    if (theAfterThis.get()) { // searching for the previous feature label
+      std::shared_ptr<Model_Data> aPrevData = 
+        std::dynamic_pointer_cast<Model_Data>(theAfterThis->data());
+      if (aPrevData.get()) {
+        aPrevFeateureLab = aPrevData->label().Father();
+      }
+    }
+    AddToRefArray(aFeaturesLab, aFeatureLab, aPrevFeateureLab);
+    // event: feature is added
+    static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+    ModelAPI_EventCreator::get()->sendUpdated(theFeature, anEvent);
+    theFeature->setDisabled(false); // by default created feature is enabled
+    updateHistory(ModelAPI_Feature::group());
+  }
+}
+
+/// Appends to the array of references a new referenced label.
+/// If theIndex is not -1, removes element at this index, not theReferenced.
+/// \returns the index of removed element
+static int RemoveFromRefArray(TDF_Label theArrayLab, TDF_Label theReferenced, 
+  const int theIndex = -1)
+{
+  int aResult = -1;  // no returned
+  Handle(TDataStd_ReferenceArray) aRefs;
+  if (theArrayLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+    if (aRefs->Length() == 1) {  // just erase an array
+      if ((theIndex == -1 && aRefs->Value(0) == theReferenced) || theIndex == 0) {
+        theArrayLab.ForgetAttribute(TDataStd_ReferenceArray::GetID());
+      }
+      aResult = 0;
+    } else {  // reduce the array
+      Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(),
+                                                                          aRefs->Upper() - 1);
+      int aCount = aRefs->Lower();
+      for (int a = aCount; a <= aRefs->Upper(); a++, aCount++) {
+        if ((theIndex == -1 && aRefs->Value(a) == theReferenced) || theIndex == a) {
+          aCount--;
+          aResult = a;
+        } else {
+          aNewArray->SetValue(aCount, aRefs->Value(a));
+        }
+      }
+      aRefs->SetInternalArray(aNewArray);
+    }
+  }
+  return aResult;
+}
+
+void Model_Objects::refsToFeature(FeaturePtr theFeature,
+  std::set<std::shared_ptr<ModelAPI_Feature> >& theRefs, const bool isSendError)
+{
+  // check the feature: it must have no depended objects on it
+  // the dependencies can be in the feature results
+  std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
+  for(; aResIter != theFeature->results().cend(); aResIter++) {
+    ResultPtr aResult = (*aResIter);
+    std::shared_ptr<Model_Data> aData = 
+      std::dynamic_pointer_cast<Model_Data>(aResult->data());
+    if (aData.get() != NULL) {
+      const std::set<AttributePtr>& aRefs = aData->refsToMe();
+      std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin(), aRefLast = aRefs.end();
+      for(; aRefIt != aRefLast; aRefIt++) {
+        FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIt)->owner());
+        if (aFeature.get() != NULL)
+          theRefs.insert(aFeature);
+      }
+    }
+  }
+  // the dependencies can be in the feature itself
+  std::shared_ptr<Model_Data> aData = 
+      std::dynamic_pointer_cast<Model_Data>(theFeature->data());
+  if (aData && !aData->refsToMe().empty()) {
+    const std::set<AttributePtr>& aRefs = aData->refsToMe();
+    std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin(), aRefLast = aRefs.end();
+    for(; aRefIt != aRefLast; aRefIt++) {
+      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIt)->owner());
+      if (aFeature.get() != NULL)
+        theRefs.insert(aFeature);
+    }
+  }
+
+  if (!theRefs.empty() && isSendError) {
+    Events_Error::send(
+      "Feature '" + theFeature->data()->name() + "' is used and can not be deleted");
+  }
+}
+
+void Model_Objects::removeFeature(FeaturePtr theFeature)
+{
+  std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theFeature->data());
+  if (aData) {
+    TDF_Label aFeatureLabel = aData->label().Father();
+    if (myFeatures.IsBound(aFeatureLabel))
+      myFeatures.UnBind(aFeatureLabel);
+    else
+      return;  // not found feature => do not remove
+
+    clearHistory(theFeature);
+    // checking that the sub-element of composite feature is removed: if yes, inform the owner
+    std::set<std::shared_ptr<ModelAPI_Feature> > aRefs;
+    refsToFeature(theFeature, aRefs, false);
+    std::set<std::shared_ptr<ModelAPI_Feature> >::iterator aRefIter = aRefs.begin();
+    for(; aRefIter != aRefs.end(); aRefIter++) {
+      std::shared_ptr<ModelAPI_CompositeFeature> aComposite = 
+        std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aRefIter);
+      if (aComposite.get()) {
+        aComposite->removeFeature(theFeature);
+      }
+    }
+    // erase fields
+    theFeature->erase();
+    static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+    ModelAPI_EventCreator::get()->sendUpdated(theFeature, EVENT_DISP);
+    // erase all attributes under the label of feature
+    aFeatureLabel.ForgetAllAttributes();
+    // remove it from the references array
+    RemoveFromRefArray(featuresLabel(), aFeatureLabel);
+    // event: feature is deleted
+    ModelAPI_EventCreator::get()->sendDeleted(theFeature->document(), ModelAPI_Feature::group());
+    // the redisplay signal should be flushed in order to erase the feature presentation in the viewer
+    Events_Loop::loop()->flush(EVENT_DISP);
+    updateHistory(ModelAPI_Feature::group());
+  }
+}
+
+void Model_Objects::clearHistory(ObjectPtr theObj)
+{
+  if (theObj) {
+    const std::string aGroup = theObj->groupName();
+    std::map<std::string, std::vector<ObjectPtr> >::iterator aHIter = myHistory.find(aGroup);
+    if (aHIter != myHistory.end())
+      myHistory.erase(aHIter); // erase from map => this means that it is not synchronized
+    if (theObj->groupName() == ModelAPI_Feature::group()) { // clear results group of the feature
+      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
+      if (aFeature->firstResult().get())
+        clearHistory(aFeature->firstResult());
+    }
+  }
+}
+
+void Model_Objects::createHistory(const std::string& theGroupID)
+{
+  std::map<std::string, std::vector<ObjectPtr> >::iterator aHIter = myHistory.find(theGroupID);
+  if (aHIter == myHistory.end()) {
+    myHistory[theGroupID] = std::vector<ObjectPtr>();
+    std::vector<ObjectPtr>& aResult = myHistory[theGroupID];
+    // iterate the array of references and get feature by feature from the array
+    bool isFeature = theGroupID == ModelAPI_Feature::group();
+    Handle(TDataStd_ReferenceArray) aRefs;
+    if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+      for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) {
+        FeaturePtr aFeature = feature(aRefs->Value(a));
+        if (aFeature.get()) {
+          if (isFeature) { // here may be also disabled features
+            if (aFeature->isInHistory()) {
+              aResult.push_back(aFeature);
+            }
+          } else if (!aFeature->isDisabled()) { // iterate all results of not-disabled feature
+            const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+            std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+            for (; aRIter != aResults.cend(); aRIter++) {
+              ResultPtr aRes = *aRIter;
+              if (aRes->groupName() != theGroupID) break; // feature have only same group results
+              if (!aRes->isDisabled() && aRes->isInHistory() && !aRes->isConcealed()) {
+                aResult.push_back(*aRIter);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+void Model_Objects::updateHistory(const std::shared_ptr<ModelAPI_Object> theObject)
+{
+  clearHistory(theObject);
+}
+
+void Model_Objects::updateHistory(const std::string theGroup)
+{
+  std::map<std::string, std::vector<ObjectPtr> >::iterator aHIter = myHistory.find(theGroup);
+  if (aHIter != myHistory.end())
+    myHistory.erase(aHIter); // erase from map => this means that it is not synchronized
+}
+
+FeaturePtr Model_Objects::feature(TDF_Label theLabel) const
+{
+  if (myFeatures.IsBound(theLabel))
+    return myFeatures.Find(theLabel);
+  return FeaturePtr();  // not found
+}
+
+ObjectPtr Model_Objects::object(TDF_Label theLabel)
+{
+  // try feature by label
+  FeaturePtr aFeature = feature(theLabel);
+  if (aFeature)
+    return feature(theLabel);
+  TDF_Label aFeatureLabel = theLabel.Father().Father();  // let's suppose it is result
+  aFeature = feature(aFeatureLabel);
+  if (aFeature) {
+    const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+    std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.cbegin();
+    for (; aRIter != aResults.cend(); aRIter++) {
+      std::shared_ptr<Model_Data> aResData = std::dynamic_pointer_cast<Model_Data>(
+          (*aRIter)->data());
+      if (aResData->label().Father().IsEqual(theLabel))
+        return *aRIter;
+    }
+  }
+  return FeaturePtr();  // not found
+}
+
+ObjectPtr Model_Objects::object(const std::string& theGroupID, const int theIndex)
+{
+  createHistory(theGroupID);
+  return myHistory[theGroupID][theIndex];
+}
+
+std::shared_ptr<ModelAPI_Object> Model_Objects::objectByName(
+    const std::string& theGroupID, const std::string& theName)
+{
+  createHistory(theGroupID);
+  std::vector<ObjectPtr>& allObjs = myHistory[theGroupID];
+  std::vector<ObjectPtr>::iterator anObjIter = allObjs.begin();
+  for(; anObjIter != allObjs.end(); anObjIter++) {
+    if ((*anObjIter)->data()->name() == theName)
+      return *anObjIter;
+  }
+  // not found
+  return ObjectPtr();
+}
+
+const int Model_Objects::index(std::shared_ptr<ModelAPI_Object> theObject)
+{
+  std::string aGroup = theObject->groupName();
+  createHistory(aGroup);
+  std::vector<ObjectPtr>& allObjs = myHistory[aGroup];
+  std::vector<ObjectPtr>::iterator anObjIter = allObjs.begin(); // iterate to search object
+  for(int anIndex = 0; anObjIter != allObjs.end(); anObjIter++, anIndex++) {
+    if ((*anObjIter) == theObject)
+      return anIndex;
+  }
+  // not found
+  return -1;
+}
+
+int Model_Objects::size(const std::string& theGroupID)
+{
+  createHistory(theGroupID);
+  return myHistory[theGroupID].size();
+}
+
+void Model_Objects::allResults(const std::string& theGroupID, std::list<ResultPtr>& theResults)
+{
+  // iterate the array of references and get feature by feature from the array
+  Handle(TDataStd_ReferenceArray) aRefs;
+  if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+    for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) {
+      FeaturePtr aFeature = feature(aRefs->Value(a));
+      if (aFeature.get()) {
+        const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+        std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+        for (; aRIter != aResults.cend(); aRIter++) {
+          ResultPtr aRes = *aRIter;
+          if (aRes->groupName() != theGroupID) break; // feature have only same group results
+          if (aRes->isInHistory() && !aRes->isConcealed()) {
+            theResults.push_back(*aRIter);
+          }
+        }
+      }
+    }
+  }
+}
+
+
+TDF_Label Model_Objects::featuresLabel() const
+{
+  return myMain.FindChild(TAG_OBJECTS);
+}
+
+void Model_Objects::setUniqueName(FeaturePtr theFeature)
+{
+  if (!theFeature->data()->name().empty())
+    return;  // not needed, name is already defined
+  std::string aName;  // result
+  // first count all features of such kind to start with index = count + 1
+  int aNumObjects = 0;
+  NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myFeatures);
+  for (; aFIter.More(); aFIter.Next()) {
+    if (aFIter.Value()->getKind() == theFeature->getKind())
+      aNumObjects++;
+  }
+  // generate candidate name
+  std::stringstream aNameStream;
+  aNameStream << theFeature->getKind() << "_" << aNumObjects + 1;
+  aName = aNameStream.str();
+  // check this is unique, if not, increase index by 1
+  for (aFIter.Initialize(myFeatures); aFIter.More();) {
+    FeaturePtr aFeature = aFIter.Value();
+    bool isSameName = aFeature->data()->name() == aName;
+    if (!isSameName) {  // check also results to avoid same results names (actual for Parts)
+      const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+      std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+      for (; aRIter != aResults.cend(); aRIter++) {
+        isSameName = (*aRIter)->data()->name() == aName;
+      }
+    }
+    if (isSameName) {
+      aNumObjects++;
+      std::stringstream aNameStream;
+      aNameStream << theFeature->getKind() << "_" << aNumObjects + 1;
+      aName = aNameStream.str();
+      // reinitialize iterator to make sure a new name is unique
+      aFIter.Initialize(myFeatures);
+    } else
+      aFIter.Next();
+  }
+  theFeature->data()->setName(aName);
+}
+
+void Model_Objects::initData(ObjectPtr theObj, TDF_Label theLab, const int theTag)
+{
+  std::shared_ptr<Model_Data> aData(new Model_Data);
+  aData->setLabel(theLab.FindChild(theTag));
+  aData->setObject(theObj);
+  theObj->setDoc(myDoc);
+  theObj->setData(aData);
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
+  if (aFeature) {
+    setUniqueName(aFeature);  // must be before "initAttributes" because duplicate part uses name
+  }
+  theObj->initAttributes();
+}
+
+void Model_Objects::synchronizeFeatures(
+  const bool theMarkUpdated, const bool theUpdateReferences, const bool theFlush)
+{
+  Model_Document* anOwner = std::dynamic_pointer_cast<Model_Document>(myDoc).get();
+  if (!anOwner) // this may happen on creation of document: nothing there, so nothing to synchronize
+    return;
+  // after all updates, sends a message that groups of features were created or updated
+  Events_Loop* aLoop = Events_Loop::loop();
+  static Events_ID aDispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  static Events_ID aCreateEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+  static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+  static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  static Events_ID aDeleteEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
+  static Events_ID aToHideEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  aLoop->activateFlushes(false);
+
+  // update all objects by checking are they on labels or not
+  std::set<FeaturePtr> aNewFeatures, aKeptFeatures;
+  TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
+  for (; aLabIter.More(); aLabIter.Next()) {
+    TDF_Label aFeatureLabel = aLabIter.Value()->Label();
+    FeaturePtr aFeature;
+    if (!myFeatures.IsBound(aFeatureLabel)) {  // a new feature is inserted
+      // create a feature
+      aFeature = std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get())->createFeature(
+        TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(aLabIter.Value())->Get())
+        .ToCString(), anOwner);
+      if (!aFeature) {  // somethig is wrong, most probably, the opened document has invalid structure
+        Events_Error::send("Invalid type of object in the document");
+        aLabIter.Value()->Label().ForgetAllAttributes();
+        continue;
+      }
+      // this must be before "setData" to redo the sketch line correctly
+      myFeatures.Bind(aFeatureLabel, aFeature);
+      aNewFeatures.insert(aFeature);
+      initData(aFeature, aFeatureLabel, TAG_FEATURE_ARGUMENTS);
+      updateHistory(aFeature);
+      aFeature->setDisabled(false); // by default created feature is enabled (this allows to recreate the results before "setCurrent" is called)
+
+      // event: model is updated
+      ModelAPI_EventCreator::get()->sendUpdated(aFeature, aCreateEvent);
+    } else {  // nothing is changed, both iterators are incremented
+      aFeature = myFeatures.Find(aFeatureLabel);
+      aKeptFeatures.insert(aFeature);
+      if (theMarkUpdated) {
+        ModelAPI_EventCreator::get()->sendUpdated(aFeature, anUpdateEvent);
+      }
+    }
+  }
+  // update results of the features (after features created because they may be connected, like sketch and sub elements)
+  std::list<FeaturePtr> aComposites; // composites must be updated after their subs (issue 360)
+  TDF_ChildIDIterator aLabIter2(featuresLabel(), TDataStd_Comment::GetID());
+  for (; aLabIter2.More(); aLabIter2.Next()) {
+    TDF_Label aFeatureLabel = aLabIter2.Value()->Label();
+    if (myFeatures.IsBound(aFeatureLabel)) {  // a new feature is inserted
+      FeaturePtr aFeature = myFeatures.Find(aFeatureLabel);
+      if (std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeature).get())
+        aComposites.push_back(aFeature);
+      updateResults(aFeature);
+    }
+  }
+  std::list<FeaturePtr>::iterator aComposite = aComposites.begin();
+  for(; aComposite != aComposites.end(); aComposite++) {
+    updateResults(*aComposite);
+  }
+
+  // check all features are checked: if not => it was removed
+  NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myFeatures);
+  while (aFIter.More()) {
+    if (aKeptFeatures.find(aFIter.Value()) == aKeptFeatures.end()
+      && aNewFeatures.find(aFIter.Value()) == aNewFeatures.end()) {
+        FeaturePtr aFeature = aFIter.Value();
+        // event: model is updated
+        //if (aFeature->isInHistory()) {
+        ModelAPI_EventCreator::get()->sendDeleted(myDoc, ModelAPI_Feature::group());
+        //}
+        // results of this feature must be redisplayed (hided)
+        // redisplay also removed feature (used for sketch and AISObject)
+        ModelAPI_EventCreator::get()->sendUpdated(aFeature, aRedispEvent);
+        updateHistory(aFeature);
+        aFeature->erase();
+        // unbind after the "erase" call: on abort sketch is removes sub-objects that corrupts aFIter
+        myFeatures.UnBind(aFIter.Key());
+        // reinitialize iterator because unbind may corrupt the previous order in the map
+        aFIter.Initialize(myFeatures);
+    } else
+      aFIter.Next();
+  }
+
+  if (theUpdateReferences) {
+    synchronizeBackRefs();
+  }
+  if (theMarkUpdated) { // this means there is no control what was modified => remove history cash
+    myHistory.clear();
+  }
+
+  anOwner->executeFeatures() = false;
+  aLoop->activateFlushes(true);
+
+  if (theFlush) {
+    aLoop->flush(aCreateEvent);
+    aLoop->flush(aDeleteEvent);
+    aLoop->flush(anUpdateEvent);
+    aLoop->flush(aRedispEvent);
+    aLoop->flush(aToHideEvent);
+  }
+  anOwner->executeFeatures() = true;
+}
+
+void Model_Objects::synchronizeBackRefs()
+{
+  // keeps the concealed flags of result to catch the change and create created/deleted events
+  std::list<std::pair<ResultPtr, bool> > aConcealed;
+  // first cycle: erase all data about back-references
+  NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFeatures(myFeatures);
+  for(; aFeatures.More(); aFeatures.Next()) {
+    FeaturePtr aFeature = aFeatures.Value();
+    std::shared_ptr<Model_Data> aFData = 
+      std::dynamic_pointer_cast<Model_Data>(aFeature->data());
+    if (aFData) {
+      aFData->eraseBackReferences();
+    }
+    const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+    std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+    for (; aRIter != aResults.cend(); aRIter++) {
+      std::shared_ptr<Model_Data> aResData = 
+        std::dynamic_pointer_cast<Model_Data>((*aRIter)->data());
+      if (aResData) {
+        aConcealed.push_back(std::pair<ResultPtr, bool>(*aRIter, (*aRIter)->isConcealed()));
+        aResData->eraseBackReferences();
+      }
+    }
+  }
+
+  // second cycle: set new back-references: only features may have reference, iterate only them
+  ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
+  for(aFeatures.Initialize(myFeatures); aFeatures.More(); aFeatures.Next()) {
+    FeaturePtr aFeature = aFeatures.Value();
+    std::shared_ptr<Model_Data> aFData = 
+      std::dynamic_pointer_cast<Model_Data>(aFeature->data());
+    if (aFData) {
+      std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
+      aFData->referencesToObjects(aRefs);
+      std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator 
+        aRefsIter = aRefs.begin();
+      for(; aRefsIter != aRefs.end(); aRefsIter++) {
+        std::list<ObjectPtr>::iterator aRefTo = aRefsIter->second.begin();
+        for(; aRefTo != aRefsIter->second.end(); aRefTo++) {
+          if (*aRefTo) {
+            std::shared_ptr<Model_Data> aRefData = 
+              std::dynamic_pointer_cast<Model_Data>((*aRefTo)->data());
+            aRefData->addBackReference(aFeature, aRefsIter->first); // here the Concealed flag is updated
+            // update enable/disable status: the nested status must be equal to the composite
+            CompositeFeaturePtr aComp = 
+              std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeature);
+            if (aComp.get()) {
+              FeaturePtr aReferenced = std::dynamic_pointer_cast<ModelAPI_Feature>(*aRefTo);
+              if (aReferenced.get()) {
+                aReferenced->setDisabled(aComp->isDisabled());
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  std::list<std::pair<ResultPtr, bool> >::iterator aCIter = aConcealed.begin();
+  for(; aCIter != aConcealed.end(); aCIter++) {
+    if (aCIter->first->isConcealed() != aCIter->second) { // somethign is changed => produce event
+      if (aCIter->second) { // was concealed become not => creation event
+        static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+        ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, anEvent);
+      } else { // was not concealed become concealed => delete event
+        ModelAPI_EventCreator::get()->sendDeleted(myDoc, aCIter->first->groupName());
+        // redisplay for the viewer (it must be disappeared also)
+        static Events_ID EVENT_DISP = 
+          Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+        ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, EVENT_DISP);
+      }
+    }
+  }
+}
+
+TDF_Label Model_Objects::resultLabel(
+  const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theResultIndex) 
+{
+  const std::shared_ptr<Model_Data>& aData = 
+    std::dynamic_pointer_cast<Model_Data>(theFeatureData);
+  return aData->label().Father().FindChild(TAG_FEATURE_RESULTS).FindChild(theResultIndex + 1);
+}
+
+void Model_Objects::storeResult(std::shared_ptr<ModelAPI_Data> theFeatureData,
+                                 std::shared_ptr<ModelAPI_Result> theResult,
+                                 const int theResultIndex)
+{
+  theResult->setDoc(myDoc);
+  initData(theResult, resultLabel(theFeatureData, theResultIndex), TAG_FEATURE_ARGUMENTS);
+  if (theResult->data()->name().empty()) {  // if was not initialized, generate event and set a name
+    std::stringstream aNewName;
+    aNewName<<theFeatureData->name();
+    if (theResultIndex > 0) // if there are several results, add unique prefix starting from second
+      aNewName<<"_"<<theResultIndex + 1;
+    theResult->data()->setName(aNewName.str());
+  }
+}
+
+std::shared_ptr<ModelAPI_ResultConstruction> Model_Objects::createConstruction(
+    const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
+{
+  TDF_Label aLab = resultLabel(theFeatureData, theIndex);
+  TDataStd_Comment::Set(aLab, ModelAPI_ResultConstruction::group().c_str());
+  ObjectPtr anOldObject = object(aLab);
+  std::shared_ptr<ModelAPI_ResultConstruction> aResult;
+  if (anOldObject) {
+    aResult = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(anOldObject);
+  }
+  if (!aResult) {
+    aResult = std::shared_ptr<ModelAPI_ResultConstruction>(new Model_ResultConstruction);
+    storeResult(theFeatureData, aResult, theIndex);
+  }
+  return aResult;
+}
+
+std::shared_ptr<ModelAPI_ResultBody> Model_Objects::createBody(
+    const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
+{
+  TDF_Label aLab = resultLabel(theFeatureData, theIndex);
+  TDataStd_Comment::Set(aLab, ModelAPI_ResultBody::group().c_str());
+  ObjectPtr anOldObject = object(aLab);
+  std::shared_ptr<ModelAPI_ResultBody> aResult;
+  if (anOldObject) {
+    aResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(anOldObject);
+  }
+  if (!aResult) {
+    aResult = std::shared_ptr<ModelAPI_ResultBody>(new Model_ResultBody);
+    storeResult(theFeatureData, aResult, theIndex);
+  }
+  return aResult;
+}
+
+std::shared_ptr<ModelAPI_ResultPart> Model_Objects::createPart(
+    const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
+{
+  TDF_Label aLab = resultLabel(theFeatureData, theIndex);
+  TDataStd_Comment::Set(aLab, ModelAPI_ResultPart::group().c_str());
+  ObjectPtr anOldObject = object(aLab);
+  std::shared_ptr<ModelAPI_ResultPart> aResult;
+  if (anOldObject) {
+    aResult = std::dynamic_pointer_cast<ModelAPI_ResultPart>(anOldObject);
+  }
+  if (!aResult) {
+    aResult = std::shared_ptr<ModelAPI_ResultPart>(new Model_ResultPart);
+    storeResult(theFeatureData, aResult, theIndex);
+  }
+  return aResult;
+}
+
+std::shared_ptr<ModelAPI_ResultGroup> Model_Objects::createGroup(
+    const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
+{
+  TDF_Label aLab = resultLabel(theFeatureData, theIndex);
+  TDataStd_Comment::Set(aLab, ModelAPI_ResultGroup::group().c_str());
+  ObjectPtr anOldObject = object(aLab);
+  std::shared_ptr<ModelAPI_ResultGroup> aResult;
+  if (anOldObject) {
+    aResult = std::dynamic_pointer_cast<ModelAPI_ResultGroup>(anOldObject);
+  }
+  if (!aResult) {
+    aResult = std::shared_ptr<ModelAPI_ResultGroup>(new Model_ResultGroup(theFeatureData));
+    storeResult(theFeatureData, aResult, theIndex);
+  }
+  return aResult;
+}
+
+std::shared_ptr<ModelAPI_ResultParameter> Model_Objects::createParameter(
+      const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
+{
+  TDF_Label aLab = resultLabel(theFeatureData, theIndex);
+  TDataStd_Comment::Set(aLab, ModelAPI_ResultParameter::group().c_str());
+  ObjectPtr anOldObject = object(aLab);
+  std::shared_ptr<ModelAPI_ResultParameter> aResult;
+  if (anOldObject) {
+    aResult = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(anOldObject);
+  }
+  if (!aResult) {
+    aResult = std::shared_ptr<ModelAPI_ResultParameter>(new Model_ResultParameter);
+    storeResult(theFeatureData, aResult, theIndex);
+  }
+  return aResult;
+}
+
+std::shared_ptr<ModelAPI_Feature> Model_Objects::feature(
+    const std::shared_ptr<ModelAPI_Result>& theResult)
+{
+  std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theResult->data());
+  if (aData) {
+    TDF_Label aFeatureLab = aData->label().Father().Father().Father();
+    return feature(aFeatureLab);
+  }
+  return FeaturePtr();
+}
+
+void Model_Objects::updateResults(FeaturePtr theFeature)
+{
+  // for not persistent is will be done by parametric updater automatically
+  //if (!theFeature->isPersistentResult()) return;
+  // check the existing results and remove them if there is nothing on the label
+  std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
+  while(aResIter != theFeature->results().cend()) {
+    ResultPtr aBody = std::dynamic_pointer_cast<ModelAPI_Result>(*aResIter);
+    if (aBody) {
+      if (!aBody->data()->isValid()) { 
+        // found a disappeared result => remove it
+        theFeature->removeResult(aBody);
+        // start iterate from beginning because iterator is corrupted by removing
+        aResIter = theFeature->results().cbegin();
+        continue;
+      }
+    }
+    aResIter++;
+  }
+  // it may be on undo
+  if (!theFeature->data() || !theFeature->data()->isValid() || theFeature->isDisabled())
+    return;
+  // check that results are presented on all labels
+  int aResSize = theFeature->results().size();
+  TDF_ChildIterator aLabIter(resultLabel(theFeature->data(), 0).Father());
+  for(; aLabIter.More(); aLabIter.Next()) {
+    // here must be GUID of the feature
+    int aResIndex = aLabIter.Value().Tag() - 1;
+    ResultPtr aNewBody;
+    if (aResSize <= aResIndex) {
+      TDF_Label anArgLab = aLabIter.Value();
+      Handle(TDataStd_Comment) aGroup;
+      if (anArgLab.FindAttribute(TDataStd_Comment::GetID(), aGroup)) {
+        if (aGroup->Get() == ModelAPI_ResultBody::group().c_str()) {
+          aNewBody = createBody(theFeature->data(), aResIndex);
+        } else if (aGroup->Get() == ModelAPI_ResultPart::group().c_str()) {
+          //aNewBody = createPart(theFeature->data(), aResIndex); 
+          theFeature->execute(); // create the part result
+          break;
+        } else if (aGroup->Get() == ModelAPI_ResultConstruction::group().c_str()) {
+          theFeature->execute(); // construction shapes are needed for sketch solver
+          break;
+        } else if (aGroup->Get() == ModelAPI_ResultGroup::group().c_str()) {
+          aNewBody = createGroup(theFeature->data(), aResIndex);
+        } else if (aGroup->Get() == ModelAPI_ResultParameter::group().c_str()) {
+          theFeature->attributeChanged("expression"); // just produce a value
+          break;
+        } else {
+          Events_Error::send(std::string("Unknown type of result is found in the document:") +
+            TCollection_AsciiString(aGroup->Get()).ToCString());
+        }
+      }
+      if (aNewBody) {
+        theFeature->setResult(aNewBody, aResIndex);
+      }
+    }
+  }
+}
+
+ResultPtr Model_Objects::findByName(const std::string theName)
+{
+  NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator anObjIter(myFeatures);
+  for(; anObjIter.More(); anObjIter.Next()) {
+    FeaturePtr& aFeature = anObjIter.ChangeValue();
+    if (!aFeature.get() || aFeature->isDisabled()) // may be on close
+      continue;
+    const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+    std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+    for (; aRIter != aResults.cend(); aRIter++) {
+      ResultPtr aRes = *aRIter;
+      if (aRes.get() && aRes->data() && aRes->data()->isValid() && !aRes->isDisabled() &&
+          aRes->data()->name() == theName) {
+        return aRes;
+      }
+    }
+  }
+  // not found
+  return ResultPtr();
+}
+
+FeaturePtr Model_Objects::nextFeature(FeaturePtr theCurrent, const bool theReverse)
+{
+  std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theCurrent->data());
+  if (aData) {
+    TDF_Label aFeatureLabel = aData->label().Father();
+    Handle(TDataStd_ReferenceArray) aRefs;
+    if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+      for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) { // iterate all existing features
+        if (aRefs->Value(a).IsEqual(aFeatureLabel)) {
+          a += theReverse ? -1 : 1;
+          if (a >= aRefs->Lower() && a <= aRefs->Upper())
+            return feature(aRefs->Value(a));
+          break; // finish iiteration: it's last feature
+        }
+      }
+    }
+  }
+  return FeaturePtr(); // not found, last, or something is wrong
+}
+
+FeaturePtr Model_Objects::firstFeature()
+{
+  Handle(TDataStd_ReferenceArray) aRefs;
+  if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+    return feature(aRefs->Value(aRefs->Lower()));
+  }
+  return FeaturePtr(); // no features at all
+}
+
+FeaturePtr Model_Objects::lastFeature()
+{
+  Handle(TDataStd_ReferenceArray) aRefs;
+  if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+    return feature(aRefs->Value(aRefs->Upper()));
+  }
+  return FeaturePtr(); // no features at all
+}
+
+Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper)
+{
+  return TDF_LabelMapHasher::HashCode(theLab, theUpper);
+
+}
+Standard_Boolean IsEqual(const TDF_Label& theLab1, const TDF_Label& theLab2)
+{
+  return TDF_LabelMapHasher::IsEqual(theLab1, theLab2);
+}
diff --git a/src/Model/Model_Objects.h b/src/Model/Model_Objects.h
new file mode 100644 (file)
index 0000000..148c1c2
--- /dev/null
@@ -0,0 +1,194 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        Model_Objects.h
+// Created:     15 May 2015
+// Author:      Mikhail PONIKAROV
+
+#ifndef Model_Objects_H_
+#define Model_Objects_H_
+
+#include <Model.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Result.h>
+#include <ModelAPI_ResultParameter.h>
+
+#include <TDocStd_Document.hxx>
+#include <NCollection_DataMap.hxx>
+#include <TDF_Label.hxx>
+#include <map>
+#include <set>
+#include <vector>
+
+// for TDF_Label map usage
+static Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper);
+static Standard_Boolean IsEqual(const TDF_Label& theLab1, const TDF_Label& theLab2);
+
+/**\class Model_Objects
+ * \ingroup DataModel
+ * \brief Manager of objects of the document. Normally one this class corresponds to
+ * one document and just helper to manage objects (ModelAPI_Objects) inside of the document
+ * on the level of data storage.
+ */
+class Model_Objects
+{
+ public:
+  //! Registers the fieature in the data structure
+  //! \param theFeature feature that must be added to the data structure
+  //! \param theAfterThis the feature will be added after this feature; 
+  //!        if it is null, the added feature will be the first
+  void addFeature(FeaturePtr theFeature, const FeaturePtr theAfterThis);
+
+  //! Return a list of features, which refers to the feature
+  //! \param theFeature a feature
+  //! \param theRefs a list of reference features
+  //! \param isSendError a flag whether the error message should be send
+  void refsToFeature(FeaturePtr theFeature,
+                     std::set<FeaturePtr>& theRefs,
+                     const bool isSendError = true);
+
+  //! Removes the feature from the document (with result)
+  //! \param theFeature a removed feature
+  void removeFeature(FeaturePtr theFeature);
+
+  //! Returns the existing feature by the label
+  //! \param theLabel base label of the feature
+  FeaturePtr feature(TDF_Label theLabel) const;
+
+  //! Returns the existing object: result or feature
+  //! \param theLabel base label of the object
+  ObjectPtr object(TDF_Label theLabel);
+
+  //! Returns the first found object in the group by the object name
+  //! \param theGroupID group that contains an object
+  //! \param theName name of the object to search
+  //! \returns null if such object is not found
+  std::shared_ptr<ModelAPI_Object> objectByName(
+    const std::string& theGroupID, const std::string& theName);
+
+  //! Returns the result by the result name
+  ResultPtr Model_Objects::findByName(const std::string theName);
+
+
+  //! Returns the object index in the group. Object must be visible. Otherwise returns -1.
+  //! \param theObject object of this document
+  //! \returns index started from zero, or -1 if object is invisible or belongs to another document
+  const int index(std::shared_ptr<ModelAPI_Object> theObject);
+
+  //! Returns the feature in the group by the index (started from zero)
+  //! \param theGroupID group that contains a feature
+  //! \param theIndex zero-based index of feature in the group
+  ObjectPtr object(const std::string& theGroupID, const int theIndex);
+
+  //! Returns the number of features in the group
+  int size(const std::string& theGroupID);
+
+  ///! Returns all (and disabled) results of the given type. Not fast method (iterates all features).
+  void allResults(const std::string& theGroupID, std::list<ResultPtr>& theResults);
+
+  /// Creates a construction cresults
+  std::shared_ptr<ModelAPI_ResultConstruction> createConstruction(
+      const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
+  /// Creates a body results
+  std::shared_ptr<ModelAPI_ResultBody> createBody(
+      const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
+  /// Creates a part results
+  std::shared_ptr<ModelAPI_ResultPart> createPart(
+      const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
+  /// Creates a group results
+  std::shared_ptr<ModelAPI_ResultGroup> createGroup(
+      const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
+
+  std::shared_ptr<ModelAPI_ResultParameter> createParameter(
+      const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
+
+  //! Returns a feature by result (owner of result)
+  std::shared_ptr<ModelAPI_Feature>
+    feature(const std::shared_ptr<ModelAPI_Result>& theResult);
+
+  //! Sets the owner of this manager
+  void setOwner(DocumentPtr theDoc);
+
+  //! Returns the owner of this manager
+  DocumentPtr owner() {return myDoc;}
+
+  //! Deletes all managed features wit hemmitting of corresponded signal
+  ~Model_Objects();
+
+ protected:
+
+  //! Returns (creates if needed) the features label
+  TDF_Label featuresLabel() const;
+
+  //! Initializes feature with a unique name in this group (unique name is generated as 
+  //! feature type + "_" + index
+  void setUniqueName(FeaturePtr theFeature);
+
+  //! Synchronizes myFeatures list with the updated document
+  //! \param theMarkUpdated causes the "update" event for all features
+  //! \param theUpdateReferences causes the update of back-references
+  //! \param theFlush makes flush all events in the end of all modifications of this method
+  void synchronizeFeatures(const bool theMarkUpdated, const bool theUpdateReferences,
+    const bool theFlush);
+  //! Synchronizes the BackReferences list in Data of Features and Results
+  void synchronizeBackRefs();
+
+  //! Creates manager on the OCAF document main label
+  Model_Objects(TDF_Label theMainLab);
+
+  //! Initializes the data fields of the feature
+  void initData(ObjectPtr theObj, TDF_Label theLab, const int theTag);
+
+  //! Allows to store the result in the data tree of the document (attaches 'data' of result to tree)
+  void storeResult(std::shared_ptr<ModelAPI_Data> theFeatureData,
+                   std::shared_ptr<ModelAPI_Result> theResult,
+                   const int theResultIndex = 0);
+
+  //! returns the label of result by index; creates this label if it was not created before
+  TDF_Label resultLabel(const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theResultIndex);
+
+  //! Updates the results list of the feature basing on the current data tree
+  void updateResults(FeaturePtr theFeature);
+
+  /// Internally makes document know that feature was removed or added in history after creation
+  void updateHistory(const std::shared_ptr<ModelAPI_Object> theObject);
+
+  /// Internally makes document know that feature was removed or added in history after creation
+  void updateHistory(const std::string theGroup);
+
+  /// Clears the history arrays related to this object
+  void clearHistory(ObjectPtr theObj);
+
+  /// Creates the history: up to date with the current state
+  void createHistory(const std::string& theGroupID);
+
+  /// Returns to the next (from the history point of view) feature, any: invisible or disabled
+  /// \param theReverse if it is true, iterates in reverced order (next becomes previous)
+  FeaturePtr nextFeature(FeaturePtr theCurrent, const bool theReverse = false);
+  /// Returns to the first (from the history point of view) feature, any: invisible or disabled
+  FeaturePtr firstFeature();
+  /// Returns to the last (from the history point of view) feature, any: invisible or disabled
+  FeaturePtr lastFeature();
+
+ private:
+  TDF_Label myMain; ///< main label of the data storage
+
+  DocumentPtr myDoc; ///< doc,ument, owner of this objects manager: needed for events creation
+
+  /// All managed features (not only in history of OB)
+  /// For optimization mapped by labels
+  NCollection_DataMap<TDF_Label, FeaturePtr> myFeatures;
+
+  /// Map from group id to the array that contains all objects located in history.
+  /// Each array is updated by demand from scratch, by browing all the features in the history.
+  std::map<std::string, std::vector<ObjectPtr> > myHistory;
+
+  friend class Model_Document;
+  friend class Model_Session;
+  friend class Model_Update;
+  friend class Model_AttributeReference;
+  friend class Model_AttributeRefAttr;
+  friend class Model_AttributeRefList;
+};
+
+#endif
index 7708c92cfbda5f6707876e72b6e6e49db579d23f..00a3871e0bcc8055ecdc6a647122b8d47e8e3c59 100644 (file)
 #include <ModelAPI_AttributeIntArray.h>
 #include <TNaming_Builder.hxx>
 #include <TNaming_NamedShape.hxx>
+#include <TNaming_Iterator.hxx>
 #include <TDataStd_Name.hxx>
+#include <TDataStd_Integer.hxx>
 #include <TopoDS.hxx>
-#include <TopoDS_Shape.hxx>
 #include <TopoDS_Face.hxx>
 #include <TDF_ChildIterator.hxx>
 #include <TopTools_MapOfShape.hxx>
@@ -50,13 +51,65 @@ void Model_ResultBody::initAttributes()
 }
 
 void Model_ResultBody::colorConfigInfo(std::string& theSection, std::string& theName,
-                                       std::string& theDefault)
+  std::string& theDefault)
 {
   theSection = "Visualization";
   theName = "result_body_color";
   theDefault = DEFAULT_COLOR();
 }
 
+// Converts evolution of naming shape to selection evelution and back to avoid
+// naming support on the disabled results. Deeply in the labels tree, recursively.
+static void EvolutionToSelection(TDF_Label theLab, const bool theFlag) {
+  std::list<std::pair<TopoDS_Shape, TopoDS_Shape> > aShapePairs; // to store old and new shapes
+  Handle(TNaming_NamedShape) aName;
+  int anEvolution = -1;
+  if (theLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) {
+    anEvolution = (int)(aName->Evolution());
+    for(TNaming_Iterator anIter(aName); anIter.More(); anIter.Next()) {
+      aShapePairs.push_back(std::pair<TopoDS_Shape, TopoDS_Shape>
+        (anIter.OldShape(), anIter.NewShape()));
+    }
+  }
+  // remove old
+  theLab.ForgetAttribute(TNaming_NamedShape::GetID());
+  // create new
+  TNaming_Builder aBuilder(theLab);
+  TNaming_Evolution anEvol = (TNaming_Evolution)(anEvolution);
+  std::list<std::pair<TopoDS_Shape, TopoDS_Shape> >::iterator aPairsIter = aShapePairs.begin();
+  for(; aPairsIter != aShapePairs.end(); aPairsIter++) {
+    if (theFlag) { // disabled => make selection
+      aBuilder.Select(aPairsIter->first, aPairsIter->second);
+    } else if (anEvol == TNaming_GENERATED) {
+      aBuilder.Generated(aPairsIter->first, aPairsIter->second);
+    } else if (anEvol == TNaming_MODIFY) {
+      aBuilder.Modify(aPairsIter->first, aPairsIter->second);
+    } else if (anEvol == TNaming_DELETE) {
+      aBuilder.Delete(aPairsIter->first);
+    } else if (anEvol == TNaming_PRIMITIVE) {
+      aBuilder.Generated(aPairsIter->first, aPairsIter->second);
+    }
+  }
+  // recursive call for all sub-labels
+  TDF_ChildIterator anIter(theLab, Standard_False);
+  for(; anIter.More(); anIter.Next()) {
+    EvolutionToSelection(anIter.Value(), theFlag);
+  }
+}
+
+bool Model_ResultBody::setDisabled(std::shared_ptr<ModelAPI_Result> theThis, const bool theFlag)
+{
+  bool aChanged = ModelAPI_ResultBody::setDisabled(theThis, theFlag);
+  if (aChanged) { // state is changed, so modifications are needed
+    std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
+    if (!aData) // unknown case
+      return aChanged;
+    TDF_Label& aShapeLab = aData->shapeLab();
+    EvolutionToSelection(aShapeLab, theFlag);
+  }
+  return aChanged;
+}
+
 void Model_ResultBody::store(const std::shared_ptr<GeomAPI_Shape>& theShape)
 {
   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
@@ -73,17 +126,17 @@ void Model_ResultBody::store(const std::shared_ptr<GeomAPI_Shape>& theShape)
       return;  // null shape inside
 
     aBuilder.Generated(aShape);        
-       // register name
-       if(!aBuilder.NamedShape()->IsEmpty()) {
-         Handle(TDataStd_Name) anAttr;
-         if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
-               std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
-               if(!aName.empty()) {
+    // register name
+    if(!aBuilder.NamedShape()->IsEmpty()) {
+      Handle(TDataStd_Name) anAttr;
+      if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
+        std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
+        if(!aName.empty()) {
           std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(document());
           aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName);
-               }
-         }
-       }
+        }
+      }
+    }
   }
 }
 
@@ -106,17 +159,17 @@ void Model_ResultBody::storeGenerated(const std::shared_ptr<GeomAPI_Shape>& theF
     if (aShapeNew.IsNull())
       return;  // null shape inside
     aBuilder.Generated(aShapeBasis, aShapeNew);
-               // register name
-       if(!aBuilder.NamedShape()->IsEmpty()) {
-         Handle(TDataStd_Name) anAttr;
-         if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
-               std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
-               if(!aName.empty()) {
+    // register name
+    if(!aBuilder.NamedShape()->IsEmpty()) {
+      Handle(TDataStd_Name) anAttr;
+      if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
+        std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
+        if(!aName.empty()) {
           std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(document());
           aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName);
-               }
-         }
-       }
+        }
+      }
+    }
   }
 }
 
@@ -138,7 +191,7 @@ void Model_ResultBody::storeModified(const std::shared_ptr<GeomAPI_Shape>& theOl
     TopoDS_Shape aShapeNew = theNewShape->impl<TopoDS_Shape>();
     if (aShapeNew.IsNull())
       return;  // null shape inside
-       aBuilder.Modify(aShapeOld, aShapeNew);
+    aBuilder.Modify(aShapeOld, aShapeNew);
   }
 }
 
@@ -269,7 +322,7 @@ void Model_ResultBody::loadAndOrientModifiedShapes (
     ListOfShape aList;
     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
     aRShape->setImpl((new TopoDS_Shape(aRoot)));
-       theMS->modified(aRShape, aList);
+    theMS->modified(aRShape, aList);
     std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator anIt = aList.begin(), aLast = aList.end();
     for (; anIt != aLast; anIt++) {
       TopoDS_Shape aNewShape = (*anIt)->impl<TopoDS_Shape>();    
@@ -279,9 +332,9 @@ void Model_ResultBody::loadAndOrientModifiedShapes (
       }
       if (!aRoot.IsSame (aNewShape)) {
         builder(theTag)->Modify(aRoot,aNewShape);
-               if(!isBuilt) 
-                 buildName(theTag, theName);           
-         }
+        if(!isBuilt) 
+          buildName(theTag, theName);          
+      }
     }
   }
 }
@@ -314,17 +367,17 @@ void Model_ResultBody::loadAndOrientGeneratedShapes (
       }
       if (!aRoot.IsSame (aNewShape)) {
         builder(theTag)->Generated(aRoot,aNewShape);
-               if(!isBuilt) 
-                 buildName(theTag, theName);   
-         }
+        if(!isBuilt) 
+          buildName(theTag, theName);  
+      }
     }
   }
 }
 
 //=======================================================================
 int getDangleShapes(const TopoDS_Shape&           theShapeIn, 
-                                       const TopAbs_ShapeEnum        theGeneratedFrom,
-                                   TopTools_DataMapOfShapeShape& theDangles) 
+  const TopAbs_ShapeEnum        theGeneratedFrom,
+  TopTools_DataMapOfShapeShape& theDangles) 
 {
   theDangles.Clear();
   TopTools_IndexedDataMapOfShapeListOfShape subShapeAndAncestors;
@@ -343,20 +396,20 @@ int getDangleShapes(const TopoDS_Shape&           theShapeIn,
 
 //=======================================================================
 void loadGeneratedDangleShapes(
-                                                          const TopoDS_Shape&      theShapeIn,
-                                              const TopAbs_ShapeEnum   theGeneratedFrom,
-                                              TNaming_Builder *        theBuilder)
+  const TopoDS_Shape&      theShapeIn,
+  const TopAbs_ShapeEnum   theGeneratedFrom,
+  TNaming_Builder *        theBuilder)
 {
   TopTools_DataMapOfShapeShape dangles;
   if (!getDangleShapes(theShapeIn, theGeneratedFrom, dangles)) return;
   TopTools_DataMapIteratorOfDataMapOfShapeShape itr(dangles);
   for (; itr.More(); itr.Next()) 
-       theBuilder->Generated(itr.Key(), itr.Value());
+    theBuilder->Generated(itr.Key(), itr.Value());
 }
 
 //=======================================================================
 void Model_ResultBody::loadNextLevels(std::shared_ptr<GeomAPI_Shape> theShape, 
-                                         const std::string& theName, int&  theTag)
+  const std::string& theName, int&  theTag)
 {
   if(theShape->isNull()) return;
   TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();    
@@ -364,12 +417,12 @@ void Model_ResultBody::loadNextLevels(std::shared_ptr<GeomAPI_Shape> theShape,
   if (aShape.ShapeType() == TopAbs_SOLID) {                
     TopExp_Explorer expl(aShape, TopAbs_FACE);
     for (; expl.More(); expl.Next()) {  
-         builder(theTag)->Generated(expl.Current()); 
-         TCollection_AsciiString aStr(theTag);
-         aName = theName + aStr.ToCString();
-         buildName(theTag, aName);
-         theTag++;
-       }
+      builder(theTag)->Generated(expl.Current()); 
+      TCollection_AsciiString aStr(theTag);
+      aName = theName + aStr.ToCString();
+      buildName(theTag, aName);
+      theTag++;
+    }
   }
   else if (aShape.ShapeType() == TopAbs_SHELL || aShape.ShapeType() == TopAbs_FACE) {
     // load faces and all the free edges
@@ -378,84 +431,84 @@ void Model_ResultBody::loadNextLevels(std::shared_ptr<GeomAPI_Shape> theShape,
     if (Faces.Extent() > 1 || (aShape.ShapeType() == TopAbs_SHELL && Faces.Extent() == 1)) {
       TopExp_Explorer expl(aShape, TopAbs_FACE);
       for (; expl.More(); expl.Next()) {
-                 builder(theTag)->Generated(expl.Current());          
-                 TCollection_AsciiString aStr(theTag);
-             aName = theName + aStr.ToCString();
-             buildName(theTag, aName);
-                 theTag++;
-         }
-       }
+        builder(theTag)->Generated(expl.Current());          
+        TCollection_AsciiString aStr(theTag);
+        aName = theName + aStr.ToCString();
+        buildName(theTag, aName);
+        theTag++;
+      }
+    }
     TopTools_IndexedDataMapOfShapeListOfShape anEdgeAndNeighbourFaces;
     TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, anEdgeAndNeighbourFaces);
     for (Standard_Integer i = 1; i <= anEdgeAndNeighbourFaces.Extent(); i++) 
-       {
+    {
       const TopTools_ListOfShape& aLL = anEdgeAndNeighbourFaces.FindFromIndex(i);
       if (aLL.Extent() < 2) {
-                 if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeAndNeighbourFaces.FindKey(i))))
+        if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeAndNeighbourFaces.FindKey(i))))
           continue;
-           builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
-               TCollection_AsciiString aStr(theTag);
-           aName = theName + aStr.ToCString();
-           buildName(theTag, aName);
-               theTag++;
+        builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
+        TCollection_AsciiString aStr(theTag);
+        aName = theName + aStr.ToCString();
+        buildName(theTag, aName);
+        theTag++;
       } else {
-         TopTools_ListIteratorOfListOfShape anIter(aLL);
-         const TopoDS_Face& aFace = TopoDS::Face(anIter.Value());
-         anIter.Next();
-         if(aFace.IsEqual(anIter.Value())) {
-               builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
-               TCollection_AsciiString aStr(theTag);
-           aName = theName + aStr.ToCString();
-           buildName(theTag, aName);
-           theTag++;
-         }
-         }
-       }
+        TopTools_ListIteratorOfListOfShape anIter(aLL);
+        const TopoDS_Face& aFace = TopoDS::Face(anIter.Value());
+        anIter.Next();
+        if(aFace.IsEqual(anIter.Value())) {
+          builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
+          TCollection_AsciiString aStr(theTag);
+          aName = theName + aStr.ToCString();
+          buildName(theTag, aName);
+          theTag++;
+        }
+      }
+    }
   } else if (aShape.ShapeType() == TopAbs_WIRE) {
     TopTools_IndexedMapOfShape Edges;
     BRepTools::Map3DEdges(aShape, Edges);
     if (Edges.Extent() == 1) {
-         builder(++theTag)->Generated(Edges.FindKey(1));
+      builder(++theTag)->Generated(Edges.FindKey(1));
       TopExp_Explorer expl(aShape, TopAbs_VERTEX);
       for (; expl.More(); expl.Next()) {
-           builder(theTag)->Generated(expl.Current());
-               TCollection_AsciiString aStr(theTag);
-           aName = theName + aStr.ToCString();
-           buildName(theTag, aName);
-           theTag++;
-         }
-       } else {
+        builder(theTag)->Generated(expl.Current());
+        TCollection_AsciiString aStr(theTag);
+        aName = theName + aStr.ToCString();
+        buildName(theTag, aName);
+        theTag++;
+      }
+    } else {
       TopExp_Explorer expl(aShape, TopAbs_EDGE); 
       for (; expl.More(); expl.Next()) {       
-               builder(theTag)->Generated(expl.Current());
-               TCollection_AsciiString aStr(theTag);
-           aName = theName + aStr.ToCString();
-           buildName(theTag, aName);
-               theTag++;
-         }   
+        builder(theTag)->Generated(expl.Current());
+        TCollection_AsciiString aStr(theTag);
+        aName = theName + aStr.ToCString();
+        buildName(theTag, aName);
+        theTag++;
+      }   
       // and load generated vertices.
       TopTools_DataMapOfShapeShape generated;
       if (getDangleShapes(aShape, TopAbs_EDGE, generated)) 
-         {
-               TNaming_Builder* pBuilder = builder(theTag++);
-               loadGeneratedDangleShapes(aShape, TopAbs_EDGE, pBuilder);  
-         }
-       }
+      {
+        TNaming_Builder* pBuilder = builder(theTag++);
+        loadGeneratedDangleShapes(aShape, TopAbs_EDGE, pBuilder);  
+      }
+    }
   } else if (aShape.ShapeType() == TopAbs_EDGE) {
     TopExp_Explorer expl(aShape, TopAbs_VERTEX);
     for (; expl.More(); expl.Next()) {      
-               builder(theTag)->Generated(expl.Current());
-               TCollection_AsciiString aStr(theTag);
-           aName = theName + aStr.ToCString();
-           buildName(theTag, aName);
-               theTag++;
-       }
+      builder(theTag)->Generated(expl.Current());
+      TCollection_AsciiString aStr(theTag);
+      aName = theName + aStr.ToCString();
+      buildName(theTag, aName);
+      theTag++;
+    }
   }
 }
 
 //=======================================================================
 int findAmbiguities(const TopoDS_Shape&           theShapeIn,                                  
-                                         TopTools_ListOfShape&   theList) 
+  TopTools_ListOfShape&   theList) 
 {
   int aNumEdges(0);
   theList.Clear();
@@ -468,36 +521,36 @@ int findAmbiguities(const TopoDS_Shape&           theShapeIn,
   for (Standard_Integer i = 1; i <= subShapeAndAncestors.Extent(); i++) {
     const TopoDS_Shape& aKeyEdge1 = subShapeAndAncestors.FindKey(i);
     const TopTools_ListOfShape& ancestors1 = subShapeAndAncestors.FindFromIndex(i);
-       aMap1.Clear();
+    aMap1.Clear();
     TopTools_ListIteratorOfListOfShape it(ancestors1);
-       for(;it.More();it.Next()) aMap1.Add(it.Value()); // fill map with key ancestors => aKey1
-       for (Standard_Integer j = 1; j <= subShapeAndAncestors.Extent(); j++) {
-         if (i == j) continue;
+    for(;it.More();it.Next()) aMap1.Add(it.Value()); // fill map with key ancestors => aKey1
+    for (Standard_Integer j = 1; j <= subShapeAndAncestors.Extent(); j++) {
+      if (i == j) continue;
       const TopoDS_Shape& aKeyEdge2 = subShapeAndAncestors.FindKey(j);
       const TopTools_ListOfShape& ancestors2 = subShapeAndAncestors.FindFromIndex(j);
-         if(ancestors1.Extent() == ancestors2.Extent() && ancestors1.Extent() > 1) {
-               int aNum (ancestors2.Extent());
-           TopTools_ListIteratorOfListOfShape it(ancestors2);
-           for(;it.More();it.Next()) 
-                       if(aMap1.Contains(it.Value())) aNum--;
-               if(aNum == 0) {
-                 if(aMap2.Add(aKeyEdge1)) 
-                       aKeyList.Append(aKeyEdge1);
-                 if(aMap2.Add(aKeyEdge2))
-                       aKeyList.Append(aKeyEdge2);
-               }
-         }
-       } // at the end ==> List of edges to be named in addition       
+      if(ancestors1.Extent() == ancestors2.Extent() && ancestors1.Extent() > 1) {
+        int aNum (ancestors2.Extent());
+        TopTools_ListIteratorOfListOfShape it(ancestors2);
+        for(;it.More();it.Next()) 
+          if(aMap1.Contains(it.Value())) aNum--;
+        if(aNum == 0) {
+          if(aMap2.Add(aKeyEdge1)) 
+            aKeyList.Append(aKeyEdge1);
+          if(aMap2.Add(aKeyEdge2))
+            aKeyList.Append(aKeyEdge2);
+        }
+      }
+    } // at the end ==> List of edges to be named in addition  
   }
   aNumEdges = aKeyList.Extent();
   if(aNumEdges)
-       theList.Assign(aKeyList);       
+    theList.Assign(aKeyList);  
   return aNumEdges; 
 }
 
 //=======================================================================
 void Model_ResultBody::loadFirstLevel(
-                    std::shared_ptr<GeomAPI_Shape> theShape, const std::string& theName, int&  theTag)
+  std::shared_ptr<GeomAPI_Shape> theShape, const std::string& theName, int&  theTag)
 {
   if(theShape->isNull()) return;
   TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>(); 
@@ -505,43 +558,43 @@ void Model_ResultBody::loadFirstLevel(
   if (aShape.ShapeType() == TopAbs_COMPOUND || aShape.ShapeType() == TopAbs_COMPSOLID) {
     TopoDS_Iterator itr(aShape);
     for (; itr.More(); itr.Next(),theTag++) {
-         builder(theTag)->Generated(itr.Value());
-         TCollection_AsciiString aStr(theTag);
-         aName = theName + aStr.ToCString();
-         buildName(theTag, aName);
-         if(!theName.empty()) buildName(theTag, aName);
+      builder(theTag)->Generated(itr.Value());
+      TCollection_AsciiString aStr(theTag);
+      aName = theName + aStr.ToCString();
+      buildName(theTag, aName);
+      if(!theName.empty()) buildName(theTag, aName);
       if (itr.Value().ShapeType() == TopAbs_COMPOUND || 
-                 itr.Value().ShapeType() == TopAbs_COMPSOLID) 
-         {
-               std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
+        itr.Value().ShapeType() == TopAbs_COMPSOLID) 
+      {
+        std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
         itrShape->setImpl(new TopoDS_Shape(itr.Value()));
-           loadFirstLevel(itrShape, theName, theTag);
+        loadFirstLevel(itrShape, theName, theTag);
       } else {
-               std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
+        std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
         itrShape->setImpl(new TopoDS_Shape(itr.Value()));              
-               loadNextLevels(itrShape, theName, theTag);
-         }
+        loadNextLevels(itrShape, theName, theTag);
+      }
     }
   } else {
     std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
     itrShape->setImpl(new TopoDS_Shape(aShape));
-       loadNextLevels(itrShape, theName, theTag); 
+    loadNextLevels(itrShape, theName, theTag); 
   }
   TopTools_ListOfShape   aList;
   if(findAmbiguities(aShape, aList)) {
-       TopTools_ListIteratorOfListOfShape it(aList);
+    TopTools_ListIteratorOfListOfShape it(aList);
     for (; it.More(); it.Next(),theTag++) {
-         builder(theTag)->Generated(it.Value());
-         TCollection_AsciiString aStr(theTag);
-         aName = theName + aStr.ToCString();
-         buildName(theTag, aName);
-       }
+      builder(theTag)->Generated(it.Value());
+      TCollection_AsciiString aStr(theTag);
+      aName = theName + aStr.ToCString();
+      buildName(theTag, aName);
+    }
   }
 }
 
 //=======================================================================
 void Model_ResultBody::loadDisconnectedEdges(
-                    std::shared_ptr<GeomAPI_Shape> theShape, const std::string& theName, int&  theTag)
+  std::shared_ptr<GeomAPI_Shape> theShape, const std::string& theName, int&  theTag)
 {
   if(theShape->isNull()) return;
   TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();  
@@ -557,33 +610,33 @@ void Model_ResultBody::loadDisconnectedEdges(
       Standard_Boolean faceIsNew = Standard_True;
       TopTools_ListIteratorOfListOfShape itrF(edgeNaborFaces.Find(anEdge));
       for (; itrF.More(); itrF.Next()) {
-           if (itrF.Value().IsSame(aFace)) {
-           faceIsNew = Standard_False;
-           break;
-               }
-         }
+        if (itrF.Value().IsSame(aFace)) {
+          faceIsNew = Standard_False;
+          break;
+        }
+      }
       if (faceIsNew) 
-           edgeNaborFaces.ChangeFind(anEdge).Append(aFace);      
-       }
+        edgeNaborFaces.ChangeFind(anEdge).Append(aFace);      
+    }
   }
 
-/*  TopTools_IndexedDataMapOfShapeListOfShape aDM;
+  /*  TopTools_IndexedDataMapOfShapeListOfShape aDM;
   TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, aDM);
   for(int i=1; i <= aDM.Extent(); i++) {
-       if(aDM.FindFromIndex(i).Extent() > 1) continue;
-       if (BRep_Tool::Degenerated(TopoDS::Edge(aDM.FindKey(i))))
-     continue;
-       builder(theTag)->Generated(aDM.FindKey(i));
-    TCollection_AsciiString aStr(theTag);
-       std::string aName = theName + aStr.ToCString();
-       buildName(theTag, aName);
-#ifdef DEB_IMPORT
-       aName +=  + ".brep";
-       BRepTools::Write(aDM.FindKey(i), aName.c_str());
-#endif
-       theTag++;
+  if(aDM.FindFromIndex(i).Extent() > 1) continue;
+  if (BRep_Tool::Degenerated(TopoDS::Edge(aDM.FindKey(i))))
+  continue;
+  builder(theTag)->Generated(aDM.FindKey(i));
+  TCollection_AsciiString aStr(theTag);
+  std::string aName = theName + aStr.ToCString();
+  buildName(theTag, aName);
+  #ifdef DEB_IMPORT
+  aName +=  + ".brep";
+  BRepTools::Write(aDM.FindKey(i), aName.c_str());
+  #endif
+  theTag++;
   }
-*/
+  */
   TopTools_MapOfShape anEdgesToDelete;
   TopExp_Explorer anEx(aShape,TopAbs_EDGE); 
   std::string aName;
@@ -595,39 +648,39 @@ void Model_ResultBody::loadDisconnectedEdges(
       if (aList1.Extent()<2) continue;
       TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itr(edgeNaborFaces);
       for (; itr.More(); itr.Next()) {
-           TopoDS_Shape anEdge2 = itr.Key();
-           if(anEdgesToDelete.Contains(anEdge2)) continue;
-           if (anEdge1.IsSame(anEdge2)) continue;
-           const TopTools_ListOfShape& aList2 = itr.Value();
-           // compare lists of the neighbour faces of edge1 and edge2
-           if (aList1.Extent() == aList2.Extent()) {
-           Standard_Integer aMatches = 0;
-           for(TopTools_ListIteratorOfListOfShape aLIter1(aList1);aLIter1.More();aLIter1.Next())
-             for(TopTools_ListIteratorOfListOfShape aLIter2(aList2);aLIter2.More();aLIter2.Next())
-               if (aLIter1.Value().IsSame(aLIter2.Value())) aMatches++;
-               if (aMatches == aList1.Extent()) {
-                 aC0=Standard_True;
-                         builder(theTag)->Generated(anEdge2);
-                 anEdgesToDelete.Add(anEdge2);
-                         TCollection_AsciiString aStr(theTag);
-                         aName = theName + aStr.ToCString();
-                 buildName(theTag, aName);
-                         theTag++;
-                       }
-               }
-         }      
+        TopoDS_Shape anEdge2 = itr.Key();
+        if(anEdgesToDelete.Contains(anEdge2)) continue;
+        if (anEdge1.IsSame(anEdge2)) continue;
+        const TopTools_ListOfShape& aList2 = itr.Value();
+        // compare lists of the neighbour faces of edge1 and edge2
+        if (aList1.Extent() == aList2.Extent()) {
+          Standard_Integer aMatches = 0;
+          for(TopTools_ListIteratorOfListOfShape aLIter1(aList1);aLIter1.More();aLIter1.Next())
+            for(TopTools_ListIteratorOfListOfShape aLIter2(aList2);aLIter2.More();aLIter2.Next())
+              if (aLIter1.Value().IsSame(aLIter2.Value())) aMatches++;
+          if (aMatches == aList1.Extent()) {
+            aC0=Standard_True;
+            builder(theTag)->Generated(anEdge2);
+            anEdgesToDelete.Add(anEdge2);
+            TCollection_AsciiString aStr(theTag);
+            aName = theName + aStr.ToCString();
+            buildName(theTag, aName);
+            theTag++;
+          }
+        }
+      }      
       TopTools_MapIteratorOfMapOfShape itDelete(anEdgesToDelete);
       for(;itDelete.More();itDelete.Next()) 
-           edgeNaborFaces.UnBind(itDelete.Key());      
+        edgeNaborFaces.UnBind(itDelete.Key());      
       edgeNaborFaces.UnBind(anEdge1);
-       }
+    }
     if (aC0) {
-         builder(theTag)->Generated(anEdge1);
-         TCollection_AsciiString aStr(theTag);
-         aName = theName + aStr.ToCString();
-         buildName(theTag, aName);      
-         theTag++;
-       }
+      builder(theTag)->Generated(anEdge1);
+      TCollection_AsciiString aStr(theTag);
+      aName = theName + aStr.ToCString();
+      buildName(theTag, aName);         
+      theTag++;
+    }
   }  
 }
 
@@ -662,11 +715,11 @@ void Model_ResultBody::loadDisconnectedVertexes(std::shared_ptr<GeomAPI_Shape> t
   for (; itr.More(); itr.Next()) {
     const TopTools_ListOfShape& naborEdges = itr.Value();
     if (naborEdges.Extent() < 2) {             
-               builder(theTag)->Generated(itr.Key());
-               TCollection_AsciiString aStr(theTag);
-           aName = theName + aStr.ToCString();
-           buildName(theTag, aName);    
-               theTag++;
-       }
+      builder(theTag)->Generated(itr.Key());
+      TCollection_AsciiString aStr(theTag);
+      aName = theName + aStr.ToCString();
+      buildName(theTag, aName);         
+      theTag++;
+    }
   }
 }
index a5ffd83027b04bba1e2ca48a2fac7b6f6df0b951..cafa565177122830702734ba0065bc4ec5d9a87f 100644 (file)
@@ -32,17 +32,22 @@ public:
   /// default color for a result body
   inline static const std::string& DEFAULT_COLOR()
   {
-    static const std::string RESULT_BODY_COLOR("#E0A01B");
+    static const std::string RESULT_BODY_COLOR("150,150,180");
     return RESULT_BODY_COLOR;
   }
 
   /// Request for initialization of data model of the result: adding all attributes
   virtual void initAttributes();
 
-  // Retuns the parameters of color definition in the resources config manager
+  /// Returns the parameters of color definition in the resources config manager
   MODEL_EXPORT virtual void colorConfigInfo(std::string& theSection, std::string& theName,
                                             std::string& theDefault);
 
+  /// Disables the result body: keeps the resulting shape as selection, but erases the underlaying
+  /// naming data structure if theFlag if false. Or restores everything on theFlag is true.
+  MODEL_EXPORT virtual bool setDisabled(std::shared_ptr<ModelAPI_Result> theThis,
+    const bool theFlag);
+
   /// Stores the shape (called by the execution method).
   MODEL_EXPORT virtual void store(const std::shared_ptr<GeomAPI_Shape>& theShape);
 
@@ -130,7 +135,7 @@ private:
   /// builds name for the shape kept at the specified tag 
   void buildName(const int theTag, const std::string& theName);
 
-  friend class Model_Document;
+  friend class Model_Objects;
 };
 
 #endif
index 84f048f6d3a98c27228084747208a29fd61cee01..e5081240976388fbd85640eaff8013c29f05530a 100644 (file)
@@ -29,7 +29,7 @@ class Model_ResultConstruction : public ModelAPI_ResultConstruction
   /// default color for a result construction
   inline static const std::string& DEFAULT_COLOR()
   {
-    static const std::string RESULT_CONSTRUCTION_COLOR("#000000");
+    static const std::string RESULT_CONSTRUCTION_COLOR("120,120,120");
     return RESULT_CONSTRUCTION_COLOR;
   }
 
@@ -63,7 +63,7 @@ class Model_ResultConstruction : public ModelAPI_ResultConstruction
   /// Makes a body on the given feature
   Model_ResultConstruction();
 
-  friend class Model_Document;
+  friend class Model_Objects;
 };
 
 #endif
index 7bfa796942d8053b4f72f03188bf3a114222444a..be220052fb987e89b2da637c0ed06c1289a91417 100644 (file)
@@ -23,7 +23,7 @@ public:
   /// default color for a result body
   inline static const std::string& DEFAULT_COLOR()
   {
-    static const std::string RESULT_GROUP_COLOR("#E0A01B");
+    static const std::string RESULT_GROUP_COLOR("150,150,180");
     return RESULT_GROUP_COLOR;
   }
   /// Request for initialization of data model of the result: adding all attributes
@@ -43,7 +43,7 @@ protected:
   /// Makes a body on the given feature data
   Model_ResultGroup(std::shared_ptr<ModelAPI_Data> theOwnerData);
 
-  friend class Model_Document;
+  friend class Model_Objects;
 };
 
 #endif
index 641155b1ef365f6d90014f48387593726847323e..7d3ca59859cd7eb2336ac985033660857ca23fa4 100644 (file)
@@ -26,7 +26,7 @@ class Model_ResultParameter : public ModelAPI_ResultParameter
  protected:
   Model_ResultParameter();
 
-  friend class Model_Document;
+  friend class Model_Objects;
 };
 
 #endif
index cda7bf6cd5f25a290116d6a99ce03f042d353243..7ebafd3ea0b22237d2b7e7ed10b3757a35fe0bc6 100644 (file)
@@ -38,7 +38,7 @@ protected:
   /// Returns true if document is activated (loaded into the memory)
   virtual bool isActivated();
 
-  friend class Model_Document;
+  friend class Model_Objects;
 };
 
 #endif
index 69c2f1b162d5421345e41028f8f37e41a676688f..de3cddb282f2560b844528f3ae709c76da93c40a 100644 (file)
@@ -9,6 +9,7 @@
 #include <ModelAPI_Plugin.h>
 #include <Model_Data.h>
 #include <Model_Document.h>
+#include <Model_Objects.h>
 #include <Model_Application.h>
 #include <Model_Events.h>
 #include <Model_Validator.h>
@@ -36,7 +37,7 @@ static Model_Session* myImpl = new Model_Session();
 
 bool Model_Session::load(const char* theFileName)
 {
-  bool aRes = ROOT_DOC->load(theFileName);
+  bool aRes = ROOT_DOC->load(theFileName, ROOT_DOC);
   return aRes;
 }
 
@@ -47,8 +48,8 @@ bool Model_Session::save(const char* theFileName, std::list<std::string>& theRes
 
 void Model_Session::closeAll()
 {
-  ROOT_DOC->close(true);
   Model_Application::getApplication()->deleteAllDocuments();
+  ROOT_DOC->close(true);
 }
 
 void Model_Session::startOperation(const std::string& theId)
@@ -216,7 +217,7 @@ void Model_Session::setActiveDocument(
       if (aDoc.get()) {
         bool aWasChecked = myCheckTransactions;
         setCheckTransactions(false);
-        aDoc->synchronizeFeatures(false, true, true);
+        aDoc->objects()->synchronizeFeatures(false, true, true);
         if (aWasChecked)
             setCheckTransactions(true);
       }
@@ -249,6 +250,11 @@ std::list<std::shared_ptr<ModelAPI_Document> > Model_Session::allOpenedDocuments
   return aResult;
 }
 
+bool Model_Session::isLoadByDemand(const std::string theDocID)
+{
+  return Model_Application::getApplication()->isLoadByDemand(theDocID);
+}
+
 std::shared_ptr<ModelAPI_Document> Model_Session::copy(
     std::shared_ptr<ModelAPI_Document> theSource, std::string theID)
 {
@@ -266,7 +272,7 @@ std::shared_ptr<ModelAPI_Document> Model_Session::copy(
   aRT->SetRelocation(aSourceRoot, aTargetRoot);
   TDF_CopyTool::Copy(aDS, aRT);
 
-  aNew->synchronizeFeatures(false, true, true);
+  aNew->objects()->synchronizeFeatures(false, true, true);
   return aNew;
 }
 
index 47e40262e3ae4cab165f84103d1467b9856724da..2584a2e201aa35a14012df0e8c79c6a08ea29d9c 100644 (file)
@@ -90,6 +90,9 @@ class Model_Session : public ModelAPI_Session, public Events_Listener
   /// Returns all the opened documents of the session (without postponed)
   MODEL_EXPORT virtual std::list<std::shared_ptr<ModelAPI_Document> > allOpenedDocuments();
 
+  /// Returns true if document is not loaded yet
+  MODEL_EXPORT virtual bool isLoadByDemand(const std::string theDocID);
+
   /// Registers the plugin that creates features.
   /// It is obligatory for each plugin to call this function on loading to be found by 
   /// the plugin manager on call of the feature)
@@ -122,6 +125,7 @@ class Model_Session : public ModelAPI_Session, public Events_Listener
   FeaturePtr createFeature(std::string theFeatureID, Model_Document* theDocOwner);
 
   friend class Model_Document;
+  friend class Model_Objects;
 };
 
 #endif
index 403b3dffc759e217a86476a58ac5d94eeb84a630..7a8e5277bc898c2da6839497a2dc0d68bba3957f 100644 (file)
@@ -7,6 +7,7 @@
 #include <Model_Update.h>
 #include <Model_Document.h>
 #include <Model_Data.h>
+#include <Model_Objects.h>
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Document.h>
@@ -17,6 +18,7 @@
 #include <ModelAPI_AttributeSelection.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_Result.h>
+#include <ModelAPI_ResultPart.h>
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_CompositeFeature.h>
 #include <ModelAPI_Session.h>
@@ -67,20 +69,17 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
   static const Events_ID kOpFinishEvent = aLoop->eventByName("FinishOperation");
   static const Events_ID kOpAbortEvent = aLoop->eventByName("AbortOperation");
   static const Events_ID kOpStartEvent = aLoop->eventByName("StartOperation");
-  bool isAutomaticChanged = false;
+  bool isOperationChanged = false;
   if (theMessage->eventID() == kChangedEvent) { // automatic and manual rebuild flag is changed
     bool aPropVal =
       Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true";
-    if (aPropVal == myIsAutomatic)
-      return; // nothing is changed, so nithing to do
-    myIsAutomatic = aPropVal;
-    if (!myIsAutomatic)
-      return; // less automatization => nothing to do
-  } else if (theMessage->eventID() == kRebuildEvent) { // the rebuild command
-    if (myIsAutomatic == false) {
-      isAutomaticChanged = true;
-      myIsAutomatic = true;
+    if (aPropVal != myIsAutomatic) { // something is changed
+      myIsAutomatic = aPropVal;
+      if (myIsAutomatic) // higher level of automatization => to rebuild
+        processOperation(false);
     }
+  } else if (theMessage->eventID() == kRebuildEvent) { // the rebuild command
+    processOperation(true);
   } else if (theMessage->eventID() == kCreatedEvent || theMessage->eventID() == kUpdatedEvent ||
              theMessage->eventID() == kMovedEvent) {
     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aMsg =
@@ -88,88 +87,126 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
     const std::set<ObjectPtr>& anObjs = aMsg->objects();
     std::set<ObjectPtr>::const_iterator anObjIter = anObjs.cbegin();
     for(; anObjIter != anObjs.cend(); anObjIter++) {
-      myJustCreatedOrUpdated.insert(*anObjIter);
       // created objects are always must be up to date (python box feature)
       // and updated not in internal uptation chain
-      if (!myIsExecuted || theMessage->eventID() == kCreatedEvent)
-        myInitial.insert(*anObjIter);
-      // TODO(mpv): check the next line. Came into dev 0.6.1 from BR_PYTHON_PLUGIN
-      // (*anObjIter)->data()->mustBeUpdated(true); // object must be updated because it was changed
+      if (theMessage->eventID() == kCreatedEvent) {
+        myJustCreated.insert(*anObjIter);
+      } else if (myJustCreated.find(*anObjIter) == myJustCreated.end()) { // moved and updated
+        myJustUpdated.insert(*anObjIter);
+      }
     }
-    if (theMessage->eventID() == kMovedEvent)
-      return; // this event is for solver update, not here
+     // this event is for solver update, not here, do not react immideately
+    if (!(theMessage->eventID() == kMovedEvent))
+      processOperation(false);
   } else if (theMessage->eventID() == kOpStartEvent) {
-    myJustCreatedOrUpdated.clear();
-    myInitial.clear();
-    return; // we don't need the update only on operation start (caused problems in PartSet_Listener::processEvent)
+    // we don't need the update only on operation start (caused problems in PartSet_Listener::processEvent)
+    isOperationChanged = true;
   } else if (theMessage->eventID() == kOpFinishEvent || theMessage->eventID() == kOpAbortEvent) {
-    if (myIsAutomatic == false) { // Apply button now works as "Rebuild"
-      isAutomaticChanged = true;
-      myIsAutomatic = true;
+    processOperation(true);
+    isOperationChanged = true;
+  }
+  if (isOperationChanged) {
+    // remove all macros before clearing all created
+    std::set<ObjectPtr>::iterator aCreatedIter = myJustCreated.begin();
+    for(; aCreatedIter != myJustCreated.end(); aCreatedIter++) {
+      FeaturePtr aFeature = 
+        std::dynamic_pointer_cast<ModelAPI_Feature>(*aCreatedIter);
+      if (aFeature.get()) {
+        // execute not-previewed feature on "apply"
+        if (!aFeature->isPreviewNeeded() && (myJustCreated.find(aFeature) != myJustCreated.end() ||
+          myJustUpdated.find(aFeature) != myJustUpdated.end())) {
+          static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
+          if (aFactory->validate(aFeature)) {
+            executeFeature(aFeature);
+          }
+        }
+        // remove macro on apply
+        if (aFeature->isMacro()) {
+          aFeature->document()->removeFeature(aFeature);
+        }
+      }
     }
-    // the hardcode (DBC asked): hide the sketch referenced by extrusion on apply
-    if (theMessage->eventID() == kOpFinishEvent) {
-      std::set<std::shared_ptr<ModelAPI_Object> >::iterator aFIter;
-      for(aFIter = myJustCreatedOrUpdated.begin(); aFIter != myJustCreatedOrUpdated.end(); aFIter++)
-      {
-        FeaturePtr aF = std::dynamic_pointer_cast<ModelAPI_Feature>(*aFIter);
-        if (aF && aF->data().get() && aF->getKind() == "Extrusion") {
-          AttributeSelectionListPtr aBase = aF->selectionList("base");
-          if (aBase.get()) {
-            for(int a = aBase->size() - 1; a >= 0; a--) {
-              ResultPtr aSketchRes = aBase->value(a)->context();
-              if (aSketchRes) {
-                static Events_ID HIDE_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TOHIDE);
-                ModelAPI_EventCreator::get()->sendUpdated(aSketchRes, HIDE_DISP);
-              }
-            }
+    myJustCreated.clear();
+    myJustUpdated.clear();
+  }
+}
+
+void Model_Update::processOperation(const bool theTotalUpdate)
+{
+  // the hardcode (DBC asked): hide the sketch referenced by extrusion on apply
+  std::set<std::shared_ptr<ModelAPI_Object> >::iterator aFIter;
+  for(aFIter = myJustCreated.begin(); aFIter != myJustCreated.end(); aFIter++)
+  {
+    FeaturePtr aF = std::dynamic_pointer_cast<ModelAPI_Feature>(*aFIter);
+    if (aF && aF->data().get() && aF->getKind() == "Extrusion") {
+      AttributeSelectionListPtr aBase = aF->selectionList("base");
+      if (aBase.get()) {
+        for(int a = aBase->size() - 1; a >= 0; a--) {
+          ResultPtr aSketchRes = aBase->value(a)->context();
+          if (aSketchRes) {
+            aSketchRes->setDisplayed(false);
           }
         }
       }
     }
   }
+  // perform update of everything if needed
+  if (!myIsExecuted) {
+    myIsExecuted = true;
+
+    bool isAutomaticChanged = false;
 
-  if (myIsExecuted)
-    return;  // nothing to do: it is executed now
+    if (theTotalUpdate && !myIsAutomatic) { // Apply button now works as "Rebuild"
+      isAutomaticChanged = true;
+      myIsAutomatic = true;
+    }
 
-  //Events_LongOp::start(this);
-  myIsExecuted = true;
-  // iterate all documents: features in Root first, then - subs
-  updateInDoc(ModelAPI_Session::get()->moduleDocument());
+    updateInDoc(ModelAPI_Session::get()->moduleDocument());
 
-  myUpdated.clear();
-  // flush to update display
-  static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-  aLoop->flush(EVENT_DISP);
-  //Events_LongOp::end(this);
-  if (isAutomaticChanged) myIsAutomatic = false;
+    if (isAutomaticChanged) myIsAutomatic = false;
+    myIsExecuted = false;
 
-  if (theMessage->eventID() == kOpFinishEvent || theMessage->eventID() == kOpAbortEvent) {
-    myJustCreatedOrUpdated.clear();
-    myInitial.clear();
+    // flush to update display
+    static Events_Loop* aLoop = Events_Loop::loop();
+    static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+    aLoop->flush(EVENT_DISP);
   }
-
-  myIsExecuted = false;
 }
 
 void Model_Update::updateInDoc(std::shared_ptr<ModelAPI_Document> theDoc)
 {
+  std::set<FeaturePtr> alreadyProcessed; // features that are processed before others
   // all features one by one
-  int aNbFeatures = theDoc->size(ModelAPI_Feature::group(), true);
-  for (int aFIndex = 0; aFIndex < aNbFeatures; aFIndex++) {
-    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(
-        theDoc->object(ModelAPI_Feature::group(), aFIndex, true));
-    if (aFeature)
-      updateFeature(aFeature);
-  }
-  // all sub-documents one by one
-  std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(theDoc);
-  if (aDoc) {
-    const std::set<std::string> aSubs = aDoc->subDocuments(true);
-    for(std::set<std::string>::iterator aSub = aSubs.begin(); aSub != aSubs.end(); aSub++) {
-      DocumentPtr aSubDoc = theDoc->subDocument(*aSub);
-      if (aSubDoc) {
-        updateInDoc(aSubDoc);
+  Model_Objects* anObjs = std::dynamic_pointer_cast<Model_Document>(theDoc)->objects();
+  if (!anObjs) return;
+  FeaturePtr aFeatureIter = anObjs->firstFeature();
+  for (; aFeatureIter.get(); aFeatureIter = anObjs->nextFeature(aFeatureIter)) {
+    if (aFeatureIter && alreadyProcessed.find(aFeatureIter) == alreadyProcessed.end()) {
+      // update selection and parameters attributes first, before sub-features analysis (sketch plane)
+      updateArguments(aFeatureIter);
+      // composite feature must be executed after sub-features execution
+      CompositeFeaturePtr aComposite = 
+        std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeatureIter);
+      if (aComposite) {
+        // number of subs can be changed in execution: like fillet
+        for(int a = 0; a < aComposite->numberOfSubs(); a++) {
+          FeaturePtr aSub = aComposite->subFeature(a);
+          updateFeature(aSub);
+          alreadyProcessed.insert(aSub);
+        }
+      }
+
+      updateFeature(aFeatureIter);
+      // update the document results recursively
+      const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeatureIter->results();
+      std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+      for (; aRIter != aResults.cend(); aRIter++) {
+        ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aRIter);
+        if (aPart.get()) {
+          if (!aPart->isDisabled() && aPart->isActivated()) {
+            updateInDoc(aPart->partDoc());
+          }
+        }
       }
     }
   }
@@ -184,7 +221,7 @@ void Model_Update::redisplayWithResults(FeaturePtr theFeature, const ModelAPI_Ex
   for (; aRIter != aResults.cend(); aRIter++) {
     std::shared_ptr<ModelAPI_Result> aRes = *aRIter;
     aRes->data()->execState(theState);
-    myUpdated[aRes] = true;
+    myJustUpdated.insert(aRes);
     ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP);
   }
   // to redisplay "presentable" feature (for ex. distance constraint)
@@ -206,50 +243,87 @@ ModelAPI_ExecState stateByReference(ObjectPtr theTarget, const ModelAPI_ExecStat
   return theCurrent;
 }
 
-bool Model_Update::updateFeature(FeaturePtr theFeature)
-{
-  // check it is already processed
-  if (myUpdated.find(theFeature) != myUpdated.end())
-    return myUpdated[theFeature];
-  // check all features this feature depended on (recursive call of updateFeature)
-  ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
-  bool aMustbeUpdated = myInitial.find(theFeature) != myInitial.end();
-  if (theFeature) {  // only real feature contains references to other objects
-    if (theFeature->data()->execState() != ModelAPI_StateDone)
-      aMustbeUpdated = true;
-
-    ModelAPI_ExecState aState = ModelAPI_StateDone;
+void Model_Update::updateArguments(FeaturePtr theFeature) {
+  static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
 
-    // check the parameters: values can be changed
-    std::list<AttributePtr> aDoubles = 
-      theFeature->data()->attributes(ModelAPI_AttributeDouble::typeId()); 
-    std::list<AttributePtr>::iterator aDoubleIter = aDoubles.begin();
-    for(; aDoubleIter != aDoubles.end(); aDoubleIter++) {
-      AttributeDoublePtr aDouble = 
-        std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(*aDoubleIter);
-      if (aDouble.get() && !aDouble->text().empty()) {
-        double aNewVal;
-        if (ModelAPI_Tools::findVariable(aDouble->text(), aNewVal)) {
-          if (aNewVal != aDouble->value()) {
-            aDouble->setValue(aNewVal);
-            aMustbeUpdated = true;
-          }
-        } else {
-          aState = ModelAPI_StateInvalidArgument;
+  if (theFeature->isDisabled()) // nothing to do with disabled feature
+    return;
+  bool aJustUpdated = false;
+  ModelAPI_ExecState aState = ModelAPI_StateDone;
+  // check the parameters: values can be changed
+  std::list<AttributePtr> aDoubles = 
+    theFeature->data()->attributes(ModelAPI_AttributeDouble::typeId()); 
+  std::list<AttributePtr>::iterator aDoubleIter = aDoubles.begin();
+  for(; aDoubleIter != aDoubles.end(); aDoubleIter++) {
+    AttributeDoublePtr aDouble = 
+      std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(*aDoubleIter);
+    if (aDouble.get() && !aDouble->text().empty()) {
+      double aNewVal;
+      if (ModelAPI_Tools::findVariable(aDouble->text(), aNewVal)) {
+        if (aNewVal != aDouble->value()) {
+          aDouble->setValue(aNewVal);
+          aJustUpdated = true;
         }
+      } else {
+        aState = ModelAPI_StateInvalidArgument;
       }
     }
+  }
 
-    // composite feature must be executed after sub-features execution
-    CompositeFeaturePtr aComposite = 
-      std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
-    if (aComposite) {
-      // number of subs can be changed in execution: like fillet
-      for(int a = 0; a < aComposite->numberOfSubs(); a++) {
-        if (updateFeature(aComposite->subFeature(a)))
-          aMustbeUpdated = true;
+  if (aState == ModelAPI_StateDone) {// all referenced objects are ready to be used
+    //std::cout<<"Execute feature "<<theFeature->getKind()<<std::endl;
+    // before execution update the selection attributes if any
+    list<AttributePtr> aRefs = 
+      theFeature->data()->attributes(ModelAPI_AttributeSelection::typeId());
+    list<AttributePtr>::iterator aRefsIter = aRefs.begin();
+    for (; aRefsIter != aRefs.end(); aRefsIter++) {
+      std::shared_ptr<ModelAPI_AttributeSelection> aSel =
+        std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*aRefsIter);
+      if (!aSel->update()) { // this must be done on execution since it may be long operation
+        if (!aFactory->isNotObligatory(theFeature->getKind(), theFeature->data()->id(aSel)) &&
+            aFactory->isCase(theFeature, theFeature->data()->id(aSel)))
+          aState = ModelAPI_StateInvalidArgument;
       }
     }
+    aRefs = theFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
+    for (aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) {
+      std::shared_ptr<ModelAPI_AttributeSelectionList> aSel =
+        std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*aRefsIter);
+      for(int a = aSel->size() - 1; a >= 0; a--) {
+        std::shared_ptr<ModelAPI_AttributeSelection> aSelAttr =
+          std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(aSel->value(a));
+        if (aSelAttr) {
+          if (!aSelAttr->update()) {
+            if (!aFactory->isNotObligatory(
+                  theFeature->getKind(), theFeature->data()->id(aSel)) &&
+                aFactory->isCase(theFeature, theFeature->data()->id(aSel)))
+              aState = ModelAPI_StateInvalidArgument;
+          }
+        }
+      }
+    }
+  }
+  if (aJustUpdated && myJustCreated.find(theFeature) == myJustCreated.end())
+  myJustUpdated.insert(theFeature);
+  if (aState != ModelAPI_StateDone)
+    theFeature->data()->execState(aState);
+}
+
+void Model_Update::updateFeature(FeaturePtr theFeature)
+{
+  // check all features this feature depended on (recursive call of updateFeature)
+  static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
+
+  if (theFeature->isDisabled()) // nothing to do with disabled feature
+    return;
+  bool aJustUpdated = false;
+
+  if (theFeature) {
+    if (theFeature->data()->execState() != ModelAPI_StateDone)
+      aJustUpdated = true;
+
+    ModelAPI_ExecState aState = ModelAPI_StateDone;
+
     // check all references: if referenced objects are updated, this object also must be updated
     // also check state of referenced objects: if they are not ready, inherit corresponding state
     std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
@@ -260,94 +334,40 @@ bool Model_Update::updateFeature(FeaturePtr theFeature)
     for(; aRef != aRefs.end(); aRef++) {
       std::list<ObjectPtr>::iterator aRefObj = aRef->second.begin();
       for(; aRefObj != aRef->second.end(); aRefObj++) {
-        if (updateObject(*aRefObj)) {
-          aMustbeUpdated = true;
+        if (myJustCreated.find(*aRefObj) != myJustCreated.end() ||
+            myJustUpdated.find(*aRefObj) != myJustUpdated.end()) {
+          aJustUpdated = true;
         }
         aState = stateByReference(*aRefObj, aState);
       }
     }
 
+    // some arguments were changed, so, this feature must be updated
+    if (myJustCreated.find(theFeature) != myJustCreated.end()) {
+      aJustUpdated = true;
+    } else {
+      if (aJustUpdated) {
+        if (myJustUpdated.find(theFeature) == myJustUpdated.end())
+          myJustUpdated.insert(theFeature);
+      } else {
+        aJustUpdated = myJustUpdated.find(theFeature) != myJustUpdated.end();
+      }
+    }
     //std::cout<<"Update feature "<<theFeature->getKind()<<" must be updated = "<<aMustbeUpdated<<std::endl;
     // execute feature if it must be updated
-    if (aMustbeUpdated) {
-      if (std::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures() ||
-          !theFeature->isPersistentResult()) {
+    if (aJustUpdated) {
+      if ((std::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures() ||
+          !theFeature->isPersistentResult()) && theFeature->isPreviewNeeded()) {
         if (aFactory->validate(theFeature)) {
           if (myIsAutomatic || 
-              (myJustCreatedOrUpdated.find(theFeature) != myJustCreatedOrUpdated.end()) ||
-              !theFeature->isPersistentResult() /* execute quick, not persistent results */) 
+              (myJustCreated.find(theFeature) != myJustCreated.end() ||
+              (myJustUpdated.find(theFeature) != myJustUpdated.end() && 
+               theFeature == theFeature->document()->currentFeature(false)) || // currently edited
+              !theFeature->isPersistentResult() /* execute quick, not persistent results */))
           {
-            if (aState == ModelAPI_StateDone) {// all referenced objects are ready to be used
-              //std::cout<<"Execute feature "<<theFeature->getKind()<<std::endl;
-              // before execution update the selection attributes if any
-              list<AttributePtr> aRefs = 
-                theFeature->data()->attributes(ModelAPI_AttributeSelection::typeId());
-              list<AttributePtr>::iterator aRefsIter = aRefs.begin();
-              for (; aRefsIter != aRefs.end(); aRefsIter++) {
-                std::shared_ptr<ModelAPI_AttributeSelection> aSel =
-                  std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*aRefsIter);
-                if (!aSel->update()) { // this must be done on execution since it may be long operation
-                  if (!aFactory->isNotObligatory(theFeature->getKind(), theFeature->data()->id(aSel)) &&
-                      aFactory->isCase(theFeature, theFeature->data()->id(aSel)))
-                    aState = ModelAPI_StateInvalidArgument;
-                }
-              }
-              aRefs = theFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
-              for (aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) {
-                std::shared_ptr<ModelAPI_AttributeSelectionList> aSel =
-                  std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*aRefsIter);
-                for(int a = aSel->size() - 1; a >= 0; a--) {
-                  std::shared_ptr<ModelAPI_AttributeSelection> aSelAttr =
-                    std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(aSel->value(a));
-                  if (aSelAttr) {
-                    if (!aSelAttr->update()) {
-                      if (!aFactory->isNotObligatory(
-                            theFeature->getKind(), theFeature->data()->id(aSel)) &&
-                          aFactory->isCase(theFeature, theFeature->data()->id(aSel)))
-                        aState = ModelAPI_StateInvalidArgument;
-                    }
-                  }
-                }
-              }
-              // for sketch after update of plane (by update of selection attribute)
-              // but before execute, all sub-elements also must be updated (due to the plane changes)
-              if (aComposite) {
-                // number of subs can be changed in execution: like fillet
-                for(int a = 0; a < aComposite->numberOfSubs(); a++) {
-                  FeaturePtr aSub = aComposite->subFeature(a);
-                  bool aWasModified = myUpdated[aSub];
-                  myUpdated.erase(myUpdated.find(aSub)); // erase to update for sure (plane may be changed)
-                  myInitial.insert(aSub);
-                  updateFeature(aSub);
-                  myUpdated[aSub] = aWasModified; // restore value
-                }
-                // re-execute after update: solver may update the previous values, so, shapes must be
-                // updated
-                for(int a = 0; a < aComposite->numberOfSubs(); a++) {
-                  if (aComposite->subFeature(a) && aFactory->validate(aComposite->subFeature(a)))
-                    aComposite->subFeature(a)->execute();
-                }
-              }
+            if (aState == ModelAPI_StateDone || aState == ModelAPI_StateMustBeUpdated) {
+              executeFeature(theFeature);
             }
-
-            // execute in try-catch to avoid internal problems of the feature
-            if (aState == ModelAPI_StateDone) {
-              theFeature->data()->execState(ModelAPI_StateDone);
-              try {
-                theFeature->execute();
-                if (theFeature->data()->execState() != ModelAPI_StateDone) {
-                  aState = ModelAPI_StateExecFailed;
-                }
-              } catch(...) {
-                aState = ModelAPI_StateExecFailed;
-                Events_Error::send(
-                  "Feature " + theFeature->getKind() + " has failed during the execution");
-              }
-            }
-            if (aState != ModelAPI_StateDone) {
-              theFeature->eraseResults();
-            }
-            redisplayWithResults(theFeature, aState);
           } else { // must be updatet, but not updated yet
             theFeature->data()->execState(ModelAPI_StateMustBeUpdated);
             const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
@@ -364,48 +384,30 @@ bool Model_Update::updateFeature(FeaturePtr theFeature)
       } else { // for automatically updated features (on abort, etc) it is necessary to redisplay anyway
         redisplayWithResults(theFeature, ModelAPI_StateNothing);
       }
-    } else {
-      // returns also true is results were updated: for sketch that 
-      // refers to sub-features but results of sub-features were changed
-      const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
-      std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
-      for (; aRIter != aResults.cend(); aRIter++) {
-        if (myInitial.find(*aRIter) != myInitial.end()) {
-          aMustbeUpdated = true;
-          break;
-        }
-      }
     }
   }
-  myUpdated[theFeature] = aMustbeUpdated;
-  return aMustbeUpdated;
 }
 
-bool Model_Update::updateObject(std::shared_ptr<ModelAPI_Object> theObject, const bool theCyclic)
+void Model_Update::executeFeature(FeaturePtr theFeature)
 {
-  if (myUpdated.find(theObject) != myUpdated.end())
-    return myUpdated[theObject];  // already processed
-
-  /*
-  if (theCyclic) { // algorithm for update of all features by dependencies tree
-    if (!theObject)
-      return false;
-    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
-    if (aFeature) {  // for feature just call update Feature
-      return updateFeature(aFeature);
-    }
-    // check general object, possible just a result
-    if (myUpdated.find(theObject) != myUpdated.end())
-      return myUpdated[theObject];  // already processed
-    // check the feature of this object must be executed
-    ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
-    if (aResult) {
-      FeaturePtr aResFeature = aResult->document()->feature(aResult);
-      if (aResFeature) {
-        return updateFeature(aResFeature);
-      }
+  // execute in try-catch to avoid internal problems of the feature
+  ModelAPI_ExecState aState = ModelAPI_StateDone;
+  theFeature->data()->execState(ModelAPI_StateDone);
+  try {
+    theFeature->execute();
+    if (theFeature->data()->execState() != ModelAPI_StateDone) {
+      aState = ModelAPI_StateExecFailed;
+    } else {
+      aState = ModelAPI_StateDone;
     }
+  } catch(...) {
+    aState = ModelAPI_StateExecFailed;
+    Events_Error::send(
+      "Feature " + theFeature->getKind() + " has failed during the execution");
   }
-  */
-  return myInitial.find(theObject) != myInitial.end();
+  if (aState != ModelAPI_StateDone) {
+    theFeature->eraseResults();
+  }
+  redisplayWithResults(theFeature, aState);
 }
+
index 6e09dc7ad324f83d670c4315d0e6e55a036a65bb..22fe573b9c061cc39282cd60d6b25f19f81a4e30 100644 (file)
@@ -23,18 +23,14 @@ class ModelAPI_Feature;
  */
 class Model_Update : public Events_Listener
 {
-  /// initial set of updated features that must be processed: caused by external changes, not
-  /// by sequence of update of this class
-  std::set<std::shared_ptr<ModelAPI_Object> > myInitial;
-  /// already updated and processed features and modificated feature flag
-  std::map<std::shared_ptr<ModelAPI_Object>, bool> myUpdated;
+  /// created features during this transaction: must be updated all the time
+  std::set<std::shared_ptr<ModelAPI_Object> > myJustCreated;
+  /// updated features during this transaction: must be updated in the end of transaction
+  std::set<std::shared_ptr<ModelAPI_Object> > myJustUpdated;
   /// to know that all next updates are caused by this execution
   bool myIsExecuted;
   /// to know execute or not automatically all update
   bool myIsAutomatic;
-  /// just created features: they must be updated immideately even in not-automatic mode for 
-  /// preview; cleared on commit operations
-  std::set<std::shared_ptr<ModelAPI_Object> > myJustCreatedOrUpdated;
 
  public:
   /// Is called only once, on startup of the application
@@ -48,14 +44,22 @@ protected:
   void updateInDoc(std::shared_ptr<ModelAPI_Document> theDoc);
   /// Recoursively checks and updates the feature if needed (calls the execute method)
   /// Returns true if feature was updated.
-  bool updateFeature(std::shared_ptr<ModelAPI_Feature> theFeature);
+  void updateFeature(std::shared_ptr<ModelAPI_Feature> theFeature);
+
+  /// Updates the selection and parametrical arguments before the later feature analysis
+  void updateArguments(std::shared_ptr<ModelAPI_Feature> theFeature);
 
-  /// Recoursively checks and updates the object (result or feature) if needed (calls updateFeature)
-  /// Returns true if object was updated.
-  bool updateObject(std::shared_ptr<ModelAPI_Object> theObject, const bool theCyclic = true);
   /// Sends the redisplay events for feature and results, updates the updated status
   void redisplayWithResults(std::shared_ptr<ModelAPI_Feature> theFeature, 
     const ModelAPI_ExecState theState);
+
+  /// On operation start/end/abort the "Just" fileds must be cleared and processed in the right way
+  /// \param theTotalUpdate force to updates everything that has been changed in this operation
+  void processOperation(const bool theTotalUpdate);
+
+  /// Performs the feature execution
+  /// \returns the status of execution
+  void executeFeature(std::shared_ptr<ModelAPI_Feature> theFeature);
 };
 
 #endif
index 0c23dc012860884f10790dd1e0fa675ecdbbdd65..5f2a841785ae112251131f4231d1aab47e84ecb4 100644 (file)
@@ -142,6 +142,7 @@ template<class T1, class T2> std::shared_ptr<T1> shared_ptr_cast(std::shared_ptr
 %template(modelAPI_ResultConstruction) shared_ptr_cast<ModelAPI_ResultConstruction, ModelAPI_Result>;
 %template(modelAPI_ResultBody) shared_ptr_cast<ModelAPI_ResultBody, ModelAPI_Result>;
 %template(modelAPI_ResultPart) shared_ptr_cast<ModelAPI_ResultPart, ModelAPI_Result>;
+%template(modelAPI_ResultParameter) shared_ptr_cast<ModelAPI_ResultParameter, ModelAPI_Result>;
 %template(modelAPI_ResultGroup) shared_ptr_cast<ModelAPI_ResultPart, ModelAPI_ResultGroup>;
 
 // Attribute casts
index 495da4180492d8eb36b9d62ba4d6e7978e6bd698..71c850e59830047483ded064f64885f76fd9bcd9 100644 (file)
@@ -42,7 +42,8 @@ class ModelAPI_AttributeSelection : public ModelAPI_Attribute
   MODELAPI_EXPORT virtual std::string attributeType();
 
   /// Returns a textual string of the selection
-  virtual std::string namingName() = 0;
+  /// \param theDefaultValue a value, which is used if the naming name can not be obtained
+  virtual std::string namingName(const std::string& theDefaultValue = "") = 0;
   
   /// Returns an id of the selection
   virtual int Id() = 0;
index ba5d1cd5ccd1d7ab26eb7c3e128aadea7e9bd7c3..5cad229fab9d0ca6f8603f9a1bb6aac653917185 100644 (file)
@@ -10,4 +10,3 @@ ModelAPI_CompositeFeature::~ModelAPI_CompositeFeature()
 {
 
 }
-
index a03a06c9bf9ff40a2c7c80cf4875558780ef2653..5d952ebfad0e004b8228e7e99a5a0120b30fe3d7 100644 (file)
@@ -147,6 +147,23 @@ class MODELAPI_EXPORT ModelAPI_Data
  protected:
   /// Objects are created for features automatically
   ModelAPI_Data();
+
+  /// Returns true if "is in history" custom behaviors is defined for the feature
+  virtual bool isInHistory() = 0;
+
+  /// Defines the custom "is in history" behavior
+  virtual void setIsInHistory(const bool theFlag) = 0;
+
+  /// Returns true if object must be displayed in the viewer: flag is stored in the
+  /// data model, so on undo/redo, open/save or recreation of object by history-playing it keeps
+  /// the original state i nthe current transaction.
+  virtual bool isDisplayed() = 0;
+
+  /// Sets the displayed/hidden state of the object. If it is changed, sends the "redisplay"
+  /// signal.
+  virtual void setDisplayed(const bool theDisplay) = 0;
+
+  friend class ModelAPI_Object;
 };
 
 typedef std::shared_ptr<ModelAPI_Data> DataPtr;
index 8093123bd4ee523c3b2c9e5da27dd9150b952e91..72a69e045c7bd51434f2f110a952521b9f2c08ef 100644 (file)
@@ -44,7 +44,9 @@ public:
 
   //! Adds to the document the new feature of the given feature id
   //! \param theID creates feature and puts it in the document (if it is not action)
-  virtual std::shared_ptr<ModelAPI_Feature> addFeature(std::string theID) = 0;
+  //! \param theMakeCurrent to make current this new feature in this document
+  virtual std::shared_ptr<ModelAPI_Feature> addFeature(std::string theID, 
+    const bool theMakeCurrent = true) = 0;
 
   //! Return a list of features, which refers to the feature
   //! \param theFeature a feature
@@ -67,10 +69,8 @@ public:
   //! Returns the object in the group by the index (started from zero)
   //! \param theGroupID group that contains an object
   //! \param theIndex zero-based index of feature in the group
-  //! \param theHidden if it is true, it counts also the features that are not in tree
   virtual std::shared_ptr<ModelAPI_Object> object(const std::string& theGroupID,
-                                                    const int theIndex,
-                                                    const bool theHidden = false) = 0;
+                                                    const int theIndex) = 0;
 
   //! Returns the first found object in the group by the object name
   //! \param theGroupID group that contains an object
@@ -79,9 +79,26 @@ public:
   virtual std::shared_ptr<ModelAPI_Object> objectByName(const std::string& theGroupID,
                                                     const std::string& theName) = 0;
 
+  //! Returns the object index in the group. Object must be visible. Otherwise returns -1.
+  //! \param theObject object of this document
+  //! \returns index started from zero, or -1 if object is invisible or belongs to another document
+  virtual const int index(std::shared_ptr<ModelAPI_Object> theObject) = 0;
+
   //! Returns the number of objects in the group of objects
-  //! If theHidden is true, it counts also the features that are not in tree
-  virtual int size(const std::string& theGroupID, const bool theHidden = false) = 0;
+  virtual int size(const std::string& theGroupID) = 0;
+
+  //! Returns the feature that is currently edited in this document, normally
+  //! this is the latest created feature
+  //! \param theVisible use visible features only: flag is true for Object Browser functionality
+  //! \returns null if next created feature must be the first
+  virtual std::shared_ptr<ModelAPI_Feature> currentFeature(const bool theVisible) = 0;
+
+  //! Sets the current feature: all features below will be disabled, new features
+  //! will be appended after this one.
+  //! \param theCurrent the selected feature as current: blow it everythin become disabled
+  //! \param theVisible use visible features only: flag is true for Object Browser functionality
+  virtual void setCurrentFeature(std::shared_ptr<ModelAPI_Feature> theCurrent,
+    const bool theVisible) = 0;
 
   /// To virtually destroy the fields of successors
   MODELAPI_EXPORT virtual ~ModelAPI_Document();
@@ -111,9 +128,12 @@ protected:
   MODELAPI_EXPORT ModelAPI_Document();
 
   /// Internally makes document know that feature was removed or added in history after creation
-  MODELAPI_EXPORT virtual void addToHistory(const std::shared_ptr<ModelAPI_Object> theObject) = 0;
+  MODELAPI_EXPORT virtual void updateHistory(const std::shared_ptr<ModelAPI_Object> theObject) = 0;
+  /// Internally makes document know that feature was removed or added in history after creation
+  MODELAPI_EXPORT virtual void updateHistory(const std::string theGroup) = 0;
 
   friend class ModelAPI_Object; // to add or remove from the history
+  friend class ModelAPI_Result; // to add or remove from the history
 };
 
 //! Pointer on document object
index 5127ad2b623fa1e9b044fdec42201226982f9a29..dbd088755502206ef3ce57e1cf4390110422115d 100644 (file)
@@ -85,7 +85,8 @@ std::list<std::string> ModelAPI_FeatureStateMessage::features() const
 }
 
 
-ModelAPI_DocumentCreatedMessage::ModelAPI_DocumentCreatedMessage(const Events_ID theID, const void* theSender)
+ModelAPI_DocumentCreatedMessage::ModelAPI_DocumentCreatedMessage(const Events_ID theID,
+                                                                 const void* theSender)
 : Events_Message(theID, theSender)
 {
 
@@ -105,3 +106,25 @@ void ModelAPI_DocumentCreatedMessage::setDocument(DocumentPtr theDocument)
 {
   myDocument = theDocument;
 }
+
+ModelAPI_AttributeEvalMessage::ModelAPI_AttributeEvalMessage(const Events_ID theID,
+                                                                         const void* theSender)
+: Events_Message(theID, theSender)
+{
+
+}
+
+ModelAPI_AttributeEvalMessage::~ModelAPI_AttributeEvalMessage()
+{
+
+}
+
+AttributePtr ModelAPI_AttributeEvalMessage::attribute() const
+{
+  return myAttribute;
+}
+
+void ModelAPI_AttributeEvalMessage::setAttribute(AttributePtr theDocument)
+{
+  myAttribute = theDocument;
+}
index 00e61330a7634b121fe47a5fc8361fe63229b7c1..89be2d89985c956e785d783abde00e6b0f93ed25 100644 (file)
@@ -10,6 +10,7 @@
 #include <ModelAPI.h>
 #include <ModelAPI_Object.h>
 #include <ModelAPI_Feature.h>
+#include <ModelAPI_Attribute.h>
 #include <Events_MessageGroup.h>
 #include <Events_Loop.h>
 
@@ -35,10 +36,6 @@ static const char * EVENT_OBJECT_TO_REDISPLAY = "ObjectsToRedisplay";
 static const char * EVENT_OPERATION_LAUNCHED = "OperationLaunched";
 /// Event ID that plugin is loaded (comes with ModelAPI_ObjectUpdatedMessage)
 static const char * EVENT_PLUGIN_LOADED = "PliginLoaded";
-/// Event ID that data of feature has to be shown (comes with ModelAPI_ObjectUpdatedMessage)
-static const char * EVENT_OBJECT_TOSHOW = "ObjectShow";
-/// Event ID that data of feature has to be shown (comes with ModelAPI_ObjectUpdatedMessage)
-static const char * EVENT_OBJECT_TOHIDE = "ObjectHide";
 //
 static const char * EVENT_DOCUMENT_CHANGED = "CurrentDocumentChanged";
 
@@ -167,4 +164,27 @@ class ModelAPI_DocumentCreatedMessage : public Events_Message
   MODELAPI_EXPORT void setDocument(DocumentPtr theDocument);
 };
 
+/// Message that attribute text should be evaluated in the attribute value
+class ModelAPI_AttributeEvalMessage : public Events_Message
+{
+  AttributePtr myAttribute;
+
+ public:
+  /// Creates an empty message
+  MODELAPI_EXPORT ModelAPI_AttributeEvalMessage(const Events_ID theID, const void* theSender = 0);
+  /// The virtual destructor
+  MODELAPI_EXPORT virtual ~ModelAPI_AttributeEvalMessage();
+  /// Static. Returns EventID of the message.
+  MODELAPI_EXPORT static Events_ID eventId()
+  {
+    static const char * MY_ATTRIBUTE_EVALUATION_EVENT_ID("AttributeEvaluationRequest");
+    return Events_Loop::eventByName(MY_ATTRIBUTE_EVALUATION_EVENT_ID);
+  }
+
+  /// Returns a document stored in the message
+  MODELAPI_EXPORT AttributePtr attribute() const;
+  /// Sets a document to the message
+  MODELAPI_EXPORT void setAttribute(AttributePtr theDocument);
+};
+
 #endif
index d9533e83e33d17c570bcc013ab65332f3be084dd..1fe0244f0d91aa4a654cf10bdf77d4a00668f4f3 100644 (file)
@@ -29,22 +29,27 @@ std::shared_ptr<ModelAPI_Result> ModelAPI_Feature::lastResult()
 
 void ModelAPI_Feature::setResult(const std::shared_ptr<ModelAPI_Result>& theResult)
 {
-  if (firstResult() == theResult) {  // just updated
-    static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
-    ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent);
-    return;
-  }
-  // created
-  while (!myResults.empty()) {  // remove one by one with messages
-    std::shared_ptr<ModelAPI_Result> aRes = *(myResults.begin());
-    myResults.erase(myResults.begin());
-    ModelAPI_EventCreator::get()->sendDeleted(aRes->document(), aRes->groupName());
+  static Events_Loop* aLoop = Events_Loop::loop();
+  static Events_ID EVENT_UPD = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+  static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
+
+  if (firstResult() == theResult) {
+    // nothing to change
+  } else if (!myResults.empty()) {  // all except first become disabled
+    std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
+    *aResIter = theResult;
+    aECreator->sendUpdated(theResult, EVENT_UPD);
+    for(aResIter++; aResIter != myResults.end(); aResIter++) {
+      (*aResIter)->setDisabled((*aResIter), true);
+    }
+  } else {
+    myResults.push_back(theResult);
   }
-  myResults.push_back(theResult);
-  static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
-  ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent);
-  // Create event for first Feature 
-  Events_Loop::loop()->flush(anEvent);
+  // in any case result becomes enabled
+  theResult->setDisabled(theResult, false);
+  // flush vidualisation changes
+  static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  aLoop->flush(aRedispEvent);
 }
 
 void ModelAPI_Feature::setResult(const std::shared_ptr<ModelAPI_Result>& theResult,
@@ -56,80 +61,51 @@ void ModelAPI_Feature::setResult(const std::shared_ptr<ModelAPI_Result>& theResu
   }
   if (aResIter == myResults.end()) {  // append
     myResults.push_back(theResult);
-    static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
-    ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent);
-    // Create event for first Feature, send it to make "created" earlier than "updated"
-    // VSV: Commenting out of this statement causes problems with circle operation for example
-    Events_Loop::loop()->flush(anEvent);
   } else {  // update
     *aResIter = theResult;
-    static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
-    ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent);
   }
+  theResult->setDisabled(theResult, false);
+  // flush visualisation changes
+  static Events_Loop* aLoop = Events_Loop::loop();
+  static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  aLoop->flush(aRedispEvent);
 }
 
 void ModelAPI_Feature::removeResult(const std::shared_ptr<ModelAPI_Result>& theResult)
 {
-  std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
-  for(; aResIter != myResults.end(); aResIter++) {
-    ResultPtr aRes = *aResIter;
-    if (aRes == theResult) {
-      std::string aGroup = aRes->groupName();
-      aRes->data()->erase();
-      myResults.erase(aResIter);
-
-      static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
-      static Events_Loop* aLoop = Events_Loop::loop();
-      static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-      static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
-      ModelAPI_EventCreator::get()->sendDeleted(document(), aGroup);
-      aECreator->sendUpdated(aRes, EVENT_DISP);
-      break;
-    }
-  }
+  theResult->setDisabled(theResult, true);
+  // flush visualisation changes
+  static Events_Loop* aLoop = Events_Loop::loop();
+  static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  aLoop->flush(aRedispEvent);
 }
 
-void ModelAPI_Feature::removeResults(const int theSinceIndex)
+void ModelAPI_Feature::removeResults(const int theSinceIndex, const bool theFlush)
 {
-  if (theSinceIndex == 0) {
-    eraseResults();
-    return;
-  }
-
   std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
   for(int anIndex = 0; anIndex < theSinceIndex && aResIter != myResults.end(); anIndex++)
     aResIter++;
   std::list<std::shared_ptr<ModelAPI_Result> >::iterator aNextIter = aResIter;
-  for(; aNextIter != myResults.end(); aNextIter++) {
-    static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
+  while( aNextIter != myResults.end()) {
+    // remove previously erased results: to enable later if needed only actual (of history change)
+    if (theSinceIndex == 0 && (*aNextIter)->isDisabled()) {
+      aNextIter = myResults.erase(aNextIter);
+    } else {
+      (*aNextIter)->setDisabled(*aNextIter, true); // just disable results
+      aNextIter++;
+    }
+  }
+  if (theFlush) {
+    // flush visualisation changes
     static Events_Loop* aLoop = Events_Loop::loop();
-    static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-    static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
-    ModelAPI_EventCreator::get()->sendDeleted(document(), (*aNextIter)->groupName());
-    aECreator->sendUpdated(*aNextIter, EVENT_DISP);
+    static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+    aLoop->flush(aRedispEvent);
   }
-  myResults.erase(aResIter, myResults.end());
 }
 
 void ModelAPI_Feature::eraseResults()
 {
-  if (!myResults.empty()) {
-    static Events_Loop* aLoop = Events_Loop::loop();
-    static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-    static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
-
-    std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
-    for(; aResIter != myResults.end(); aResIter++) {
-      (*aResIter)->data()->erase();
-      ModelAPI_EventCreator::get()->sendDeleted(document(), (*aResIter)->groupName());
-      aECreator->sendUpdated(*aResIter, EVENT_DISP);
-    }
-    myResults.clear();
-    // flush it to avoid left presentations after input of invalid arguments (radius=0)
-    static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
-    Events_Loop::loop()->flush(anEvent);
-    Events_Loop::loop()->flush(EVENT_DISP);
-  }
+  removeResults(0);
 }
 
 const std::string& ModelAPI_Feature::documentToAdd()
@@ -171,3 +147,36 @@ FeaturePtr ModelAPI_Feature::feature(ObjectPtr theObject)
   }
   return aFeature;
 }
+
+bool ModelAPI_Feature::isMacro() const
+{
+  return false;
+}
+
+bool ModelAPI_Feature::setDisabled(const bool theFlag)
+{
+  if (myIsDisabled != theFlag) {
+    myIsDisabled = theFlag;
+    if (myIsDisabled) {
+      removeResults(0, false); // flush will be in setCurrentFeature
+    } else {
+      // enable all disabled previously results
+      std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
+      for(; aResIter != myResults.end(); aResIter++) {
+        (*aResIter)->setDisabled(*aResIter, false);
+      }
+    }
+    return true;
+  }
+  return false;
+}
+
+bool ModelAPI_Feature::isDisabled() const
+{
+  return myIsDisabled;
+}
+
+bool ModelAPI_Feature::isPreviewNeeded() const
+{
+  return true;
+}
index 85ebe38b533d0c7ce3093fb575c3ebd67aa07b0b..436a1adbfec81f98050d257a3084e5993634eafe 100644 (file)
@@ -26,6 +26,8 @@ class ModelAPI_Feature : public ModelAPI_Object
 {
   ///< list of current results of this feature
   std::list<std::shared_ptr<ModelAPI_Result> > myResults;
+  ///< is feature disabled or not
+  bool myIsDisabled;
  public:
   /// Returns the unique kind of a feature (like "Point")
   virtual const std::string& getKind() = 0;
@@ -81,7 +83,9 @@ class ModelAPI_Feature : public ModelAPI_Object
   /// removes the result from the feature
   MODELAPI_EXPORT void removeResult(const std::shared_ptr<ModelAPI_Result>& theResult);
   /// removes all results starting from the gived index (zero-based)
-  MODELAPI_EXPORT void removeResults(const int theSinceIndex);
+  /// \param theSinceIndex - index of the deleted result and all after also will be deleted
+  /// \param theFlush - if it is false, REDISPLAY message is not flushed
+  MODELAPI_EXPORT void removeResults(const int theSinceIndex, const bool theFlush = true);
   /// removes all results from the feature
   MODELAPI_EXPORT void eraseResults();
   /// removes all fields from this feature: results, data, etc
@@ -98,10 +102,27 @@ class ModelAPI_Feature : public ModelAPI_Object
     return false;
   }
 
+  /// Returns true if this feature is used as macro: creates other features and then removed.
+  /// \returns false by default
+  MODELAPI_EXPORT virtual bool isMacro() const;
+
+  /// Returns true if preview update during the edition needed. Otherwise the update-mechanism
+  /// calls the \a execute function only on "apply" of the operation
+  /// \returns true by default
+  MODELAPI_EXPORT virtual bool isPreviewNeeded() const;
+
   /// Must return document where the new feature must be added to
   /// By default it is empty: it is added to the document this method is called to
   MODELAPI_EXPORT virtual const std::string& documentToAdd();
 
+  /// Enables/disables the feature. The disabled feature has no results and does not participate in
+  /// any calculation.
+  /// \returns true if state is really changed
+  MODELAPI_EXPORT virtual bool setDisabled(const bool theFlag);
+
+  /// Returns the feature is disabled or not.
+  MODELAPI_EXPORT virtual bool isDisabled() const;
+
   /// To virtually destroy the fields of successors
   MODELAPI_EXPORT virtual ~ModelAPI_Feature();
 
index 573b2d12fa83a7abf599b3b48e23ec5e35a83643..24a2b2d55c32740f5976a67d7bb7fc97c0f94b6b 100644 (file)
@@ -6,18 +6,26 @@
 
 #include "ModelAPI_Object.h"
 #include "ModelAPI_Document.h"
+#include "ModelAPI_Data.h"
+#include "ModelAPI_Events.h"
+#include <Events_Loop.h>
 
 bool ModelAPI_Object::isInHistory()
 {
-  return myInHistory;
+  if (myData.get() && myData->isValid()) {
+    return myData->isInHistory();
+  }
+  return true; // default value
 }
 
 void ModelAPI_Object::setInHistory(
   const std::shared_ptr<ModelAPI_Object> theObject, const bool theFlag)
 {
-  if (myInHistory != theFlag) {
-    myInHistory = theFlag;
-    myDoc->addToHistory(theObject);
+  if (isInHistory() != theFlag) {
+    if (myData.get() && myData->isValid()) {
+      myData->setIsInHistory(theFlag);
+    }
+    myDoc->updateHistory(theObject);
   }
 }
 
@@ -40,7 +48,7 @@ void ModelAPI_Object::attributeChanged(const std::string& theID)
 {
 }
 
-ModelAPI_Object::ModelAPI_Object() : myInHistory(true)
+ModelAPI_Object::ModelAPI_Object()
 {
 }
 
@@ -63,3 +71,13 @@ void ModelAPI_Object::erase()
   if (myData) myData->erase();
   setData(DataPtr());
 }
+
+bool ModelAPI_Object::isDisplayed()
+{
+  return myData->isDisplayed();
+}
+
+void ModelAPI_Object::setDisplayed(const bool theDisplay)
+{
+  myData->setDisplayed(theDisplay);
+}
index f04d10ad5da5c417579b140e78188980c76d471c..9d1d04c395f3cfb593370a51ee38a11cd12f2311 100644 (file)
@@ -28,7 +28,6 @@ class ModelAPI_Object
 {
   std::shared_ptr<ModelAPI_Data> myData;  ///< manager of the data model of a feature
   std::shared_ptr<ModelAPI_Document> myDoc;  ///< document this object belongs to
-  bool myInHistory; ///< keep the information about the presense of the object in the history tree
  public:
   /// By default object is displayed in the object browser.
   MODELAPI_EXPORT virtual bool isInHistory();
@@ -54,6 +53,9 @@ class ModelAPI_Object
   /// Request for initialization of data model of the object: adding all attributes
   virtual void initAttributes() = 0;
 
+  /// Returns the feature is disabled or not.
+  virtual bool isDisabled() const = 0;
+
   /// Called on change of any argument-attribute of this object
   /// \param theID identifier of changed attribute
   MODELAPI_EXPORT virtual void attributeChanged(const std::string& theID);
@@ -64,6 +66,15 @@ class ModelAPI_Object
   /// To use virtuality for destructors
   MODELAPI_EXPORT virtual ~ModelAPI_Object();
 
+  /// Returns true if object must be displayed in the viewer: flag is stored in the
+  /// data model, so on undo/redo, open/save or recreation of object by history-playing it keeps
+  /// the original state i nthe current transaction.
+  MODELAPI_EXPORT virtual bool isDisplayed();
+
+  /// Sets the displayed/hidden state of the object. If it is changed, sends the "redisplay"
+  /// signal.
+  MODELAPI_EXPORT virtual void setDisplayed(const bool theDisplay);
+
  protected:
   /// Sets the data manager of an object (document does)
   MODELAPI_EXPORT virtual void setData(std::shared_ptr<ModelAPI_Data> theData);
@@ -74,7 +85,7 @@ class ModelAPI_Object
   /// removes all fields from this feature
   MODELAPI_EXPORT virtual void erase();
 
-  friend class Model_Document;
+  friend class Model_Objects;
 
 };
 
index d435920149f5dc4e44a33c7421caae8750c59771..1816c54d990c9392093afc6958decc215000bf3c 100644 (file)
 
 ModelAPI_Result::~ModelAPI_Result()
 {
+}
 
+bool ModelAPI_Result::setDisabled(std::shared_ptr<ModelAPI_Result> theThis, const bool theFlag)
+{
+  if (myIsDisabled != theFlag) {
+    myIsDisabled = theFlag;
+    // this must be before "updated" message send to have history updated for OB update
+    document()->updateHistory(groupName()); // to update the history cash data in the document
+    // generate related events
+    static Events_Loop* aLoop = Events_Loop::loop();
+    static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
+    if (myIsDisabled) { // disabled result looks like removed
+      aECreator->sendDeleted(document(), groupName());
+    } else { // un-disabled equals to created
+      static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+      aECreator->sendUpdated(theThis, anEvent /*, false*/); // flush is in setCurrentFeature
+    }
+    static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+    aECreator->sendUpdated(theThis, EVENT_DISP/*, false*/); // flush is in setCurrentFeature
+    return true;
+  }
+  return false;
+}
+
+bool ModelAPI_Result::isDisabled() const
+{
+  return myIsDisabled;
 }
 
+void ModelAPI_Result::setIsConcealed(const bool theValue)
+{
+  if (myIsConcealed != theValue) {
+    myIsConcealed = theValue;
+    if (document().get()) // can be on creation of result
+      document()->updateHistory(groupName()); // to update the history cash data in the document
+  }
+}
+
+
 std::shared_ptr<GeomAPI_Shape> ModelAPI_Result::shape()
 {
   return std::shared_ptr<GeomAPI_Shape>();
index 472fe0056924b7b43f3658d172c19469438e9be2..dedee45d769f2d11c3687fbd49d5e736b946b2d3 100644 (file)
@@ -21,9 +21,12 @@ class ModelAPI_Feature;
 class ModelAPI_Result : public ModelAPI_Object
 {
   bool myIsConcealed; ///< the result is concealed from the data tree (referenced by other objects)
+  bool myIsDisabled; ///< the result is disabled: removed for the user, but keeps the general info
  public:
 
-  /// Reference to the color of the result
+  /// Reference to the color of the result.
+  /// The integer array is used. It contains tree values for red green and blue values. The values are in
+  /// [0, 255] range
   inline static const std::string& COLOR_ID()
   {
     static const std::string MY_COLOR_ID("Color");
@@ -37,10 +40,19 @@ class ModelAPI_Result : public ModelAPI_Object
   }
 
   /// Returns true if the result is concealed from the data tree (referenced by other objects)
-  inline void setIsConcealed(const bool theValue)
-  {
-    myIsConcealed = theValue;
-  }
+  MODELAPI_EXPORT void setIsConcealed(const bool theValue);
+
+  /// Enables/disables the result. The disabled result does not participate in any calculation
+  /// and visualization: like it was removed. But it keeps the general parameters: colors, 
+  /// visibility, etc.
+  /// \param theThis pointer to this object, needed to generate all events if it is neccessary
+  /// \param theFlag makes disabled if it is true
+  /// \returns true if state is really changed
+  MODELAPI_EXPORT virtual bool setDisabled(std::shared_ptr<ModelAPI_Result> theThis,
+    const bool theFlag);
+
+  /// Returns the result is disabled or not.
+  MODELAPI_EXPORT virtual bool isDisabled() const;
 
   // Retuns the parameters of color definition in the resources config manager
   virtual void colorConfigInfo(std::string& theSection, std::string& theName,
index 5c927e7d3eec56226d1b56c43e9e9cbe23acf550..47f6071810e4980069cec0671d47fde61f3e3bf1 100644 (file)
@@ -93,6 +93,9 @@ class MODELAPI_EXPORT ModelAPI_Session
   /// Returns all the opened documents of the session (without postponed)
   virtual std::list<std::shared_ptr<ModelAPI_Document> > allOpenedDocuments() = 0;
 
+  /// Returns true if document is not loaded yet
+  virtual bool isLoadByDemand(const std::string theDocID) = 0;
+
   /// Copies the document to the new one with the given id
   virtual std::shared_ptr<ModelAPI_Document> copy(std::shared_ptr<ModelAPI_Document> theSource,
                                                     std::string theID) = 0;
index 1d8e0bf10b089e5011efaf50f7b95f8b7283da82..1073922eef634e345372e1020a95115d70df8550 100644 (file)
@@ -12,6 +12,7 @@
 #include <ModelAPI_ResultParameter.h>
 
 #include <list>
+#include <map>
 
 namespace ModelAPI_Tools {
 
@@ -57,4 +58,99 @@ bool findVariable(const std::string& theName, double& outValue)
   return false;
 }
 
+static std::map<int, std::vector<int> > myColorMap;
+
+void appendValues(std::vector<int>& theRGB, const int theRed, const int theGreen, const int theBlue)
+{
+  theRGB.push_back(theRed);
+  theRGB.push_back(theGreen);
+  theRGB.push_back(theBlue);
+}
+
+bool containsValues(std::map<int, std::vector<int> >& theColorMap, std::vector<int>& theValues)
+{
+  std::map<int, std::vector<int> >::const_iterator anIt = theColorMap.begin(), aLast = theColorMap.end();
+  bool isFound = false;
+  for (; anIt != aLast && !isFound; anIt++) {
+    std::vector<int> aValues = anIt->second;
+    isFound = aValues[0] == theValues[0] &&
+              aValues[1] == theValues[1] &&
+              aValues[2] == theValues[2];
+  }
+  return isFound;
+}
+
+std::vector<int> HSVtoRGB(int theH, int theS, int theV)
+{
+  std::vector<int> aRGB;
+  if (theH < 0 || theH > 360 ||
+      theS < 0 || theS > 100 ||
+      theV < 0 || theV > 100)
+    return aRGB;
+
+  int aHi = (int)theH/60;
+
+  double aV = theV;
+  double aVmin = (100 - theS)*theV/100;
+
+  double anA = (theV - aVmin)* (theH % 60) / 60;
+
+  double aVinc = aVmin + anA;
+  double aVdec = theV - anA;
+
+  double aPercentToValue = 255./100;
+  int aV_int    = (int)(aV*aPercentToValue);
+  int aVinc_int = (int)(aVinc*aPercentToValue);
+  int aVmin_int = (int)(aVmin*aPercentToValue);
+  int aVdec_int = (int)(aVdec*aPercentToValue);
+
+  switch(aHi) {
+    case 0: appendValues(aRGB, aV_int,    aVinc_int, aVmin_int); break;
+    case 1: appendValues(aRGB, aVdec_int, aV_int,    aVmin_int); break;
+    case 2: appendValues(aRGB, aVmin_int, aV_int,    aVinc_int); break;
+    case 3: appendValues(aRGB, aVmin_int, aVdec_int, aV_int); break;
+    case 4: appendValues(aRGB, aVinc_int, aVmin_int, aV_int); break;
+    case 5: appendValues(aRGB, aV_int,    aVmin_int, aVdec_int); break;
+    default: break;
+  }
+  return aRGB;
+}
+
+
+void fillColorMap()
+{
+  if (!myColorMap.empty())
+    return;
+
+  int i = 0;
+  for (int s = 100; s > 0; s = s - 50)
+  {
+    for (int v = 100; v >= 40; v = v - 20)
+    {
+      for (int h = 0; h < 359 ; h = h + 60)
+      {
+        std::vector<int> aColor = HSVtoRGB(h, s, v);
+        if (containsValues(myColorMap, aColor))
+          continue;
+        myColorMap[i] = aColor;
+        i++;
+      }
+    }
+  }
+}
+
+void findRandomColor(std::vector<int>& theValues)
+{
+  theValues.clear();
+  if (myColorMap.empty()) {
+    fillColorMap();
+  }
+
+  int aSize = myColorMap.size();
+  int anIndex = rand() % aSize;
+  if (myColorMap.find(anIndex) != myColorMap.end()) {
+    theValues = myColorMap.at(anIndex);
+  }
+}
+
 } // namespace ModelAPI_Tools
index 9d63757ea0f5ee85d6ed85ccc6560e68d5108df8..e89a713ce23507f04d22c29243699f2600e14454 100644 (file)
@@ -11,6 +11,8 @@
 #include <ModelAPI_Result.h>
 #include <GeomAPI_Shape.h>
 
+#include <vector>
+
 namespace ModelAPI_Tools {
 /// Returns shape from the given Result object
 MODELAPI_EXPORT std::shared_ptr<GeomAPI_Shape> shape(const ResultPtr& theResult);
@@ -22,6 +24,12 @@ MODELAPI_EXPORT std::shared_ptr<GeomAPI_Shape> shape(const ResultPtr& theResult)
  */
 MODELAPI_EXPORT bool findVariable(const std::string& theName, double& outValue);
 
+/*!
+ * Returns the values of the next random color. The values are in range [0, 255]
+ * \param theValues a container of component of RGB value: red, green, blue
+ */
+MODELAPI_EXPORT void findRandomColor(std::vector<int>& theValues);
+
 }
 
 #endif
index d52f98a5207aa269d00169242262901985516c5a..c54208e1205b88f74a51fcd0b62e9efc913eb41f 100644 (file)
@@ -21,12 +21,12 @@ SET(PROJECT_HEADERS
        ModuleBase_IWorkshop.h
        ModuleBase_Definitions.h
        ModuleBase_SelectionValidator.h
-       ModuleBase_ISelection.h
        ModuleBase_ViewerPrs.h
        ModuleBase_WidgetChoice.h
        ModuleBase_WidgetFileSelector.h
        ModuleBase_DoubleSpinBox.h
        ModuleBase_IPropertyPanel.h
+       ModuleBase_ISelection.h
        ModuleBase_IViewer.h
        ModuleBase_WidgetLineEdit.h
        ModuleBase_WidgetMultiSelector.h
@@ -46,6 +46,8 @@ SET(PROJECT_HEADERS
        ModuleBase_WidgetValidated.h
        ModuleBase_WidgetExprEditor.h
        ModuleBase_ParamSpinBox.h
+       ModuleBase_WidgetIntValue.h
+    ModuleBase_IDocumentDataModel.h
 )
 
 SET(PROJECT_SOURCES
@@ -54,6 +56,7 @@ SET(PROJECT_SOURCES
        ModuleBase_FilterValidated.cpp
        ModuleBase_Tools.cpp
        ModuleBase_IModule.cpp
+       ModuleBase_ISelection.cpp
        ModuleBase_IWorkshop.cpp
        ModuleBase_Operation.cpp
        ModuleBase_OperationDescription.cpp
@@ -83,6 +86,7 @@ SET(PROJECT_SOURCES
        ModuleBase_WidgetExprEditor.cpp
        ModuleBase_ParamSpinBox.cpp
        ModuleBase_SelectionValidator.cpp
+       ModuleBase_WidgetIntValue.cpp
 )
 
 SET(PROJECT_LIBRARIES
diff --git a/src/ModuleBase/ModuleBase_IDocumentDataModel.h b/src/ModuleBase/ModuleBase_IDocumentDataModel.h
new file mode 100644 (file)
index 0000000..b18866e
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:        ModuleBase_IDocumentDataModel.h
+// Created:     28 Apr 2015
+// Author:      Vitaly SMETANNIKOV
+
+
+#ifndef ModuleBase_IDocumentDataModel_H
+#define ModuleBase_IDocumentDataModel_H
+
+#include "ModuleBase.h"
+#include <QAbstractItemModel>
+#include <ModelAPI_Object.h>
+
+class MODULEBASE_EXPORT ModuleBase_IDocumentDataModel : public QAbstractItemModel
+{
+Q_OBJECT
+public:
+  ModuleBase_IDocumentDataModel(QObject* theParent): QAbstractItemModel(theParent) {}
+
+  //! Returns an object by the given Model index.
+  //! Returns 0 if the given index is not index of an object
+  virtual ObjectPtr object(const QModelIndex& theIndex) const = 0;
+
+  //! Returns index of the object
+  //! \param theObject object to find
+  virtual QModelIndex objectIndex(const ObjectPtr theObject) const = 0;
+
+  //! Clear internal data
+  virtual void clear() {}
+
+  //! Rebuild data tree
+  virtual void rebuildDataTree() {}
+};
+
+#endif
\ No newline at end of file
index 7ba5cfe1e09693d931618d6f73c189f268fdc02e..1b3081dd976012fba8772e83870c09b9500b76f7 100644 (file)
@@ -23,6 +23,7 @@ class Config_WidgetAPI;
 class ModuleBase_ModelWidget;\r
 class ModuleBase_Operation;\r
 class ModuleBase_IWorkshop;\r
+class ModuleBase_IDocumentDataModel;\r
 \r
 /**\r
  * \ingroup GUI\r
@@ -78,11 +79,11 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject
   /// \param theMenu a popup menu to be shown in the viewer\r
   /// \param theStdActions a map of standard actions\r
   /// \return true if items are added and there is no necessity to provide standard menu\r
-  virtual bool addViewerItems(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const { return false; }\r
+  virtual bool addViewerMenu(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const { return false; }\r
 \r
   /// Add menu atems for object browser into the given menu\r
   /// \param theMenu a popup menu to be shown in the object browser\r
-  virtual void addObjectBrowserItems(QMenu* theMenu) const {};\r
+  virtual void addObjectBrowserMenu(QMenu* theMenu) const {};\r
 \r
   /// Called when it is necessary to update a command state (enable or disable it)\r
   //virtual bool isFeatureEnabled(const QString& theCmdId) const = 0;\r
@@ -120,6 +121,17 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject
   /// \returns true if the action is processed\r
   virtual bool deleteObjects() { return false; };\r
 \r
+  /// Returns data model object for representation of data tree in Object browser\r
+  virtual ModuleBase_IDocumentDataModel* dataModel() const = 0;\r
+\r
+  /// Returns a list of modes, where the AIS objects should be activated\r
+  /// \param theModes a list of modes\r
+  virtual void activeSelectionModes(QIntList& theModes) {}\r
+\r
+  /// This method is called on object browser creation for customisation of module specific features\r
+  /// \param theObjectBrowser a pinter on Object Browser widget\r
+  virtual void customizeObjectBrowser(QWidget* theObjectBrowser) {}\r
+\r
 public slots:\r
   /// Called on call of command corresponded to a feature\r
   void onFeatureTriggered();\r
index fe8a110e00e3577fa5c3fdd5a9be7cd909dfe74d..3a18c858b3b0c7d5031ca2daf8cacd9bcb080844 100644 (file)
@@ -35,6 +35,9 @@ public:
   /// Returns all property panel's widget created by WidgetFactory
   virtual const QList<ModuleBase_ModelWidget*>& modelWidgets() const = 0;
 
+  /// Removes all widgets in the widget area of the property panel
+  virtual void cleanContent() = 0;
+
   /// Editing mode depends on mode of current operation. This value is defined by it.
   /// \param isEditing state of editing mode flag
   virtual void setEditingMode(bool isEditing) { myIsEditing = isEditing; }
diff --git a/src/ModuleBase/ModuleBase_ISelection.cpp b/src/ModuleBase/ModuleBase_ISelection.cpp
new file mode 100644 (file)
index 0000000..1904476
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#include "ModuleBase_ISelection.h"
+
+QList<ModuleBase_ViewerPrs> ModuleBase_ISelection::getViewerPrs(const QObjectPtrList& theObjects)
+{
+  QList<ModuleBase_ViewerPrs> aSelectedPrs;
+  QObjectPtrList::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
+  for (; anIt != aLast; anIt++) {
+    ObjectPtr anObject = *anIt;
+    if (anObject.get() != NULL) {
+      aSelectedPrs.append(ModuleBase_ViewerPrs(anObject, TopoDS_Shape(), NULL));
+    }
+  }
+  return aSelectedPrs;
+}
index b2686be48496f03077af7524b2bb656e6d7e461c..86cfd4f527c5ef6ed7b404ef947b30b0f737cb5e 100644 (file)
@@ -70,6 +70,11 @@ class ModuleBase_ISelection
   virtual void selectedShapes(NCollection_List<TopoDS_Shape>& theList, 
     std::list<ObjectPtr>& theOwners) const = 0;
 
+  //! Wraps the object list into the viewer prs list
+  //! \param theObjects a list of objects
+  //! \return a list of prs, where only object is not empty
+  static MODULEBASE_EXPORT QList<ModuleBase_ViewerPrs> getViewerPrs(
+                                                       const QObjectPtrList& theObjects);
 };
 
 #endif
index 87da9de589b76ae6357534a30311acb75bb9ca89..229b6e2e3c55aac56022606073eac7c327deb6d1 100644 (file)
@@ -10,6 +10,7 @@
 #include "ModuleBase.h"
 #include "ModuleBase_Definitions.h"
 #include <ModuleBase_FilterValidated.h>
+#include <ModuleBase_ViewerPrs.h>
 
 #include <ModelAPI_Object.h>
 #include <GeomAPI_AISObject.h>
@@ -78,7 +79,7 @@ Q_OBJECT
 
   //! Select features clearing previous selection. 
   //! If the list is empty then selection will be cleared
-  virtual void setSelected(const QObjectPtrList& theFeatures) = 0;
+  virtual void setSelected(const QList<ModuleBase_ViewerPrs>& theValues) = 0;
 
 signals:
   /// Signal selection chaged.
index 8adb5bc7682306b89c2037bff1b43af353ecc8a0..a6ad2ca97fec81c3ff6e7b094fb99f6d4de81da1 100644 (file)
@@ -73,8 +73,9 @@ Q_OBJECT
 
   /// Set the given wrapped value to the current widget
   /// This value should be processed in the widget according to the needs
-  /// \param theValue the wrapped widget value
-  virtual bool setSelection(ModuleBase_ViewerPrs theValue)
+  /// \param theValues the wrapped selection values
+  /// \param thePosition an index in the list of values, the values should be get from the index
+  virtual bool setSelection(const QList<ModuleBase_ViewerPrs>& theValues, int& thePosition)
   {
     return false;
   }
index 1016d90e8e762decc26a335379bac3fbb1178789..ae623079c0d85b9071b6a3c6d2dcfdb0df5883ac 100644 (file)
@@ -64,14 +64,20 @@ FeaturePtr ModuleBase_Operation::feature() const
 
 bool ModuleBase_Operation::isValid() const
 {
-  if (!myFeature)
+  if (!myFeature || !myFeature->data().get())
     return true; // rename operation
   if (myFeature->isAction())
     return true;
   //Get validators for the Id
   SessionPtr aMgr = ModelAPI_Session::get();
   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
-  return aFactory->validate(myFeature);
+  bool aValid = aFactory->validate(myFeature);
+
+  // the feature exec state should be checked in order to do not apply features, which result can not
+  // be built. E.g. extrusion on sketch, where the "to" is a perpendicular plane to the sketch
+  bool isDone = myFeature->data()->execState() == ModelAPI_StateDone;
+
+  return aValid && isDone;
 }
 
 
@@ -131,7 +137,7 @@ void ModuleBase_Operation::start()
 {
   QString anId = getDescription()->operationId();
   if (myIsEditing) {
-      anId = anId.append(EditSuffix());
+    anId = anId.append(EditSuffix());
   }
   ModelAPI_Session::get()->startOperation(anId.toStdString());
 
@@ -146,6 +152,13 @@ void ModuleBase_Operation::start()
       return;
     }
   }
+  /// Set current feature and remeber old current feature
+  if (myIsEditing) {
+    SessionPtr aMgr = ModelAPI_Session::get();
+    DocumentPtr aDoc = aMgr->activeDocument();
+    myCurrentFeature = aDoc->currentFeature(true);
+    aDoc->setCurrentFeature(feature(), false);
+  }
 
   startOperation();
   emit started();
@@ -166,10 +179,19 @@ void ModuleBase_Operation::resume()
 
 void ModuleBase_Operation::abort()
 {
+  if (myIsEditing) {
+    SessionPtr aMgr = ModelAPI_Session::get();
+    DocumentPtr aDoc = aMgr->activeDocument();
+    aDoc->setCurrentFeature(myCurrentFeature, true);
+    myCurrentFeature = FeaturePtr();
+  }
   abortOperation();
   emit aborted();
 
   stopOperation();
+  // is is necessary to deactivate current widgets before the model operation is aborted
+  // because abort removes the feature and activated filters should not check it
+  propertyPanel()->cleanContent();
 
   ModelAPI_Session::get()->abortOperation();
   emit stopped();
@@ -178,14 +200,26 @@ void ModuleBase_Operation::abort()
 bool ModuleBase_Operation::commit()
 {
   if (canBeCommitted()) {
+    SessionPtr aMgr = ModelAPI_Session::get();
+    /// Set current feature and remeber old current feature
+    if (myIsEditing) {
+      DocumentPtr aDoc = aMgr->activeDocument();
+      bool aIsOp = aMgr->isOperation();
+      if (!aIsOp)
+        aMgr->startOperation();
+      aDoc->setCurrentFeature(myCurrentFeature, true);
+      if (!aIsOp)
+        aMgr->finishOperation();
+      myCurrentFeature = FeaturePtr();
+    }
     commitOperation();
     // check whether there are modifications performed during the current operation
     // in the model
     // in case if there are no modifications, do not increase the undo/redo stack
-    if (ModelAPI_Session::get()->isModified())
-      ModelAPI_Session::get()->finishOperation();
+    if (aMgr->isModified())
+      aMgr->finishOperation();
     else
-      ModelAPI_Session::get()->abortOperation();
+      aMgr->abortOperation();
 
     stopOperation();
     emit stopped();
@@ -216,19 +250,15 @@ void ModuleBase_Operation::activateByPreselection()
   
   ModuleBase_ModelWidget* aWgt, *aFilledWgt = 0;
   QList<ModuleBase_ModelWidget*>::const_iterator aWIt;
-  QList<ModuleBase_ViewerPrs>::const_iterator aPIt;
   bool isSet = false;
   // 1. apply the selection to controls
-  for (aWIt = aWidgets.constBegin(), aPIt = myPreSelection.constBegin();
-       (aWIt != aWidgets.constEnd()) && (aPIt != myPreSelection.constEnd());
-       ++aWIt) {
+  int aCurrentPosition = 0;
+  for (aWIt = aWidgets.constBegin(); aWIt != aWidgets.constEnd(); ++aWIt) {
     aWgt = (*aWIt);
-    ModuleBase_ViewerPrs aValue = (*aPIt);
     if (!aWgt->canSetValue())
       continue;
 
-    ++aPIt;
-    if (!aWgt->setSelection(aValue)) {
+    if (!aWgt->setSelection(myPreSelection, aCurrentPosition/*aValue*/)) {
       isSet = false;
       break;
     } else {
index c453e6b0616196a613694f90c9cd55214308dc3e..97e742eae9d3e346154ac63feb2c6043ab196486 100644 (file)
@@ -264,6 +264,8 @@ signals:
   /// before operation feature creating
   CompositeFeaturePtr myParentFeature;  
 
+  /// Last current feature before editing operation
+  FeaturePtr myCurrentFeature;
 };
 
 #endif
index 1631a8726977793d1572ab557a586a6466d98953..d50d3a594f08c08df1c6751299178909bf82a54c 100644 (file)
@@ -31,7 +31,10 @@ void ModuleBase_PageGroupBox::placeModelWidget(ModuleBase_ModelWidget* theWidget
 {
   const int kCol = 0;
   const int kRow = myMainLayout->count();
-  myMainLayout->addWidget(theWidget, kRow, kCol, Qt::AlignTop | Qt::AlignLeft);
+  // it seems, that the align on left is not necessary here, but leads to widgets, which are
+  // not extended on full width of the parent page. The case is grouped widgets in
+  // the sketch translation operation
+  myMainLayout->addWidget(theWidget, kRow, kCol, Qt::AlignTop);// | Qt::AlignLeft);
   myMainLayout->setRowStretch(kRow, 0);
 
 }
index 1fdad51d3682ff889c22d401bd96be370ce285e5..cce85ab35a9d451db0748d433ab27e9e4f678d1e 100644 (file)
@@ -83,12 +83,11 @@ void ModuleBase_ParamSpinBox::onTextChanged(const QString& text)
  */
 double ModuleBase_ParamSpinBox::valueFromText(const QString& theText) const
 {
-  if (!hasVariable(theText))
+  if (!hasVariable(theText)) {
     return ModuleBase_DoubleSpinBox::valueFromText(theText);
-
-  double aValue = 0;
-  findVariable(theText, aValue);
-  return aValue;
+  }
+  // small hack: return length of the string to iniiate valuesChanged signal
+  return theText.length();
 }
 
 QString ModuleBase_ParamSpinBox::textFromValue (double theValue) const
@@ -112,21 +111,8 @@ QValidator::State ModuleBase_ParamSpinBox::validate(QString& str, int& pos) cons
     return ModuleBase_DoubleSpinBox::validate(str, pos);
 
   QValidator::State res = QValidator::Invalid;
-
-  // Considering the input text as a variable name
-  // Applying Python identifier syntax:
-  // either a string starting with a letter, or a string starting with
-  // an underscore followed by at least one alphanumeric character
   if (isAcceptVariables()) {
-    QRegExp varNameMask("[_a-zA-Z][a-zA-Z0-9_]*");
-    if (varNameMask.exactMatch(str))
-      res = QValidator::Acceptable;
-
-    if (res == QValidator::Invalid) {
-      varNameMask.setPattern("_");
-      if (varNameMask.exactMatch(str))
-        res = QValidator::Intermediate;
-    }
+    res = QValidator::Acceptable;
   }
   return res;
 }
@@ -176,8 +162,8 @@ bool ModuleBase_ParamSpinBox::hasVariable() const
 
 bool ModuleBase_ParamSpinBox::hasVariable(const QString& theText) const
 {
-  QRegExp varNameMask("([a-z]|[A-Z]|_).*");
-  return varNameMask.exactMatch(theText);
+  QRegExp varNameMask("[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?");
+  return !varNameMask.exactMatch(theText);
 }
 
 /*!
index f97a9ed7f4cbabe15350fc9165530511dd40a6f8..c4a8fa2ef6367f87c75f330e2c9710d67dd52fdd 100644 (file)
@@ -262,7 +262,7 @@ void ModuleBase_PreferencesDlg::createViewerPage(int thePageId)
   myPreferences->setItemProperty("image_formats", aImgFiles, bgId);
 
   //Config_PropManager::registerProp("Visualization", "object_default_color", "Object color",
-  //                                 Config_Prop::Color, "#ffffff");
+  //                                 Config_Prop::Color, "225,225,225");
 
   Config_PropManager::registerProp("Visualization", "result_body_color", "Body color",
                                    Config_Prop::Color, Model_ResultBody::DEFAULT_COLOR());
index eb022a2bf0d853202e1a3180a9dee43da9aade9b..2f85e9a992f03f38b128adedf969a5700818f3b9 100644 (file)
@@ -64,6 +64,10 @@ void ModuleBase_ResultPrs::Compute(const Handle(PrsMgr_PresentationManager3d)& t
 void ModuleBase_ResultPrs::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
                                             const Standard_Integer aMode)
 {
+  if (aMode > TopAbs_SHAPE)
+    // In order to avoid using custom selection modes
+    return;
+
   if (myIsSketchMode) {
     if (aMode == TopAbs_FACE) {
       BRep_Builder aBuilder;
index 1d87b4ae22475427772f15b6eefe99eb075f9f67..5fa98fc5db0d58d8552e91a059219f65cfe97a00 100644 (file)
@@ -5,11 +5,13 @@
 // Author:      Vitaly Smetannikov
 
 #include "ModuleBase_Tools.h"
+#include <ModuleBase_ParamSpinBox.h>
 
 #include <ModelAPI_Result.h>
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Attribute.h>
 #include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_ResultParameter.h>
 
 #include <GeomDataAPI_Point2D.h>
 #include <Events_Error.h>
@@ -107,6 +109,13 @@ QPixmap lighter(const QString& theIcon, const int theLighterValue)
   return QPixmap::fromImage(aResult);
 }
 
+void setSpinText(ModuleBase_ParamSpinBox* theSpin, const QString& theText)
+{
+  bool isBlocked = theSpin->blockSignals(true);
+  theSpin->setText(theText);
+  theSpin->blockSignals(isBlocked);
+}
+
 void setSpinValue(QDoubleSpinBox* theSpin, double theValue)
 {
   bool isBlocked = theSpin->blockSignals(true);
@@ -179,6 +188,24 @@ TopAbs_ShapeEnum shapeType(const QString& theType)
   return TopAbs_SHAPE;
 }
 
+void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFeature, bool& hasParameter)
+{
+  hasResult = false;
+  hasFeature = false;
+  hasParameter = false;
+  foreach(ObjectPtr aObj, theObjects) {
+    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+    ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+    ResultParameterPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aResult);
+
+    hasResult = (aResult.get() != NULL);
+    hasFeature = (aFeature.get() != NULL);
+    hasParameter = (aConstruction.get() != NULL);
+    if (hasFeature && hasResult  && hasParameter)
+      break;
+  }
+}
+
 
 }
 
index 75c6b95fead59ea4ca584d3f93051389952b1304..410f01de2b77459e2df124391b060fbc968ec858 100644 (file)
@@ -8,6 +8,7 @@
 #define ModuleBase_Tools_H
 
 #include "ModuleBase.h"
+#include "ModuleBase_Definitions.h"
 
 #include <ModelAPI_Feature.h>
 #include <TopAbs_ShapeEnum.hxx>
@@ -17,6 +18,7 @@
 class QWidget;
 class QLayout;
 class QDoubleSpinBox;
+class ModuleBase_ParamSpinBox;
 
 namespace ModuleBase_Tools {
 
@@ -60,6 +62,11 @@ MODULEBASE_EXPORT QPixmap lighter(const QString& theIcon, const int theLighterVa
 /// \param theValue a new value
 MODULEBASE_EXPORT void setSpinValue(QDoubleSpinBox* theSpin, double theValue);
 
+/// Sets programmatically the value to the spin box without emitting any signals(e.g. valueChanged)
+/// \param theSpin an ModuleBase_ParamSpinBox that accepts text
+/// \param theText a new value
+MODULEBASE_EXPORT void setSpinText(ModuleBase_ParamSpinBox* theSpin, const QString& theText);
+
 /// Converts the object to the feature or a result and generate information string
 /// \param theObj an object
 /// \param isUseAttributesInfo a flag whether the attribute values information is used
@@ -71,6 +78,14 @@ MODULEBASE_EXPORT QString objectInfo(const ObjectPtr& theObj, const bool isUseAt
 /// \return TopAbs_ShapeEnum value
 MODULEBASE_EXPORT TopAbs_ShapeEnum shapeType(const QString& theType);
 
+/*!
+Check types of objects which are in the given list
+\param theObjects the list of objects
+\param hasResult will be set to true if list contains Result objects
+\param hasFeature will be set to true if list contains Feature objects
+\param hasParameter will be set to true if list contains Parameter objects
+*/
+MODULEBASE_EXPORT void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFeature, bool& hasParameter);
 }
 
 #endif
index 9e222e9869d3d007ef441173dc7b041830977705..38d47563f878fd24d725014ad6c0dbc1dfa23787 100644 (file)
@@ -4,27 +4,26 @@
 // Created:     04 June 2014
 // Author:      Vitaly Smetannikov
 
-#include <ModuleBase_WidgetDoubleValue.h>
-#include <ModuleBase_ParamSpinBox.h>
-#include <ModuleBase_Tools.h>
-
-#include <ModelAPI_AttributeDouble.h>
-#include <ModelAPI_AttributeString.h>
-#include <ModelAPI_Data.h>
-
 #include <Config_Keywords.h>
 #include <Config_WidgetAPI.h>
 
-#include <Events_Loop.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Object.h>
 #include <ModelAPI_Events.h>
 
-#include <QWidget>
+#include <ModuleBase_ParamSpinBox.h>
+#include <ModuleBase_Tools.h>
+#include <ModuleBase_WidgetDoubleValue.h>
+
 #include <QFormLayout>
 #include <QLabel>
-#include <QEvent>
-#include <QTimer>
+#include <QList>
+#include <QObject>
+#include <QPixmap>
+#include <QString>
 
-#include <math.h>
+#include <cfloat>
 
 #ifndef DBL_MAX
 #define DBL_MAX 1.7976931348623158e+308 
@@ -87,7 +86,7 @@ ModuleBase_WidgetDoubleValue::ModuleBase_WidgetDoubleValue(QWidget* theParent,
   mySpinBox->setToolTip(aTTip);
 
   aControlLay->addRow(myLabel, mySpinBox);
-  connect(mySpinBox, SIGNAL(valueChanged(double)), this, SIGNAL(valuesChanged()));
+  connect(mySpinBox, SIGNAL(valueChanged(const QString&)), this, SIGNAL(valuesChanged()));
 }
 
 ModuleBase_WidgetDoubleValue::~ModuleBase_WidgetDoubleValue()
@@ -106,7 +105,7 @@ void ModuleBase_WidgetDoubleValue::reset()
     // reset the value just if there is a default value definition in the XML definition
     // if the double value can not be found by the default value, do nothing
     if (isOk) {
-      ModuleBase_Tools::setSpinValue(mySpinBox, isOk ? aDefValue : 0.0);
+      ModuleBase_Tools::setSpinValue(mySpinBox, aDefValue);
       storeValueCustom();
     }
   }
@@ -116,14 +115,22 @@ bool ModuleBase_WidgetDoubleValue::storeValueCustom() const
 {
   DataPtr aData = myFeature->data();
   AttributeDoublePtr aReal = aData->real(attributeID());
-  aReal->setValue(mySpinBox->value());
-  std::string aTextRepr = aReal->text();
-  if (mySpinBox->hasVariable()) {
-    aTextRepr = mySpinBox->text().toStdString();
+  if (!mySpinBox->hasVariable()) {
+    aReal->setValue(mySpinBox->value());
+    // In order to synchronize value and text
+    // If it is not synchronized sometimes it could take vale not as a digit but as a string
+    aReal->setText(mySpinBox->text().toStdString());
   } else {
-    aTextRepr = "";
+    // Here is a text of a real value or an expression.
+    std::string aText = mySpinBox->text().toStdString();
+    aReal->setText(aText);
+    // Send it to evaluator to convert into the double and store in the attribute
+    static Events_ID anId = ModelAPI_AttributeEvalMessage::eventId();
+    std::shared_ptr<ModelAPI_AttributeEvalMessage> aMessage =
+      std::shared_ptr<ModelAPI_AttributeEvalMessage>(new ModelAPI_AttributeEvalMessage(anId, this));
+    aMessage->setAttribute(aData->attribute(attributeID()));
+    Events_Loop::loop()->send(aMessage);
   }
-  aReal->setText(aTextRepr);
   updateObject(myFeature);
   return true;
 }
@@ -134,9 +141,7 @@ bool ModuleBase_WidgetDoubleValue::restoreValue()
   AttributeDoublePtr aRef = aData->real(attributeID());
   std::string aTextRepr = aRef->text();
   if (!aTextRepr.empty()) {
-    bool isBlocked = mySpinBox->blockSignals(true);
-    mySpinBox->setText(QString::fromStdString(aTextRepr));
-    mySpinBox->blockSignals(isBlocked);
+    ModuleBase_Tools::setSpinText(mySpinBox, QString::fromStdString(aTextRepr));
   } else {
     ModuleBase_Tools::setSpinValue(mySpinBox, aRef->value());
   }
index aa612eb28329f114451a0d1553d679e36701bc3b..1c26b11ebf3b0aa43ee8ac060a66976cfa7c160a 100644 (file)
 
 #include <GeomDataAPI_Point2D.h>
 
-#include <QWidget>
-#include <QLineEdit>
-//#include <QTimer>
-#include <QDialog>
-#include <QLayout>
 #include <QApplication>
+#include <QLineEdit>
+#include <QMenu>
+#include <QWidget>
+#include <QWidgetAction>
+#include <QRegExp>
+#include <QRegExpValidator>
 
 ModuleBase_WidgetEditor::ModuleBase_WidgetEditor(QWidget* theParent,
                                                  const Config_WidgetAPI* theData,
@@ -39,27 +40,31 @@ ModuleBase_WidgetEditor::~ModuleBase_WidgetEditor()
 {
 }
 
-double editedValue(double theValue, bool& isDone)
+void editedValue(double& outValue, QString& outText)
 {
-  QDialog aDlg;
-  aDlg.setWindowFlags(Qt::FramelessWindowHint);
-  QHBoxLayout* aLay = new QHBoxLayout(&aDlg);
-  ModuleBase_Tools::zeroMargins(aLay);
+  QMenu* aPopup = new QMenu();
+
+  QLineEdit* aEditor = new QLineEdit(QString::number(outValue), aPopup);
+  QWidgetAction* aLineEditAction = new QWidgetAction(aPopup);
+  aLineEditAction->setDefaultWidget(aEditor);
+  aPopup->addAction(aLineEditAction);
 
-  QLineEdit* aEditor = new QLineEdit(QString::number(theValue), &aDlg);
+  aEditor->setFocus();
   aEditor->selectAll();
-  aEditor->setValidator(new QDoubleValidator(aEditor));
-  QObject::connect(aEditor, SIGNAL(returnPressed()), &aDlg, SLOT(accept()));
-  aLay->addWidget(aEditor);
-
-  QPoint aPoint = QCursor::pos();
-  aDlg.move(aPoint);
-
-  isDone = aDlg.exec() == QDialog::Accepted;
-  double aValue = theValue;
-  if (isDone)
-    aValue = aEditor->text().toDouble();
-  return aValue;
+  QString anExpression("([0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?)|([_a-zA-Z][a-zA-Z0-9_]*)");
+  aEditor->setValidator(new QRegExpValidator(QRegExp(anExpression), aEditor));
+  QObject::connect(aEditor, SIGNAL(returnPressed()), aLineEditAction, SIGNAL(triggered()));
+  QObject::connect(aLineEditAction, SIGNAL(triggered()), aPopup, SLOT(hide()));
+
+  QAction* aResult = aPopup->exec(QCursor::pos());
+  outText = aEditor->text();
+  bool isDouble;
+  double aValue = outText.toDouble(&isDouble);
+  if (isDouble) {
+    outValue = aValue;
+  //  outText = ""; // return empty string, if it's can be converted to a double
+  }
+  aPopup->deleteLater();
 }
 
 bool ModuleBase_WidgetEditor::focusTo()
@@ -86,25 +91,13 @@ void ModuleBase_WidgetEditor::showPopupEditor()
   // White while all events will be processed
   //QApplication::processEvents();
   double aValue = mySpinBox->value();
-  bool isDone;
-  aValue = editedValue(aValue, isDone);
-
-  if (isDone) {
+  QString aText;
+  editedValue(aValue, aText);
+  if (aText.isEmpty()) {
     ModuleBase_Tools::setSpinValue(mySpinBox, aValue);
+  } else {
+    ModuleBase_Tools::setSpinText(mySpinBox, aText);
   }
   emit valuesChanged();
   emit focusOutWidget(this);
 }
-
-void ModuleBase_WidgetEditor::editFeatureValue(FeaturePtr theFeature,
-                                               const std::string theAttribute)
-{
-  DataPtr aData = theFeature->data();
-  AttributeDoublePtr aRef = aData->real(theAttribute);
-  double aValue = aRef->value();
-
-  bool isDone;
-  aValue = editedValue(aValue, isDone);
-  if (isDone)
-    aRef->setValue(aValue);
-}
index c992e60f9c406f9aed6fcb823c9f980c05449abc..8bdf6f9e1d3e43a6acd35f556265b72e22a458ce 100644 (file)
@@ -43,11 +43,6 @@ Q_OBJECT
   /// \return the state whether the widget can accept the focus
   virtual bool focusTo();
 
-  /// Creates an editor for the real value and set the new value to the feature
-  /// \param theFeature the model feature
-  /// \param theAttribute the feature attribute
-  static void editFeatureValue(FeaturePtr theFeature, const std::string theAttribute);
-
  private slots:
    /// Shous popup window under cursor for data editing
    void showPopupEditor();
index c9561a13ba458fddc63d95e139bcaa1c7bc18fb1..2787b00acf3b0d97fd9921592528380e9a906b5d 100644 (file)
@@ -15,6 +15,7 @@
 #include <ModuleBase_WidgetSwitch.h>
 #include <ModuleBase_WidgetShapeSelector.h>
 #include <ModuleBase_WidgetDoubleValue.h>
+#include <ModuleBase_WidgetIntValue.h>
 #include <ModuleBase_WidgetBoolValue.h>
 #include <ModuleBase_WidgetFileSelector.h>
 #include <ModuleBase_WidgetChoice.h>
@@ -122,6 +123,8 @@ ModuleBase_ModelWidget* ModuleBase_WidgetFactory::createWidgetByType(const std::
     result = new ModuleBase_WidgetLabel(theParent, myWidgetApi, myParentId);
   } else if (theType == WDG_DOUBLEVALUE) {
     result = new ModuleBase_WidgetDoubleValue(theParent, myWidgetApi, myParentId);
+  } else if (theType == WDG_INTEGERVALUE) {
+    result = new ModuleBase_WidgetIntValue(theParent, myWidgetApi, myParentId);
   } else if (theType == WDG_SHAPE_SELECTOR) {
     result = new ModuleBase_WidgetShapeSelector(theParent, myWorkshop, myWidgetApi, myParentId);
   } else if (theType == WDG_BOOLVALUE) {
index ac79ba82330ead050dcd9f6b306741734b812950..3292d70f228ac8df147ad4f46f07cc449e47e85f 100644 (file)
 
 #include <Config_WidgetAPI.h>
 
-#include <QGridLayout>
 #include <QFileDialog>
+#include <QGridLayout>
+#include <QLabel>
 #include <QLineEdit>
 #include <QList>
 #include <QObject>
 #include <QPushButton>
+#include <QRegExp>
 #include <QString>
-#include <QLabel>
 
 #include <memory>
 #include <string>
@@ -35,6 +36,7 @@ ModuleBase_WidgetFileSelector::ModuleBase_WidgetFileSelector(QWidget* theParent,
     : ModuleBase_ModelWidget(theParent, theData, theParentId)
 {
   myTitle = QString::fromStdString(theData->getProperty("title"));
+  myType = (theData->getProperty("type") == "save") ? WFS_SAVE : WFS_OPEN;
   myDefaultPath = QString::fromStdString(theData->getProperty("path"));
 
   QGridLayout* aMainLay = new QGridLayout(this);
@@ -67,7 +69,7 @@ ModuleBase_WidgetFileSelector::~ModuleBase_WidgetFileSelector()
 bool ModuleBase_WidgetFileSelector::storeValueCustom() const
 {
   // A rare case when plugin was not loaded. 
-  if(!myFeature)
+  if (!myFeature)
     return false;
   DataPtr aData = myFeature->data();
   AttributeStringPtr aStringAttr = aData->string(attributeID());
@@ -80,7 +82,7 @@ bool ModuleBase_WidgetFileSelector::storeValueCustom() const
 bool ModuleBase_WidgetFileSelector::restoreValue()
 {
   // A rare case when plugin was not loaded. 
-  if(!myFeature)
+  if (!myFeature)
     return false;
   DataPtr aData = myFeature->data();
   AttributeStringPtr aStringAttr = aData->string(attributeID());
@@ -103,15 +105,19 @@ QList<QWidget*> ModuleBase_WidgetFileSelector::getControls() const
 
 bool ModuleBase_WidgetFileSelector::isCurrentPathValid()
 {
-  QFileInfo aFile (myPathField->text());
+  QFileInfo aFile(myPathField->text());
   return aFile.exists();
 }
 
-
 void ModuleBase_WidgetFileSelector::onPathSelectionBtn()
 {
-  QString aFilter = formatsString();
-  QString aFileName = QFileDialog::getOpenFileName(this, myTitle, myDefaultPath, aFilter);
+  QString aDefaultPath = myPathField->text().isEmpty()
+      ? myDefaultPath
+      : QFileInfo(myPathField->text()).absolutePath();
+  QString aFilter = filterString();
+  QString aFileName = (myType == WFS_SAVE)
+      ? QFileDialog::getSaveFileName(this, myTitle, aDefaultPath, aFilter, &mySelectedFilter)
+      : QFileDialog::getOpenFileName(this, myTitle, aDefaultPath, aFilter, &mySelectedFilter);
   if (!aFileName.isEmpty()) {
     myPathField->setText(aFileName);
   }
@@ -119,46 +125,52 @@ void ModuleBase_WidgetFileSelector::onPathSelectionBtn()
 
 void ModuleBase_WidgetFileSelector::onPathChanged()
 {
-  if(!isCurrentPathValid())
+  if (myType == WFS_OPEN && !isCurrentPathValid())
     return;
   storeValue();
   emit valuesChanged();
 }
 
-QString ModuleBase_WidgetFileSelector::formatsString() const
+QString ModuleBase_WidgetFileSelector::formatToFilter( const QString & theFormat )
 {
-  QStringList aResult;
-  QStringList aValidatorFormats = getValidatorFormats();
+  if (theFormat.isEmpty() && !theFormat.contains(":"))
+    return QString();
 
-  foreach(QString eachFormat, aValidatorFormats)  {
-    aResult << QString("%1 files (*.%1)").arg(eachFormat);
-  }
-  aResult << QString("All files (*.*)");
-  return aResult.join(";;");
+  QStringList aExtesionList = theFormat.section(':', 0, 0).split("|");
+  QString aFormat = theFormat.section(':', 1, 1);
+  return QString("%1 files (%2)").arg(aFormat)
+      .arg(QStringList(aExtesionList).replaceInStrings(QRegExp("^(.*)$"), "*.\\1").join(" "));
 }
 
 QStringList ModuleBase_WidgetFileSelector::getValidatorFormats() const
 {
   SessionPtr aMgr = ModelAPI_Session::get();
   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
+
   std::list<ModelAPI_Validator*> allValidators;
   std::list<std::list<std::string> > allArguments;
   aFactory->validators(myFeature->getKind(), myAttributeID, allValidators, allArguments);
-  //TODO(sbh): extract as separate method
-  if(allArguments.empty())
-    return QStringList();
+
+  QStringList aResult;
   std::list<std::string> anArgumentList = allArguments.front();
   std::list<std::string>::const_iterator it = anArgumentList.begin();
-  QStringList aResult;
   for (; it != anArgumentList.end(); ++it) {
-    std::string anArg = *it;
-    int aSepPos = anArg.find(":");
-    if (aSepPos == std::string::npos) {
-      continue;
-    }
-    QString aFormat = QString::fromStdString(anArg.substr(0, aSepPos));
-    aFormat = aFormat.toUpper();
-    aResult.append(aFormat);
+    QString aFormat = QString::fromStdString(*it);
+    if (!aFormat.isEmpty())
+      aResult << aFormat;
   }
   return aResult;
 }
+
+QString ModuleBase_WidgetFileSelector::filterString() const
+{
+  QStringList aResult;
+  QStringList aValidatorFormats = getValidatorFormats();
+
+  foreach(const QString & eachFormat, aValidatorFormats) {
+    aResult << formatToFilter(eachFormat);
+  }
+  if (myType == WFS_OPEN)
+    aResult << QString("All files (*.*)");
+  return aResult.join(";;");
+}
index 744770c61d9087afa07cfcb70cc5dd938a767939..2ddc684acc015d75b8320b8f51d3b2a5f7d84157 100644 (file)
@@ -27,6 +27,7 @@ class QLineEdit;
 *  \code
 *      <file_selector
 *          id="import_file_selector"
+*          type="open"
 *          title="Import file"
 *          path="">
 *          <validator id="ExchangePlugin_ImportFormat" parameters="BREP:BREPImport,STEP:STEPImport" />
@@ -66,20 +67,29 @@ protected:
   /// \return True in success
   virtual bool storeValueCustom() const;
 
- protected:
-   /// Returns string containing formats
-  QString formatsString() const;
+protected:
+  /// Converts format to filter string
+  static QString formatToFilter( const QString & theFormat );
 
-  /// Return list of validator formats
+  /// Returns list of validator formats
   QStringList getValidatorFormats() const;
 
- private:
+  /// Returns string containing formats
+  QString filterString() const;
+
+protected:
    /// A control for path input
   QLineEdit* myPathField;
 
   /// A title of open file dialog box
   QString myTitle;
 
+  /// A current format
+  QString mySelectedFilter;
+
+  /// A title of open file dialog box
+  enum { WFS_OPEN, WFS_SAVE } myType;
+
   /// Default path
   QString myDefaultPath;
 };
diff --git a/src/ModuleBase/ModuleBase_WidgetIntValue.cpp b/src/ModuleBase/ModuleBase_WidgetIntValue.cpp
new file mode 100644 (file)
index 0000000..aab5d1d
--- /dev/null
@@ -0,0 +1,139 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        ModuleBase_Widgets.h
+// Created:     04 June 2014
+// Author:      Vitaly Smetannikov
+
+#include <ModuleBase_WidgetIntValue.h>
+#include <ModuleBase_ParamSpinBox.h>
+#include <ModuleBase_Tools.h>
+
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_Data.h>
+
+#include <Config_Keywords.h>
+#include <Config_WidgetAPI.h>
+
+#include <Events_Loop.h>
+#include <ModelAPI_Events.h>
+
+#include <QWidget>
+#include <QFormLayout>
+#include <QLabel>
+#include <QEvent>
+#include <QTimer>
+#include <QSpinBox>
+
+#include <math.h>
+
+#ifndef INT_MAX
+#define INT_MAX   2147483647 
+#endif
+
+#ifdef _DEBUG
+#include <iostream>
+#endif
+
+ModuleBase_WidgetIntValue::ModuleBase_WidgetIntValue(QWidget* theParent,
+                                                           const Config_WidgetAPI* theData,
+                                                           const std::string& theParentId)
+    : ModuleBase_ModelWidget(theParent, theData, theParentId)
+{
+  QFormLayout* aControlLay = new QFormLayout(this);
+  ModuleBase_Tools::adjustMargins(aControlLay);
+
+  QString aLabelText = QString::fromStdString(theData->widgetLabel());
+  QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
+  myLabel = new QLabel(aLabelText, this);
+  if (!aLabelIcon.isEmpty())
+    myLabel->setPixmap(QPixmap(aLabelIcon));
+
+  mySpinBox = new QSpinBox(this);
+  QString anObjName = QString::fromStdString(attributeID());
+  mySpinBox->setObjectName(anObjName);
+
+  bool isOk = false;
+  std::string aProp = theData->getProperty(DOUBLE_WDG_MIN);
+  int aMinVal = QString::fromStdString(aProp).toInt(&isOk);
+  if (isOk) {
+    mySpinBox->setMinimum(aMinVal);
+  } else {
+    mySpinBox->setMinimum(-INT_MAX);
+  }
+
+  aProp = theData->getProperty(DOUBLE_WDG_MAX);
+  int aMaxVal = QString::fromStdString(aProp).toInt(&isOk);
+  if (isOk) {
+    mySpinBox->setMaximum(aMaxVal);
+  } else {
+    mySpinBox->setMaximum(INT_MAX);
+  }
+
+  aProp = theData->getProperty(DOUBLE_WDG_STEP);
+  int aStepVal = QString::fromStdString(aProp).toInt(&isOk);
+  if (isOk) {
+    mySpinBox->setSingleStep(aStepVal);
+  }
+
+  int aDefVal = QString::fromStdString(getDefaultValue()).toInt(&isOk);
+  if (isOk) {
+    mySpinBox->setValue(aDefVal);
+  }
+
+  QString aTTip = QString::fromStdString(theData->widgetTooltip());
+  mySpinBox->setToolTip(aTTip);
+
+  aControlLay->addRow(myLabel, mySpinBox);
+  connect(mySpinBox, SIGNAL(valueChanged(int)), this, SIGNAL(valuesChanged()));
+}
+
+ModuleBase_WidgetIntValue::~ModuleBase_WidgetIntValue()
+{
+}
+
+void ModuleBase_WidgetIntValue::reset()
+{
+  if (isComputedDefault()) {
+    return;
+    //if (myFeature->compute(myAttributeID))
+    //  restoreValue();
+  } else {
+    bool isOk;
+    int aDefValue = QString::fromStdString(getDefaultValue()).toInt(&isOk);
+    // reset the value just if there is a default value definition in the XML definition
+    // if the double value can not be found by the default value, do nothing
+    if (isOk) {
+      bool isBlocked = mySpinBox->blockSignals(true);
+      mySpinBox->setValue(isOk ? aDefValue : 0);
+      mySpinBox->blockSignals(isBlocked);
+      storeValueCustom();
+    }
+  }
+}
+
+bool ModuleBase_WidgetIntValue::storeValueCustom() const
+{
+  DataPtr aData = myFeature->data();
+  AttributeIntegerPtr aIntVal = aData->integer(attributeID());
+  int aVal = mySpinBox->value();
+  aIntVal->setValue(mySpinBox->value());
+  updateObject(myFeature);
+  return true;
+}
+
+bool ModuleBase_WidgetIntValue::restoreValue()
+{
+  DataPtr aData = myFeature->data();
+  AttributeIntegerPtr aRef = aData->integer(attributeID());
+  bool isBlocked = mySpinBox->blockSignals(true);
+  mySpinBox->setValue(aRef->value());
+  mySpinBox->blockSignals(isBlocked);
+  return true;
+}
+
+QList<QWidget*> ModuleBase_WidgetIntValue::getControls() const
+{
+  QList<QWidget*> aList;
+  aList.append(mySpinBox);
+  return aList;
+}
diff --git a/src/ModuleBase/ModuleBase_WidgetIntValue.h b/src/ModuleBase/ModuleBase_WidgetIntValue.h
new file mode 100644 (file)
index 0000000..b795bc1
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        ModuleBase_WidgetIntValue.h
+// Created:     04 June 2014
+// Author:      Vitaly Smetannikov
+
+#ifndef ModuleBase_WidgetIntValue_H
+#define ModuleBase_WidgetIntValue_H
+
+#include "ModuleBase.h"
+#include "ModuleBase_ModelWidget.h"
+
+class Config_WidgetAPI;
+class QWidget;
+class QLabel;
+class QTimer;
+class QSpinBox;
+
+/**
+* \ingroup GUI
+* A class of property panel widget for double value input
+* It can be defined with "doublevalue" keyword. For example:
+* \code
+* <doublevalue id="x" label="X:" icon=":pictures/x_point.png" tooltip="X coordinate"/>
+* \endcode
+*/
+class MODULEBASE_EXPORT ModuleBase_WidgetIntValue : public ModuleBase_ModelWidget
+{
+Q_OBJECT
+ public:
+  /// Constructor
+  /// \param theParent the parent object
+  /// \param theData the widget configuation. The attribute of the model widget is obtained from
+  /// \param theParentId is Id of a parent structure (widget, operation, group)
+  ModuleBase_WidgetIntValue(QWidget* theParent, const Config_WidgetAPI* theData,
+                               const std::string& theParentId);
+
+  virtual ~ModuleBase_WidgetIntValue();
+
+  /// Fills the widget with default values
+  virtual void reset();
+
+  //! Read value of corresponded attribute from data model to the input control
+  // \return True in success
+  virtual bool restoreValue();
+
+  /// Returns list of widget controls
+  /// \return a control list
+  virtual QList<QWidget*> getControls() const;
+
+
+protected:
+  /// Saves the internal parameters to the given feature
+  /// \return True in success
+  virtual bool storeValueCustom() const;
+
+protected:
+  /// Label of the widget
+  QLabel* myLabel;
+
+  /// Input value control
+  QSpinBox* mySpinBox;
+};
+
+#endif
index 57e2ce9492683be78fd14faa38f6fece0beee4ba..312183b9e0a5cdb5ea304c76616dc6335a40d019 100644 (file)
@@ -13,6 +13,7 @@
 #include <ModuleBase_IWorkshop.h>
 #include <ModuleBase_IViewer.h>
 #include <ModuleBase_Tools.h>
+#include <ModuleBase_Definitions.h>
 
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Object.h>
@@ -38,7 +39,7 @@ ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParen
                                                                const Config_WidgetAPI* theData,
                                                                const std::string& theParentId)
     : ModuleBase_WidgetValidated(theParent, theData, theParentId),
-      myWorkshop(theWorkshop), myIsActive(false)
+      myWorkshop(theWorkshop)
 {
   QGridLayout* aMainLay = new QGridLayout(this);
   ModuleBase_Tools::adjustMargins(aMainLay);
@@ -93,8 +94,8 @@ ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParen
 
 ModuleBase_WidgetMultiSelector::~ModuleBase_WidgetMultiSelector()
 {
-  myIsActive = false;
-  activateShapeSelection();
+  activateShapeSelection(false);
+  activateFilters(myWorkshop, false);
 }
 
 //********************************************************************
@@ -105,16 +106,20 @@ void ModuleBase_WidgetMultiSelector::activateCustom()
           this,       SLOT(onSelectionChanged()), 
           Qt::UniqueConnection);
 
-  myIsActive = true;
-  activateShapeSelection();
+  activateShapeSelection(true);
+
+  // Restore selection in the viewer by the attribute selection list
+  myWorkshop->setSelected(getAttributeSelection());
+
+  activateFilters(myWorkshop, true);
 }
 
 //********************************************************************
 void ModuleBase_WidgetMultiSelector::deactivate()
 {
   disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
-  myIsActive = false;
-  activateShapeSelection();
+  activateShapeSelection(false);
+  activateFilters(myWorkshop, false);
 }
 
 //********************************************************************
@@ -149,7 +154,8 @@ bool ModuleBase_WidgetMultiSelector::restoreValue()
 
   if (aSelectionListAttr) {
     // Restore shape type
-    setCurrentShapeType(ModuleBase_Tools::shapeType(aSelectionListAttr->selectionType().c_str()));
+    if (!aSelectionListAttr->selectionType().empty())
+      setCurrentShapeType(ModuleBase_Tools::shapeType(aSelectionListAttr->selectionType().c_str()));
     updateSelectionList(aSelectionListAttr);
     return true;
   }
@@ -194,6 +200,36 @@ void ModuleBase_WidgetMultiSelector::restoreAttributeValue(bool/* theValid*/)
   }
 }
 
+//********************************************************************
+bool ModuleBase_WidgetMultiSelector::setSelection(const QList<ModuleBase_ViewerPrs>& theValues,
+                                                  int& thePosition)
+{
+  if (thePosition < 0)
+    return false;
+
+  QList<ModuleBase_ViewerPrs>::const_iterator anIt = theValues.begin(), aLast = theValues.end();
+  bool isDone = false;
+  for (int i = thePosition; i < theValues.size(); i++) {
+    ModuleBase_ViewerPrs aValue = theValues[i];
+    thePosition++;
+    bool aProcessed = false;
+    if (isValidSelection(aValue)) {
+      aProcessed = setSelectionCustom(aValue);
+    }
+    // if there is at least one set, the result is true
+    isDone = isDone || aProcessed;
+    // when an object, which do not satisfy the validating process, stop set selection
+    if (!aProcessed)
+      break;
+  }
+  if (isDone) {
+    updateObject(myFeature);
+    // this emit is necessary to call store/restore method an restore type of selection
+    emit valuesChanged();
+  }
+  return isDone;
+}
+
 //********************************************************************
 bool ModuleBase_WidgetMultiSelector::setSelectionCustom(const ModuleBase_ViewerPrs& thePrs)
 {
@@ -270,8 +306,9 @@ bool ModuleBase_WidgetMultiSelector::eventFilter(QObject* theObj, QEvent* theEve
 //********************************************************************
 void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
 {
-  activateShapeSelection();
-  QObjectPtrList anEmptyList;
+  activateShapeSelection(true);
+  activateFilters(myWorkshop, true);
+  QList<ModuleBase_ViewerPrs> anEmptyList;
   // This method will call Selection changed event which will call onSelectionChanged
   // To clear mySelection, myListControl and storeValue()
   // So, we don't need to call it
@@ -310,23 +347,24 @@ void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const TopAbs_ShapeEnum
     aShapeTypeName = myTypeCombo->itemText(idx);
     TopAbs_ShapeEnum aRefType = ModuleBase_Tools::shapeType(aShapeTypeName);
     if(aRefType == theShapeType && idx != myTypeCombo->currentIndex()) {
-      myIsActive = false;
-      activateShapeSelection();
+      activateShapeSelection(false);
+      activateFilters(myWorkshop, false);
       bool isBlocked = myTypeCombo->blockSignals(true);
       myTypeCombo->setCurrentIndex(idx);
-      myIsActive = true;
       myTypeCombo->blockSignals(isBlocked);
-      activateShapeSelection();
+
+      activateShapeSelection(true);
+      activateFilters(myWorkshop, true);
       break;
     }
   }
 }
 
-void ModuleBase_WidgetMultiSelector::activateShapeSelection()
+void ModuleBase_WidgetMultiSelector::activateShapeSelection(const bool isActivated)
 {
   ModuleBase_IViewer* aViewer = myWorkshop->viewer();
 
-  if (myIsActive) {
+  if (isActivated) {
     QString aNewType = myTypeCombo->currentText();
     QIntList aList;
     aList.append(ModuleBase_Tools::shapeType(aNewType));
@@ -334,8 +372,32 @@ void ModuleBase_WidgetMultiSelector::activateShapeSelection()
   } else {
     myWorkshop->deactivateSubShapesSelection();
   }
+}
 
-  activateFilters(myWorkshop, myIsActive);
+QList<ModuleBase_ViewerPrs> ModuleBase_WidgetMultiSelector::getAttributeSelection() const
+{
+  QList<ModuleBase_ViewerPrs> aSelected;
+  // Restore selection in the viewer by the attribute selection list
+  if(myFeature) {
+    DataPtr aData = myFeature->data();
+    AttributeSelectionListPtr aListAttr = 
+      std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aData->attribute(attributeID()));
+    if (aListAttr) {
+      for (int i = 0; i < aListAttr->size(); i++) {
+        AttributeSelectionPtr anAttr = aListAttr->value(i);
+        ResultPtr anObject = anAttr->context();
+        if (anObject.get()) {
+          TopoDS_Shape aShape;
+          std::shared_ptr<GeomAPI_Shape> aShapePtr = anAttr->value();
+          if (aShapePtr.get()) {
+            aShape = aShapePtr->impl<TopoDS_Shape>();
+          }
+          aSelected.append(ModuleBase_ViewerPrs(anObject, aShape, NULL));
+        }
+      }
+    }
+  }
+  return aSelected;
 }
 
 //********************************************************************
index cc702f6a129f0da3763c4e498e26bb4c6e84eeab..033b260b4888c3912ea80ef46cb338fd3cee7407 100644 (file)
@@ -72,6 +72,12 @@ class MODULEBASE_EXPORT ModuleBase_WidgetMultiSelector : public ModuleBase_Widge
   /// The methiod called when widget is deactivated
   virtual void deactivate();
 
+  /// Set the given wrapped value to the current widget
+  /// This value should be processed in the widget according to the needs
+  /// \param theValues the wrapped selection values
+  /// \param thePosition an index in the list of values, the values should be get from the index
+  virtual bool setSelection(const QList<ModuleBase_ViewerPrs>& theValues, int& thePosition);
+
   /// Fills the attribute with the value of the selected owner
   /// \param theOwner a selected owner
   virtual bool setSelectionCustom(const ModuleBase_ViewerPrs& thePrs);
@@ -113,7 +119,13 @@ protected slots:
   void setCurrentShapeType(const TopAbs_ShapeEnum theShapeType);
 
   /// Start shape selection
-  void activateShapeSelection();
+  /// \param isActivated a state whether the shape is activated or deactivated in selection
+  void activateShapeSelection(const bool isActivated);
+
+  /// Return the attribute values wrapped in a list of viewer presentations
+  /// \return a list of viewer presentations, which contains an attribute result and
+  /// a shape. If the attribute do not uses the shape, it is empty
+  QList<ModuleBase_ViewerPrs> getAttributeSelection() const;
 
  protected:
    /// Update selection list
@@ -128,9 +140,6 @@ protected slots:
   //TODO: Move into the base of selectors
   ModuleBase_IWorkshop* myWorkshop;
 
-  /// If true then local selector has to be activated in context
-  bool myIsActive;
-
   /// Provides correspondance between Result object and its shape
   typedef QPair<ResultPtr, GeomShapePtr> GeomSelection;
 
index 73035992a958d7bf425c8140479a8a13873f685b..785e98b4141f73de40e9fbe431f8e9ee1d31ca67 100644 (file)
@@ -71,7 +71,7 @@ ModuleBase_WidgetShapeSelector::ModuleBase_WidgetShapeSelector(QWidget* theParen
                                                      const Config_WidgetAPI* theData,
                                                      const std::string& theParentId)
     : ModuleBase_WidgetValidated(theParent, theData, theParentId),
-      myWorkshop(theWorkshop), myIsActive(false)
+      myWorkshop(theWorkshop)
 {
   QFormLayout* aLayout = new QFormLayout(this);
   ModuleBase_Tools::adjustMargins(aLayout);
@@ -99,6 +99,7 @@ ModuleBase_WidgetShapeSelector::ModuleBase_WidgetShapeSelector(QWidget* theParen
 ModuleBase_WidgetShapeSelector::~ModuleBase_WidgetShapeSelector()
 {
   activateSelection(false);
+  activateFilters(myWorkshop, false);
 }
 
 //********************************************************************
@@ -145,6 +146,26 @@ bool ModuleBase_WidgetShapeSelector::setObject(ObjectPtr theSelectedObject,
   return isChanged;
 }
 
+//********************************************************************
+QList<ModuleBase_ViewerPrs> ModuleBase_WidgetShapeSelector::getAttributeSelection() const
+{
+  QList<ModuleBase_ViewerPrs> aSelected;
+  if(myFeature) {
+    DataPtr aData = myFeature->data();
+    AttributePtr anAttribute = myFeature->attribute(attributeID());
+
+    ObjectPtr anObject = GeomValidators_Tools::getObject(anAttribute);
+    TopoDS_Shape aShape;
+    std::shared_ptr<GeomAPI_Shape> aShapePtr = getShape();
+    if (aShapePtr.get()) {
+      aShape = aShapePtr->impl<TopoDS_Shape>();
+    }
+    ModuleBase_ViewerPrs aPrs(anObject, aShape, NULL);
+    aSelected.append(aPrs);
+  }
+  return aSelected;
+}
+
 //********************************************************************
 void ModuleBase_WidgetShapeSelector::clearAttribute()
 {
@@ -186,61 +207,26 @@ QList<QWidget*> ModuleBase_WidgetShapeSelector::getControls() const
 //********************************************************************
 void ModuleBase_WidgetShapeSelector::onSelectionChanged()
 {
-  // In order to make reselection possible
-  // TODO: check with MPV clearAttribute();
+  // In order to make reselection possible, set empty object and shape should be done
+  setObject(ObjectPtr(), std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape()));
 
+  bool aHasObject = false;
   QList<ModuleBase_ViewerPrs> aSelectedPrs = getSelectedEntitiesOrObjects(myWorkshop->selection());
-  if (aSelectedPrs.empty())
-    return;
-  ModuleBase_ViewerPrs aPrs = aSelectedPrs.first();
-  if (aPrs.isEmpty() || !isValidSelection(aPrs))
-    return;
-
-  if (!aPrs.isEmpty() && isValidSelection(aPrs)) {
-    setSelectionCustom(aPrs);
-    // the updateObject method should be called to flush the updated sigal. The workshop listens it,
-    // calls validators for the feature and, as a result, updates the Apply button state.
-    updateObject(myFeature);
-    //if (theObj) {
-      //  raisePanel();
-    //} 
-    //updateSelectionName();
-    //emit valuesChanged();
-    emit focusOutWidget(this);
+  if (!aSelectedPrs.empty()) {
+    ModuleBase_ViewerPrs aPrs = aSelectedPrs.first();
+    if (!aPrs.isEmpty() && isValidSelection(aPrs)) {
+      setSelectionCustom(aPrs);
+      aHasObject = true;
+    }
   }
-
+  // the updateObject method should be called to flush the updated sigal. The workshop listens it,
+  // calls validators for the feature and, as a result, updates the Apply button state.
+  updateObject(myFeature);
+  // the widget loses the focus only if the selected object is set
+  if (aHasObject)
+    emit focusOutWidget(this);
 }
 
-//********************************************************************
-//bool ModuleBase_WidgetShapeSelector::acceptObjectShape(const ObjectPtr theResult) const
-//{
-//  ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theResult);
-//
-//  // Check that the shape of necessary type
-//  std::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(aResult);
-//  if (!aShapePtr)
-//    return false;
-//  TopoDS_Shape aShape = aShapePtr->impl<TopoDS_Shape>();
-//  if (aShape.IsNull())
-//    return false;
-//
-//  TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
-//  if (aShapeType == TopAbs_COMPOUND) {
-//    foreach (QString aType,
-//      myShapeTypes) {
-//      TopExp_Explorer aEx(aShape, shapeType(aType));
-//      if (aEx.More())
-//        return true;
-//    }
-//  } else {
-//    foreach (QString aType, myShapeTypes) {
-//      if (shapeType(aType) == aShapeType)
-//        return true;
-//    }
-//  }
-//  return false;
-//}
-
 //********************************************************************
 bool ModuleBase_WidgetShapeSelector::acceptSubShape(std::shared_ptr<GeomAPI_Shape> theShape) const
 {
@@ -277,7 +263,7 @@ void ModuleBase_WidgetShapeSelector::updateSelectionName()
   bool isNameUpdated = false;
   AttributeSelectionPtr aSelect = aData->selection(attributeID());
   if (aSelect) {
-    myTextLine->setText(QString::fromStdString(aSelect->namingName()));
+    myTextLine->setText(QString::fromStdString(aSelect->namingName(getDefaultValue())));
     isNameUpdated = true;
   }
   if (!isNameUpdated) {
@@ -296,8 +282,8 @@ void ModuleBase_WidgetShapeSelector::updateSelectionName()
           myTextLine->setText(QString::fromStdString(aName.str()));
         }
       }
-      else if (myIsActive) {
-        myTextLine->setText("");
+      else {
+        myTextLine->setText(getDefaultValue().c_str());
       }
     }
   }
@@ -307,12 +293,9 @@ void ModuleBase_WidgetShapeSelector::updateSelectionName()
 //********************************************************************
 void ModuleBase_WidgetShapeSelector::activateSelection(bool toActivate)
 {
-  if (myIsActive == toActivate)
-    return;
-  myIsActive = toActivate;
   updateSelectionName();
 
-  if (myIsActive) {
+  if (toActivate) {
     QIntList aList;
     foreach (QString aType, myShapeTypes) {
       aList.append(ModuleBase_Tools::shapeType(aType));
@@ -321,8 +304,6 @@ void ModuleBase_WidgetShapeSelector::activateSelection(bool toActivate)
   } else {
     myWorkshop->deactivateSubShapesSelection();
   }
-
-  activateFilters(myWorkshop, myIsActive);
 }
 
 //********************************************************************
@@ -347,6 +328,11 @@ void ModuleBase_WidgetShapeSelector::activateCustom()
 {
   connect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
   activateSelection(true);
+
+  // Restore selection in the viewer by the attribute selection list
+  myWorkshop->setSelected(getAttributeSelection());
+
+  activateFilters(myWorkshop, true);
 }
 
 //********************************************************************
@@ -438,5 +424,6 @@ bool ModuleBase_WidgetShapeSelector::setSelectionCustom(const ModuleBase_ViewerP
 void ModuleBase_WidgetShapeSelector::deactivate()
 {
   activateSelection(false);
+  activateFilters(myWorkshop, false);
   disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
 }
index bf0fb6800d39f5d4b5029b6b29d53ee6aba28c6e..2dcd3662d1fa3457edf6be3d096680d4a8f34ea6 100644 (file)
@@ -122,10 +122,6 @@ Q_OBJECT
   /// \param theShape a shape
   virtual bool acceptSubShape(std::shared_ptr<GeomAPI_Shape> theShape) const;
 
-  // Get the shape from the attribute it the attribute contain a shape, e.g. selection attribute
-  /// \return a shape
-  GeomShapePtr getShape() const;
-
   /// Clear attribute
   void clearAttribute();
 
@@ -136,6 +132,15 @@ Q_OBJECT
   /// \return true if it is succeed
   virtual bool setObject(ObjectPtr theSelectedObject, GeomShapePtr theShape);
 
+  /// Get the shape from the attribute if the attribute contains a shape, e.g. selection attribute
+  /// \return a shape
+  virtual GeomShapePtr getShape() const;
+
+  /// Return the attribute values wrapped in a list of viewer presentations
+  /// \return a list of viewer presentations, which contains an attribute result and
+  /// a shape. If the attribute do not uses the shape, it is empty
+  QList<ModuleBase_ViewerPrs> getAttributeSelection() const;
+
   //----------- Class members -------------
   protected:
   /// Label of the widget
@@ -150,9 +155,6 @@ Q_OBJECT
   /// List of accepting shapes types
   QStringList myShapeTypes;
 
-  /// Active/inactive flag
-  bool myIsActive;
-
   /// backup parameters of the model attribute. The class processes three types of attribute:
   /// Reference, RefAttr and Selection. Depending on the attribute type, only the attribute parameter
   /// values are reserved in the backup
index caadc6be7582cc17eb8121963161c657c171b058..4dcf23973ff31c7239325deba633f9aa06dfabf9 100644 (file)
@@ -29,12 +29,17 @@ ModuleBase_WidgetValidated::~ModuleBase_WidgetValidated()
 }
 
 //********************************************************************
-bool ModuleBase_WidgetValidated::setSelection(ModuleBase_ViewerPrs theValue)
+bool ModuleBase_WidgetValidated::setSelection(const QList<ModuleBase_ViewerPrs>& theValues, int& thePosition)
 {
+  if (thePosition < 0 || thePosition >= theValues.size())
+    return false;
+  ModuleBase_ViewerPrs aValue = theValues[thePosition];
+  thePosition++;
+
   bool isDone = false;
 
-  if (isValidSelection(theValue)) {
-    isDone = setSelectionCustom(theValue);
+  if (isValidSelection(aValue)) {
+    isDone = setSelectionCustom(aValue);
     updateObject(myFeature);
     emit valuesChanged();
   }
@@ -131,13 +136,7 @@ QList<ModuleBase_ViewerPrs> ModuleBase_WidgetValidated::getSelectedEntitiesOrObj
   if (aSelectedPrs.empty()) {
     // the selection in Object Browser
     QObjectPtrList anObjects = theSelection->selectedObjects();
-    QObjectPtrList::const_iterator anIt = anObjects.begin(), aLast = anObjects.end();
-    for (; anIt != aLast; anIt++) {
-      ObjectPtr anObject = *anIt;
-      if (anObject.get() != NULL) {
-        aSelectedPrs.append(ModuleBase_ViewerPrs(anObject, TopoDS_Shape(), NULL));
-      }
-    }
+    aSelectedPrs = ModuleBase_ISelection::getViewerPrs(anObjects);
   }
   return aSelectedPrs;
 }
index 8c05cbb046a64055f2bf67cee0ec5aa0d22c5c2b..95f558029661cddad8f1bd80aafaa1a936600933 100644 (file)
@@ -48,8 +48,9 @@ class MODULEBASE_EXPORT ModuleBase_WidgetValidated : public ModuleBase_ModelWidg
   /// This value should be processed in the widget according to the needs
   /// The method is called by the current operation to process the operation preselection.
   /// It is redefined to check the value validity and if it is, fill the attribute with by value
-  /// \param theValue the wrapped widget value
-  virtual bool setSelection(ModuleBase_ViewerPrs theValue);
+  /// \param theValues the wrapped selection values
+  /// \param thePosition an index in the list of values, the values should be get from the index
+  virtual bool setSelection(const QList<ModuleBase_ViewerPrs>& theValues, int& thePosition);
 
 protected:
   /// Creates a backup of the current values of the attribute
index cddf1a2a0307f1c6850b378cc4d94ee83eedc948..88d61de5bbb4f0f32c2a65d8bc39d4ebfba2445d 100644 (file)
@@ -506,7 +506,7 @@ void NewGeom_Module::selectionChanged()
 //******************************************************
 void NewGeom_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
 {
-  myWorkshop->contextMenuMgr()->addViewerItems(theMenu);
+  myWorkshop->contextMenuMgr()->addViewerMenu(theMenu);
   LightApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
 }
 
index ff42227ce6a4229c1da45e2c4539287324ae69e0..787390bff336a7c2c298de9c8f4b36d17138a64a 100644 (file)
@@ -46,6 +46,9 @@ QWidget * NewGeom_NestedButton::createWidget(QWidget * theParent)
   QHBoxLayout* aBoxLay = new QHBoxLayout(myButtonFrame);
   aBoxLay->setContentsMargins(2, 0, 0, 0);
   aBoxLay->setSpacing(1);
+  QSizePolicy aSizePolicy;
+  aSizePolicy.setControlType(QSizePolicy::ToolButton);
+  myButtonFrame->setSizePolicy(aSizePolicy);
 
   myThisButton = new QToolButton(myButtonFrame);
   myThisButton->setDefaultAction(this);
index 86e2d8f1b2e5b61d42ce62c760279ed70a5676a8..8bc67c748f7dc50bb8ef68125108aeac44d0a8dc 100644 (file)
@@ -3,7 +3,6 @@
 #include "NewGeom_SalomeViewer.h"
 #include "NewGeom_OCCSelector.h"
 
-#include <OCCViewer_ViewWindow.h>
 #include <OCCViewer_ViewPort3d.h>
 #include <OCCViewer_ViewFrame.h>
 
@@ -231,12 +230,21 @@ void NewGeom_SalomeViewer::onDeleteView(SUIT_ViewWindow*)
 void NewGeom_SalomeViewer::onViewCreated(SUIT_ViewWindow* theView)
 {
   myView->setCurrentView(theView);
+
+  OCCViewer_ViewFrame* aView = dynamic_cast<OCCViewer_ViewFrame*>(theView);
+
+  OCCViewer_ViewWindow* aWnd = aView->getView(OCCViewer_ViewFrame::MAIN_VIEW);
+  if (aWnd)
+    connect(aWnd, SIGNAL(vpTransformationFinished(OCCViewer_ViewWindow::OperationType)),
+      this, SLOT(onViewTransformed(OCCViewer_ViewWindow::OperationType)));
+
   emit viewCreated(myView);
 }
 
 //**********************************************
-void NewGeom_SalomeViewer::onActivated(SUIT_ViewWindow*)
+void NewGeom_SalomeViewer::onActivated(SUIT_ViewWindow* theView)
 {
+  myView->setCurrentView(theView);
   emit activated(myView);
 }
 
@@ -338,3 +346,9 @@ void NewGeom_SalomeViewer::update()
     aContext->UpdateCurrentViewer();
   }
 }
+
+//***************************************
+void NewGeom_SalomeViewer::onViewTransformed(OCCViewer_ViewWindow::OperationType theType)
+{
+  emit viewTransformed((int) theType);
+}
index 6dbd6b6df9846cecda9d3c9fd5392706e7a87576..b02058daa824f627f902124eeb499148cd240597 100644 (file)
@@ -9,6 +9,8 @@
 #include <ModuleBase_IViewer.h>
 #include <ModuleBase_IViewWindow.h>
 
+#include <OCCViewer_ViewWindow.h>
+
 #include <V3d_View.hxx>
 
 class SUIT_ViewWindow;
@@ -138,6 +140,7 @@ Q_OBJECT
   void onActivated(SUIT_ViewWindow*);
 
   void onSelectionChanged();
+  void onViewTransformed(OCCViewer_ViewWindow::OperationType);
 
  private:
   NewGeom_OCCSelector* mySelector;
index f10bf2e848a4cbddcc08a0144d9c5773a779753b..4111075fb0ab39f2ec3faa817342ecfa30de24da 100644 (file)
@@ -1,5 +1,6 @@
 INCLUDE(Common)
 INCLUDE(FindPython)
+INCLUDE(UnitTest)
 
 SET(PROJECT_HEADERS
     ParametersPlugin.h
@@ -7,6 +8,7 @@ SET(PROJECT_HEADERS
     ParametersPlugin_Parameter.h
     ParametersPlugin_PyInterp.h
     ParametersPlugin_Validators.h
+    ParametersPlugin_EvalListener.h
 )
  
 SET(PROJECT_SOURCES
@@ -14,6 +16,7 @@ SET(PROJECT_SOURCES
     ParametersPlugin_Parameter.cpp
     ParametersPlugin_PyInterp.cpp
     ParametersPlugin_Validators.cpp
+    ParametersPlugin_EvalListener.cpp
 )
 
 SET(XML_RESOURCES
@@ -45,3 +48,6 @@ TARGET_LINK_LIBRARIES(ParametersPlugin ${PROJECT_LIBRARIES})
 
 INSTALL(TARGETS ParametersPlugin DESTINATION plugins)
 INSTALL(FILES ${XML_RESOURCES} DESTINATION plugins)
+
+ADD_UNIT_TESTS(TestParameterCreation.py
+              )
diff --git a/src/ParametersPlugin/ParametersPlugin_EvalListener.cpp b/src/ParametersPlugin/ParametersPlugin_EvalListener.cpp
new file mode 100644 (file)
index 0000000..ff05cd5
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * ParametersPlugin_EvalListener.cpp
+ *
+ *  Created on: Apr 28, 2015
+ *      Author: sbh
+ */
+
+#include <ParametersPlugin_EvalListener.h>
+
+#include <Events_Error.h>
+
+#include <ModelAPI_Events.h>
+#include <ModelAPI_Tools.h>
+#include <ModelAPI_AttributeDouble.h>
+
+#include <string>
+#include <sstream>
+
+ParametersPlugin_EvalListener::ParametersPlugin_EvalListener()
+{
+  Events_Loop* aLoop = Events_Loop::loop();
+  const Events_ID kEvaluationEvent = ModelAPI_AttributeEvalMessage::eventId();
+  aLoop->registerListener(this, kEvaluationEvent, NULL, true);
+
+  myInterp = std::shared_ptr<ParametersPlugin_PyInterp>(new ParametersPlugin_PyInterp());
+  myInterp->initialize();
+}
+
+ParametersPlugin_EvalListener::~ParametersPlugin_EvalListener()
+{
+}
+
+void ParametersPlugin_EvalListener::processEvent(const std::shared_ptr<Events_Message>& theMessage)
+{
+  if (!theMessage.get())
+    return;
+
+  const Events_ID kEvaluationEvent = ModelAPI_AttributeEvalMessage::eventId();
+  if (theMessage->eventID() == kEvaluationEvent) {
+    std::shared_ptr<ModelAPI_AttributeEvalMessage> aMessage =
+        std::dynamic_pointer_cast<ModelAPI_AttributeEvalMessage>(theMessage);
+    AttributeDoublePtr aDoubleAttribute =
+        std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aMessage->attribute());
+    if (aDoubleAttribute.get()) {
+      std::string anError;
+      double aValue = evaluate(aDoubleAttribute->text(), anError);
+      if (anError.empty()) {
+        aDoubleAttribute->setValue(aValue);
+      }
+    }
+  } else {
+    Events_Error::send(std::string("ParametersPlugin python interpreter, unhandled message caught: ")
+                       + theMessage->eventID().eventText());
+  }
+}
+
+double ParametersPlugin_EvalListener::evaluate(const std::string& theExpression,
+                                               std::string& theError)
+{
+  std::list<std::string> anExprParams = myInterp->compile(theExpression);
+  // find expression's params in the model
+  std::list<std::string> aContext;
+  std::list<std::string>::iterator it = anExprParams.begin();
+  for ( ; it != anExprParams.end(); it++) {
+    double aValue;
+    if (!ModelAPI_Tools::findVariable(*it, aValue)) continue;
+
+    std::ostringstream sstream;
+    sstream << aValue;
+    std::string aParamValue = sstream.str();
+    aContext.push_back(*it + "=" + aParamValue);
+  }
+  myInterp->extendLocalContext(aContext);
+  double result = myInterp->evaluate(theExpression, theError);
+  myInterp->clearLocalContext();
+  return result;
+}
+
diff --git a/src/ParametersPlugin/ParametersPlugin_EvalListener.h b/src/ParametersPlugin/ParametersPlugin_EvalListener.h
new file mode 100644 (file)
index 0000000..057ca79
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * ParametersPlugin_EvalListener.h
+ *
+ *  Created on: Apr 28, 2015
+ *      Author: sbh
+ */
+
+#ifndef SRC_PARAMETERSPLUGIN_EVALLISTENER_H_
+#define SRC_PARAMETERSPLUGIN_EVALLISTENER_H_
+
+#include <ParametersPlugin.h>
+#include <Events_Loop.h>
+#include <ParametersPlugin_PyInterp.h>
+
+class PARAMETERSPLUGIN_EXPORT ParametersPlugin_EvalListener : public Events_Listener
+{
+ public:
+  ParametersPlugin_EvalListener();
+  virtual ~ParametersPlugin_EvalListener();
+
+  virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+ protected:
+  double evaluate(const std::string& theExpression,
+                  std::string& theError) ;
+
+ private:
+  std::shared_ptr<ParametersPlugin_PyInterp> myInterp;
+};
+
+#endif /* SRC_PARAMETERSPLUGIN_PARAMETERSPLUGIN_EVALLISTENER_H_ */
index 48f5d731236e99c4d008b66a7bccb0206c73d53f..f9fdc7c6d114d6493101b5874747048e15ffef87 100644 (file)
 
 ParametersPlugin_Parameter::ParametersPlugin_Parameter()
 {
-  myInterp = new ParametersPlugin_PyInterp();
+  myInterp = std::shared_ptr<ParametersPlugin_PyInterp>(new ParametersPlugin_PyInterp());
   myInterp->initialize();
 }
 
 ParametersPlugin_Parameter::~ParametersPlugin_Parameter()
 {
-  delete myInterp;
 }
 
 void ParametersPlugin_Parameter::initAttributes()
index c36d7764fa3e5d1059cf4bac2168b0ff4af43bb8..a65a5ff38005e82ebb6971b70065aad056e48a5d 100644 (file)
@@ -10,6 +10,8 @@
 #include "ParametersPlugin.h"
 #include <ModelAPI_Feature.h>
 
+#include <memory>
+
 class ParametersPlugin_PyInterp;
 
 class ParametersPlugin_Parameter : public ModelAPI_Feature
@@ -20,8 +22,8 @@ class ParametersPlugin_Parameter : public ModelAPI_Feature
   /// Extrusion kind
   inline static const std::string& ID()
   {
-    static const std::string MY_EXTRUSION_ID("Parameter");
-    return MY_EXTRUSION_ID;
+    static const std::string MY_PARAMETER_ID("Parameter");
+    return MY_PARAMETER_ID;
   }
   /// attribute name of references sketch entities list, it should contain a sketch result or
   /// a pair a sketch result to sketch face
@@ -62,7 +64,7 @@ class ParametersPlugin_Parameter : public ModelAPI_Feature
   double evaluate(const std::string& theExpression, std::string& theError);
 
  private:
-  ParametersPlugin_PyInterp* myInterp;
+  std::shared_ptr<ParametersPlugin_PyInterp> myInterp;
 };
 
 #endif
index 97fa7a9fdd795f27fd0e09d3323f7bce50bebffe..e80aa1b69c32e47652491f31936e6f435c11aa7f 100644 (file)
@@ -23,6 +23,8 @@ ParametersPlugin_Plugin::ParametersPlugin_Plugin()
                               new ParametersPlugin_VariableValidator);
   aFactory->registerValidator("Parameters_ExpressionValidator",
                               new ParametersPlugin_ExpressionValidator);
+
+  myEvalListener = std::shared_ptr<ParametersPlugin_EvalListener>(new ParametersPlugin_EvalListener());
 }
 
 FeaturePtr ParametersPlugin_Plugin::createFeature(std::string theFeatureID)
index d82198f60ed0db673ba03da83f1d0f8cc9e7c157..d4d35283fe705245ca095c054f700fcef2959978 100644 (file)
@@ -4,6 +4,8 @@
 #define PARAMETERSPLUGIN_PLUGIN_H_
 
 #include <ParametersPlugin.h>
+#include <ParametersPlugin_EvalListener.h>
+
 #include <ModelAPI_Plugin.h>
 #include <ModelAPI_Feature.h>
 
@@ -18,6 +20,8 @@ class PARAMETERSPLUGIN_EXPORT ParametersPlugin_Plugin : public ModelAPI_Plugin
 
  public:
   ParametersPlugin_Plugin();
+
+  std::shared_ptr<ParametersPlugin_EvalListener> myEvalListener;
 };
 
 #endif
index 4afbfaa2a93f75a404e12d1f7cd57c2dd6bb12ee..53659f23fdbd89ab61bc1438f5a380aa2575e536 100644 (file)
@@ -136,7 +136,14 @@ bool ParametersPlugin_PyInterp::initContext()
   }
   _global_context = PyModule_GetDict(m);          // get interpreter global variable context
   Py_INCREF(_global_context);
-  _local_context = _global_context;
+  _local_context = PyDict_New();
+  Py_INCREF(_local_context);
 
   return PyRun_SimpleString("from math import *") == 0;
 }
+
+void ParametersPlugin_PyInterp::closeContext()
+{
+  Py_XDECREF(_local_context);
+  PyInterp_Interp::closeContext();
+}
index 0e3cdee56401f7819ae60e5d31ce7a63102f2a99..0a631f6e22f42ce3e30251ad9869bc29efd3f12a 100644 (file)
@@ -29,6 +29,7 @@ class PARAMETERSPLUGIN_EXPORT ParametersPlugin_PyInterp : public PyInterp_Interp
   std::string errorMessage();
   // Overrides PyInterp_Interp
   virtual bool initContext();
+  virtual void closeContext();
 };
 
 #endif /* PARAMETERSPLUGIN_PYINTERP_H_ */
diff --git a/src/ParametersPlugin/Test/TestParameterCreation.py b/src/ParametersPlugin/Test/TestParameterCreation.py
new file mode 100644 (file)
index 0000000..d775d73
--- /dev/null
@@ -0,0 +1,160 @@
+"""
+    TestParameterCreation.py
+    
+    class ParametersPlugin_Parameter
+    static const std::string MY_PARAMETER_ID("Parameter");
+    static const std::string MY_VARIABLE_ID("variable");
+    static const std::string MY_EXPRESSION_ID("expression");
+    
+    data()->addAttribute(ParametersPlugin_Parameter::VARIABLE_ID(),
+                         ModelAPI_AttributeString::typeId());
+    data()->addAttribute(ParametersPlugin_Parameter::EXPRESSION_ID(),
+                         ModelAPI_AttributeString::typeId());
+                         
+    class ModelAPI_ResultParameter
+    static const std::string MY_VALUE_ID("Value");
+    static const std::string MY_VALUE_ID("State");
+"""
+
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+from GeomDataAPI import *
+from ModelAPI import *
+import math
+
+__updated__ = "2015-04-27"
+
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+#=========================================================================
+# Creation of a sketch
+#=========================================================================
+aSession.startOperation()
+aSketchCommonFeature = aDocument.addFeature("Sketch")
+aSketchFeature = featureToCompositeFeature(aSketchCommonFeature)
+origin = geomDataAPI_Point(aSketchFeature.attribute("Origin"))
+origin.setValue(0, 0, 0)
+dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX"))
+dirx.setValue(1, 0, 0)
+norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
+norm.setValue(0, 0, 1)
+aSession.finishOperation()
+#=========================================================================
+# Create several parameters.
+# 1. Basic parameter definition:
+#    x1 = 150.0, y1 = 50.0, cr1 = 100.0, cl = 250.0;
+# 2. Check referencing between parameters:
+#    x2 = x1 + 100.0, y2 = y1/2.
+# 3. Check math module
+#    tm = 2 * pi
+#=========================================================================
+ltNames = ["x1", "y1", "cr1", "cl1"]
+ltExpressions = ["150.", "50.", "100.", "250."]
+dtParams = {}
+aSession.startOperation()
+for name, expr in zip(ltNames, ltExpressions):
+    aParam = aDocument.addFeature("Parameter")
+    aParamName = aParam.string("variable")
+    aParamName.setValue(name)
+    aParamExpr = aParam.string("expression")
+    aParamExpr.setValue(expr)
+    dtParams[name] = aParam
+aSession.finishOperation()
+assert (len(dtParams) == len(ltNames))
+# Check results
+for name, expr in zip(ltNames, ltExpressions):
+    aParam = dtParams[name]
+    aResultAttr = modelAPI_ResultParameter(aParam.firstResult())
+    assert(aResultAttr.data())
+    assert(aResultAttr.data().real("Value"))
+    aResultValue = aResultAttr.data().real("Value").value()
+    print aResultValue, " == ", float(expr)
+    assert(aResultValue == float(expr))
+
+# Check referencing between parameters
+aSession.startOperation()
+ltNames = ["x2", "y2"]
+ltExpressions = ["x1 + 100.0", "y1/2."]
+aSession.startOperation()
+for name, expr in zip(ltNames, ltExpressions):
+    aParam = aDocument.addFeature("Parameter")
+    aParamName = aParam.string("variable")
+    aParamName.setValue(name)
+    aParamExpr = aParam.string("expression")
+    aParamExpr.setValue(expr)
+    dtParams[name] = aParam
+aSession.finishOperation()
+
+aParam = dtParams["x2"]
+aResultAttr = modelAPI_ResultParameter(aParam.firstResult())
+assert(aResultAttr.data())
+assert(aResultAttr.data().real("Value"))
+aX2Value = aResultAttr.data().real("Value").value()
+assert (aX2Value == 250.)
+aParam = dtParams["y2"]
+aResultAttr = modelAPI_ResultParameter(aParam.firstResult())
+assert(aResultAttr.data())
+assert(aResultAttr.data().real("Value"))
+aY2Value = aResultAttr.data().real("Value").value()
+assert (aY2Value == 25.)
+# check math
+aSession.startOperation()
+aParam = aDocument.addFeature("Parameter")
+aParamName = aParam.string("variable")
+aParamName.setValue("tm")
+aParamExpr = aParam.string("expression")
+aParamExpr.setValue("round(2 * pi, 6)")
+aSession.finishOperation()
+aResultAttr = modelAPI_ResultParameter(aParam.firstResult())
+assert(aResultAttr.data())
+assert(aResultAttr.data().real("Value"))
+aTmValue = aResultAttr.data().real("Value").value()
+assert (aTmValue == round(2 * math.pi, 6))
+#=========================================================================
+# Use parameters to set radius of a circle :
+# 1. Create a circle (250., 250), r = 25.
+# 2. Set a 'cr1' as text value of radius attribute
+#=========================================================================
+aSession.startOperation()
+aSketchCircle = aSketchFeature.addFeature("SketchCircle")
+anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
+aRadiusAttr = aSketchCircle.real("CircleRadius")
+anCircleCentr.setValue(250., 250)
+aRadiusAttr.setValue(25.)
+aSession.finishOperation()
+# Apply parameter
+aSession.startOperation()
+aRadiusAttr.setText("cr1")
+aSession.finishOperation()
+assert(aRadiusAttr.value() == 100.)
+#=========================================================================
+# Use parameters for a length constraint on a line:
+# 1. Create a line A(10., 10.) - B(-10., -10.)
+# 2. Create a length constraint, l = 100;
+# 3. Set a 'cl1' as text value of length attribute
+#=========================================================================
+aSession.startOperation()
+aSketchLine = aSketchFeature.addFeature("SketchLine")
+aLineStartPoint = geomDataAPI_Point2D(aSketchLine.attribute("StartPoint"))
+aLineEndPoint = geomDataAPI_Point2D(aSketchLine.attribute("EndPoint"))
+aLineStartPoint.setValue(10., 10.)
+aLineEndPoint.setValue(-10., -10.)
+aSession.finishOperation()
+# Length constraint
+aSession.startOperation()
+aLengthConstraint = aSketchFeature.addFeature("SketchConstraintLength")
+refattrA = aLengthConstraint.refattr("ConstraintEntityA")
+refattrA.setObject(modelAPI_ResultConstruction(aSketchLine.firstResult()))
+aLengthConstraint.execute()
+aSession.finishOperation()
+
+# Apply parameter
+aSession.startOperation()
+aLengthAttr = aLengthConstraint.real("ConstraintValue")
+aLengthAttr.setText("cl1")
+aSession.finishOperation()
+assert(aLengthAttr.value() == 250.)
+#=========================================================================
+# End of test
+#=========================================================================
index d254192961fc430f65667c8edfb12bfd195298cd..8c69ea96b1017673d68e69fa75d4b2277e5bc667 100644 (file)
@@ -13,13 +13,18 @@ SET(PROJECT_HEADERS
        PartSet_WidgetSketchLabel.h
        PartSet_Validators.h
        PartSet_WidgetPoint2d.h
+       PartSet_WidgetPoint2dAngle.h
        PartSet_WidgetEditor.h
        PartSet_WidgetMultiSelector.h
        PartSet_WidgetPoint2dDistance.h
        PartSet_WidgetShapeSelector.h
+       PartSet_WidgetFileSelector.h
        PartSet_Filters.h
        PartSet_SketcherMgr.h
        PartSet_MenuMgr.h
+    PartSet_DocumentDataModel.h
+    PartSet_PartDataModel.h
+    PartSet_DataTreeModel.h
 )
 
 SET(PROJECT_SOURCES
@@ -31,11 +36,15 @@ SET(PROJECT_SOURCES
        PartSet_WidgetEditor.cpp
        PartSet_WidgetMultiSelector.cpp
        PartSet_WidgetPoint2d.cpp
+       PartSet_WidgetPoint2dAngle.cpp
        PartSet_WidgetPoint2dDistance.cpp
        PartSet_WidgetShapeSelector.cpp
+       PartSet_WidgetFileSelector.cpp
        PartSet_Filters.cpp
        PartSet_SketcherMgr.cpp
        PartSet_MenuMgr.cpp
+    PartSet_DocumentDataModel.cpp
+    PartSet_PartDataModel.cpp
 )
 
 SET(PROJECT_RESOURCES 
@@ -85,6 +94,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/XGUI
                     ${CMAKE_SOURCE_DIR}/src/SketchPlugin
                     ${CMAKE_SOURCE_DIR}/src/SketcherPrs
                     ${CMAKE_SOURCE_DIR}/src/FeaturesPlugin
+                    ${CMAKE_SOURCE_DIR}/src/PartSetPlugin
                     ${CMAKE_SOURCE_DIR}/src/GeomAPI
                     ${CMAKE_SOURCE_DIR}/src/GeomValidators
                     ${CMAKE_SOURCE_DIR}/src/AppElements
diff --git a/src/PartSet/PartSet_DataTreeModel.h b/src/PartSet/PartSet_DataTreeModel.h
new file mode 100644 (file)
index 0000000..ff96baf
--- /dev/null
@@ -0,0 +1,104 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+#ifndef PartSet_DataTreeModel_H
+#define PartSet_DataTreeModel_H
+
+#include "PartSet.h"
+
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_Session.h>
+
+#include <QAbstractItemModel>
+#include <QColor>
+
+/**\class PartSet_FeaturesModel
+ * \ingroup GUI
+ * \brief Abstaract class of model object which operates with features data.
+ */
+class PARTSET_EXPORT PartSet_FeaturesModel : public QAbstractItemModel
+{
+ public:
+   /// Constructor
+   /// \param theParent a parent object
+  PartSet_FeaturesModel(QObject* theParent)
+      : QAbstractItemModel(theParent),
+        myItemsColor(Qt::black)
+  {
+  }
+
+  //! Returns Feature object by the given Model index.
+  //! Returns 0 if the given index is not index of a feature
+  /// \param theIndex a model index
+  virtual ObjectPtr object(const QModelIndex& theIndex) const = 0;
+
+  //! Returns QModelIndex which corresponds to the given feature
+  //! If the feature is not found then index is not valid
+  virtual QModelIndex objectIndex(const ObjectPtr& theFeature) const = 0;
+
+  //! Returns parent index of the given feature
+  virtual QModelIndex findParent(const ObjectPtr& theObject) const = 0;
+
+  //! Returns index corresponded to the group
+  //! \param theGroup a group name
+  virtual QModelIndex findGroup(const std::string& theGroup) const = 0;
+
+  //! Set color of items
+  void setItemsColor(const QColor& theColor)
+  {
+    myItemsColor = theColor;
+  }
+
+  //! Returns color of items
+  QColor itemsColor() const
+  {
+    return myItemsColor;
+  }
+
+ protected:
+   /// Color of items
+  QColor myItemsColor;
+};
+
+/**\class PartSet_PartModel
+ * \ingroup GUI
+ * \brief Abstaract class of model object which operates with parts data.
+ */
+class PartSet_PartModel : public PartSet_FeaturesModel
+{
+ public:
+   /// Constructor
+   /// \param theParent a parent object
+  PartSet_PartModel(QObject* theParent)
+      : PartSet_FeaturesModel(theParent)
+  {
+  }
+
+  /// Set part id
+  /// \param theId a new id
+  void setPart(FeaturePtr thePart)
+  {
+    myPart = thePart;
+  }
+
+  /// Returns Id of the part
+  FeaturePtr part() const { return myPart; }
+
+  //! Returns true if the given document is a sub-document of this tree
+  //! \param theDoc a document to check
+  virtual bool hasDocument(const DocumentPtr& theDoc) const = 0;
+
+  /// Returns position of the part in history 
+  int position() const 
+  {
+    DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+    return aRootDoc->index(myPart);
+  }
+
+ protected:
+  //! Id of the current part object in the document
+  FeaturePtr myPart;
+};
+
+#endif
diff --git a/src/PartSet/PartSet_DocumentDataModel.cpp b/src/PartSet/PartSet_DocumentDataModel.cpp
new file mode 100644 (file)
index 0000000..50bae54
--- /dev/null
@@ -0,0 +1,843 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+#include "PartSet_DocumentDataModel.h"
+#include "PartSet_PartDataModel.h"
+#include "PartSet_Module.h"
+//#include "XGUI_Tools.h"
+
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_Events.h>
+#include <ModelAPI_Object.h>
+
+#include <Events_Loop.h>
+
+#include <Config_FeatureMessage.h>
+#include <ModuleBase_Tools.h>
+#include <ModuleBase_ActionInfo.h>
+
+#include <PartSetPlugin_Part.h>
+
+#include <QIcon>
+#include <QString>
+#include <QBrush>
+#include <QTreeView>
+
+#include <set>
+
+#define ACTIVE_COLOR QColor(0,72,140)
+#define PASSIVE_COLOR Qt::black
+
+QMap<QString, QString> PartSet_DocumentDataModel::myIcons;
+
+
+PartSet_DocumentDataModel::PartSet_DocumentDataModel(QObject* theParent)
+    : ModuleBase_IDocumentDataModel(theParent),
+      myActivePartModel(0)
+{
+  // Create a top part of data tree model
+  myModel = new PartSet_TopDataModel(this);
+  myModel->setItemsColor(ACTIVE_COLOR);
+
+  Events_Loop* aLoop = Events_Loop::loop();
+  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
+  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
+  aLoop->registerListener(this, Events_Loop::eventByName(Config_FeatureMessage::GUI_EVENT()));
+}
+
+PartSet_DocumentDataModel::~PartSet_DocumentDataModel()
+{
+  clearModelIndexes();
+  clearSubModels();
+}
+
+void PartSet_DocumentDataModel::processEvent(const std::shared_ptr<Events_Message>& theMessage)
+{
+  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+
+
+  // Created object event *******************
+  if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
+    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
+        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
+    std::set<ObjectPtr> aObjects = aUpdMsg->objects();
+
+    std::set<ObjectPtr>::const_iterator aIt;
+    for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
+      ObjectPtr aObject = (*aIt);
+      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
+      if (aFeature && (!aFeature->isInHistory()))
+        continue;
+
+      DocumentPtr aDoc = aObject->document();
+      if (aDoc == aRootDoc) {  // If root objects
+        if (aObject->groupName() == ModelAPI_ResultPart::group()) {  // Update only Parts group
+            // Add a new part
+          int aStart = aRootDoc->size(ModelAPI_ResultPart::group());
+          if (aStart > 0) {
+            FeaturePtr aPartFeature = ModelAPI_Feature::feature(aObject);
+            PartSet_PartDataModel* aModel = new PartSet_PartDataModel(this);
+            int anId = aRootDoc->index(aPartFeature);
+            aModel->setPart(aPartFeature);
+            myPartModels.append(aModel);
+            insertRow(aStart, partFolderNode(0));
+          }
+        } else {  // Update top groups (other except parts
+          QModelIndex aIndex = myModel->findParent(aObject);
+          int aStart = myModel->rowCount(aIndex) - 1;
+          if (aStart < 0)
+            aStart = 0;
+          aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
+          insertRow(aStart, aIndex);
+        }
+      } else {  // if sub-objects of first level nodes
+        PartSet_PartModel* aPartModel = 0;
+        foreach (PartSet_PartModel* aPart, myPartModels) {
+          if (aPart->hasDocument(aDoc)) {
+            aPartModel = aPart;
+            break;
+          }
+        }
+        if (aPartModel) {
+          QModelIndex aIndex = aPartModel->findParent(aObject);
+          int aStart = aPartModel->rowCount(aIndex);  // check this index
+          aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
+          insertRow(aStart, aIndex);
+        } else
+          reset();
+      }
+    }
+    // Deleted object event ***********************
+  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
+    std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
+        std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
+    DocumentPtr aDoc = aUpdMsg->document();
+    std::set<std::string> aGroups = aUpdMsg->groups();
+
+    std::set<std::string>::const_iterator aIt;
+    for (aIt = aGroups.begin(); aIt != aGroups.end(); ++aIt) {
+      std::string aGroup = (*aIt);
+      if (aDoc == aRootDoc) {  // If root objects
+        if (aGroup == ModelAPI_ResultPart::group()) {  // Update only Parts group
+          PartSet_PartModel* aDelPartModel = 0;
+          foreach (PartSet_PartModel* aPartModel, myPartModels) {
+            if (aPartModel->position() == -1) {
+              aDelPartModel = aPartModel;
+              break;
+            }
+          }
+          if (aDelPartModel) {
+            deactivatePart();
+            int aStart = myPartModels.size() - 1;
+            removeSubModel(aDelPartModel);
+            removeRow(aStart, partFolderNode(0));
+          }
+        } else {  // Update top groups (other except parts
+          QModelIndex aIndex = myModel->findGroup(aGroup);
+          int aStart = myModel->rowCount(aIndex);
+          aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
+          removeRow(aStart, aIndex);
+        }
+      } else {
+        PartSet_PartModel* aPartModel = 0;
+        foreach (PartSet_PartModel* aPart, myPartModels) {
+          if (aPart->hasDocument(aDoc)) {
+            aPartModel = aPart;
+            break;
+          }
+        }
+        if (aPartModel) {
+          QModelIndex aIndex = aPartModel->findGroup(aGroup);
+          int aStart = aPartModel->rowCount(aIndex);
+          aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
+          removeRow(aStart, aIndex);
+        }
+      }
+    }
+    // Deleted object event ***********************
+  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
+    //std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg = std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
+    //ObjectPtr aFeature = aUpdMsg->feature();
+    //DocumentPtr aDoc = aFeature->document();
+
+    // TODO: Identify the necessary index by the modified feature
+    QModelIndex aIndex;
+    emit dataChanged(aIndex, aIndex);
+
+    // Reset whole tree **************************
+  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(Config_FeatureMessage::GUI_EVENT())) {
+    std::shared_ptr<Config_FeatureMessage> aFeatureMsg =
+       std::dynamic_pointer_cast<Config_FeatureMessage>(theMessage);
+    if (!aFeatureMsg->isInternal()) {
+      ActionInfo aFeatureInfo;
+      aFeatureInfo.initFrom(aFeatureMsg);
+      // Remember features icons
+      myIcons[QString::fromStdString(aFeatureMsg->id())] = aFeatureInfo.iconFile;
+    }
+  } else {
+    rebuildDataTree();
+  }
+}
+
+void PartSet_DocumentDataModel::rebuildDataTree()
+{
+  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+
+  beginResetModel();
+  clearModelIndexes();
+
+  // Delete extra models
+  ObjectPtr aObj;
+  FeaturePtr aFeature;
+  QList<PartSet_PartModel*> aDelList;
+  foreach (PartSet_PartModel* aPartModel, myPartModels) {
+    if (aPartModel->position() == -1) 
+      aDelList.append(aPartModel);
+  }
+  foreach (PartSet_PartModel* aPartModel, aDelList) {
+    removeSubModel(aPartModel);
+  }
+  // Add non existing models
+  int aHistNb = aRootDoc->size(ModelAPI_Feature::group());
+  for (int i = 0; i < aHistNb; i++) {
+    aObj = aRootDoc->object(ModelAPI_Feature::group(), i);
+    aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+    if (aFeature->getKind() == PartSetPlugin_Part::ID()) {
+      if (!findPartModel(aFeature)) {
+        PartSet_PartDataModel* aModel = new PartSet_PartDataModel(this);
+        aModel->setPart(aFeature);
+        myPartModels.append(aModel);
+      }
+    }
+  }
+  endResetModel();
+}
+
+QVariant PartSet_DocumentDataModel::data(const QModelIndex& theIndex, int theRole) const
+{
+  if (!theIndex.isValid())
+    return QVariant();
+
+  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+  QModelIndex aParent = theIndex.parent();
+  if ((theIndex.column() == 1) ) {
+    if ((theIndex.internalId() >= PartsFolder) && (theIndex.internalId() <= PartResult)) {
+      if (ModelAPI_Session::get()->activeDocument() == aRootDoc) {
+        if (!aParent.isValid()) {
+          switch (theRole) {
+          case Qt::DecorationRole:
+            if (theIndex.row() == lastHistoryRow())
+              return QIcon(":pictures/arrow.png");
+          }
+        }
+      }
+    } else {
+      QModelIndex* aIndex = toSourceModelIndex(theIndex);
+      const QAbstractItemModel* aModel = aIndex->model();
+      if (isPartSubModel(aModel)) {
+        return aModel->data(*aIndex, theRole);
+      }
+    }
+    return QVariant();
+  }
+
+  switch (theIndex.internalId()) {
+    case PartsFolder:
+      switch (theRole) {
+        case Qt::DisplayRole:
+          return tr("Parts") + QString(" (%1)").arg(rowCount(theIndex));
+        case Qt::DecorationRole:
+          return QIcon(":pictures/constr_folder.png");
+        case Qt::ToolTipRole:
+          return tr("Parts folder");
+        case Qt::ForegroundRole:
+          if (myActivePartIndex.isValid())
+              return QBrush(PASSIVE_COLOR);
+            else
+              return QBrush(ACTIVE_COLOR);
+        default:
+          return QVariant();
+      }
+      break;
+    case HistoryNode:
+      {
+        int aOffset = historyOffset();
+        ObjectPtr aObj = aRootDoc->object(ModelAPI_Feature::group(), theIndex.row() - aOffset);
+        FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+        if (!aFeature)
+          return QVariant();
+        switch (theRole) {
+          case Qt::DisplayRole:
+            if (aFeature)
+              return aFeature->data()->name().c_str();
+            else
+              return QVariant();
+          case Qt::DecorationRole:
+            return featureIcon(aFeature);
+          case Qt::ToolTipRole:
+            return tr("Feature object");
+          case Qt::ForegroundRole:
+            if (theIndex.row() > lastHistoryRow())
+              return QBrush(Qt::lightGray);
+            else {
+              if (myActivePartIndex.isValid())
+                return QBrush(PASSIVE_COLOR);
+              else
+                return QBrush(ACTIVE_COLOR);
+            }
+          default:
+            return QVariant();
+        }
+      }
+      break;
+    case PartResult:
+      {
+        ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), theIndex.row());
+        if (aObject) {
+          switch (theRole) {
+            case Qt::DisplayRole:
+              return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
+            case Qt::DecorationRole:
+              return QIcon(":pictures/part_ico.png");
+            case Qt::ForegroundRole:
+              {
+                if (theIndex == myActivePartIndex)
+                  return QBrush(ACTIVE_COLOR);
+                else
+                  return QBrush(PASSIVE_COLOR);
+              }
+            default:
+              return QVariant();
+          }
+        }
+      }
+      break;
+  }
+  if (aParent.internalId() == HistoryNode) {
+    int aId = aParent.row() - historyOffset();
+    QModelIndex* aIndex = toSourceModelIndex(theIndex);
+    return findPartModel(aId)->data(*aIndex, theRole);
+  }
+  return toSourceModelIndex(theIndex)->data(theRole);
+}
+
+QVariant PartSet_DocumentDataModel::headerData(int theSection, Qt::Orientation theOrient,
+                                            int theRole) const
+{
+  return QVariant();
+}
+
+int PartSet_DocumentDataModel::rowCount(const QModelIndex& theParent) const
+{
+  SessionPtr aSession = ModelAPI_Session::get();
+  if (!aSession->hasModuleDocument())
+    return 0;
+  DocumentPtr aRootDoc = aSession->moduleDocument();
+  if (!theParent.isValid()) {
+    // Size of external models
+    int aVal = historyOffset();
+    // Plus history size
+    aVal += aRootDoc->size(ModelAPI_Feature::group());
+    return aVal;
+  }
+  if (theParent.internalId() == PartsFolder) {
+    return aRootDoc->size(ModelAPI_ResultPart::group());
+    //int aSize = myPartModels.size();
+    //return myPartModels.size();
+  }
+  if (theParent.internalId() == HistoryNode) {
+    int aId = theParent.row() - historyOffset();
+    PartSet_PartModel* aModel = findPartModel(aId);
+    if (aModel)
+      return aModel->rowCount(QModelIndex());
+    return 0;
+  }
+  if (theParent.internalId() == PartResult)
+    return 0;
+  QModelIndex* aParent = toSourceModelIndex(theParent);
+  const QAbstractItemModel* aModel = aParent->model();
+  if (!isSubModel(aModel))
+    return 0;
+
+  /*if (isPartSubModel(aModel)) {
+   if (aModel != myActivePart)
+   return 0;
+   }*/
+  return aModel->rowCount(*aParent);
+}
+
+int PartSet_DocumentDataModel::columnCount(const QModelIndex& theParent) const
+{
+  return 2;
+}
+
+QModelIndex PartSet_DocumentDataModel::index(int theRow, int theColumn,
+                                          const QModelIndex& theParent) const
+{
+  QModelIndex aIndex;
+  if (!theParent.isValid()) {
+    int aOffs = myModel->rowCount();
+    if (theRow < aOffs) {
+      aIndex = myModel->index(theRow, theColumn, theParent);
+      aIndex = createIndex(theRow, theColumn, (void*) getModelIndex(aIndex));
+    } else {
+      if (theRow == aOffs)  // Create Parts node
+        aIndex = partFolderNode(theColumn);
+      else {
+        // create history node
+        aIndex = createIndex(theRow, theColumn, HistoryNode);
+      }
+    }
+  } else {
+    if (theParent.internalId() == PartsFolder) {
+       aIndex = createIndex(theRow, theColumn, PartResult);
+    } else { 
+      if (theParent.internalId() == HistoryNode) {
+        int aId = theParent.row() - historyOffset();
+        aIndex = findPartModel(aId)->index(theRow, theColumn, QModelIndex());
+      } else {
+        QModelIndex* aParent = (QModelIndex*) theParent.internalPointer();
+        aIndex = aParent->model()->index(theRow, theColumn, (*aParent));
+      }
+      aIndex = createIndex(theRow, theColumn, (void*) getModelIndex(aIndex));
+    }
+  }
+  return aIndex;
+}
+
+QModelIndex PartSet_DocumentDataModel::parent(const QModelIndex& theIndex) const
+{
+  if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
+    return QModelIndex();
+
+  if (theIndex.internalId() == PartResult)
+    return partFolderNode(0);
+
+  QModelIndex* aIndex = toSourceModelIndex(theIndex);
+  const QAbstractItemModel* aModel = aIndex->model();
+  if (!isSubModel(aModel))
+    return QModelIndex();
+
+  QModelIndex aIndex1 = aModel->parent(*aIndex);
+  const PartSet_PartModel* aPartModel = dynamic_cast<const PartSet_PartModel*>(aModel);
+  if (aPartModel && (!aIndex1.isValid())) {
+    int aId = aPartModel->position();
+    int aRow = aId + historyOffset();
+    return createIndex(aRow, 0, (qint32) HistoryNode);
+  }
+
+  if (aIndex1.isValid())
+    return createIndex(aIndex1.row(), 0, (void*) getModelIndex(aIndex1));
+  return aIndex1;
+}
+
+bool PartSet_DocumentDataModel::hasChildren(const QModelIndex& theParent) const
+{
+  if (!theParent.isValid())
+    return true;
+  return rowCount(theParent) > 0;
+}
+
+QModelIndex* PartSet_DocumentDataModel::toSourceModelIndex(const QModelIndex& theProxy) const
+{
+  QModelIndex* aIndexPtr = static_cast<QModelIndex*>(theProxy.internalPointer());
+  return aIndexPtr;
+}
+
+QModelIndex* PartSet_DocumentDataModel::findModelIndex(const QModelIndex& theIndex) const
+{
+  QList<QModelIndex*>::const_iterator aIt;
+  for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt) {
+    QModelIndex* aIndex = (*aIt);
+    if ((*aIndex) == theIndex)
+      return aIndex;
+  }
+  return 0;
+}
+
+QModelIndex* PartSet_DocumentDataModel::getModelIndex(const QModelIndex& theIndex) const
+{
+  QModelIndex* aIndexPtr = findModelIndex(theIndex);
+  if (!aIndexPtr) {
+    aIndexPtr = new QModelIndex(theIndex);
+    PartSet_DocumentDataModel* that = (PartSet_DocumentDataModel*) this;
+    that->myIndexes.append(aIndexPtr);
+  }
+  return aIndexPtr;
+}
+
+void PartSet_DocumentDataModel::clearModelIndexes()
+{
+  foreach (QModelIndex* aIndex, myIndexes) 
+    delete aIndex;
+  myIndexes.clear();
+}
+
+void PartSet_DocumentDataModel::clearSubModels()
+{
+  foreach (PartSet_PartModel* aPart, myPartModels) 
+    delete aPart;
+  myPartModels.clear();
+}
+
+ObjectPtr PartSet_DocumentDataModel::object(const QModelIndex& theIndex) const
+{
+  if (theIndex.internalId() == PartsFolder)
+    return ObjectPtr();
+  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+  if (theIndex.internalId() == HistoryNode) {
+    int aOffset = historyOffset();
+    return aRootDoc->object(ModelAPI_Feature::group(), theIndex.row() - aOffset);
+  }
+  if (theIndex.internalId() == PartResult) {
+    return aRootDoc->object(ModelAPI_ResultPart::group(), theIndex.row());
+  }
+  QModelIndex* aIndex = toSourceModelIndex(theIndex);
+  if (!isSubModel(aIndex->model()))
+    return ObjectPtr();
+
+  const PartSet_FeaturesModel* aModel = dynamic_cast<const PartSet_FeaturesModel*>(aIndex->model());
+  return aModel->object(*aIndex);
+}
+
+bool PartSet_DocumentDataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
+{
+  beginInsertRows(theParent, theRow, theRow + theCount - 1);
+  //endInsertRows();
+
+  // Update history
+  QModelIndex aRoot;
+  int aRow = rowCount(aRoot);
+  beginInsertRows(aRoot, aRow, aRow);
+  endInsertRows();
+
+  return true;
+}
+
+bool PartSet_DocumentDataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
+{
+  beginRemoveRows(theParent, theRow, theRow + theCount - 1);
+  endRemoveRows();
+  return true;
+}
+
+void PartSet_DocumentDataModel::removeSubModel(int theModelId)
+{
+  PartSet_PartModel* aModel = myPartModels.at(theModelId);
+  removeSubModel(aModel);
+}
+
+void PartSet_DocumentDataModel::removeSubModel(PartSet_PartModel* theModel)
+{
+  QIntList aToRemove;
+  for (int i = 0; i < myIndexes.size(); i++) {
+    if (myIndexes.at(i)->model() == theModel)
+      aToRemove.append(i);
+  }
+  int aId;
+  while (aToRemove.size() > 0) {
+    aId = aToRemove.last();
+    delete myIndexes.at(aId);
+    myIndexes.removeAt(aId);
+    aToRemove.removeLast();
+  }
+  delete theModel;
+  myPartModels.removeAll(theModel);
+}
+
+
+bool PartSet_DocumentDataModel::isSubModel(const QAbstractItemModel* theModel) const
+{
+  if (theModel == myModel)
+    return true;
+  return isPartSubModel(theModel);
+}
+
+bool PartSet_DocumentDataModel::isPartSubModel(const QAbstractItemModel* theModel) const
+{
+  return myPartModels.contains((PartSet_PartModel*) theModel);
+}
+
+QModelIndex PartSet_DocumentDataModel::partFolderNode(int theColumn) const
+{
+  int aPos = myModel->rowCount(QModelIndex());
+  return createIndex(aPos, theColumn, PartsFolder);
+}
+
+int PartSet_DocumentDataModel::historyOffset() const
+{
+  // Nb of rows of top model + Parts folder
+  return myModel->rowCount(QModelIndex()) + 1;
+}
+
+bool PartSet_DocumentDataModel::activatePart(const QModelIndex& theIndex)
+{
+  if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
+    return false;
+
+  if (theIndex.isValid() && (theIndex.internalId() == PartResult)) {
+    myActivePartIndex = theIndex;
+    myModel->setItemsColor(PASSIVE_COLOR);
+    if (myActivePartModel) 
+      myActivePartModel->setItemsColor(PASSIVE_COLOR);
+    
+    // Find activated part feature by its ID
+    ResultPartPtr aPartRes = activePart();
+    FeaturePtr aFeature = ModelAPI_Feature::feature(aPartRes);
+    if (aFeature.get()) {
+      myActivePartModel = findPartModel(aFeature);
+      myActivePartModel->setItemsColor(ACTIVE_COLOR);
+    }
+  } 
+  return true;
+}
+
+ResultPartPtr PartSet_DocumentDataModel::activePart() const
+{
+  if (myActivePartIndex.isValid()) {
+    DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+    ObjectPtr aObj = aRootDoc->object(ModelAPI_ResultPart::group(), myActivePartIndex.row());
+    return std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
+  }
+  return ResultPartPtr();
+}
+
+QModelIndex PartSet_DocumentDataModel::activePartTree() const
+{
+  if (myActivePartModel) {
+    return createIndex(myActivePartModel->position() + historyOffset(), 0, HistoryNode);
+  }
+  return QModelIndex();
+}
+
+void PartSet_DocumentDataModel::deactivatePart()
+{
+  if (myActivePartIndex.isValid()) {
+    if (myActivePartModel) 
+      myActivePartModel->setItemsColor(PASSIVE_COLOR);
+    myActivePartModel = 0;
+    myActivePartIndex = QModelIndex();
+    myModel->setItemsColor(ACTIVE_COLOR);
+  }
+}
+
+Qt::ItemFlags PartSet_DocumentDataModel::flags(const QModelIndex& theIndex) const
+{
+  if ((theIndex.internalId() >= PartsFolder) && (theIndex.internalId() <= PartResult)) {
+    Qt::ItemFlags aFlags = Qt::ItemIsSelectable;
+    if (object(theIndex)) {
+      aFlags |= Qt::ItemIsEditable;
+    }
+    // Disable items which are below of last history row
+    // Do not disable second column
+    if (theIndex.internalId() == HistoryNode) {
+      if (theIndex.row() <= lastHistoryRow() || (theIndex.column() == 1))
+        aFlags |= Qt::ItemIsEnabled;
+    } else
+      aFlags |= Qt::ItemIsEnabled;
+    return aFlags;
+  } else {
+    QModelIndex* aIndex = toSourceModelIndex(theIndex);
+    const QAbstractItemModel* aModel = aIndex->model();
+    return aModel->flags(*aIndex);
+  }
+}
+
+QModelIndex PartSet_DocumentDataModel::partIndex(const ResultPartPtr& theObject) const
+{
+  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+  int aNb = aRootDoc->size(ModelAPI_ResultPart::group());
+  for (int aId = 0; aId < aNb; aId++) {
+    if (theObject == aRootDoc->object(ModelAPI_ResultPart::group(), aId))
+      return createIndex(aId, 0, PartResult);
+  }
+  return QModelIndex();
+}
+
+QModelIndex PartSet_DocumentDataModel::objectIndex(const ObjectPtr theObject) const
+{
+  // Check that this feature belongs to root document
+  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+  DocumentPtr aDoc = theObject->document();
+  if (aDoc == aRootDoc) {
+    // This feature belongs to histrory or top model
+    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
+    if (aFeature) {
+      int aId;
+      int aNb = aRootDoc->size(ModelAPI_Feature::group());
+      for (aId = 0; aId < aNb; aId++) {
+        if (theObject == aRootDoc->object(ModelAPI_Feature::group(), aId))
+          break;
+      }
+      if (aId < aNb)
+        return index(aId + historyOffset(), 0, QModelIndex());
+    } else {
+      QModelIndex aIndex = myModel->objectIndex(theObject);
+      return
+          aIndex.isValid() ?
+              createIndex(aIndex.row(), 0, (void*) getModelIndex(aIndex)) :
+              QModelIndex();
+    }
+  } else {
+    PartSet_PartModel* aPartModel = 0;
+    foreach(PartSet_PartModel* aModel, myPartModels) {
+      if (aModel->hasDocument(aDoc)) {
+        aPartModel = aModel;
+        break;
+      }
+    }
+    if (aPartModel) {
+      QModelIndex aIndex = aPartModel->objectIndex(theObject);
+      return aIndex.isValid() ?
+              createIndex(aIndex.row(), 0, (void*) getModelIndex(aIndex)) :
+              QModelIndex();
+    }
+  }
+  return QModelIndex();
+}
+
+
+void PartSet_DocumentDataModel::clear()
+{
+  clearModelIndexes();
+  clearSubModels();
+  //myActivePart = 0;
+  myActivePartIndex = QModelIndex();
+  myModel->setItemsColor(ACTIVE_COLOR);
+}
+
+int PartSet_DocumentDataModel::lastHistoryRow() const
+{
+  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+  FeaturePtr aFeature = aRootDoc->currentFeature(true);
+  if (aFeature.get())
+    return historyOffset() + aRootDoc->index(aFeature);
+  else 
+    return historyOffset() - 1;
+}
+
+void PartSet_DocumentDataModel::setLastHistoryItem(const QModelIndex& theIndex)
+{
+  SessionPtr aMgr = ModelAPI_Session::get();
+  DocumentPtr aRootDoc = aMgr->moduleDocument();
+  std::string aOpName = tr("History change").toStdString();
+  if (theIndex.internalId() == HistoryNode) {
+    ObjectPtr aObject = object(theIndex);
+    aMgr->startOperation(aOpName);
+    aRootDoc->setCurrentFeature(std::dynamic_pointer_cast<ModelAPI_Feature>(aObject), true);
+    aMgr->finishOperation();
+  } else {
+    aMgr->startOperation(aOpName);
+    aRootDoc->setCurrentFeature(FeaturePtr(), true);
+    aMgr->finishOperation();
+  }
+}
+
+QModelIndex PartSet_DocumentDataModel::lastHistoryItem() const
+{
+  return index(lastHistoryRow(), 1);
+}
+
+
+QIcon PartSet_DocumentDataModel::featureIcon(const FeaturePtr& theFeature)
+{
+  QIcon anIcon;
+
+  std::string aKind = theFeature->getKind();
+  QString aId(aKind.c_str());
+  if (!myIcons.contains(aId))
+    return anIcon;
+
+  QString anIconString = myIcons[aId];
+
+  ModelAPI_ExecState aState = theFeature->data()->execState();
+  switch(aState) {
+    case ModelAPI_StateDone:
+    case ModelAPI_StateNothing: {
+      anIcon = QIcon(anIconString);
+    }
+    break;
+    case ModelAPI_StateMustBeUpdated: {
+      anIcon = ModuleBase_Tools::lighter(anIconString);
+    }
+    break;
+    case ModelAPI_StateExecFailed: {
+      anIcon = ModuleBase_Tools::composite(":icons/exec_state_failed.png", anIconString);
+    }
+    break;
+    case ModelAPI_StateInvalidArgument: {
+      anIcon = ModuleBase_Tools::composite(":icons/exec_state_invalid_parameters.png",
+                                           anIconString);
+    }
+    break;
+    default: break;  
+  }
+  return anIcon;  
+}
+
+void PartSet_DocumentDataModel::onMouseDoubleClick(const QModelIndex& theIndex)
+{
+  if (theIndex.column() != 1)
+    return;
+  QTreeView* aTreeView = dynamic_cast<QTreeView*>(sender());
+  if ((theIndex.internalId() >= PartsFolder) && (theIndex.internalId() <= PartResult)) {
+    if (myActivePartModel)
+      // It means that the root document is not active
+      return;
+    QModelIndex aNewIndex;
+    if (theIndex.internalId() == HistoryNode) 
+      aNewIndex = theIndex;
+    int aOldId = lastHistoryRow();
+    setLastHistoryItem(theIndex);
+    int aStartRow = std::min(aOldId, theIndex.row());
+    int aEndRow = std::max(aOldId, theIndex.row());
+    for (int i = aStartRow; i <= aEndRow; i++) {
+      aTreeView->update(createIndex(i, 0, HistoryNode));
+      aTreeView->update(createIndex(i, 1, HistoryNode));
+    }
+    
+  } else {
+    QModelIndex* aIndex = toSourceModelIndex(theIndex);
+    const QAbstractItemModel* aModel = aIndex->model();
+    if (isPartSubModel(aModel)) {
+      PartSet_PartDataModel* aPartModel = (PartSet_PartDataModel*)aModel;
+      QModelIndex aOldItem = aPartModel->lastHistoryItem();
+      aPartModel->setLastHistoryItem(*aIndex);
+      QModelIndex aOldIndex = createIndex(aOldItem.row(), aOldItem.column(), (void*) getModelIndex(aOldItem));
+      int aStartRow = std::min(aOldItem.row(), aIndex->row());
+      int aEndRow = std::max(aOldItem.row(), aIndex->row());
+      for (int i = aStartRow; i <= aEndRow; i++) {
+        QModelIndex aInd1 = aPartModel->index(i, 0);
+        QModelIndex aInd2 = createIndex(i, 0, (void*) getModelIndex(aInd1));
+        aTreeView->update(aInd2);
+        aInd1 = aPartModel->index(i, 1);
+        aInd2 = createIndex(i, 1, (void*) getModelIndex(aInd1));
+        aTreeView->update(aInd2);
+      }
+    }
+  }
+} 
+
+
+PartSet_PartModel* PartSet_DocumentDataModel::findPartModel(FeaturePtr thePart) const
+{
+  foreach (PartSet_PartModel* aModel, myPartModels) {
+    if (aModel->part() == thePart)
+      return aModel;
+  }
+  return 0;
+}
+
+PartSet_PartModel* PartSet_DocumentDataModel::findPartModel(int thePosition) const
+{
+  foreach (PartSet_PartModel* aModel, myPartModels) {
+    if (aModel->position() == thePosition)
+      return aModel;
+  }
+  return 0;
+}
\ No newline at end of file
diff --git a/src/PartSet/PartSet_DocumentDataModel.h b/src/PartSet/PartSet_DocumentDataModel.h
new file mode 100644 (file)
index 0000000..360a1d6
--- /dev/null
@@ -0,0 +1,210 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+#ifndef PartSet_DocumentDataModel_H
+#define PartSet_DocumentDataModel_H
+
+#include "PartSet.h"
+#include <ModuleBase_Definitions.h>
+#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_Feature.h>
+#include <ModuleBase_IDocumentDataModel.h>
+
+#include <Events_Listener.h>
+#include <QList>
+#include <QMap>
+
+class ModelAPI_Document;
+class PartSet_PartModel;
+class PartSet_TopDataModel;
+
+/**\class PartSet_DocumentDataModel
+ * \ingroup GUI
+ * \brief This is a proxy data model for Object Browser (QTreeView).
+ * It contains several sub-models for generation of each sub-part of data tree.
+ */
+class PARTSET_EXPORT PartSet_DocumentDataModel : public ModuleBase_IDocumentDataModel, public Events_Listener
+{
+Q_OBJECT
+ public:
+   /// Constructor
+   /// \param theParent a parent object
+  PartSet_DocumentDataModel(QObject* theParent);
+  virtual ~PartSet_DocumentDataModel();
+
+  /// Event Listener method
+  /// \param theMessage an event message
+  virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+  /// Returns the data stored under the given role for the item referred to by the index.
+  /// \param theIndex a model index
+  /// \param theRole a data role (see Qt::ItemDataRole)
+  virtual QVariant data(const QModelIndex& theIndex, int theRole) const;
+
+  /// Returns the data for the given role and section in the header with the specified orientation.
+  /// \param theSection a section
+  /// \param theOrient an orientation
+  /// \param theRole a data role (see Qt::ItemDataRole)
+  virtual QVariant headerData(int theSection, Qt::Orientation theOrient, int theRole =
+                                  Qt::DisplayRole) const;
+
+  /// Returns the number of rows under the given parent. When the parent is valid it means that 
+  /// rowCount is returning the number of children of parent.
+  /// \param theParent a parent model index
+  virtual int rowCount(const QModelIndex& theParent = QModelIndex()) const;
+
+  /// Returns the number of columns for the children of the given parent.
+  /// It has a one column
+  /// \param theParent a parent model index
+  virtual int columnCount(const QModelIndex& theParent = QModelIndex()) const;
+
+  /// Returns the index of the item in the model specified by the given row, column and parent index.
+  /// \param theRow a row
+  /// \param theColumn a column
+  /// \param theParent a parent model index
+  virtual QModelIndex index(int theRow, int theColumn, const QModelIndex &theParent =
+                                QModelIndex()) const;
+
+  /// Returns the parent of the model item with the given index. 
+  /// If the item has no parent, an invalid QModelIndex is returned.
+  /// \param theIndex a model index
+  virtual QModelIndex parent(const QModelIndex& theIndex) const;
+
+  /// Returns true if parent has any children; otherwise returns false.
+  /// \param theParent a parent model index
+  virtual bool hasChildren(const QModelIndex& theParent = QModelIndex()) const;
+
+  /// Inserts count rows into the model before the given row. 
+  /// Items in the new row will be children of the item represented by the parent model index.
+  /// \param theRow a start row
+  /// \param theCount a nember of rows to insert
+  /// \param theParent a parent model index
+  bool insertRows(int theRow, int theCount, const QModelIndex& theParent = QModelIndex());
+
+  /// Removes count rows starting with the given row under parent parent from the model.
+  /// \param theRow a start row
+  /// \param theCount a nember of rows to remove
+  /// \param theParent a parent model index
+  bool removeRows(int theRow, int theCount, const QModelIndex& theParent = QModelIndex());
+
+  /// Returns the item flags for the given index.
+  /// \param theIndex a model index
+  virtual Qt::ItemFlags flags(const QModelIndex& theIndex) const;
+
+  //! Returns an object by the given Model index.
+  //! Returns 0 if the given index is not index of an object
+  virtual ObjectPtr object(const QModelIndex& theIndex) const;
+
+  //! Returns index of the object
+  //! \param theObject object to find
+  virtual QModelIndex objectIndex(const ObjectPtr theObject) const;
+
+  //! Returns QModelIndex which corresponds to the given part
+  //! If the object is not found then index is not valid
+  //! \param thePart a part for analysis
+  QModelIndex partIndex(const ResultPartPtr& thePart) const;
+
+  //! Activates a part data model if the index is a Part node index. 
+  //! Returns true if active part changed.
+  //! \param theIndex a model index
+  bool activatePart(const QModelIndex& theIndex);
+
+  //! Retrurns active part
+  ResultPartPtr activePart() const;
+
+  //! Retrurns QModelIndex of active part
+  QModelIndex activePartIndex() const
+  {
+    return myActivePartIndex;
+  }
+
+  //! Returns parent index of active part tree (index of Part feature) 
+  QModelIndex activePartTree() const;
+
+  //! Deactivates a Part
+  void deactivatePart();
+
+  //! Rebuild data tree
+  virtual void rebuildDataTree();
+
+  //! Clear internal data
+  virtual void clear();
+
+  //! Set an Index which will be considered as a last history index
+  //! \param theIndex a last index for history
+  void setLastHistoryItem(const QModelIndex& theIndex);
+
+  //! Returns last history item
+  QModelIndex lastHistoryItem() const;
+
+  //! Returns icon name according to feature
+  static QIcon featureIcon(const FeaturePtr& theFeature);
+
+ public slots:
+   void onMouseDoubleClick(const QModelIndex& theIndex);
+
+ private:
+
+  enum
+  {
+    PartsFolder = -100,
+    HistoryNode,
+    PartResult
+  };
+
+  //! Converts QModelIndex of this model to QModelIndex of a one of sub-models.
+  QModelIndex* toSourceModelIndex(const QModelIndex& theProxy) const;
+
+  //! Finds a pointer on QModelIndex which is equal to the given one
+  QModelIndex* findModelIndex(const QModelIndex& theIndex) const;
+
+  //! Returns pointer on QModelIndex which is equal to the given one.
+  QModelIndex* getModelIndex(const QModelIndex& theIndex) const;
+
+  //! Deletes all saved pointers on QModelIndex objects.
+  void clearModelIndexes();
+
+  //! Deletes all saved pointers on QModelIndex objects.
+  void clearSubModels();
+
+  //! Removes sub-model on removing a part object. Also it removes QModelIndex-es which refer to this model
+  void removeSubModel(int theModelId);
+
+  //! Removes sub-model on removing a part object. Also it removes QModelIndex-es which refer to this model
+  void removeSubModel(PartSet_PartModel* theModel);
+
+  //! Returns true if the given model is a one of sub-models (of both types)
+  bool isSubModel(const QAbstractItemModel* theModel) const;
+
+  //! Returns true if the given model is a one of sub-models of Part type
+  bool isPartSubModel(const QAbstractItemModel* theModel) const;
+
+  //! Returns Parts Folder node
+  //! \param theColumn an Id of column
+  QModelIndex partFolderNode(int theColumn) const;
+
+  int lastHistoryRow() const;
+
+  int historyOffset() const;
+
+  PartSet_PartModel* findPartModel(FeaturePtr thePart) const;
+
+  PartSet_PartModel* findPartModel(int thePosition) const;
+
+  //! Data model of top part of data tree (not parts object)
+  PartSet_TopDataModel* myModel;
+
+  //! Data models for Parts data tree representation (one data model per a one part)
+  QList<PartSet_PartModel*> myPartModels;
+
+  //! Active part in part editing mode
+  PartSet_PartModel* myActivePartModel;
+
+  QModelIndex myActivePartIndex;
+
+  //! List of saved QModelIndexes created by sub-models
+  QList<QModelIndex*> myIndexes;
+
+  static QMap<QString, QString> myIcons;
+};
+
+#endif
index 91b6f859e32c9ba101dce6d18885978fc8b9cb44..1664be7692736498a7cd55c83dd4d6c7c301c247 100644 (file)
@@ -9,6 +9,8 @@
 #include "PartSet_SketcherMgr.h"
 #include "PartSet_Tools.h"
 
+#include <PartSetPlugin_Part.h>
+
 #include <GeomAPI_Pnt2d.h>
 #include <GeomDataAPI_Point2D.h>
 
@@ -28,6 +30,8 @@
 #include <Events_Loop.h>
 #include <ModelAPI_Events.h>
 #include <ModelAPI_Session.h>
+#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_ResultParameter.h>
 
 #include <QAction>
 #include <QMenu>
@@ -60,11 +64,28 @@ void PartSet_MenuMgr::addAction(const QString& theId, QAction* theAction)
 
 void PartSet_MenuMgr::createActions()
 {
-  QAction* anAction;
+  QAction* aAction;
+
+  aAction = new QAction(tr("Auxiliary"), this);
+  aAction->setCheckable(true);
+  addAction("AUXILIARY_CMD", aAction);
+
+  aAction = new QAction(QIcon(":icons/activate.png"), tr("Activate"), this);
+  connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onActivatePart(bool)));
+  myActions["ACTIVATE_PART_CMD"] = aAction;
+
+  aAction = new QAction(QIcon(":icons/deactivate.png"), tr("Deactivate"), this);
+  connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onActivatePartSet(bool)));
+  myActions["DEACTIVATE_PART_CMD"] = aAction;
 
-  anAction = new QAction(tr("Auxiliary"), this);
-  anAction->setCheckable(true);
-  addAction("AUXILIARY_CMD", anAction);
+  // Activate PartSet
+  aAction = new QAction(QIcon(":icons/activate.png"), tr("Activate"), this);
+  connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onActivatePartSet(bool)));
+  myActions["ACTIVATE_PARTSET_CMD"] = aAction;
+
+  aAction = new QAction(QIcon(":icons/edit.png"), tr("Edit..."), this);
+  connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onEdit(bool)));
+  myActions["EDIT_CMD"] = aAction;
 }
 
 
@@ -99,10 +120,6 @@ std::shared_ptr<GeomAPI_Pnt2d> getPoint(std::shared_ptr<ModelAPI_Feature>& theFe
     aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
         aFeature->data()->attribute(SketchPlugin_Point::COORD_ID()));
 
-  else if (aFeature &&  aFeature->getKind() == SketchPlugin_Circle::ID())
-    aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-        aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID()));
-
   else if (anAttr->attr()) {
     aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
   }
@@ -121,6 +138,8 @@ void findCoincidences(FeaturePtr theStartCoin, QList<FeaturePtr>& theList, std::
   FeaturePtr aObj = ModelAPI_Feature::feature(aPnt->object());
   if (!theList.contains(aObj)) {
     std::shared_ptr<GeomAPI_Pnt2d> aOrig = getPoint(theStartCoin, theAttr);
+    if (aOrig.get() == NULL)
+      return;
     theList.append(aObj);
     const std::set<AttributePtr>& aRefsList = aObj->data()->refsToMe();
     std::set<AttributePtr>::const_iterator aIt;
@@ -129,7 +148,7 @@ void findCoincidences(FeaturePtr theStartCoin, QList<FeaturePtr>& theList, std::
       FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
       if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) { 
         std::shared_ptr<GeomAPI_Pnt2d> aPnt = getPoint(aConstrFeature, theAttr);
-        if (aOrig->isEqual(aPnt)) {
+        if (aPnt.get() && aOrig->isEqual(aPnt)) {
           findCoincidences(aConstrFeature, theList, SketchPlugin_ConstraintCoincidence::ENTITY_A());
           findCoincidences(aConstrFeature, theList, SketchPlugin_ConstraintCoincidence::ENTITY_B());
         }
@@ -139,7 +158,7 @@ void findCoincidences(FeaturePtr theStartCoin, QList<FeaturePtr>& theList, std::
 }
 
 
-bool PartSet_MenuMgr::addViewerItems(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const
+bool PartSet_MenuMgr::addViewerMenu(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const
 {
   ModuleBase_Operation* anOperation = myModule->workshop()->currentOperation();
   if (!PartSet_SketcherMgr::isSketchOperation(anOperation) &&
@@ -191,11 +210,18 @@ bool PartSet_MenuMgr::addViewerItems(QMenu* theMenu, const QMap<QString, QAction
           std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
           FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
           if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) { 
-            std::shared_ptr<GeomAPI_Pnt2d> a2dPnt = getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
-            if (aSelPnt->isEqual(a2dPnt)) { 
+            std::shared_ptr<GeomAPI_Pnt2d> a2dPnt = 
+              getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
+            if (a2dPnt.get() && aSelPnt->isEqual(a2dPnt)) { 
               aCoincident = aConstrFeature;
               break;
-            } 
+            } else {
+              a2dPnt = getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B());
+              if (a2dPnt.get() && aSelPnt->isEqual(a2dPnt)) { 
+                aCoincident = aConstrFeature;
+                break;
+              }
+            }
           }
         }
         // If we have coincidence then add Detach menu
@@ -269,6 +295,9 @@ void PartSet_MenuMgr::onLineDetach(QAction* theAction)
   int aId = theAction->data().toInt();
   FeaturePtr aLine = myCoinsideLines.at(aId);
   std::shared_ptr<GeomAPI_Pnt2d> aOrig = getPoint(mySelectedFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
+  if (aOrig.get() == NULL)
+    aOrig = getPoint(mySelectedFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B());
+  
   gp_Pnt aOr = aOrig->impl<gp_Pnt>();
   const std::set<AttributePtr>& aRefsList = aLine->data()->refsToMe();
 
@@ -280,6 +309,10 @@ void PartSet_MenuMgr::onLineDetach(QAction* theAction)
     FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
     if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) { 
       std::shared_ptr<GeomAPI_Pnt2d> aPnt = getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
+      if (aPnt.get() == NULL)
+        aPnt = getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B());
+      if (aPnt.get() == NULL)
+        return;
       gp_Pnt aP = aPnt->impl<gp_Pnt>();
       if (aOrig->isEqual(aPnt)) {
         aToDelFeatures.append(aConstrFeature);
@@ -434,3 +467,41 @@ bool PartSet_MenuMgr::canSetAuxiliary(bool& theValue) const
   theValue = anObjects.size() && !isNotAuxiliaryFound;
   return anEnabled;
 }
+
+void PartSet_MenuMgr::onActivatePart(bool)
+{
+  QObjectPtrList aObjects = myModule->workshop()->selection()->selectedObjects();
+  if (aObjects.size() > 0) {
+    ObjectPtr aObj = aObjects.first();
+    ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
+    if (!aPart.get()) {
+      FeaturePtr aPartFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+      if (aPartFeature.get() && (aPartFeature->getKind() == PartSetPlugin_Part::ID())) {
+        aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aPartFeature->firstResult());
+      }
+    }
+    if (aPart.get())
+      aPart->activate();
+  }
+}
+
+void PartSet_MenuMgr::onActivatePartSet(bool)
+{
+  SessionPtr aMgr = ModelAPI_Session::get();
+  aMgr->setActiveDocument(aMgr->moduleDocument());
+}
+
+void PartSet_MenuMgr::onEdit(bool)
+{
+  QObjectPtrList aObjects = myModule->workshop()->selection()->selectedObjects();
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObjects.first());
+  if (aFeature == NULL) {
+    ResultParameterPtr aParam = 
+      std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObjects.first());
+    if (aParam.get() != NULL) {
+      aFeature = ModelAPI_Feature::feature(aParam);
+    }
+  }
+  if (aFeature.get() != NULL)
+    myModule->editFeature(aFeature);
+}
index 117098644fe0f4e76b69d584c7a35bd7554a84c1..93f545360bc5f771b99c94e244ba4d5f4abe41ec 100644 (file)
@@ -40,7 +40,7 @@ public:
   /// \param theMenu a popup menu to be shown in the viewer
   /// \param theStdActions a map of standard actions
   /// \return true if items are added and there is no necessity to provide standard menu
-  bool addViewerItems(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const;
+  bool addViewerMenu(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const;
 
 public slots:
   /// Processes the context menu action click
@@ -60,6 +60,15 @@ private slots:
   /// \param theAction an action of the selected item
   void onLineDetach(QAction* theAction);
 
+  /// A slot called on Part activation command
+  void onActivatePart(bool);
+
+  /// A slot called on PartSet activation command
+  void onActivatePartSet(bool);
+
+  /// A slot called on edit of feature
+  void onEdit(bool);
+
 private:
   /// Returns true if the current operation is sketch entity create operation
   /// \param theValue the current auxiliary value
index 110ac6e7447f8b9dad71ec58dc90a5a67a4d0173..0927b50ee2d560bf28cfc81164ad307c744cc9ce 100644 (file)
@@ -1,25 +1,31 @@
 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
 
 #include "PartSet_Module.h"
-#include <PartSet_WidgetSketchLabel.h>
-#include <PartSet_Validators.h>
-#include <PartSet_Tools.h>
-#include <PartSet_WidgetPoint2d.h>
-#include <PartSet_WidgetPoint2dDistance.h>
-#include <PartSet_WidgetShapeSelector.h>
-#include <PartSet_WidgetMultiSelector.h>
-#include <PartSet_WidgetEditor.h>
+#include "PartSet_WidgetSketchLabel.h"
+#include "PartSet_Validators.h"
+#include "PartSet_Tools.h"
+#include "PartSet_WidgetPoint2d.h"
+#include "PartSet_WidgetPoint2dDistance.h"
+#include "PartSet_WidgetShapeSelector.h"
+#include "PartSet_WidgetPoint2dAngle.h"
+#include "PartSet_WidgetMultiSelector.h"
+#include "PartSet_WidgetEditor.h"
+#include "PartSet_WidgetFileSelector.h"
 #include "PartSet_SketcherMgr.h"
 #include "PartSet_MenuMgr.h"
 
+#include <PartSetPlugin_Remove.h>
+#include <PartSetPlugin_Part.h>
+
 #include <ModuleBase_Operation.h>
 #include <ModuleBase_IViewer.h>
 #include <ModuleBase_IViewWindow.h>
 #include <ModuleBase_IPropertyPanel.h>
 #include <ModuleBase_WidgetEditor.h>
 #include <ModuleBase_FilterFactory.h>
-#include <GeomValidators_Edge.h>
-#include <GeomValidators_EdgeOrVertex.h>
+#include <ModuleBase_Tools.h>
+#include <GeomValidators_ShapeType.h>
+
 #include <GeomValidators_Face.h>
 #include <GeomValidators_ConstructionComposite.h>
 
@@ -42,6 +48,7 @@
 #include <XGUI_ModuleConnector.h>
 #include <XGUI_ContextMenuMgr.h>
 #include <XGUI_Tools.h>
+#include <XGUI_ObjectsBrowser.h>
 
 #include <SketchPlugin_Feature.h>
 #include <SketchPlugin_Sketch.h>
@@ -76,6 +83,7 @@
 #include <QApplication>
 #include <QMessageBox>
 #include <QMainWindow>
+#include <QLineEdit>
 
 #include <GeomAlgoAPI_FaceBuilder.h>
 #include <GeomDataAPI_Dir.h>
@@ -84,6 +92,8 @@
 #include <QDebug>
 #endif
 
+
+
 /*!Create and return new instance of XGUI_Module*/
 extern "C" PARTSET_EXPORT ModuleBase_IModule* createModule(ModuleBase_IWorkshop* theWshop)
 {
@@ -91,10 +101,11 @@ extern "C" PARTSET_EXPORT ModuleBase_IModule* createModule(ModuleBase_IWorkshop*
 }
 
 PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
-  : ModuleBase_IModule(theWshop), 
+  : ModuleBase_IModule(theWshop),
   myRestartingMode(RM_None), myVisualLayerId(0)
 {
   mySketchMgr = new PartSet_SketcherMgr(this);
+  myDataModel = new PartSet_DocumentDataModel(this);
 
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWshop);
   XGUI_Workshop* aWorkshop = aConnector->workshop();
@@ -111,6 +122,9 @@ PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
           SLOT(onViewTransformed(int)));
 
   myMenuMgr = new PartSet_MenuMgr(this);
+
+  Events_Loop* aLoop = Events_Loop::loop();
+  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED));
 }
 
 PartSet_Module::~PartSet_Module()
@@ -138,9 +152,7 @@ void PartSet_Module::registerValidators()
   aFactory->registerValidator("PartSet_DifferentObjects", new PartSet_DifferentObjectsValidator);
   aFactory->registerValidator("PartSet_DifferentShapes", new ModelAPI_ShapeValidator);
 
-  aFactory->registerValidator("GeomValidators_Edge", new GeomValidators_Edge);
-  aFactory->registerValidator("GeomValidators_EdgeOrVertex",
-                              new GeomValidators_EdgeOrVertex);
+  aFactory->registerValidator("GeomValidators_ShapeType", new GeomValidators_ShapeType);
   aFactory->registerValidator("GeomValidators_Face", new GeomValidators_Face);
 
   aFactory->registerValidator("GeomValidators_ConstructionComposite",
@@ -283,9 +295,16 @@ bool PartSet_Module::canDisplayObject(const ObjectPtr& theObject) const
 }
 
 
-bool PartSet_Module::addViewerItems(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const
+bool PartSet_Module::addViewerMenu(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const
 {
-  return myMenuMgr->addViewerItems(theMenu, theStdActions);
+  return myMenuMgr->addViewerMenu(theMenu, theStdActions);
+}
+
+void PartSet_Module::activeSelectionModes(QIntList& theModes)
+{
+  theModes.clear();
+  if (mySketchMgr->activeSketch().get())
+    PartSet_SketcherMgr::sketchSelectionModes(theModes);
 }
 
 bool PartSet_Module::isMouseOverWindow()
@@ -453,24 +472,30 @@ ModuleBase_ModelWidget* PartSet_Module::createWidgetByType(const std::string& th
     aPointWgt->setSketch(mySketchMgr->activeSketch());
     connect(aPointWgt, SIGNAL(vertexSelected()), this, SLOT(onVertexSelected()));
     aWgt = aPointWgt;
-  } if (theType == "point2ddistance") {
+  } else if (theType == "point2ddistance") {
     PartSet_WidgetPoint2dDistance* aDistanceWgt = new PartSet_WidgetPoint2dDistance(theParent, theWidgetApi, theParentId);
     aDistanceWgt->setWorkshop(aWorkshop);
     aDistanceWgt->setSketch(mySketchMgr->activeSketch());
     aWgt = aDistanceWgt;
-  } if (theType == "sketch_shape_selector") {
+  } else if(theType == "point2dangle") {
+    PartSet_WidgetPoint2dAngle* anAngleWgt = new PartSet_WidgetPoint2dAngle(theParent, theWidgetApi, theParentId);
+    anAngleWgt->setWorkshop(aWorkshop);
+    anAngleWgt->setSketch(mySketchMgr->activeSketch());
+    aWgt = anAngleWgt;
+  } else if (theType == "sketch_shape_selector") {
     PartSet_WidgetShapeSelector* aShapeSelectorWgt =
       new PartSet_WidgetShapeSelector(theParent, workshop(), theWidgetApi, theParentId);
     aShapeSelectorWgt->setSketcher(mySketchMgr->activeSketch());
     aWgt = aShapeSelectorWgt;
-  } if (theType == "sketch_multi_selector") {
+  } else if (theType == "sketch_multi_selector") {
     PartSet_WidgetMultiSelector* aShapeSelectorWgt =
       new PartSet_WidgetMultiSelector(theParent, workshop(), theWidgetApi, theParentId);
     aShapeSelectorWgt->setSketcher(mySketchMgr->activeSketch());
     aWgt = aShapeSelectorWgt;
-  }
-  if (theType == WDG_DOUBLEVALUE_EDITOR) {
+  } else if (theType == WDG_DOUBLEVALUE_EDITOR) {
     aWgt = new PartSet_WidgetEditor(theParent, workshop(), theWidgetApi, theParentId);
+  } else if (theType == "export_file_selector") {
+    aWgt = new PartSet_WidgetFileSelector(theParent, workshop(), theWidgetApi, theParentId);
   } 
   return aWgt;
 }
@@ -478,60 +503,75 @@ ModuleBase_ModelWidget* PartSet_Module::createWidgetByType(const std::string& th
 
 bool PartSet_Module::deleteObjects()
 {
+  SessionPtr aMgr = ModelAPI_Session::get();
   // 1. check whether the delete should be processed in the module
   ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
   bool isSketchOp = PartSet_SketcherMgr::isSketchOperation(anOperation),
        isNestedOp = PartSet_SketcherMgr::isNestedSketchOperation(anOperation);
-  if (!isSketchOp && !isNestedOp)
-    return false;
-
-  // 2. find selected presentations
-  // selected objects should be collected before the current operation abort because
-  // the abort leads to selection lost on constraint objects. It can be corrected after #386 issue
-  XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
-  XGUI_Workshop* aWorkshop = aConnector->workshop();
-  ModuleBase_ISelection* aSel = workshop()->selection();
-  QObjectPtrList aSelectedObj = aSel->selectedPresentations();
-  // if there are no selected objects in the viewer, that means that the selection in another
-  // place cased this method. It is necessary to return the false value to understande in above
-  // method that delete is not processed
-  if (aSelectedObj.count() == 0)
-    return false;
-
-  // avoid delete of the objects, which are not belong to the current sketch
-  // in order to do not delete results of other sketches
-  QObjectPtrList aSketchObjects;
-  QObjectPtrList::const_iterator anIt = aSelectedObj.begin(), aLast = aSelectedObj.end();
-  for ( ; anIt != aLast; anIt++) {
-    ObjectPtr anObject = *anIt;
-    if (mySketchMgr->isObjectOfSketch(anObject))
-      aSketchObjects.append(anObject);
-  }
-  // if the selection contains only local selected presentations from other sketches,
-  // the Delete operation should not be done at all
-  if (aSketchObjects.size() == 0)
-    return true;
-
-  // the active nested sketch operation should be aborted unconditionally
-  if (isNestedOp)
-    anOperation->abort();
-
-  // 3. start operation
-  QString aDescription = aWorkshop->contextMenuMgr()->action("DELETE_CMD")->text();
-  SessionPtr aMgr = ModelAPI_Session::get();
-  aMgr->startOperation(aDescription.toStdString());
-
-  // 4. delete features
-  // sketch feature should be skipped, only sub-features can be removed
-  // when sketch operation is active
-  std::set<FeaturePtr> anIgnoredFeatures;
-  anIgnoredFeatures.insert(mySketchMgr->activeSketch());
-  aWorkshop->deleteFeatures(aSketchObjects, anIgnoredFeatures);
+  if (isSketchOp || isNestedOp) {
+    // 2. find selected presentations
+    // selected objects should be collected before the current operation abort because
+    // the abort leads to selection lost on constraint objects. It can be corrected after #386 issue
+    XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
+    XGUI_Workshop* aWorkshop = aConnector->workshop();
+    ModuleBase_ISelection* aSel = workshop()->selection();
+    QObjectPtrList aSelectedObj = aSel->selectedPresentations();
+    // if there are no selected objects in the viewer, that means that the selection in another
+    // place cased this method. It is necessary to return the false value to understande in above
+    // method that delete is not processed
+    if (aSelectedObj.count() == 0)
+      return false;
+
+    // avoid delete of the objects, which are not belong to the current sketch
+    // in order to do not delete results of other sketches
+    QObjectPtrList aSketchObjects;
+    QObjectPtrList::const_iterator anIt = aSelectedObj.begin(), aLast = aSelectedObj.end();
+    for ( ; anIt != aLast; anIt++) {
+      ObjectPtr anObject = *anIt;
+      if (mySketchMgr->isObjectOfSketch(anObject))
+        aSketchObjects.append(anObject);
+    }
+    // if the selection contains only local selected presentations from other sketches,
+    // the Delete operation should not be done at all
+    if (aSketchObjects.size() == 0)
+      return true;
+
+    // the active nested sketch operation should be aborted unconditionally
+    if (isNestedOp)
+      anOperation->abort();
+
+    // 3. start operation
+    QString aDescription = aWorkshop->contextMenuMgr()->action("DELETE_CMD")->text();
+    aMgr->startOperation(aDescription.toStdString());
+
+    // 4. delete features
+    // sketch feature should be skipped, only sub-features can be removed
+    // when sketch operation is active
+    std::set<FeaturePtr> anIgnoredFeatures;
+    anIgnoredFeatures.insert(mySketchMgr->activeSketch());
+    aWorkshop->deleteFeatures(aSketchObjects, anIgnoredFeatures);
   
-  // 5. stop operation
-  aWorkshop->displayer()->updateViewer();
-  aMgr->finishOperation();
-
+    // 5. stop operation
+    aWorkshop->displayer()->updateViewer();
+    aMgr->finishOperation();
+  } else {
+    // Delete part with help of PartSet plugin
+    // TODO: the deleted objects has to be processed by multiselection
+    QObjectPtrList aObjects = myWorkshop->selection()->selectedObjects();
+    if (aObjects.size() == 1) {
+      ObjectPtr aObj = aObjects.first();
+      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+      if (aFeature.get() && (aFeature->getKind() == PartSetPlugin_Part::ID())) {
+        std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
+        aMgr->startOperation(PartSetPlugin_Remove::ID());
+        FeaturePtr aFeature = aDoc->addFeature(PartSetPlugin_Remove::ID());
+        aFeature->execute();
+        aMgr->finishOperation();
+      } else
+        return false;
+    } else
+      return false;
+  }
   return true;
 }
 
@@ -560,14 +600,29 @@ void PartSet_Module::onViewTransformed(int theTrsfType)
     return;
 
   ModuleBase_IViewer* aViewer = myWorkshop->viewer();
-  Handle(V3d_View) aView = aViewer->activeView();
+  //Handle(V3d_View) aView = aViewer->activeView();
 
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
   XGUI_Workshop* aWorkshop = aConnector->workshop();
   XGUI_Displayer* aDisplayer = aWorkshop->displayer();
-  Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
-
-  double aLen = aView->Convert(15);
+  Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
+
+  Handle(V3d_Viewer) aV3dViewer = aContext->CurrentViewer();
+  Handle(V3d_View) aView;
+  double aScale = 0;
+  for (aV3dViewer->InitDefinedViews(); 
+       aV3dViewer->MoreDefinedViews(); 
+       aV3dViewer->NextDefinedViews()) {
+    Handle(V3d_View) aV = aV3dViewer->DefinedView();
+    double aS = aV->Scale();
+    if (aS > aScale) {
+      aScale = aS;
+      aView = aV;
+    }
+  }
+  if (aView.IsNull())
+    return;
+  double aLen = aView->Convert(20);
 
   SketcherPrs_Tools::setArrowSize(aLen);
   bool isModified = false;
@@ -585,3 +640,108 @@ void PartSet_Module::onViewTransformed(int theTrsfType)
   if (isModified)
     aDisplayer->updateViewer();
 }
+
+
+void PartSet_Module::customizeObjectBrowser(QWidget* theObjectBrowser)
+{
+  XGUI_ObjectsBrowser* aOB = dynamic_cast<XGUI_ObjectsBrowser*>(theObjectBrowser);
+  if (aOB) {
+    QLineEdit* aLabel = aOB->activeDocLabel();
+    QPalette aPalet = aLabel->palette();
+    aPalet.setColor(QPalette::Text, QColor(0, 72, 140));
+    aLabel->setPalette(aPalet);
+    connect(aOB->treeView(), SIGNAL(doubleClicked(const QModelIndex&)), 
+      myDataModel, SLOT(onMouseDoubleClick(const QModelIndex&)));
+  }
+}
+
+
+void PartSet_Module::addObjectBrowserMenu(QMenu* theMenu) const
+{
+  QObjectPtrList aObjects = myWorkshop->selection()->selectedObjects();
+  int aSelected = aObjects.size();
+  SessionPtr aMgr = ModelAPI_Session::get();
+  if (aSelected == 1) {
+    bool hasResult = false;
+    bool hasFeature = false;
+    bool hasParameter = false;
+    ModuleBase_Tools::checkObjects(aObjects, hasResult, hasFeature, hasParameter);
+
+    ObjectPtr aObject = aObjects.first();
+    if (aObject) {
+      ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
+      FeaturePtr aPartFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
+      bool isPart = aPart.get() || 
+        (aPartFeature.get() && (aPartFeature->getKind() == PartSetPlugin_Part::ID()));
+      if (isPart) {
+        DocumentPtr aPartDoc;
+        if (!aPart.get()) {
+          aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aPartFeature->firstResult());
+        }
+        if (aPart.get()) // this may be null is Part feature is disabled
+          aPartDoc = aPart->partDoc();
+        if (aMgr->activeDocument() == aPartDoc)
+          theMenu->addAction(myMenuMgr->action("DEACTIVATE_PART_CMD"));
+        else
+          theMenu->addAction(myMenuMgr->action("ACTIVATE_PART_CMD"));
+      } else if (aObject->document() == aMgr->activeDocument()) {
+        if (hasParameter || hasFeature)
+          theMenu->addAction(myMenuMgr->action("EDIT_CMD"));
+      }
+    } else {  // If feature is 0 the it means that selected root object (document)
+      if (aMgr->activeDocument() != aMgr->moduleDocument())
+        theMenu->addAction(myMenuMgr->action("ACTIVATE_PARTSET_CMD"));
+    }
+  } else if (aSelected == 0) {
+    // if there is no selection then it means that upper label is selected
+    QModelIndexList aIndexes = myWorkshop->selection()->selectedIndexes();
+    if (aIndexes.size() == 0) // it means that selection happens in top label outside of tree view
+      if (aMgr->activeDocument() != aMgr->moduleDocument())
+        theMenu->addAction(myMenuMgr->action("ACTIVATE_PARTSET_CMD"));
+  }
+}
+
+void PartSet_Module::processEvent(const std::shared_ptr<Events_Message>& theMessage)
+{
+  if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
+    XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
+    XGUI_Workshop* aWorkshop = aConnector->workshop();
+    XGUI_DataTree* aTreeView = aWorkshop->objectBrowser()->treeView();
+    QLineEdit* aLabel = aWorkshop->objectBrowser()->activeDocLabel();
+    QPalette aPalet = aLabel->palette();
+
+    SessionPtr aMgr = ModelAPI_Session::get();
+    DocumentPtr aActiveDoc = aMgr->activeDocument();
+    DocumentPtr aDoc = aMgr->moduleDocument();
+    QModelIndex aOldIndex = myDataModel->activePartTree();
+    if (aActiveDoc == aDoc) {
+      if (aOldIndex.isValid())
+        aTreeView->setExpanded(aOldIndex, false);
+      myDataModel->deactivatePart();
+      aPalet.setColor(QPalette::Text, QColor(0, 72, 140));
+    } else {
+      std::string aGrpName = ModelAPI_ResultPart::group();
+      for (int i = 0; i < aDoc->size(aGrpName); i++) {
+        ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aDoc->object(aGrpName, i));
+        if (aPart->partDoc() == aActiveDoc) {
+          QModelIndex aIndex = myDataModel->partIndex(aPart);
+          if (myDataModel->activatePart(aIndex)) {
+            aTreeView->setExpanded(aOldIndex, false);
+            aTreeView->setExpanded(myDataModel->activePartTree(), true);
+            aPalet.setColor(QPalette::Text, Qt::black);
+          }
+          break;
+        }
+      }
+    }
+    aLabel->setPalette(aPalet);
+    aWorkshop->updateCommandStatus();
+
+    // Update displayed objects in order to update active color
+    XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+    QObjectPtrList aObjects = aDisplayer->displayedObjects();
+    foreach(ObjectPtr aObj, aObjects)
+      aDisplayer->redisplay(aObj, false);
+    aDisplayer->updateViewer();
+  }
+}
index 3120798c6c598a82c67686bb6d17e1085477da01..cc5e97ae051b1f43a1ac92e79f39b935e37b7888 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "PartSet.h"
 #include "PartSet_Filters.h"
+#include "PartSet_DocumentDataModel.h"
 
 #include <ModuleBase_IModule.h>
 #include <ModuleBase_Definitions.h>
@@ -12,6 +13,8 @@
 #include <ModelAPI_Attribute.h>
 #include <ModelAPI_CompositeFeature.h>
 
+#include <Events_Listener.h>
+
 //#include <StdSelect_FaceFilter.hxx>
 #include <TopoDS_Shape.hxx>
 
@@ -34,7 +37,7 @@ class QAction;
 * \ingroup Modules
 * Implementation of Partset module
 */
-class PARTSET_EXPORT PartSet_Module : public ModuleBase_IModule
+class PARTSET_EXPORT PartSet_Module : public ModuleBase_IModule, public Events_Listener
 {
 Q_OBJECT
 
@@ -47,6 +50,7 @@ enum RestartingMode {
 };
 
 public:
+
   /// Constructor
   /// \param theWshop a pointer to a workshop
   PartSet_Module(ModuleBase_IWorkshop* theWshop);
@@ -97,11 +101,19 @@ public:
   /// \param theObject a model object
   virtual bool canDisplayObject(const ObjectPtr& theObject) const;
 
+  /// Add menu atems for object browser into the given menu
+  /// \param theMenu a popup menu to be shown in the object browser
+  virtual void addObjectBrowserMenu(QMenu* theMenu) const;
+
   /// Add menu atems for viewer into the given menu
   /// \param theMenu a popup menu to be shown in the viewer
   /// \param theStdActions a map of standard actions
   /// \return true if items are added and there is no necessity to provide standard menu
-  virtual bool addViewerItems(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const;
+  virtual bool addViewerMenu(QMenu* theMenu, const QMap<QString, QAction*>& theStdActions) const;
+
+  /// Returns a list of modes, where the AIS objects should be activated
+  /// \param theModes a list of modes
+  virtual void activeSelectionModes(QIntList& theModes);
 
   /// Returns whether the mouse enter the viewer's window
   /// \return true if items are added and there is no necessity to provide standard menu
@@ -109,6 +121,17 @@ public:
 
   PartSet_SketcherMgr* sketchMgr() const { return mySketchMgr; }
 
+  /// Returns data model object for representation of data tree in Object browser
+  virtual ModuleBase_IDocumentDataModel* dataModel() const { return myDataModel; }
+
+  /// Event Listener method
+  /// \param theMessage an event message
+  virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+  /// This method is called on object browser creation for customisation of module specific features
+  /// \param theObjectBrowser a pinter on Object Browser widget
+  virtual void customizeObjectBrowser(QWidget* theObjectBrowser);
+
 public slots:
   /// SLOT, that is called by no more widget signal emitted by property panel
   /// Set a specific flag to restart the sketcher operation
@@ -150,6 +173,10 @@ protected slots:
   /// \param theOperation the operation
   virtual void sendOperation(ModuleBase_Operation* theOperation);
 
+  //! Activates or deactivates a part
+  //! If PartPtr is Null pointer then PartSet will be activated
+  //void activatePart(std::shared_ptr<ModelAPI_ResultPart> theFeature);
+
  private slots:
    /// Processing of vertex selected
    void onVertexSelected();
@@ -180,6 +207,8 @@ protected slots:
   PartSet_MenuMgr* myMenuMgr;
 
   int myVisualLayerId;
+
+  PartSet_DocumentDataModel* myDataModel;
 };
 
 #endif
diff --git a/src/PartSet/PartSet_PartDataModel.cpp b/src/PartSet/PartSet_PartDataModel.cpp
new file mode 100644 (file)
index 0000000..d124d80
--- /dev/null
@@ -0,0 +1,609 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+#include "PartSet_PartDataModel.h"
+#include "PartSet_Module.h"
+#include "PartSet_DocumentDataModel.h"
+
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Result.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_AttributeDocRef.h>
+#include <ModelAPI_Object.h>
+#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_ResultParameter.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultGroup.h>
+#include <ModelAPI_AttributeDouble.h>
+
+#include <QIcon>
+#include <QBrush>
+
+
+PartSet_TopDataModel::PartSet_TopDataModel(QObject* theParent)
+    : PartSet_FeaturesModel(theParent)
+{
+}
+
+PartSet_TopDataModel::~PartSet_TopDataModel()
+{
+}
+
+QVariant PartSet_TopDataModel::data(const QModelIndex& theIndex, int theRole) const
+{
+  if (theIndex.column() == 1)
+    return QVariant();
+
+  switch (theRole) {
+    case Qt::DisplayRole:
+      // return a name
+      switch (theIndex.internalId()) {
+        case ParamsFolder:
+          return tr("Parameters") + QString(" (%1)").arg(rowCount(theIndex));
+        case ParamObject: {
+          DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+          ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultParameter::group(), theIndex.row());
+          if (aObject) {
+            ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObject);
+            AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
+            QString aVal = QString::number(aValueAttribute->value());
+            QString aTitle = QString(aObject->data()->name().c_str());
+            return aTitle + " = " + aVal;
+          }
+        }
+          break;
+        case ConstructFolder:
+          return tr("Constructions") + QString(" (%1)").arg(rowCount(theIndex));
+        case ConstructObject: {
+          DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+          ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultConstruction::group(),
+                                               theIndex.row());
+          if (aObject)
+            return aObject->data()->name().c_str();
+        }
+          break;
+        //case GroupsFolder:
+        //  return tr("Groups") + QString(" (%1)").arg(rowCount(theIndex));
+        //case GroupObject: {
+        //  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+        //  ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultGroup::group(),
+        //                                       theIndex.row());
+        //  if (aObject)
+        //    return aObject->data()->name().c_str();
+        //}
+        //  break;
+      }
+      break;
+
+    case Qt::DecorationRole:
+      {
+      // return an Icon
+      switch (theIndex.internalId()) {
+        case ParamsFolder:
+          return QIcon(":pictures/params_folder.png");
+        case ConstructFolder:
+          return QIcon(":pictures/constr_folder.png");
+        case ConstructObject:
+          return QIcon(":pictures/constr_object.png");
+        //case GroupsFolder:
+        //  return QIcon(":pictures/constr_folder.png");
+        }
+      }
+      break;
+
+    case Qt::ToolTipRole:
+      // return Tooltip
+      break;
+    case Qt::ForegroundRole:
+      return QBrush(myItemsColor);
+      break;
+  }
+  return QVariant();
+}
+
+QVariant PartSet_TopDataModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+  return QVariant();
+}
+
+int PartSet_TopDataModel::rowCount(const QModelIndex& theParent) const
+{
+  if (!theParent.isValid())
+    return 2;  // In case of groups using it has to be +1
+
+  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+  if (theParent.internalId() == ParamsFolder)
+    return aRootDoc->size(ModelAPI_ResultParameter::group());
+
+  if (theParent.internalId() == ConstructFolder)
+    return aRootDoc->size(ModelAPI_ResultConstruction::group());
+
+  //if (theParent.internalId() == GroupsFolder)
+  //  return aRootDoc->size(ModelAPI_ResultGroup::group());
+
+  return 0;
+}
+
+int PartSet_TopDataModel::columnCount(const QModelIndex &parent) const
+{
+  return 1;
+}
+
+QModelIndex PartSet_TopDataModel::index(int theRow, int theColumn, const QModelIndex& theParent) const
+{
+  if (!theParent.isValid()) {
+    switch (theRow) {
+      case 0:
+        return createIndex(theRow, theColumn, (qint32) ParamsFolder);
+      case 1:
+        return createIndex(theRow, theColumn, (qint32) ConstructFolder);
+      //case 2:
+      //  return createIndex(theRow, theColumn, (qint32) GroupsFolder);
+    }
+  } else {
+    if (theParent.internalId() == ParamsFolder)
+      return createIndex(theRow, theColumn, (qint32) ParamObject);
+
+    if (theParent.internalId() == ConstructFolder)
+      return createIndex(theRow, theColumn, (qint32) ConstructObject);
+
+    //if (theParent.internalId() == GroupsFolder)
+    //  return createIndex(theRow, theColumn, (qint32) GroupObject);
+  }
+  return QModelIndex();
+}
+
+QModelIndex PartSet_TopDataModel::parent(const QModelIndex& theIndex) const
+{
+  int aId = (int) theIndex.internalId();
+  switch (aId) {
+    case ParamsFolder:
+    case ConstructFolder:
+    //case GroupsFolder:
+      return QModelIndex();
+    case ParamObject:
+      return createIndex(0, 0, (qint32) ParamsFolder);
+    case ConstructObject:
+      return createIndex(1, 0, (qint32) ConstructFolder);
+    //case GroupObject:
+    //  return createIndex(2, 0, (qint32) GroupsFolder);
+  }
+  return QModelIndex();
+}
+
+bool PartSet_TopDataModel::hasChildren(const QModelIndex& theParent) const
+{
+  return rowCount(theParent) > 0;
+}
+
+ObjectPtr PartSet_TopDataModel::object(const QModelIndex& theIndex) const
+{
+  switch (theIndex.internalId()) {
+    case ParamsFolder:
+    case ConstructFolder:
+      return ObjectPtr();
+    case ParamObject: {
+      DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+      return aRootDoc->object(ModelAPI_ResultParameter::group(), theIndex.row());
+    }
+    case ConstructObject: {
+      DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+      return aRootDoc->object(ModelAPI_ResultConstruction::group(), theIndex.row());
+    }
+    //case GroupObject: {
+    //  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+    //  return aRootDoc->object(ModelAPI_ResultGroup::group(), theIndex.row());
+    //}
+  }
+  return ObjectPtr();
+}
+
+QModelIndex PartSet_TopDataModel::findParent(const ObjectPtr& theObject) const
+{
+  return findGroup(theObject->groupName().c_str());
+}
+
+QModelIndex PartSet_TopDataModel::findGroup(const std::string& theGroup) const
+{
+  if (theGroup == ModelAPI_ResultParameter::group())
+    return createIndex(0, 0, (qint32) ParamsFolder);
+  if (theGroup == ModelAPI_ResultConstruction::group())
+    return createIndex(1, 0, (qint32) ConstructFolder);
+  //if (theGroup == ModelAPI_ResultGroup::group())
+  //  return createIndex(2, 0, (qint32) ConstructFolder);
+  return QModelIndex();
+}
+
+QModelIndex PartSet_TopDataModel::objectIndex(const ObjectPtr& theObject) const
+{
+  QModelIndex aIndex;
+  if (theObject) {
+    DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+    std::string aGroup = theObject->groupName();
+    int aNb = aRootDoc->size(aGroup);
+    int aRow = -1;
+    for (int i = 0; i < aNb; i++) {
+      if (aRootDoc->object(aGroup, i) == theObject) {
+        aRow = i;
+        break;
+      }
+    }
+    if (aRow != -1) {
+      if (aGroup == ModelAPI_ResultParameter::group())
+        return createIndex(aRow, 0, (qint32) ParamObject);
+      if (aGroup == ModelAPI_ResultConstruction::group())
+        return createIndex(aRow, 0, (qint32) ConstructObject);
+      //if (aGroup == ModelAPI_ResultGroup::group())
+      //  return createIndex(aRow, 0, (qint32) GroupObject);
+    }
+  }
+  return aIndex;
+}
+
+//******************************************************************
+//******************************************************************
+//******************************************************************
+PartSet_PartDataModel::PartSet_PartDataModel(QObject* theParent)
+    : PartSet_PartModel(theParent)
+{
+}
+
+PartSet_PartDataModel::~PartSet_PartDataModel()
+{
+}
+
+QVariant PartSet_PartDataModel::data(const QModelIndex& theIndex, int theRole) const
+{
+  DocumentPtr aPartDoc = partDocument();
+  if (theIndex.column() == 1) {
+    DocumentPtr aActiveDoc = ModelAPI_Session::get()->activeDocument();
+    QModelIndex aParent = theIndex.parent();
+    if (aActiveDoc == aPartDoc) {
+      if (!aParent.isValid()) {
+        switch (theRole) {
+        case Qt::DecorationRole:
+          if (theIndex.row() == lastHistoryRow())
+            return QIcon(":pictures/arrow.png");
+        }
+      }
+    }
+    return QVariant();
+  }
+
+  switch (theRole) {
+    case Qt::DisplayRole:
+      // return a name
+      switch (theIndex.internalId()) {
+        //case MyRoot: {
+        //  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+        //  ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), myId);
+        //  if (aObject)
+        //    return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
+        //}
+        case ParamsFolder:
+          return tr("Parameters") + QString(" (%1)").arg(rowCount(theIndex));
+        case ConstructFolder:
+          return tr("Constructions") + QString(" (%1)").arg(rowCount(theIndex));
+        case BodiesFolder:
+          return tr("Bodies") + QString(" (%1)").arg(rowCount(theIndex));
+        case GroupsFolder:
+          return tr("Groups") + QString(" (%1)").arg(rowCount(theIndex));
+        case ParamObject: {
+          ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultParameter::group(), theIndex.row());
+          if (aObject) {
+            ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObject);
+            AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
+            QString aVal = QString::number(aValueAttribute->value());
+            QString aTitle = QString(aObject->data()->name().c_str());
+            return aTitle + " = " + aVal;
+          }
+        }
+          break;
+        case ConstructObject: {
+          ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultConstruction::group(), theIndex.row());
+          if (aObject)
+            return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
+        }
+          break;
+        case BodiesObject: {
+          ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultBody::group(), theIndex.row());
+          if (aObject)
+            return aObject->data()->name().c_str();
+        }
+          break;
+        case GroupObject: {
+          ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultGroup::group(), theIndex.row());
+          if (aObject)
+            return aObject->data()->name().c_str();
+        }
+        case HistoryObject: {
+          ObjectPtr aObject = aPartDoc->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
+          if (aObject)
+            return aObject->data()->name().c_str();
+        }
+      }
+      break;
+    case Qt::DecorationRole:
+      // return an Icon
+      switch (theIndex.internalId()) {
+        //case MyRoot:
+        //  return QIcon(":pictures/part_ico.png");
+        case ParamsFolder:
+          return QIcon(":pictures/params_folder.png");
+        case ConstructFolder:
+        case BodiesFolder:
+          return QIcon(":pictures/constr_folder.png");
+        case GroupsFolder:
+          return QIcon(":pictures/constr_folder.png");
+        case ConstructObject:
+        case GroupObject:
+        case BodiesObject: {
+          std::string aGroup = theIndex.internalId() == ConstructObject ?
+            ModelAPI_ResultConstruction::group() : ModelAPI_ResultBody::group();
+          ObjectPtr anObject = aPartDoc->object(aGroup, theIndex.row());
+          if (anObject && anObject->data() && 
+              anObject->data()->execState() == ModelAPI_StateMustBeUpdated) {
+            return QIcon(":pictures/constr_object_modified.png");
+          }
+          return QIcon(":pictures/constr_object.png");
+        }
+        case HistoryObject: {
+          ObjectPtr aObject = aPartDoc->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
+          FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
+          if (aFeature)
+            return PartSet_DocumentDataModel::featureIcon(aFeature);
+        }
+      }
+      break;
+    case Qt::ToolTipRole:
+      // return Tooltip
+      break;
+    case Qt::ForegroundRole:
+      if (theIndex.internalId() == HistoryObject) {
+        if (theIndex.row() > lastHistoryRow())
+          return QBrush(Qt::lightGray);
+      }
+      return QBrush(myItemsColor);
+  }
+  return QVariant();
+}
+
+QVariant PartSet_PartDataModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+  return QVariant();
+}
+
+int PartSet_PartDataModel::rowCount(const QModelIndex& parent) const
+{
+  if (!parent.isValid()) {
+    DocumentPtr aDoc = partDocument();
+    if (aDoc.get()) {
+      return getRowsNumber() + aDoc->size(ModelAPI_Feature::group());
+    } else 
+      return 0;
+  }
+  switch (parent.internalId()) {
+    case ParamsFolder:
+      return partDocument()->size(ModelAPI_ResultParameter::group());
+    case ConstructFolder:
+      return partDocument()->size(ModelAPI_ResultConstruction::group());
+    case BodiesFolder:
+      return partDocument()->size(ModelAPI_ResultBody::group());
+    case GroupsFolder:
+      return partDocument()->size(ModelAPI_ResultGroup::group());
+  }
+  return 0;
+}
+
+int PartSet_PartDataModel::columnCount(const QModelIndex &parent) const
+{
+  return 2;
+}
+
+QModelIndex PartSet_PartDataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const
+{
+  if (!theParent.isValid()) {
+    switch (theRow) {
+      case 0:
+        return createIndex(theRow, theColumn, (qint32) ParamsFolder);
+      case 1:
+        return createIndex(theRow, theColumn, (qint32) ConstructFolder);
+      case 2:
+        return createIndex(theRow, theColumn, (qint32) BodiesFolder);
+      case 3:
+        {
+        int aSize = partDocument()->size(ModelAPI_ResultGroup::group());
+        if (aSize > 0)
+          return createIndex(theRow, theColumn, (qint32) GroupsFolder);
+        else
+          return createIndex(theRow, theColumn, (qint32) HistoryObject);
+        }
+      default:
+        return createIndex(theRow, theColumn, (qint32) HistoryObject);
+    }
+  } else {
+    int aId = (int) theParent.internalId();
+    switch (aId) {
+      case ParamsFolder:
+        return createIndex(theRow, theColumn, (qint32) ParamObject);
+      case ConstructFolder:
+        return createIndex(theRow, theColumn, (qint32) ConstructObject);
+      case BodiesFolder:
+        return createIndex(theRow, theColumn, (qint32) BodiesObject);
+      case GroupsFolder:
+        return createIndex(theRow, theColumn, (qint32) GroupObject);
+    }
+  }
+  return QModelIndex();
+}
+
+QModelIndex PartSet_PartDataModel::parent(const QModelIndex& theIndex) const
+{
+  switch (theIndex.internalId()) {
+    case ParamsFolder:
+    case ConstructFolder:
+    case BodiesFolder:
+    case GroupsFolder:
+    case HistoryObject:
+      return QModelIndex();
+
+    case ParamObject:
+      return createIndex(0, 0, (qint32) ParamsFolder);
+    case ConstructObject:
+      return createIndex(1, 0, (qint32) ConstructFolder);
+    case BodiesObject:
+      return createIndex(2, 0, (qint32) BodiesFolder);
+    case GroupObject:
+      return createIndex(3, 0, (qint32) GroupsFolder);
+  }
+  return QModelIndex();
+}
+
+bool PartSet_PartDataModel::hasChildren(const QModelIndex& theParent) const
+{
+  return rowCount(theParent) > 0;
+}
+
+DocumentPtr PartSet_PartDataModel::partDocument() const
+{
+  ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(myPart->firstResult()); 
+  if (aPart.get()) // this may be null is Part feature is disabled
+    return aPart->partDoc();
+  return DocumentPtr();
+}
+
+ObjectPtr PartSet_PartDataModel::object(const QModelIndex& theIndex) const
+{
+  switch (theIndex.internalId()) {
+    case ParamsFolder:
+    case ConstructFolder:
+    case BodiesFolder:
+    case GroupsFolder:
+      return ObjectPtr();
+
+    case ParamObject:
+      return partDocument()->object(ModelAPI_ResultParameter::group(), theIndex.row());
+    case ConstructObject:
+      return partDocument()->object(ModelAPI_ResultConstruction::group(), theIndex.row());
+    case BodiesObject:
+      return partDocument()->object(ModelAPI_ResultBody::group(), theIndex.row());
+    case GroupObject:
+      return partDocument()->object(ModelAPI_ResultGroup::group(), theIndex.row());
+    case HistoryObject:
+      return partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
+  }
+  return ObjectPtr();
+}
+
+bool PartSet_PartDataModel::hasDocument(const DocumentPtr& theDoc) const
+{
+  return (partDocument() == theDoc);
+}
+
+QModelIndex PartSet_PartDataModel::findParent(const ObjectPtr& theObject) const
+{
+  return findGroup(theObject->groupName().c_str());
+}
+
+QModelIndex PartSet_PartDataModel::findGroup(const std::string& theGroup) const
+{
+  if (theGroup == ModelAPI_ResultParameter::group())
+    return createIndex(0, 0, (qint32) ParamsFolder);
+  if (theGroup == ModelAPI_ResultConstruction::group())
+    return createIndex(1, 0, (qint32) ConstructFolder);
+  if (theGroup == ModelAPI_ResultBody::group())
+    return createIndex(2, 0, (qint32) BodiesFolder);
+  if (theGroup == ModelAPI_ResultGroup::group())
+    return createIndex(3, 0, (qint32) GroupsFolder);
+  return QModelIndex();
+}
+
+QModelIndex PartSet_PartDataModel::objectIndex(const ObjectPtr& theObject) const
+{
+  QModelIndex aIndex;
+  if (theObject) {
+    if (part() == theObject)
+      return aIndex;
+
+    std::string aGroup = theObject->groupName();
+    DocumentPtr aDoc = theObject->document();
+    int aNb = aDoc->size(aGroup);
+    int aRow = -1;
+    for (int i = 0; i < aNb; i++) {
+      if (aDoc->object(aGroup, i) == theObject) {
+        aRow = i;
+        break;
+      }
+    }
+    if (aRow == -1)
+      return aIndex;
+    if (aGroup == ModelAPI_ResultParameter::group())
+      return createIndex(aRow, 0, (qint32) ParamObject);
+    else if (aGroup == ModelAPI_ResultConstruction::group())
+      return createIndex(aRow, 0, (qint32) ConstructObject);
+    else if (aGroup == ModelAPI_ResultBody::group())
+      return createIndex(aRow, 0, (qint32) BodiesObject);
+    else if (aGroup == ModelAPI_ResultGroup::group())
+      return createIndex(aRow, 0, (qint32) GroupObject);
+    else
+      return createIndex(aRow + getRowsNumber(), 0, (qint32) HistoryObject);
+  }
+  return aIndex;
+}
+
+
+int PartSet_PartDataModel::getRowsNumber() const
+{
+  int aSize = partDocument()->size(ModelAPI_ResultGroup::group());
+  if (aSize == 0) // If there are no groups then do not show group folder
+    return 3;
+  return 4;
+}
+
+int PartSet_PartDataModel::lastHistoryRow() const
+{
+  DocumentPtr aDoc = partDocument();
+  FeaturePtr aFeature = aDoc->currentFeature(true);
+  if (aFeature.get())
+    return getRowsNumber() + aDoc->index(aFeature);
+  else
+    return getRowsNumber() - 1;
+}
+
+void PartSet_PartDataModel::setLastHistoryItem(const QModelIndex& theIndex)
+{
+  SessionPtr aMgr = ModelAPI_Session::get();
+  DocumentPtr aDoc = partDocument();
+  std::string aOpName = tr("History change").toStdString();
+  if (theIndex.internalId() == HistoryObject) {
+    ObjectPtr aObject = object(theIndex);
+    aMgr->startOperation(aOpName);
+    aDoc->setCurrentFeature(std::dynamic_pointer_cast<ModelAPI_Feature>(aObject), true);
+    aMgr->finishOperation();
+  } else {
+    aMgr->startOperation(aOpName);
+    aDoc->setCurrentFeature(FeaturePtr(), true);
+    aMgr->finishOperation();
+  }
+}
+
+QModelIndex PartSet_PartDataModel::lastHistoryItem() const
+{
+  return index(lastHistoryRow(), 1);
+}
+
+Qt::ItemFlags PartSet_PartDataModel::flags(const QModelIndex& theIndex) const
+{
+  Qt::ItemFlags aFlags = Qt::ItemIsSelectable;
+  if (object(theIndex)) {
+    aFlags |= Qt::ItemIsEditable;
+  }
+  if (theIndex.internalId() == HistoryObject) {
+    if (theIndex.row() <= lastHistoryRow() || (theIndex.column() == 1))
+      aFlags |= Qt::ItemIsEnabled;
+  } else
+    aFlags |= Qt::ItemIsEnabled;
+  return aFlags;
+}
diff --git a/src/PartSet/PartSet_PartDataModel.h b/src/PartSet/PartSet_PartDataModel.h
new file mode 100644 (file)
index 0000000..9789f79
--- /dev/null
@@ -0,0 +1,200 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+#ifndef PartSet_PartDataModel_H
+#define PartSet_PartDataModel_H
+
+#include "PartSet.h"
+#include "PartSet_DataTreeModel.h"
+
+/**\class PartSet_TopDataModel
+ * \ingroup GUI
+ * \brief This is a data model for Object Browser (QTreeView).
+ * It represents only upper part of data tree (non-parts tree items)
+ */
+class PARTSET_EXPORT PartSet_TopDataModel : public PartSet_FeaturesModel
+{
+Q_OBJECT
+ public:
+   /// Constructor
+   /// \param theParent a parent object
+  PartSet_TopDataModel(QObject* theParent);
+  virtual ~PartSet_TopDataModel();
+
+  // Reimpl from QAbstractItemModel
+
+  /// Returns the data stored under the given role for the item referred to by the index.
+  /// \param theIndex a model index
+  /// \param theRole a data role (see Qt::ItemDataRole)
+  virtual QVariant data(const QModelIndex& theIndex, int theRole) const;
+
+  /// Returns the data for the given role and section in the header with the specified orientation.
+  /// \param theSection a section
+  /// \param theOrient an orientation
+  /// \param theRole a data role (see Qt::ItemDataRole)
+  virtual QVariant headerData(int theSection, Qt::Orientation theOrient,
+                              int theRole = Qt::DisplayRole) const;
+
+  /// Returns the number of rows under the given parent. When the parent is valid it means that 
+  /// rowCount is returning the number of children of parent.
+  /// \param theParent a parent model index
+  virtual int rowCount(const QModelIndex &theParent = QModelIndex()) const;
+
+  /// Returns the number of columns for the children of the given parent.
+  /// It has a one column
+  /// \param theParent a parent model index
+  virtual int columnCount(const QModelIndex &theParent = QModelIndex()) const;
+
+
+  /// Returns the index of the item in the model specified by the given row, column and parent index.
+  /// \param theRow a row
+  /// \param theColumn a column
+  /// \param theParent a parent model index
+  virtual QModelIndex index(int theRow, int theColumn, const QModelIndex& theParent =
+                                QModelIndex()) const;
+
+  /// Returns the parent of the model item with the given index. 
+  /// If the item has no parent, an invalid QModelIndex is returned.
+  /// \param theIndex a model index
+  virtual QModelIndex parent(const QModelIndex& theIndex) const;
+
+  /// Returns true if parent has any children; otherwise returns false.
+  /// \param theParent a parent model index
+  virtual bool hasChildren(const QModelIndex& theParent = QModelIndex()) const;
+
+  //! Returns object by the given Model index.
+  //! Returns 0 if the given index is not index of a object
+  virtual ObjectPtr object(const QModelIndex& theIndex) const;
+
+  //! Returns QModelIndex which corresponds to the given object
+  //! If the object is not found then index is not valid
+  virtual QModelIndex objectIndex(const ObjectPtr& theObject) const;
+
+  //! Returns parent index of the given object
+  virtual QModelIndex findParent(const ObjectPtr& theObject) const;
+
+  //! Returns index corresponded to the group
+  virtual QModelIndex findGroup(const std::string& theGroup) const;
+
+ private:
+  //! Types of QModelIndexes
+  enum DataIds
+  {
+    ParamsFolder,
+    ParamObject,
+    ConstructFolder,
+    ConstructObject
+    //GroupsFolder,
+    //GroupObject
+  };
+
+};
+
+/**\class PartSet_PartDataModel
+ * \ingroup GUI
+ * \brief This is a data model for Object Browser (QTreeView).
+ * It represents data tree only of a one part
+ */
+class PartSet_PartDataModel : public PartSet_PartModel
+{
+Q_OBJECT
+ public:
+   /// Constructor
+   /// \param theParent a parent object
+  PartSet_PartDataModel(QObject* theParent);
+  virtual ~PartSet_PartDataModel();
+
+  // Reimpl from QAbstractItemModel
+
+  /// Returns the data stored under the given role for the item referred to by the index.
+  /// \param theIndex a model index
+  /// \param theRole a data role (see Qt::ItemDataRole)
+  virtual QVariant data(const QModelIndex& theIndex, int theRole) const;
+
+  /// Returns the data for the given role and section in the header with the specified orientation.
+  /// \param theSection a section
+  /// \param theOrient an orientation
+  /// \param theRole a data role (see Qt::ItemDataRole)
+  virtual QVariant headerData(int theSection, Qt::Orientation theOrient,
+                              int theRole = Qt::DisplayRole) const;
+
+  /// Returns the number of rows under the given parent. When the parent is valid it means that 
+  /// rowCount is returning the number of children of parent.
+  /// \param theParent a parent model index
+  virtual int rowCount(const QModelIndex &theParent = QModelIndex()) const;
+
+  /// Returns the number of columns for the children of the given parent.
+  /// It has a one column
+  /// \param theParent a parent model index
+  virtual int columnCount(const QModelIndex &theParent = QModelIndex()) const;
+
+  /// Returns the item flags for the given index.
+  /// \param theIndex a model index
+  virtual Qt::ItemFlags flags(const QModelIndex& theIndex) const;
+
+  /// Returns the index of the item in the model specified by the given row, column and parent index.
+  /// \param theRow a row
+  /// \param theColumn a column
+  /// \param theParent a parent model index
+  virtual QModelIndex index(int theRow, int theColumn, const QModelIndex& theParent =
+                                QModelIndex()) const;
+
+  /// Returns the parent of the model item with the given index. 
+  /// If the item has no parent, an invalid QModelIndex is returned.
+  /// \param theIndex a model index
+  virtual QModelIndex parent(const QModelIndex& theIndex) const;
+
+  /// Returns true if parent has any children; otherwise returns false.
+  /// \param theParent a parent model index
+  virtual bool hasChildren(const QModelIndex& theParent = QModelIndex()) const;
+
+  //! Returns object by the given Model index.
+  //! Returns 0 if the given index is not index of a object
+  virtual ObjectPtr object(const QModelIndex& theIndex) const;
+
+  //! Returns QModelIndex which corresponds to the given object
+  //! If the object is not found then index is not valid
+  virtual QModelIndex objectIndex(const ObjectPtr& theObject) const;
+
+  //! Returns true if the given document is a sub-document of this tree
+  virtual bool hasDocument(const DocumentPtr& theDoc) const;
+
+  //! Returns parent index of the given object
+  virtual QModelIndex findParent(const ObjectPtr& theObject) const;
+
+  //! Returns index corresponded to the group
+  virtual QModelIndex findGroup(const std::string& theGroup) const;
+
+  //! Set an Index which will be considered as a last history index
+  //! \param theIndex a last index for history
+  void setLastHistoryItem(const QModelIndex& theIndex);
+
+  //! Returns last history item
+  QModelIndex lastHistoryItem() const;
+
+ private:
+
+  //! Returns document of the current part
+  DocumentPtr partDocument() const;
+
+  //! Returns defult number of rows
+  int getRowsNumber() const;
+
+  int lastHistoryRow() const;
+
+  //! Types of QModelIndexes
+  enum DataIds
+  {
+    //MyRoot,
+    ParamsFolder,
+    ParamObject,
+    ConstructFolder,
+    ConstructObject,
+    BodiesFolder,
+    BodiesObject,
+    GroupsFolder,
+    GroupObject,
+    HistoryObject
+  };
+};
+
+#endif
index 2634dd7a3a7b825e9f388080ade8a2c29d3baeb3..9394b1a6bb190628bbdd67204583f90df7a3f207 100644 (file)
@@ -56,6 +56,8 @@
 #include <SketchPlugin_ConstraintCoincidence.h>
 #include <SketchPlugin_ConstraintFillet.h>
 #include <SketchPlugin_ConstraintMirror.h>
+#include <SketchPlugin_MultiRotation.h>
+#include <SketchPlugin_MultiTranslation.h>
 
 #include <SketcherPrs_Tools.h>
 
@@ -598,19 +600,8 @@ const QStringList& PartSet_SketcherMgr::sketchOperationIdList()
     aIds << SketchPlugin_Point::ID().c_str();
     aIds << SketchPlugin_Arc::ID().c_str();
     aIds << SketchPlugin_Circle::ID().c_str();
-    aIds << SketchPlugin_ConstraintLength::ID().c_str();
-    aIds << SketchPlugin_ConstraintDistance::ID().c_str();
-    aIds << SketchPlugin_ConstraintRigid::ID().c_str();
-    aIds << SketchPlugin_ConstraintRadius::ID().c_str();
-    aIds << SketchPlugin_ConstraintPerpendicular::ID().c_str();
-    aIds << SketchPlugin_ConstraintParallel::ID().c_str();
-    aIds << SketchPlugin_ConstraintHorizontal::ID().c_str();
-    aIds << SketchPlugin_ConstraintVertical::ID().c_str();
-    aIds << SketchPlugin_ConstraintEqual::ID().c_str();
-    aIds << SketchPlugin_ConstraintTangent::ID().c_str();
-    aIds << SketchPlugin_ConstraintCoincidence::ID().c_str();
     aIds << SketchPlugin_ConstraintFillet::ID().c_str();
-    aIds << SketchPlugin_ConstraintMirror::ID().c_str();
+    aIds.append(constraintsIdList());
   }
   return aIds;
 }
@@ -631,10 +622,22 @@ const QStringList& PartSet_SketcherMgr::constraintsIdList()
     aIds << SketchPlugin_ConstraintTangent::ID().c_str();
     aIds << SketchPlugin_ConstraintCoincidence::ID().c_str();
     aIds << SketchPlugin_ConstraintMirror::ID().c_str();
+    aIds << SketchPlugin_MultiRotation::ID().c_str();
+    aIds << SketchPlugin_MultiTranslation::ID().c_str();
   }
   return aIds;
 }
 
+void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes)
+{
+  theModes.clear();
+
+  theModes.append(SketcherPrs_Tools::Sel_Dimension_Text);
+  theModes.append(SketcherPrs_Tools::Sel_Dimension_Line);
+  theModes.append(SketcherPrs_Tools::Sel_Constraint);
+  theModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum) TopAbs_VERTEX));
+  theModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum) TopAbs_EDGE));
+}
 
 bool PartSet_SketcherMgr::isSketchOperation(ModuleBase_Operation* theOperation)
 {
@@ -674,15 +677,14 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
   // Display all sketcher sub-Objects
   myCurrentSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theOperation->feature());
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
-  XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
 
   // Hide sketcher result
   std::list<ResultPtr> aResults = myCurrentSketch->results();
   std::list<ResultPtr>::const_iterator aIt;
   for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
-    aDisplayer->erase((*aIt), false);
+    (*aIt)->setDisplayed(false);
   }
-  aDisplayer->erase(myCurrentSketch, false);
+  myCurrentSketch->setDisplayed(false);
 
   // Display sketcher objects
   for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
@@ -690,9 +692,9 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
     std::list<ResultPtr> aResults = aFeature->results();
     std::list<ResultPtr>::const_iterator aIt;
     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
-      aDisplayer->display((*aIt), false);
+      (*aIt)->setDisplayed(true);
     }
-    aDisplayer->display(aFeature, false);
+    aFeature->setDisplayed(true);
   }
 
   if (myPlaneFilter.IsNull()) 
@@ -704,7 +706,10 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
     std::shared_ptr<GeomAPI_Pln> aPln = PartSet_Tools::sketchPlane(myCurrentSketch);
     myPlaneFilter->setPlane(aPln->impl<gp_Pln>());
   }
-  aDisplayer->updateViewer();
+  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+  // all sketch objects should be activated in the sketch selection modes by edit operation start
+  if (theOperation->isEditOperation())
+    activateObjectsInSketchMode(true);
 }
 
 void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
@@ -716,10 +721,10 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
   activateObjectsInSketchMode(false);
 
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
-  XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
 
   DataPtr aData = myCurrentSketch->data();
   if ((!aData) || (!aData->isValid())) {
+    XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
     // The sketch was aborted
     myCurrentSketch = CompositeFeaturePtr();
     myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);
@@ -730,7 +735,7 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
     foreach (ObjectPtr aObj, aObjects) {
       DataPtr aObjData = aObj->data();
       if ((!aObjData) || (!aObjData->isValid()))
-        aDisplayer->erase(aObj);
+        aObj->setDisplayed(false);
     }
     return; 
   }
@@ -740,21 +745,21 @@ void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
     std::list<ResultPtr> aResults = aFeature->results();
     std::list<ResultPtr>::const_iterator aIt;
     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
-      aDisplayer->erase((*aIt), false);
+      (*aIt)->setDisplayed(false);
     }
-    aDisplayer->erase(aFeature, false);
+    aFeature->setDisplayed(false);
   }
   // Display sketcher result
   std::list<ResultPtr> aResults = myCurrentSketch->results();
   std::list<ResultPtr>::const_iterator aIt;
   for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
-    aDisplayer->display((*aIt), false);
+    (*aIt)->setDisplayed(true);
   }
-  aDisplayer->display(myCurrentSketch);
+  myCurrentSketch->setDisplayed(true);
     
   myCurrentSketch = CompositeFeaturePtr();
   myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);
-  aDisplayer->updateViewer();
+  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
 }
 
 void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation)
@@ -804,8 +809,9 @@ bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const
     // it is hidden by a sketch operation start and shown by a sketch stop, just the sketch 
     // nested features can be visualized
     FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
-    if (aFeature.get() != NULL && aFeature == activeSketch())
+    if (aFeature.get() != NULL && aFeature == activeSketch()) {
       aCanDisplay = false;
+    }
   }
   else { // there are no an active sketch
     // 2. sketch sub-features should not be visualized if the sketch operation is not active
@@ -813,8 +819,9 @@ bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const
     if (aFeature.get() != NULL) {
       std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
                               std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
-      if (aSketchFeature.get())
+      if (aSketchFeature.get()) {
         aCanDisplay = false;
+      }
     }
   }
 
@@ -836,8 +843,10 @@ bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const
       }
     }
   }
-  if (!isObjectFound)
+  if (!isObjectFound) {
+    theObject->setDisplayed(aCanDisplay); // If it be set into True - set to False
     return aCanDisplay;
+  }
 
   // 4. For created nested feature operation do not display the created feature if
   // the mouse curstor leaves the OCC window.
@@ -860,6 +869,7 @@ bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const
     }
   }
   #endif
+  theObject->setDisplayed(aCanDisplay); // If it be set into True - set to False
   return aCanDisplay;
 }
 
@@ -1055,28 +1065,27 @@ void PartSet_SketcherMgr::visualizeFeature(ModuleBase_Operation* theOperation,
 
   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
-  XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
 
   // 1. change visibility of the object itself, here the presentable object is processed,
   // e.g. constraints features
   FeaturePtr aFeature = theOperation->feature();
   std::list<ResultPtr> aResults = aFeature->results();
   if (isToDisplay)
-    aDisplayer->display(aFeature, false);
+    aFeature->setDisplayed(true);
   else
-    aDisplayer->erase(aFeature, false);
+    aFeature->setDisplayed(false);
 
   // change visibility of the object results, e.g. non-constraint features
   std::list<ResultPtr>::const_iterator aIt;
   for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
     if (isToDisplay) {
-      aDisplayer->display(*aIt, false);
+      (*aIt)->setDisplayed(true);
     }
     else {
-      aDisplayer->erase(*aIt, false);
+      (*aIt)->setDisplayed(false);
     }
   }
-  aDisplayer->updateViewer();
+  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
 }
 
 void PartSet_SketcherMgr::activateObjectsInSketchMode(const bool isActive)
@@ -1086,13 +1095,8 @@ void PartSet_SketcherMgr::activateObjectsInSketchMode(const bool isActive)
   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
 
   QIntList aModes;
-  if (isActive) {
-    aModes.append(SketcherPrs_Tools::Sel_Dimension_Text);
-    aModes.append(SketcherPrs_Tools::Sel_Dimension_Line);
-    aModes.append(SketcherPrs_Tools::Sel_Constraint);
-    aModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum) TopAbs_VERTEX));
-    aModes.append(AIS_Shape::SelectionMode((TopAbs_ShapeEnum) TopAbs_EDGE));
-  }
+  if (isActive)
+    sketchSelectionModes(aModes);
   aDisplayer->activateObjects(aModes);
 }
 
@@ -1151,17 +1155,16 @@ void PartSet_SketcherMgr::onShowConstraintsToggle(bool theOn)
 
   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
-  XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
 
   const QStringList& aConstrIds = constraintsIdList();
   for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
     FeaturePtr aSubFeature = myCurrentSketch->subFeature(i);
     if (aConstrIds.contains(QString(aSubFeature->getKind().c_str()))) {
       if (myIsConstraintsShown) 
-        aDisplayer->display(aSubFeature, false);
+        aSubFeature->setDisplayed(true);
       else
-        aDisplayer->erase(aSubFeature, false);
+        aSubFeature->setDisplayed(false);
     }
   }
-  aDisplayer->updateViewer();
+  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
 }
index f302a589e77685ea4a831a212623d8721b248f04..f82f450f5a16270fd21229e04b53a7566aaa0bf1 100644 (file)
@@ -162,6 +162,10 @@ public:
   /// Returns list of strings which contains id's of constraints operations
   static const QStringList& constraintsIdList();
 
+  /// Returns a list of modes, where the AIS objects should be activated
+  /// \param theModes a list of modes
+  static void sketchSelectionModes(QIntList& theModes);
+
 public slots:
   /// Process sketch plane selected event
   void onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePln);
diff --git a/src/PartSet/PartSet_WidgetFileSelector.cpp b/src/PartSet/PartSet_WidgetFileSelector.cpp
new file mode 100644 (file)
index 0000000..0b91dc0
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+/*
+ * PartSet_WidgetFileSelector.cpp
+ *
+ *  Created on: May 18, 2015
+ *      Author: spo
+ */
+
+#include "PartSet_WidgetFileSelector.h"
+
+#include <ModelAPI_AttributeString.h>
+
+PartSet_WidgetFileSelector::PartSet_WidgetFileSelector(QWidget* theParent,
+                                                       ModuleBase_IWorkshop* theWorkshop,
+                                                       const Config_WidgetAPI* theData,
+                                                       const std::string& theParentId)
+: ModuleBase_WidgetFileSelector(theParent, theData, theParentId)
+, myWorkshop(theWorkshop)
+{
+}
+
+bool PartSet_WidgetFileSelector::restoreValue()
+{
+  // A rare case when plugin was not loaded.
+  if (!myFeature)
+    return false;
+
+  DataPtr aData = myFeature->data();
+  AttributeStringPtr aStringAttr = aData->string("export_file_format");
+  mySelectedFilter = formatToFilter(shortFormatToFullFormat(QString::fromStdString(aStringAttr->value())));
+
+  return ModuleBase_WidgetFileSelector::restoreValue();
+}
+
+bool PartSet_WidgetFileSelector::storeValueCustom() const
+{
+  // A rare case when plugin was not loaded.
+  if (!myFeature)
+    return false;
+
+  DataPtr aData = myFeature->data();
+  AttributeStringPtr aStringAttr = aData->string("export_file_format");
+  aStringAttr->setValue(filterToShortFormat(mySelectedFilter).toStdString());
+
+  return ModuleBase_WidgetFileSelector::storeValueCustom();
+}
+
+QString PartSet_WidgetFileSelector::filterToShortFormat( const QString & theFilter )
+{
+  return theFilter.section(' ', 0, 0);
+}
+
+QString PartSet_WidgetFileSelector::shortFormatToFullFormat( const QString & theFormat ) const
+{
+  foreach(const QString & eachFormat, getValidatorFormats())
+    if (filterToShortFormat(formatToFilter(eachFormat)) == theFormat)
+      return eachFormat;
+  return QString();
+}
diff --git a/src/PartSet/PartSet_WidgetFileSelector.h b/src/PartSet/PartSet_WidgetFileSelector.h
new file mode 100644 (file)
index 0000000..8d8c8ee
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+/*
+ * PartSet_WidgetFileSelector.h
+ *
+ *  Created on: May 18, 2015
+ *      Author: spo
+ */
+
+#ifndef PARTSET_WIDGETFILESELECTOR_H_
+#define PARTSET_WIDGETFILESELECTOR_H_
+
+#include "PartSet.h"
+
+#include <ModuleBase_WidgetFileSelector.h>
+
+class ModuleBase_IWorkshop;
+
+/**
+* \ingroup Modules
+* Customization of ModuleBase_WidgetFileSelector in order to write
+* format of exported file.
+*/
+class PARTSET_EXPORT PartSet_WidgetFileSelector : public ModuleBase_WidgetFileSelector
+{
+  Q_OBJECT
+public:
+  /// Constructor
+  /// \param theParent the parent object
+  /// \param theWorkshop instance of workshop interface
+  /// \param theData the widget configuration. The attribute of the model widget is obtained from
+  /// \param theParentId is Id of a parent of the current attribute
+  PartSet_WidgetFileSelector(QWidget* theParent,
+                             ModuleBase_IWorkshop* theWorkshop,
+                             const Config_WidgetAPI* theData,
+                             const std::string& theParentId);
+
+  virtual ~PartSet_WidgetFileSelector() {}
+
+  /// Reimplemented from ModuleBase_WidgetFileSelector::restoreValue()
+  virtual bool restoreValue();
+
+protected:
+  /// Reimplemented from ModuleBase_WidgetFileSelector::storeValueCustom()
+  virtual bool storeValueCustom() const;
+
+  /// Returns a short format string of theFilter string
+  static QString filterToShortFormat( const QString & theFilter );
+
+  /// Returns a full format string for the short format
+  QString shortFormatToFullFormat( const QString & theShortFormat ) const;
+
+private:
+  ModuleBase_IWorkshop* myWorkshop; // the current workshop
+};
+
+#endif /* PARTSET_WIDGETFILESELECTOR_H_ */
index ba7ffea5497942228d1df1a2d90b3fffd4f4a5c0..8b71001e8c147cb98fe5213b77feb2834ade8bea 100644 (file)
@@ -36,6 +36,9 @@ Q_OBJECT
 
   virtual ~PartSet_WidgetMultiSelector();
 
+  /// Defines if it is supposed that the widget should interact with the viewer.
+  virtual bool isViewerSelector() { return true; }
+
   /// Set sketcher
   /// \param theSketch a sketcher object
   void setSketcher(CompositeFeaturePtr theSketch) { mySketch = theSketch; }
index 10f6de95fd65dc663d5e28d6d00fcbcab2f4ebed..3d8c89ad1871602e7608812c70376eb572a6ed4f 100644 (file)
@@ -31,6 +31,7 @@
 #include <GeomAPI_Pnt2d.h>
 
 #include <SketchPlugin_Feature.h>
+#include <SketchPlugin_ConstraintCoincidence.h>
 
 #include <QGroupBox>
 #include <QGridLayout>
@@ -120,11 +121,16 @@ PartSet_WidgetPoint2D::~PartSet_WidgetPoint2D()
 {
 }
 
-bool PartSet_WidgetPoint2D::setSelection(ModuleBase_ViewerPrs theValue)
+bool PartSet_WidgetPoint2D::setSelection(const QList<ModuleBase_ViewerPrs>& theValues, int& thePosition)
 {
+  if (thePosition < 0 || thePosition >= theValues.size())
+    return false;
+  ModuleBase_ViewerPrs aValue = theValues[thePosition];
+  thePosition++;
+
   Handle(V3d_View) aView = myWorkshop->viewer()->activeView();
   bool isDone = false;
-  TopoDS_Shape aShape = theValue.shape();
+  TopoDS_Shape aShape = aValue.shape();
   double aX, aY;
   if (getPoint2d(aView, aShape, aX, aY)) {
     isDone = setPoint(aX, aY);
@@ -207,8 +213,7 @@ void PartSet_WidgetPoint2D::activateCustom()
 
   QIntList aModes;
   aModes << TopAbs_VERTEX;
-  if (isEditingMode())
-    aModes << TopAbs_EDGE;
+  aModes << TopAbs_EDGE;
   myWorkshop->moduleConnector()->activateSubShapesSelection(aModes);
 }
 
@@ -276,6 +281,25 @@ void PartSet_WidgetPoint2D::onMouseRelease(ModuleBase_IViewWindow* theWnd, QMous
       emit vertexSelected();
       emit focusOutWidget(this);
       return;
+    } else if (aShape.ShapeType() == TopAbs_EDGE) {
+      // Create point-edge coincedence
+      FeaturePtr aFeature = mySketch->addFeature(SketchPlugin_ConstraintCoincidence::ID());
+      std::shared_ptr<ModelAPI_Data> aData = aFeature->data();
+
+      std::shared_ptr<ModelAPI_AttributeRefAttr> aRef1 = std::dynamic_pointer_cast<
+          ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+      AttributePtr aThisAttr = feature()->data()->attribute(attributeID());
+      std::shared_ptr<GeomDataAPI_Point2D> aThisPoint = 
+        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aThisAttr);
+      aRef1->setAttr(aThisPoint);
+
+      std::shared_ptr<ModelAPI_AttributeRefAttr> aRef2 = std::dynamic_pointer_cast<
+          ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
+      aRef2->setObject(aObject);
+      aFeature->execute();
+      emit vertexSelected();
+      emit focusOutWidget(this);
+      return;
     }
   }
   // End of Bug dependent fragment
index e39011c9054e32484b65472bdf9bdda846078354..a2fe2aa8df1b53afbc3caca4e3fccd53ddf55756 100644 (file)
@@ -53,7 +53,7 @@ Q_OBJECT
   /// Set the given wrapped value to the current widget
   /// This value should be processed in the widget according to the needs
   /// \param theValue the wrapped widget value
-  virtual bool setSelection(ModuleBase_ViewerPrs theValue);
+  virtual bool setSelection(const QList<ModuleBase_ViewerPrs>& theValues, int& thePosition);
 
   virtual bool restoreValue();
 
diff --git a/src/PartSet/PartSet_WidgetPoint2dAngle.cpp b/src/PartSet/PartSet_WidgetPoint2dAngle.cpp
new file mode 100644 (file)
index 0000000..b014d34
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        PartSet_WidgetPoint2dAngle.h
+// Created:     23 June 2014
+// Author:      Vitaly Smetannikov
+
+#include "PartSet_WidgetPoint2dAngle.h"
+
+#include <ModuleBase_ParamSpinBox.h>
+
+#include <ModuleBase_Tools.h>
+
+#include <GeomAPI_Pnt2d.h>
+#include <GeomDataAPI_Point2D.h>
+
+#include <ModelAPI_Data.h>
+#include <ModelAPI_AttributeDouble.h>
+
+#include <QMouseEvent>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+
+#define PI 3.1415926535897932
+
+PartSet_WidgetPoint2dAngle::PartSet_WidgetPoint2dAngle(QWidget* theParent,
+                                                       const Config_WidgetAPI* theData,
+                                                       const std::string& theParentId)
+: PartSet_WidgetPoint2dDistance(theParent, theData, theParentId)
+{
+}
+
+PartSet_WidgetPoint2dAngle::~PartSet_WidgetPoint2dAngle()
+{
+}
+
+double PartSet_WidgetPoint2dAngle::computeValue(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPnt,
+                                                const std::shared_ptr<GeomAPI_Pnt2d>& theCurrentPnt)
+{
+  std::shared_ptr<GeomAPI_Dir2d> aHorizontalDir(new GeomAPI_Dir2d(1, 0));
+  std::shared_ptr<GeomAPI_XY> aStartPnt = theFirstPnt->xy();
+  std::shared_ptr<GeomAPI_XY> aEndPnt = theCurrentPnt->xy();
+
+  std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
+
+  double aValue = aHorizontalDir->angle(aLineDir);
+  aValue *= 180.0 / PI;
+
+  return aValue;
+}
diff --git a/src/PartSet/PartSet_WidgetPoint2dAngle.h b/src/PartSet/PartSet_WidgetPoint2dAngle.h
new file mode 100644 (file)
index 0000000..6dac991
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        PartSet_WidgetPoint2dAngle.h
+// Created:     30 Apr 2015
+// Author:      Natalia Ermolaeva
+
+#ifndef PartSet_WidgetPoint2dAngle_H
+#define PartSet_WidgetPoint2dAngle_H
+
+#include "PartSet.h"
+#include "PartSet_WidgetPoint2dDistance.h"
+
+#include <ModelAPI_Feature.h>
+
+class GeomAPI_Pnt2d;
+
+/**
+* \ingroup Modules
+* Implementation of model widget for widget which provides input of an anble between two points
+* The XML definion is the same as the parent one.
+*/ 
+class PARTSET_EXPORT PartSet_WidgetPoint2dAngle : public PartSet_WidgetPoint2dDistance
+{
+Q_OBJECT
+ public:
+  /// Constructor
+  /// \param theParent the parent object
+  /// \param theData the widget configuation. The attribute of the model widget is obtained from
+  /// \param theParentId is Id of a parent of the current attribute
+  PartSet_WidgetPoint2dAngle(QWidget* theParent, const Config_WidgetAPI* theData,
+                             const std::string& theParentId);
+
+  virtual ~PartSet_WidgetPoint2dAngle();
+
+protected:
+  /// Compute an angle between points
+  /// \param theFirstPnt a point value of the out point attribute
+  /// \param theCurrentPnt a point of the current widget
+  /// \return a double value
+  virtual double computeValue(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPnt,
+                              const std::shared_ptr<GeomAPI_Pnt2d>& theCurrentPnt);
+};
+
+#endif
index e20186a26a43eb68422d222064f729855b826731..07cf1877b7303c76a175fdc316933b3122bc3d61 100644 (file)
@@ -60,16 +60,22 @@ void PartSet_WidgetPoint2dDistance::setPoint(FeaturePtr theFeature,
   if (!aPoint)
     return;
 
-  double aRadius = thePnt->distance(aPoint->pnt());
+  double aValue = computeValue(aPoint->pnt(), thePnt);
   AttributeDoublePtr aReal = aData->real(attributeID());
-  if (aReal && (aReal->value() != aRadius)) {
-    aReal->setValue(aRadius);
+  if (aReal && (aReal->value() != aValue)) {
+    aReal->setValue(aValue);
     
-    ModuleBase_Tools::setSpinValue(mySpinBox, aRadius);
+    ModuleBase_Tools::setSpinValue(mySpinBox, aValue);
     storeValue();
   }
 }
 
+double PartSet_WidgetPoint2dDistance::computeValue(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPnt,
+                                                   const std::shared_ptr<GeomAPI_Pnt2d>& theCurrentPnt)
+{
+  return theCurrentPnt->distance(theFirstPnt);
+}
+
 void PartSet_WidgetPoint2dDistance::activateCustom()
 {
   XGUI_ViewerProxy* aViewer = myWorkshop->viewer();
index 95fc0ed19c450222bb2239c8c81d63f33cfcc7e4..c3020e3a97c5208ba601087d7dedc893b6928d7d 100644 (file)
@@ -85,11 +85,18 @@ protected:
   /// Set the second point which defines a value in the widget as a distance with a first point defined by feature
   void setPoint(FeaturePtr theFeature, const std::shared_ptr<GeomAPI_Pnt2d>& thePnt);
 
+  /// Compute the distance between points
+  /// \param theFirstPnt a point value of the out point attribute
+  /// \param theCurrentPnt a point of the current widget
+  /// \return a double value
+  virtual double computeValue(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPnt,
+                              const std::shared_ptr<GeomAPI_Pnt2d>& theCurrentPnt);
+
 private slots:
   /// Process values changed event
   void onValuesChanged();
 
- private:
+protected:
   XGUI_Workshop* myWorkshop;
   std::string myFirstPntName;
 
index 275a65d17197c6db7749c82ab78b8e0fb44f24f4..a4dbf44f6f70884839b7e4e019812914989f153b 100644 (file)
 
 #include <XGUI_Workshop.h>
 
+#include <XGUI_ModuleConnector.h>
+#include <XGUI_Displayer.h>
+#include <XGUI_SelectionMgr.h>
+#include <XGUI_Selection.h>
+#include <SelectMgr_IndexedMapOfOwner.hxx>
+#include <StdSelect_BRepOwner.hxx>
+
 PartSet_WidgetShapeSelector::PartSet_WidgetShapeSelector(QWidget* theParent,
                                                          ModuleBase_IWorkshop* theWorkshop,
                                                          const Config_WidgetAPI* theData,
@@ -38,7 +45,7 @@ PartSet_WidgetShapeSelector::~PartSet_WidgetShapeSelector()
 bool PartSet_WidgetShapeSelector::setObject(ObjectPtr theSelectedObject, GeomShapePtr theShape)
 {
   ObjectPtr aSelectedObject = theSelectedObject;
-  GeomShapePtr aShape = theShape;
+  //GeomShapePtr aShape = theShape;
 
   FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(aSelectedObject);
   if (aSelectedFeature == myFeature)  // In order to avoid selection of the same object
@@ -51,47 +58,77 @@ bool PartSet_WidgetShapeSelector::setObject(ObjectPtr theSelectedObject, GeomSha
   if ((aSPFeature.get() != NULL) && aSPFeature->isExternal() && (!myExternalObjectMgr->useExternal()))
     return false;
 
-  if (aSPFeature.get() == NULL && aShape.get() != NULL && !aShape->isNull() && myExternalObjectMgr->useExternal()) {
+  if (aSPFeature.get() == NULL && theShape.get() != NULL && !theShape->isNull() && myExternalObjectMgr->useExternal()) {
     aSelectedObject = myExternalObjectMgr->externalObject(theSelectedObject, theShape, sketch());
   } else {
     // Processing of sketch object
-    DataPtr aData = myFeature->data();
-    if (aShape) {
-      AttributePtr aAttr = aData->attribute(attributeID());
-      AttributeRefAttrPtr aRefAttr = 
-        std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aAttr);
-      if (aRefAttr) {
-        // it is possible that the point feature is selected. It should be used itself
-        // instead of searching an attribute for the shape
-        bool aShapeIsResult = false;
-        /*ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theSelectedObject);
-        if (aResult.get() != NULL) {
-          GeomShapePtr aShapePtr = aResult->shape();
-          // it is important to call isEqual of the shape of result.
-          // It is a GeomAPI_Vertex shape for the point. The shape of the parameter is 
-          // GeomAPI_Shape. It is important to use the realization of the isEqual method from
-          // GeomAPI_Vertex class
-          aShapeIsResult = aShapePtr.get() != NULL && aShapePtr->isEqual(theShape);
-        }*/
-
-        AttributePtr aPntAttr;
-        if (!aShapeIsResult) {
-          TopoDS_Shape aTDSShape = aShape->impl<TopoDS_Shape>();
-          aPntAttr = PartSet_Tools::findAttributeBy2dPoint(aSelectedObject, aTDSShape, mySketch);
+    if (theShape.get()) {
+      setPointAttribute(theSelectedObject, theShape);
+      return true;
+    }
+  }
+  return ModuleBase_WidgetShapeSelector::setObject(aSelectedObject, theShape);
+}
+
+//********************************************************************
+GeomShapePtr PartSet_WidgetShapeSelector::getShape() const
+{
+  // an empty shape by default
+  GeomShapePtr aShape;
+
+  // 1. find an attribute value in attribute reference attribute value
+  DataPtr aData = myFeature->data();
+  AttributePtr aAttr = aData->attribute(attributeID());
+  AttributeRefAttrPtr aRefAttr = 
+    std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aAttr);
+  if (aRefAttr) {
+    if (!aRefAttr->isObject()) {
+      AttributePtr anAttribute = aRefAttr->attr();
+      if (anAttribute.get()) {
+        XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
+        XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
+
+        // 2. find visualized vertices of the attribute and if the attribute of the vertex is
+        // the same, return it
+        FeaturePtr anAttributeFeature = ModelAPI_Feature::feature(anAttribute->owner());
+        // 2.1 get visualized results of the feature
+        const std::list<ResultPtr>& aResList = anAttributeFeature->results();
+        std::list<ResultPtr>::const_iterator anIt = aResList.begin(), aLast = aResList.end();
+        for (; anIt != aLast; anIt++) {
+          AISObjectPtr aAISObj = aDisplayer->getAISObject(*anIt);
+          if (aAISObj.get() != NULL) {
+            Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
+            // 2.2 find selected owners of a visualizedd object
+            SelectMgr_IndexedMapOfOwner aSelectedOwners;  
+            aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
+            for  (Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++) {
+              Handle(SelectMgr_EntityOwner) anOwner = aSelectedOwners(i);
+              if (!anOwner.IsNull()) {
+                Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(anOwner);
+                if (!aBRepOwner.IsNull() && aBRepOwner->HasShape()) {
+                  const TopoDS_Shape& aBRepShape = aBRepOwner->Shape();
+                  if (aBRepShape.ShapeType() == TopAbs_VERTEX) {
+                    // 2.3 if the owner is vertex and an attribute of the vertex is equal to the initial
+                    // attribute, returns the shape
+                    AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(anAttributeFeature,
+                                                                                  aBRepShape, sketch());
+                    if (aPntAttr.get() != NULL && aPntAttr == anAttribute) {
+                      aShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape);
+                      aShape->setImpl(new TopoDS_Shape(aBRepShape));
+                      break;
+                    }
+                  }
+                }
+              }
+            }
+          }
         }
-        // this is an alternative, whether the attribute should be set or object in the attribute
-        // the first check is the attribute because the object already exist
-        // the object is set only if there is no selected attribute
-        // test case is - preselection for distance operation, which contains two points selected on lines
-        if (aPntAttr)
-          aRefAttr->setAttr(aPntAttr);
-        else if (aSelectedObject)
-          aRefAttr->setObject(aSelectedObject);
-        return true;
       }
     }
   }
-  return ModuleBase_WidgetShapeSelector::setObject(aSelectedObject, aShape);
+  if (!aShape.get())
+    aShape = ModuleBase_WidgetShapeSelector::getShape();
+  return aShape;
 }
 
 //********************************************************************
@@ -100,3 +137,40 @@ void PartSet_WidgetShapeSelector::restoreAttributeValue(const bool theValid)
   ModuleBase_WidgetShapeSelector::restoreAttributeValue(theValid);
   myExternalObjectMgr->removeExternal(sketch(), myFeature);
 }
+
+//********************************************************************
+void PartSet_WidgetShapeSelector::setPointAttribute(ObjectPtr theSelectedObject, GeomShapePtr theShape)
+{
+  DataPtr aData = myFeature->data();
+  AttributePtr aAttr = aData->attribute(attributeID());
+  AttributeRefAttrPtr aRefAttr = 
+    std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aAttr);
+  if (aRefAttr) {
+    // it is possible that the point feature is selected. It should be used itself
+    // instead of searching an attribute for the shape
+    bool aShapeIsResult = false;
+    /*ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theSelectedObject);
+    if (aResult.get() != NULL) {
+      GeomShapePtr aShapePtr = aResult->shape();
+      // it is important to call isEqual of the shape of result.
+      // It is a GeomAPI_Vertex shape for the point. The shape of the parameter is 
+      // GeomAPI_Shape. It is important to use the realization of the isEqual method from
+      // GeomAPI_Vertex class
+      aShapeIsResult = aShapePtr.get() != NULL && aShapePtr->isEqual(theShape);
+    }*/
+
+    AttributePtr aPntAttr;
+    if (!aShapeIsResult) {
+      TopoDS_Shape aTDSShape = theShape->impl<TopoDS_Shape>();
+      aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theSelectedObject, aTDSShape, mySketch);
+    }
+    // this is an alternative, whether the attribute should be set or object in the attribute
+    // the first check is the attribute because the object already exist
+    // the object is set only if there is no selected attribute
+    // test case is - preselection for distance operation, which contains two points selected on lines
+    if (aPntAttr)
+      aRefAttr->setAttr(aPntAttr);
+    else
+      aRefAttr->setObject(theSelectedObject);
+  }
+}
index 5aa7ca28314e227b957e45fce3f085e549f448f9..050b64e271b479860c10a54c7952c24125d1482d 100644 (file)
@@ -19,7 +19,7 @@ class PartSet_ExternalObjectsMgr;
 /**
 * \ingroup Modules
 * Customosation of ModuleBase_WidgetShapeSelector in order to provide 
-* working with sketch specific objects.
+* working with sketch specific objects and external objects.
 */
 class PARTSET_EXPORT PartSet_WidgetShapeSelector: public ModuleBase_WidgetShapeSelector
 {
@@ -49,12 +49,25 @@ protected:
   /// \param theShape a selected shape, which is used in the selection attribute
   virtual bool setObject(ObjectPtr theSelectedObject, GeomShapePtr theShape);
 
+  /// Get the shape from the attribute if the attribute contain a shape
+  /// It processes the ref attr type of attributes. It obtains the referenced attribute,
+  /// results of the attribute feature. And it founds a vertes in the owners of the results
+  /// If the vertex is found, it creates a geom shape on it.
+  /// \return a shape
+  virtual GeomShapePtr getShape() const;
+
   /// Creates a backup of the current values of the attribute
   /// It should be realized in the specific widget because of different
   /// parameters of the current attribute
   /// \param theValid a boolean flag, if restore happens for valid parameters
   void restoreAttributeValue(const bool theValid);
 
+  /// Found the sketch point attribute by the shape and set it in the feature attribute
+  /// otherwise set the selected object
+  /// \param theSelectedObject an object
+  /// \param theShape a selected shape, which is used in the selection attribute
+  void setPointAttribute(ObjectPtr theSelectedObject, GeomShapePtr theShape);
+
 protected:
   PartSet_ExternalObjectsMgr* myExternalObjectMgr;
   /// Pointer to a sketch 
index 6912c64b7601628c526549e08363b443fd8b29d4..2ce6f152e509dc63d733a5228c3e3a327f96f137 100644 (file)
@@ -85,7 +85,7 @@ PartSet_WidgetSketchLabel::~PartSet_WidgetSketchLabel()
   erasePreviewPlanes();
 }
 
-bool PartSet_WidgetSketchLabel::setSelection(ModuleBase_ViewerPrs theValue)
+bool PartSet_WidgetSketchLabel::setSelection(const QList<ModuleBase_ViewerPrs>& theValues, int& thePosition)
 {
   // do not use the given selection if the plane of the sketch has been already set.
   // If this check is absent, a selected plane in the viewer can be set in the sketch
@@ -93,7 +93,7 @@ bool PartSet_WidgetSketchLabel::setSelection(ModuleBase_ViewerPrs theValue)
   if (plane().get())
     return true;
 
-  return ModuleBase_WidgetValidated::setSelection(theValue);
+  return ModuleBase_WidgetValidated::setSelection(theValues, thePosition);
 }
 
 QList<QWidget*> PartSet_WidgetSketchLabel::getControls() const
index eea79ea6d552119bf2d568384f6fdd64c2647de6..6a39f04891bb0a5f6c5e4ce1cfa8c7907dae187a 100644 (file)
@@ -52,8 +52,9 @@ Q_OBJECT
   /// This value should be processed in the widget according to the needs
   /// The method is called by the current operation to process the operation preselection.
   /// It is redefined to do nothing if the plane of the sketch has been already set.
-  /// \param theValue the wrapped widget value
-  virtual bool setSelection(ModuleBase_ViewerPrs theValue);
+  /// \param theValues the wrapped selection values
+  /// \param thePosition an index in the list of values, the values should be get from the index
+  virtual bool setSelection(const QList<ModuleBase_ViewerPrs>& theValues, int& thePosition);
 
   virtual bool restoreValue()
   {
index b37f9e71a15296dd4da7597fd00aa8dc52b30285..efc034cb5ee420db422506a8e656f3bf722389fb 100644 (file)
@@ -1,10 +1,14 @@
  <!DOCTYPE RCC><RCC version="1.0">
  <qresource>
+     <file>icons/angle.png</file>
+     <file>icons/angle_up.png</file>
+     <file>icons/angle_down.png</file>
      <file>icons/arc.png</file>
      <file>icons/circle.png</file>
      <file>icons/color.png</file>
      <file>icons/point.png</file>
      <file>icons/plane.png</file>
+     <file>icons/plane_inverted.png</file>
      <file>icons/axis.png</file>
      <file>icons/duplicate.png</file>
      <file>icons/remove.png</file>
      <file>icons/revol.png</file>
      <file>icons/common.png</file>
      <file>icons/import.png</file>
+     <file>icons/export.png</file>
      <file>icons/line.png</file>
      <file>icons/sketch.png</file>
      <file>icons/hand_point.png</file>
+     <file>icons/dimension_up.png</file>
+     <file>icons/dimension_down.png</file>
      <file>icons/dimension_v.png</file>
      <file>icons/radius.png</file>
      <file>icons/perpendicular.png</file>
      <file>icons/fillet.png</file>
      <file>icons/coincedence.png</file>
      <file>icons/mirror.png</file>
+     <file>icons/translate.png</file>
+     <file>icons/rotate.png</file>
+     <file>icons/exec_state_failed.png</file>
+     <file>icons/exec_state_invalid_parameters.png</file>
+     <file>icons/activate.png</file>
+     <file>icons/deactivate.png</file>
+     <file>icons/edit.png</file>
  </qresource>
  </RCC>
diff --git a/src/PartSet/icons/activate.png b/src/PartSet/icons/activate.png
new file mode 100644 (file)
index 0000000..f829179
Binary files /dev/null and b/src/PartSet/icons/activate.png differ
diff --git a/src/PartSet/icons/angle.png b/src/PartSet/icons/angle.png
new file mode 100644 (file)
index 0000000..6330d60
Binary files /dev/null and b/src/PartSet/icons/angle.png differ
diff --git a/src/PartSet/icons/angle_down.png b/src/PartSet/icons/angle_down.png
new file mode 100644 (file)
index 0000000..495ee77
Binary files /dev/null and b/src/PartSet/icons/angle_down.png differ
diff --git a/src/PartSet/icons/angle_up.png b/src/PartSet/icons/angle_up.png
new file mode 100644 (file)
index 0000000..dc085e7
Binary files /dev/null and b/src/PartSet/icons/angle_up.png differ
diff --git a/src/PartSet/icons/deactivate.png b/src/PartSet/icons/deactivate.png
new file mode 100644 (file)
index 0000000..1b1c71a
Binary files /dev/null and b/src/PartSet/icons/deactivate.png differ
diff --git a/src/PartSet/icons/dimension_down.png b/src/PartSet/icons/dimension_down.png
new file mode 100644 (file)
index 0000000..1117200
Binary files /dev/null and b/src/PartSet/icons/dimension_down.png differ
diff --git a/src/PartSet/icons/dimension_up.png b/src/PartSet/icons/dimension_up.png
new file mode 100644 (file)
index 0000000..08bd84c
Binary files /dev/null and b/src/PartSet/icons/dimension_up.png differ
diff --git a/src/PartSet/icons/edit.png b/src/PartSet/icons/edit.png
new file mode 100644 (file)
index 0000000..43a3174
Binary files /dev/null and b/src/PartSet/icons/edit.png differ
diff --git a/src/PartSet/icons/exec_state_failed.png b/src/PartSet/icons/exec_state_failed.png
new file mode 100644 (file)
index 0000000..738f303
Binary files /dev/null and b/src/PartSet/icons/exec_state_failed.png differ
diff --git a/src/PartSet/icons/exec_state_invalid_parameters.png b/src/PartSet/icons/exec_state_invalid_parameters.png
new file mode 100644 (file)
index 0000000..1346f97
Binary files /dev/null and b/src/PartSet/icons/exec_state_invalid_parameters.png differ
diff --git a/src/PartSet/icons/export.png b/src/PartSet/icons/export.png
new file mode 100644 (file)
index 0000000..bd35270
Binary files /dev/null and b/src/PartSet/icons/export.png differ
diff --git a/src/PartSet/icons/plane_inverted.png b/src/PartSet/icons/plane_inverted.png
new file mode 100644 (file)
index 0000000..a13a8bb
Binary files /dev/null and b/src/PartSet/icons/plane_inverted.png differ
diff --git a/src/PartSet/icons/rotate.png b/src/PartSet/icons/rotate.png
new file mode 100644 (file)
index 0000000..b4cbe21
Binary files /dev/null and b/src/PartSet/icons/rotate.png differ
diff --git a/src/PartSet/icons/translate.png b/src/PartSet/icons/translate.png
new file mode 100644 (file)
index 0000000..7939511
Binary files /dev/null and b/src/PartSet/icons/translate.png differ
index 95fa5f06bee10875028b822faaf7c3e3bc11a62b..09a768acf8b9f2b19cc385c1d3bbf96ef8e70cc2 100644 (file)
@@ -27,7 +27,11 @@ void PartSetPlugin_Part::execute()
   if (!aResult) {
     aResult = document()->createPart(data());
     setResult(aResult);
-    aResult->activate();
+    // do not activate part by simple execution if it is not loaded yet: it must be explicitly
+    // activated for this
+    if (!ModelAPI_Session::get()->isLoadByDemand(aResult->data()->name())) {
+      aResult->activate();
+    }
   }
 }
 
index 0a24df58e6fda822b05db56b1cad3ff3b59e7aaf..d679d9ccf62b9586d704309d5b437b0ec3d499ad 100644 (file)
@@ -46,12 +46,6 @@ class PartSetPlugin_Part : public ModelAPI_Feature
   /// Part must be added only to PartSet
   PARTSETPLUGIN_EXPORT virtual const std::string& documentToAdd();
 
-  /// Returns true if this feature must be displayed in the history (top level of Part tree)
-  PARTSETPLUGIN_EXPORT virtual bool isInHistory()
-  {
-    return false;
-  }
-
   /// Use plugin manager for features creation
   PartSetPlugin_Part();
 };
index ecb7fbe79f5561f1bbd547a8367af46fbf44ac98..785fba6ab1848bc96a2d9fbec64a2aa4492345ba 100644 (file)
@@ -18,7 +18,7 @@ class Extrusion():
     else:
          self.my.data().boolean("reverse").setValue(False)
 
-    self.my.data().real("size").setValue(size)
+    self.my.data().real("to_size").setValue(size)
 
     if ModelAPI_Session.get().validators().validate(self.my):
       self.my.execute()
@@ -34,7 +34,7 @@ class Extrusion():
     else:
       self.my.data().boolean("reverse").setValue(False)
 
-    self.my.data().real("size").setValue(size)
+    self.my.data().real("to_size").setValue(size)
     self.my.execute()
 
   def result (self):
index 675b84c42087649765af1ead4b6a36b0fb32d2a6..d5d5e8e07c6efaa2bf603bb04e3a5cbf8e8b6adb 100644 (file)
@@ -82,8 +82,9 @@ class BoxFeature(modeler.Feature):
     self.base.setValue( self.length, length )
     self.box.setSize( height )
 
-    # Publishing the result
-    self.addResult( self.box.result() )
-
-       
-
+    # Publishing the result: not needed for Macro feature
+    #self.addResult( self.box.result() )
+  
+  def isMacro(self):
+    # Box feature is macro: removes itself on the creation transaction finish
+    return True
index f7e3f9aca2bf11eea7cc0bb7d90bb41b198da79b..b4aa3d2cd75278a921a678bbefe014ee28354261 100644 (file)
@@ -28,6 +28,8 @@ SET(PROJECT_HEADERS
     SketchPlugin_ConstraintTangent.h
     SketchPlugin_ConstraintMirror.h
     SketchPlugin_ConstraintFillet.h
+    SketchPlugin_MultiRotation.h
+    SketchPlugin_MultiTranslation.h
     SketchPlugin_ExternalValidator.h
     SketchPlugin_Validators.h
 )
@@ -55,6 +57,8 @@ SET(PROJECT_SOURCES
     SketchPlugin_ConstraintTangent.cpp
     SketchPlugin_ConstraintMirror.cpp
     SketchPlugin_ConstraintFillet.cpp
+    SketchPlugin_MultiRotation.cpp
+    SketchPlugin_MultiTranslation.cpp
     SketchPlugin_ExternalValidator.cpp
     SketchPlugin_Validators.cpp
 )
index 623b6c62549757eaf2b35f54ff9ddb38437baebf..8625d578bb3508c5751b2f9a2cd20404d707a4ee 100644 (file)
@@ -51,12 +51,7 @@ void SketchPlugin_Circle::execute()
       std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
       //std::cout<<"Execute circle "<<aCenter->x()<<" "<<aCenter->y()<<" "<<aCenter->z()<<std::endl;
       // make a visible point
-      std::shared_ptr<GeomAPI_Shape> aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter);
-      std::shared_ptr<ModelAPI_ResultConstruction> aConstr1 = document()->createConstruction(
-          data(), 0);
-      aConstr1->setShape(aCenterPointShape);
-      aConstr1->setIsInHistory(false);
-      setResult(aConstr1, 0);
+      SketchPlugin_Sketch::createPoint2DResult(this, sketch(), CENTER_ID(), 0);
 
       // make a visible circle
       std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
index ddf0cbf7fff2f6a9dff2f5a0f5e32da590c82c6a..cd7155409b14f2de533dcbefd9c2549878287858 100644 (file)
@@ -30,8 +30,8 @@
  *    Also the list of possible attributes is provided to simplify assignment.
  */
 
-#define SKETCH_CONSTRAINT_COLOR "#ffff00"
-#define SKETCH_DIMENSION_COLOR "#ff00ff"
+#define SKETCH_CONSTRAINT_COLOR "225,225,0"
+#define SKETCH_DIMENSION_COLOR "64,128,225"
 
 /** \class SketchPlugin_ConstraintBase
  *  \ingroup Plugins
index ce8fa25de2daa4b3f1637189d2bf912210e683ef..4f5110400708e8c5b4bdd8636a44208c1fd4ca19 100644 (file)
@@ -36,9 +36,9 @@ AISObjectPtr SketchPlugin_ConstraintCoincidence::getAISObject(AISObjectPtr thePr
   AISObjectPtr anAIS = thePrevious;
   if (!anAIS) {
     anAIS = SketcherPrs_Factory::coincidentConstraint(this, sketch()->coordinatePlane());
-  std::vector<int> aRGB = Config_PropManager::color("Visualization", "sketch_constraint_color",
-                                                    SKETCH_DIMENSION_COLOR);
-  anAIS->setColor(aRGB[0], aRGB[1], aRGB[2]);
+  //std::vector<int> aRGB = Config_PropManager::color("Visualization", "sketch_constraint_color",
+  //                                                  SKETCH_DIMENSION_COLOR);
+  //anAIS->setColor(aRGB[0], aRGB[1], aRGB[2]);
   }
   return anAIS;
 }
diff --git a/src/SketchPlugin/SketchPlugin_MultiRotation.cpp b/src/SketchPlugin/SketchPlugin_MultiRotation.cpp
new file mode 100644 (file)
index 0000000..f0ad011
--- /dev/null
@@ -0,0 +1,273 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:    SketchPlugin_MultiRotation.cpp
+// Created: 21 Apr 2015
+// Author:  Artem ZHIDKOV
+
+#include "SketchPlugin_MultiRotation.h"
+
+#include <GeomDataAPI_Point2D.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_Events.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_XY.h>
+
+#include <SketcherPrs_Factory.h>
+
+#include <cmath>
+
+#define PI 3.1415926535897932
+
+SketchPlugin_MultiRotation::SketchPlugin_MultiRotation()
+{
+}
+
+void SketchPlugin_MultiRotation::initAttributes()
+{
+  data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(ANGLE_ID(), ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(NUMBER_OF_COPIES_ID(), ModelAPI_AttributeInteger::typeId());
+  data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefList::typeId());
+  data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::typeId());
+  AttributeSelectionListPtr aSelection = 
+    std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
+    ROTATION_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
+  aSelection->setSelectionType("EDGE");
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_A());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_B());
+}
+
+void SketchPlugin_MultiRotation::execute()
+{
+  AttributeSelectionListPtr aRotationObjectRefs = selectionList(ROTATION_LIST_ID());
+  int aNbCopies = integer(NUMBER_OF_COPIES_ID())->value();
+
+  // Obtain center and angle of rotation
+  std::shared_ptr<GeomDataAPI_Point2D> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      attribute(CENTER_ID()));
+  if (!aCenter || !aCenter->isInitialized())
+    return;
+  // make a visible points
+  SketchPlugin_Sketch::createPoint2DResult(this, sketch(), CENTER_ID(), 0);
+
+  double anAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+      attribute(ANGLE_ID()))->value();
+  // Convert angle to radians
+  anAngle *= PI / 180.0;
+
+  // Wait all objects being created, then send update events
+  static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+  bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
+  if (isUpdateFlushed)
+    Events_Loop::loop()->setFlushed(anUpdateEvent, false);
+
+  std::shared_ptr<ModelAPI_Data> aData = data();
+  AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+      aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  AttributeRefListPtr aRefListOfRotated = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+      aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
+  int aCurrentNbCopies = aRefListOfShapes->size() ?
+      aRefListOfRotated->size() / aRefListOfShapes->size() - 1 : 0;
+  std::list<ObjectPtr> anInitialList = aRefListOfShapes->list();
+  std::list<ObjectPtr> aTargetList = aRefListOfRotated->list();
+  std::list<ResultPtr> anAddition;
+  std::vector<bool> isUsed(anInitialList.size(), false);
+  // collect new items and check the items to remove
+  for(int anInd = 0; anInd < aRotationObjectRefs->size(); anInd++) {
+    std::shared_ptr<ModelAPI_AttributeSelection> aSelect = aRotationObjectRefs->value(anInd);
+    std::list<ObjectPtr>::const_iterator anIt = anInitialList.begin();
+    std::vector<bool>::iterator aUsedIt = isUsed.begin();
+    for (; anIt != anInitialList.end(); anIt++, aUsedIt++)
+      if (*anIt == aSelect->context()) {
+        *aUsedIt = true;
+        break;
+      }
+    if (anIt == anInitialList.end())
+      anAddition.push_back(aSelect->context());
+  }
+  // remove unused items
+  std::list<ObjectPtr>::iterator anInitIter = anInitialList.begin();
+  std::list<ObjectPtr>::iterator aTargetIter = aTargetList.begin();
+  std::vector<bool>::iterator aUsedIter = isUsed.begin();
+  for (; aUsedIter != isUsed.end(); aUsedIter++) {
+    if (!(*aUsedIter)) {
+      aRefListOfShapes->remove(*anInitIter);
+      for (int i = 0; i < aCurrentNbCopies && aTargetIter != aTargetList.end(); i++, aTargetIter++) {
+        aRefListOfRotated->remove(*aTargetIter);
+        // remove the corresponding feature from the sketch
+        ResultConstructionPtr aRC =
+            std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aTargetIter);
+        DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
+        FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
+        if (aFeature)
+          aDoc->removeFeature(aFeature);
+      }
+    } else {
+      for (int i = 0; i <= aNbCopies && aTargetIter != aTargetList.end(); i++)
+        aTargetIter++;
+    }
+    if (anInitIter != anInitialList.end())
+      anInitIter++;
+  }
+  // change number of copies
+  if (aCurrentNbCopies != 0 && aNbCopies != aCurrentNbCopies) {
+    bool isAdd = aNbCopies > aCurrentNbCopies;
+    int aMinCopies = isAdd ? aCurrentNbCopies : aNbCopies;
+    int aMaxCopies = isAdd ? aNbCopies : aCurrentNbCopies;
+    int ind = 0;
+
+    aTargetList = aRefListOfRotated->list();
+    aTargetIter = aTargetList.begin();
+    ObjectPtr anObjToCopy = *aTargetIter;
+    while (aTargetIter != aTargetList.end()) {
+      aRefListOfRotated->remove(*aTargetIter);
+      aTargetIter++;
+      ind++;
+      if (ind > aMinCopies && ind <=aMaxCopies) {
+        while (ind <= aMaxCopies) {
+          if (isAdd) {
+            // Add new shifted item
+            ObjectPtr anObject = copyFeature(anObjToCopy);
+            aTargetList.insert(aTargetIter, anObject);
+          } else {
+            // remove object
+            std::list<ObjectPtr>::iterator aRemoveIt = aTargetIter++;
+            ObjectPtr anObject = *aRemoveIt;
+            aTargetList.erase(aRemoveIt);
+            aRefListOfRotated->remove(anObject);
+            // remove the corresponding feature from the sketch
+            ResultConstructionPtr aRC =
+                std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(anObject);
+            DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
+            FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
+            if (aFeature)
+              aDoc->removeFeature(aFeature);
+          }
+          ind++;
+        }
+        ind = 0;
+        if (aTargetIter != aTargetList.end())
+          anObjToCopy = *aTargetIter;
+      }
+    }
+
+    for (aTargetIter = aTargetList.begin(); aTargetIter != aTargetList.end(); aTargetIter++)
+      aRefListOfRotated->append(*aTargetIter);
+  }
+  // add new items
+  std::list<ResultPtr>::iterator anAddIter = anAddition.begin();
+  for (; anAddIter != anAddition.end(); anAddIter++) {
+    aRefListOfShapes->append(*anAddIter);
+    aRefListOfRotated->append(*anAddIter);
+    for (int i = 0; i < aNbCopies; i++) {
+      ObjectPtr anObject = copyFeature(*anAddIter);
+      aRefListOfRotated->append(anObject);
+    }
+  }
+
+////  if (fabs(anAngle) > 1.e-12) {
+////    // Recalculate positions of features
+////    aTargetList = aRefListOfRotated->list();
+////    aTargetIter = aTargetList.begin();
+////    while (aTargetIter != aTargetList.end()) {
+////      ObjectPtr anInitialObject = *aTargetIter++;
+////      for (int i = 0; i < aNbCopies && aTargetIter != aTargetList.end(); i++, aTargetIter++)
+////        rotateFeature(anInitialObject, *aTargetIter, aCenter->x(), aCenter->y(), anAngle * (i + 1));
+////    }
+////  }
+
+  // send events to update the sub-features by the solver
+  if (isUpdateFlushed)
+    Events_Loop::loop()->setFlushed(anUpdateEvent, true);
+}
+
+AISObjectPtr SketchPlugin_MultiRotation::getAISObject(AISObjectPtr thePrevious)
+{
+  if (!sketch())
+    return thePrevious;
+
+  AISObjectPtr anAIS = thePrevious;
+  if (!anAIS) {
+    anAIS = SketcherPrs_Factory::rotateConstraint(this, sketch()->coordinatePlane());
+  }
+  return anAIS;
+}
+
+
+ObjectPtr SketchPlugin_MultiRotation::copyFeature(ObjectPtr theObject)
+{
+  ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theObject);
+  FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+  if (!aFeature || !aResult)
+    return ObjectPtr();
+
+  FeaturePtr aNewFeature = sketch()->addFeature(aFeature->getKind());
+  aFeature->data()->copyTo(aNewFeature->data());
+  aNewFeature->execute();
+
+  static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  ModelAPI_EventCreator::get()->sendUpdated(aNewFeature, aRedisplayEvent);
+
+  std::shared_ptr<GeomAPI_Shape> aShapeIn = aResult->shape();
+  const std::list<ResultPtr>& aResults = aNewFeature->results();
+  std::list<ResultPtr>::const_iterator anIt = aResults.begin();
+  for (; anIt != aResults.end(); anIt++) {
+    ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anIt);
+    if (!aRC) continue;
+    std::shared_ptr<GeomAPI_Shape> aShapeOut = aRC->shape();
+    if ((aShapeIn->isVertex() && aShapeOut->isVertex()) ||
+        (aShapeIn->isEdge() && aShapeOut->isEdge()) ||
+        (aShapeIn->isFace() && aShapeOut->isFace()))
+      return aRC;
+  }
+  return ObjectPtr();
+}
+
+void SketchPlugin_MultiRotation::rotateFeature(
+    ObjectPtr theInitial, ObjectPtr theTarget,
+    double theCenterX, double theCenterY, double theAngle)
+{
+  std::shared_ptr<GeomAPI_Pnt2d> aCenter(new GeomAPI_Pnt2d(theCenterX, theCenterY));
+  double cosA = std::cos(theAngle);
+  double sinA = std::sin(theAngle);
+
+  FeaturePtr anInitialFeature = ModelAPI_Feature::feature(theInitial);
+  FeaturePtr aTargetFeature = ModelAPI_Feature::feature(theTarget);
+
+  // block feature update
+  aTargetFeature->data()->blockSendAttributeUpdated(true);
+
+  std::list<AttributePtr> anInitAttrList =
+      anInitialFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
+  std::list<AttributePtr> aTargetAttrList =
+      aTargetFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
+  std::list<AttributePtr>::iterator anInitIt = anInitAttrList.begin();
+  std::list<AttributePtr>::iterator aTargetIt = aTargetAttrList.begin();
+  for (; anInitIt != anInitAttrList.end(); anInitIt++, aTargetIt++) {
+    std::shared_ptr<GeomDataAPI_Point2D> aPointFrom =
+        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anInitIt);
+    std::shared_ptr<GeomDataAPI_Point2D> aPointTo =
+        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aTargetIt);
+    std::shared_ptr<GeomAPI_XY> aPnt = aPointFrom->pnt()->xy();
+    if (aPnt->distance(aCenter->xy()) > 1.e-7) {
+      std::shared_ptr<GeomAPI_XY> aDir = aPnt->decreased(aCenter->xy());
+      double dx = cosA * aDir->x() - sinA * aDir->y();
+      double dy = sinA * aDir->x() + cosA * aDir->y();
+      aPnt->setX(aCenter->x() + dx);
+      aPnt->setY(aCenter->y() + dy);
+    }
+    aPointTo->setValue(aPnt->x(), aPnt->y());
+  }
+
+  // unblock feature update
+  aTargetFeature->data()->blockSendAttributeUpdated(false);
+}
+
diff --git a/src/SketchPlugin/SketchPlugin_MultiRotation.h b/src/SketchPlugin/SketchPlugin_MultiRotation.h
new file mode 100644 (file)
index 0000000..e743386
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:    SketchPlugin_MultiRotation.h
+// Created: 21 Apr 2015
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchPlugin_MultiRotation_H_
+#define SketchPlugin_MultiRotation_H_
+
+#include "SketchPlugin.h"
+#include <SketchPlugin_Sketch.h>
+#include "SketchPlugin_ConstraintBase.h"
+
+/** \class SketchPlugin_MultiRotation
+ *  \ingroup Plugins
+ *  \brief Feature for creation of a number of rotated copies of a list of objects
+ *
+ *  This constraint has two attributes:
+ *  SketchPlugin_Constraint::ENTITY_A() for initial list of objects and
+ *  SketchPlugin_Constraint::ENTITY_B() for the list of created objects
+ *
+ *  The list of created objects contains a number of copies of each object given in
+ *  the NUMBER_OF_COPIES_ID() attribute plus 1 (the initial objects are stored into this
+ *  attribute too). At the start of the list, there are collected N copies
+ *  of first object from initial list, then N copies of second object etc.
+ */
+class SketchPlugin_MultiRotation : public SketchPlugin_ConstraintBase
+{
+ public:
+  /// Multi-rotation kind
+  inline static const std::string& ID()
+  {
+    static const std::string MY_CONSTRAINT_ROTATION_ID("SketchMultiRotation");
+    return MY_CONSTRAINT_ROTATION_ID;
+  }
+  /// \brief Returns the kind of a feature
+  SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = SketchPlugin_MultiRotation::ID();
+    return MY_KIND;
+  }
+
+  /// List of objects to be mirrored
+  inline static const std::string& ROTATION_LIST_ID()
+  {
+    static const std::string MY_ROTATION_LIST_ID("MultiRotationList");
+    return MY_ROTATION_LIST_ID;
+  }
+
+  /// Center of rotation
+  inline static const std::string& CENTER_ID()
+  {
+    static const std::string MY_CENTER_ID("MultiRotationCenter");
+    return MY_CENTER_ID;
+  }
+  /// End point of translation
+  inline static const std::string& ANGLE_ID()
+  {
+    static const std::string MY_ANGLE_ID("MultiRotationAngle");
+    return MY_ANGLE_ID;
+  }
+  /// Number of translated objects
+  inline static const std::string& NUMBER_OF_COPIES_ID()
+  {
+    static const std::string MY_NUMBER_OF_COPIES_ID("MultiRotationCopies");
+    return MY_NUMBER_OF_COPIES_ID;
+  }
+
+  /// \brief Creates a new part document if needed
+  SKETCHPLUGIN_EXPORT virtual void execute();
+
+  /// \brief Request for initialization of data model of the feature: adding all attributes
+  SKETCHPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Returns the AIS preview
+  SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
+
+  /// \brief Use plugin manager for features creation
+  SketchPlugin_MultiRotation();
+
+private:
+  ObjectPtr copyFeature(ObjectPtr theObject);
+  void rotateFeature(ObjectPtr theInitial, ObjectPtr theTarget,
+                     double theCenterX, double theCenterY, double theAngle);
+};
+
+#endif
diff --git a/src/SketchPlugin/SketchPlugin_MultiTranslation.cpp b/src/SketchPlugin/SketchPlugin_MultiTranslation.cpp
new file mode 100644 (file)
index 0000000..71eca57
--- /dev/null
@@ -0,0 +1,216 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:    SketchPlugin_MultiTranslation.cpp
+// Created: 21 Apr 2015
+// Author:  Artem ZHIDKOV
+
+#include "SketchPlugin_MultiTranslation.h"
+
+#include <GeomAPI_XY.h>
+#include <GeomDataAPI_Point2D.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_Events.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+
+#include <SketcherPrs_Factory.h>
+
+SketchPlugin_MultiTranslation::SketchPlugin_MultiTranslation()
+{
+}
+
+void SketchPlugin_MultiTranslation::initAttributes()
+{
+  data()->addAttribute(START_POINT_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(END_POINT_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(NUMBER_OF_COPIES_ID(), ModelAPI_AttributeInteger::typeId());
+  data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefList::typeId());
+  data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::typeId());
+  AttributeSelectionListPtr aSelection = 
+    std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
+    TRANSLATION_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
+  aSelection->setSelectionType("EDGE");
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_A());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_B());
+}
+
+void SketchPlugin_MultiTranslation::execute()
+{
+  AttributeSelectionListPtr aTranslationObjectRefs = selectionList(TRANSLATION_LIST_ID());
+  int aNbCopies = integer(NUMBER_OF_COPIES_ID())->value();
+
+  // Calculate shift vector
+  std::shared_ptr<GeomDataAPI_Point2D> aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      attribute(START_POINT_ID()));
+  std::shared_ptr<GeomDataAPI_Point2D> aEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      attribute(END_POINT_ID()));
+  if (!aStart || !aEnd || !aStart->isInitialized() || !aEnd->isInitialized())
+    return;
+
+  // make a visible points
+  SketchPlugin_Sketch::createPoint2DResult(this, sketch(), START_POINT_ID(), 0);
+  SketchPlugin_Sketch::createPoint2DResult(this, sketch(), END_POINT_ID(), 1);
+
+  std::shared_ptr<GeomAPI_XY> aShiftVec(new GeomAPI_XY(aEnd->x() - aStart->x(), aEnd->y() - aStart->y()));
+
+  // Wait all objects being created, then send update events
+  static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+  bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
+  if (isUpdateFlushed)
+    Events_Loop::loop()->setFlushed(anUpdateEvent, false);
+
+  std::shared_ptr<ModelAPI_Data> aData = data();
+  AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+      aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  AttributeRefListPtr aRefListOfTranslated = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+      aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
+  int aCurrentNbCopies = aRefListOfShapes->size() ?
+      aRefListOfTranslated->size() / aRefListOfShapes->size() - 1 : 0;
+  std::list<ObjectPtr> anInitialList = aRefListOfShapes->list();
+  std::list<ObjectPtr> aTargetList = aRefListOfTranslated->list();
+  std::list<ResultPtr> anAddition;
+  std::vector<bool> isUsed(anInitialList.size(), false);
+  // collect new items and check the items to remove
+  for(int anInd = 0; anInd < aTranslationObjectRefs->size(); anInd++) {
+    std::shared_ptr<ModelAPI_AttributeSelection> aSelect = aTranslationObjectRefs->value(anInd);
+    std::list<ObjectPtr>::const_iterator anIt = anInitialList.begin();
+    std::vector<bool>::iterator aUsedIt = isUsed.begin();
+    for (; anIt != anInitialList.end(); anIt++, aUsedIt++)
+      if (*anIt == aSelect->context()) {
+        *aUsedIt = true;
+        break;
+      }
+    if (anIt == anInitialList.end())
+      anAddition.push_back(aSelect->context());
+  }
+  // remove unused items
+  std::list<ObjectPtr>::iterator anInitIter = anInitialList.begin();
+  std::list<ObjectPtr>::iterator aTargetIter = aTargetList.begin();
+  std::vector<bool>::iterator aUsedIter = isUsed.begin();
+  for (; aUsedIter != isUsed.end(); aUsedIter++) {
+    if (!(*aUsedIter)) {
+      aRefListOfShapes->remove(*anInitIter);
+      for (int i = 0; i < aCurrentNbCopies && aTargetIter != aTargetList.end(); i++, aTargetIter++) {
+        aRefListOfTranslated->remove(*aTargetIter);
+        // remove the corresponding feature from the sketch
+        ResultConstructionPtr aRC =
+            std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aTargetIter);
+        DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
+        FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
+        if (aFeature)
+          aDoc->removeFeature(aFeature);
+      }
+    } else {
+      for (int i = 0; i <= aNbCopies && aTargetIter != aTargetList.end(); i++)
+        aTargetIter++;
+    }
+    if (anInitIter != anInitialList.end())
+      anInitIter++;
+  }
+  // change number of copies
+  if (aCurrentNbCopies != 0 && aNbCopies != aCurrentNbCopies) {
+    bool isAdd = aNbCopies > aCurrentNbCopies;
+    int aMinCopies = isAdd ? aCurrentNbCopies : aNbCopies;
+    int aMaxCopies = isAdd ? aNbCopies : aCurrentNbCopies;
+    int ind = 0;
+
+    aTargetList = aRefListOfTranslated->list();
+    aTargetIter = aTargetList.begin();
+    ObjectPtr anObjToCopy = *aTargetIter;
+    while (aTargetIter != aTargetList.end()) {
+      aRefListOfTranslated->remove(*aTargetIter);
+      aTargetIter++;
+      ind++;
+      if (ind > aMinCopies && ind <=aMaxCopies) {
+        while (ind <= aMaxCopies) {
+          if (isAdd) {
+            // Add new shifted item
+            ObjectPtr anObject = copyFeature(anObjToCopy);
+            aTargetList.insert(aTargetIter, anObject);
+          } else {
+            // remove object
+            std::list<ObjectPtr>::iterator aRemoveIt = aTargetIter++;
+            ObjectPtr anObject = *aRemoveIt;
+            aTargetList.erase(aRemoveIt);
+            aRefListOfTranslated->remove(anObject);
+            // remove the corresponding feature from the sketch
+            ResultConstructionPtr aRC =
+                std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(anObject);
+            DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
+            FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
+            if (aFeature)
+              aDoc->removeFeature(aFeature);
+          }
+          ind++;
+        }
+        ind = 0;
+        if (aTargetIter != aTargetList.end())
+          anObjToCopy = *aTargetIter;
+      }
+    }
+
+    for (aTargetIter = aTargetList.begin(); aTargetIter != aTargetList.end(); aTargetIter++)
+      aRefListOfTranslated->append(*aTargetIter);
+  }
+  // add new items
+  std::list<ResultPtr>::iterator anAddIter = anAddition.begin();
+  for (; anAddIter != anAddition.end(); anAddIter++) {
+    aRefListOfShapes->append(*anAddIter);
+    aRefListOfTranslated->append(*anAddIter);
+    for (int i = 0; i < aNbCopies; i++) {
+      ObjectPtr anObject = copyFeature(*anAddIter);
+      aRefListOfTranslated->append(anObject);
+    }
+  }
+
+  // send events to update the sub-features by the solver
+  if (isUpdateFlushed)
+    Events_Loop::loop()->setFlushed(anUpdateEvent, true);
+}
+
+AISObjectPtr SketchPlugin_MultiTranslation::getAISObject(AISObjectPtr thePrevious)
+{
+  if (!sketch())
+    return thePrevious;
+
+  AISObjectPtr anAIS = thePrevious;
+  if (!anAIS) {
+    anAIS = SketcherPrs_Factory::translateConstraint(this, sketch()->coordinatePlane());
+  }
+  return anAIS;
+}
+
+ObjectPtr SketchPlugin_MultiTranslation::copyFeature(ObjectPtr theObject)
+{
+  ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theObject);
+  FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+  if (!aFeature || !aResult)
+    return ObjectPtr();
+
+  FeaturePtr aNewFeature = sketch()->addFeature(aFeature->getKind());
+  aFeature->data()->copyTo(aNewFeature->data());
+  aNewFeature->execute();
+
+  static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  ModelAPI_EventCreator::get()->sendUpdated(aNewFeature, aRedisplayEvent);
+
+  std::shared_ptr<GeomAPI_Shape> aShapeIn = aResult->shape();
+  const std::list<ResultPtr>& aResults = aNewFeature->results();
+  std::list<ResultPtr>::const_iterator anIt = aResults.begin();
+  for (; anIt != aResults.end(); anIt++) {
+    ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*anIt);
+    if (!aRC) continue;
+    std::shared_ptr<GeomAPI_Shape> aShapeOut = aRC->shape();
+    if ((aShapeIn->isVertex() && aShapeOut->isVertex()) ||
+        (aShapeIn->isEdge() && aShapeOut->isEdge()) ||
+        (aShapeIn->isFace() && aShapeOut->isFace()))
+      return aRC;
+  }
+  return ObjectPtr();
+}
+
diff --git a/src/SketchPlugin/SketchPlugin_MultiTranslation.h b/src/SketchPlugin/SketchPlugin_MultiTranslation.h
new file mode 100644 (file)
index 0000000..f741d2e
--- /dev/null
@@ -0,0 +1,85 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File:    SketchPlugin_MultiTranslation.h
+// Created: 21 Apr 2015
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchPlugin_MultiTranslation_H_
+#define SketchPlugin_MultiTranslation_H_
+
+#include "SketchPlugin.h"
+#include <SketchPlugin_Sketch.h>
+#include "SketchPlugin_ConstraintBase.h"
+
+/** \class SketchPlugin_MultiTranslation
+ *  \ingroup Plugins
+ *  \brief Feature for creation of a number of shifted copies of a list of objects
+ *
+ *  This constraint has two attributes:
+ *  SketchPlugin_Constraint::ENTITY_A() for initial list of objects and
+ *  SketchPlugin_Constraint::ENTITY_B() for the list of created objects
+ *
+ *  The list of created objects contains a number of copies of each object given in
+ *  the NUMBER_OF_COPIES_ID() attribute plus 1 (the initial objects are stored into this
+ *  attribute too). At the start of the list, there are collected N copies
+ *  of first object from initial list, then N copies of second object etc.
+ */
+class SketchPlugin_MultiTranslation : public SketchPlugin_ConstraintBase
+{
+ public:
+  /// Multi-translation kind
+  inline static const std::string& ID()
+  {
+    static const std::string MY_CONSTRAINT_TRANSLATION_ID("SketchMultiTranslation");
+    return MY_CONSTRAINT_TRANSLATION_ID;
+  }
+  /// \brief Returns the kind of a feature
+  SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = SketchPlugin_MultiTranslation::ID();
+    return MY_KIND;
+  }
+
+  /// List of objects to be mirrored
+  inline static const std::string& TRANSLATION_LIST_ID()
+  {
+    static const std::string MY_TRANSLATION_LIST_ID("MultiTranslationList");
+    return MY_TRANSLATION_LIST_ID;
+  }
+
+  /// Start point of translation
+  inline static const std::string& START_POINT_ID()
+  {
+    static const std::string MY_START_POINT_ID("MultiTranslationStartPoint");
+    return MY_START_POINT_ID;
+  }
+  /// End point of translation
+  inline static const std::string& END_POINT_ID()
+  {
+    static const std::string MY_END_POINT_ID("MultiTranslationEndPoint");
+    return MY_END_POINT_ID;
+  }
+  /// Number of translated objects
+  inline static const std::string& NUMBER_OF_COPIES_ID()
+  {
+    static const std::string MY_NUMBER_OF_COPIES_ID("MultiTranslationCopies");
+    return MY_NUMBER_OF_COPIES_ID;
+  }
+
+  /// \brief Creates a new part document if needed
+  SKETCHPLUGIN_EXPORT virtual void execute();
+
+  /// \brief Request for initialization of data model of the feature: adding all attributes
+  SKETCHPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Returns the AIS preview
+  SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
+
+  /// \brief Use plugin manager for features creation
+  SketchPlugin_MultiTranslation();
+
+private:
+  ObjectPtr copyFeature(ObjectPtr theObject);
+};
+
+#endif
index 91a92ce7b2f89dd8498c70cd8c2b9066af0a7e37..904fe1e2200957c9fc4a255efc923214e7844e1a 100644 (file)
@@ -19,6 +19,8 @@
 #include <SketchPlugin_ConstraintRigid.h>
 #include <SketchPlugin_ConstraintTangent.h>
 #include <SketchPlugin_ConstraintVertical.h>
+#include <SketchPlugin_MultiRotation.h>
+#include <SketchPlugin_MultiTranslation.h>
 #include <SketchPlugin_Validators.h>
 #include <SketchPlugin_ExternalValidator.h>
 
@@ -61,6 +63,10 @@ SketchPlugin_Plugin::SketchPlugin_Plugin()
                               new SketchPlugin_EqualAttrValidator);
   aFactory->registerValidator("SketchPlugin_MirrorAttr",
                               new SketchPlugin_MirrorAttrValidator);
+  aFactory->registerValidator("SketchPlugin_CoincidenceAttr",
+                              new SketchPlugin_CoincidenceAttrValidator);
+  aFactory->registerValidator("SketchPlugin_CopyValidator",
+                              new SketchPlugin_CopyValidator);
 
   // register this plugin
   ModelAPI_Session::get()->registerPlugin(this);
@@ -129,6 +135,10 @@ FeaturePtr SketchPlugin_Plugin::createFeature(string theFeatureID)
     return FeaturePtr(new SketchPlugin_ConstraintMirror);
   } else if (theFeatureID == SketchPlugin_ConstraintFillet::ID()) {
     return FeaturePtr(new SketchPlugin_ConstraintFillet);
+  } else if (theFeatureID == SketchPlugin_MultiTranslation::ID()) {
+    return FeaturePtr(new SketchPlugin_MultiTranslation);
+  } else if (theFeatureID == SketchPlugin_MultiRotation::ID()) {
+    return FeaturePtr(new SketchPlugin_MultiRotation);
   }
   // feature of such kind is not found
   return FeaturePtr();
index 64b0c09f6f36f39ddaa0dd51a6c0f9071ec65e01..2d02f0dd10f3a64e2900c035b30f96cb48e06cb9 100644 (file)
@@ -15,6 +15,9 @@
 
 #include <GeomAlgoAPI_FaceBuilder.h>
 
+#include <GeomDataAPI_Point2D.h>
+#include <GeomAlgoAPI_PointBuilder.h>
+
 #include <ModelAPI_AttributeRefList.h>
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Document.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_Session.h>
+#include <ModelAPI_Events.h>
 
 #include <SketchPlugin_Sketch.h>
 #include <SketchPlugin_Feature.h>
 #include <SketchPlugin_SketchEntity.h>
 
+#include <Events_Loop.h>
+
 #include <memory>
 
 #include <math.h>
@@ -119,11 +125,13 @@ void SketchPlugin_Sketch::execute()
 
 std::shared_ptr<ModelAPI_Feature> SketchPlugin_Sketch::addFeature(std::string theID)
 {
-  std::shared_ptr<ModelAPI_Feature> aNew = document()->addFeature(theID);
+  std::shared_ptr<ModelAPI_Feature> aNew = document()->addFeature(theID, false);
   if (aNew) {
     std::dynamic_pointer_cast<SketchPlugin_Feature>(aNew)->setSketch(this);
     data()->reflist(SketchPlugin_Sketch::FEATURES_ID())->append(aNew);
   }
+   // set as current also after it becomes sub to set correctly enabled for other sketch subs
+  document()->setCurrentFeature(aNew, false);
   return aNew;
 }
 
@@ -240,5 +248,35 @@ void SketchPlugin_Sketch::attributeChanged(const std::string& theID) {
         std::shared_ptr<GeomAPI_Dir> aDir = aPlane->direction();
       }
     }
+  } else if (theID == SketchPlugin_Sketch::NORM_ID() || theID == SketchPlugin_Sketch::DIRX_ID()) {
+    // send all sub-elements are also updated: all entities become created on different plane
+    static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+    std::list<ObjectPtr> aSubs = data()->reflist(SketchPlugin_Sketch::FEATURES_ID())->list();
+    std::list<ObjectPtr>::iterator aSub = aSubs.begin();
+    for(; aSub != aSubs.end(); aSub++) {
+      ModelAPI_EventCreator::get()->sendUpdated(*aSub, anUpdateEvent);
+    }
   }
 }
+
+void SketchPlugin_Sketch::createPoint2DResult(ModelAPI_Feature* theFeature,
+                                              SketchPlugin_Sketch* theSketch,
+                                              const std::string& theAttributeID, const int theIndex)
+{
+  std::shared_ptr<GeomDataAPI_Point2D> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+    theFeature->attribute(theAttributeID));
+
+  if (!aPoint || !aPoint->isInitialized())
+    return;
+
+  std::shared_ptr<GeomAPI_Pnt> aCenter(theSketch->to3D(aPoint->x(), aPoint->y()));
+  //std::cout<<"Execute circle "<<aCenter->x()<<" "<<aCenter->y()<<" "<<aCenter->z()<<std::endl;
+  // make a visible point
+  std::shared_ptr<GeomAPI_Shape> aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter);
+  std::shared_ptr<ModelAPI_ResultConstruction> aResult = theFeature->document()->createConstruction(
+                     theFeature->data(), theIndex);
+  aResult->setShape(aCenterPointShape);
+  aResult->setIsInHistory(false);
+
+  theFeature->setResult(aResult, theIndex);
+}
index d7e65d5486ff8bcc8bbf6a0b08c4573e2c0e79ed..9f5f4a4580113b7c147890da43f3499099f075c2 100644 (file)
 #include <GeomAPI_Pnt.h>
 #include <GeomAPI_Pln.h>
 #include <GeomAPI_IPresentable.h>
+#include <GeomAPI_ICustomPrs.h>
+
 #include <GeomAPI_Ax3.h>
 #include <GeomAPI_XYZ.h>
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Dir.h>
 #include <list>
 
-#define YZ_PLANE_COLOR "#ff0000"
-#define XZ_PLANE_COLOR "#00ff00"
-#define XY_PLANE_COLOR "#0000ff"
+#define YZ_PLANE_COLOR "225,0,0"
+#define XZ_PLANE_COLOR "0,225,0"
+#define XY_PLANE_COLOR "0,0,225"
 
 /**\class SketchPlugin_Sketch
  * \ingroup Plugins
  * \brief Feature for creation of the new part in PartSet.
  */
-class SketchPlugin_Sketch : public ModelAPI_CompositeFeature//, public GeomAPI_IPresentable
+class SketchPlugin_Sketch : public ModelAPI_CompositeFeature, public GeomAPI_ICustomPrs//, public GeomAPI_IPresentable
 {
  public:
   /// Sketch feature kind
@@ -194,6 +196,27 @@ class SketchPlugin_Sketch : public ModelAPI_CompositeFeature//, public GeomAPI_I
   SKETCHPLUGIN_EXPORT virtual bool isPersistentResult() {return false;}
 
   SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+  /// \brief Create a result for the point in the attribute if the attribute is initialized
+  /// \param theAttributeID an attribute string
+  /// \param theIndex an index of the result
+  static void createPoint2DResult(ModelAPI_Feature* theFeature,
+                                  SketchPlugin_Sketch* theSketch,
+                                  const std::string& theAttributeID, const int theIndex);
+  /// Customize presentation of the feature
+  virtual bool customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
+                                     std::shared_ptr<GeomAPI_ICustomPrs> theDefaultPrs)
+  {
+    bool isCustomized = false;
+    // apply the color of the result to the presentation
+    if (theDefaultPrs.get())
+      isCustomized = theDefaultPrs->customisePresentation(theResult, thePrs, theDefaultPrs);
+    // set the sketch presentation bold    
+    isCustomized = thePrs->setWidth(2) || isCustomized;
+  
+    return isCustomized;
+  }
+
 };
 
 #endif
index 8f716c79f1de1427c742db9c61afbc18f7b67255..95c4505b6a8034a1489dba34014ba2186e5aa19f 100644 (file)
@@ -20,9 +20,9 @@
 
 #include <Config_PropManager.h>
 
-#define SKETCH_ENTITY_COLOR "#ff0000"
-#define SKETCH_EXTERNAL_COLOR "#00ff00"
-#define SKETCH_AUXILIARY_COLOR "#000000"
+#define SKETCH_ENTITY_COLOR "225,0,0"
+#define SKETCH_EXTERNAL_COLOR "170,0,225"
+#define SKETCH_AUXILIARY_COLOR "0,85,0"
 
 /**\class SketchPlugin_SketchEntity
  * \ingroup Plugins
index 72f0b61d1cb6872e656d70b75d631b8353ab22c1..9dfdb517155a23638c3f2808b20bcf96365c0cda 100644 (file)
@@ -11,6 +11,7 @@
 #include "SketchPlugin_Line.h"
 #include "SketchPlugin_Arc.h"
 #include "SketchPlugin_Circle.h"
+#include "SketchPlugin_Point.h"
 
 #include "SketcherPrs_Tools.h"
 
@@ -22,7 +23,7 @@
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_Session.h>
 
-#include <GeomValidators_Edge.h>
+#include <GeomValidators_ShapeType.h>
 
 #include <GeomDataAPI_Point2D.h>
 
@@ -47,20 +48,20 @@ bool SketchPlugin_DistanceAttrValidator::isValid(
     // 1. check whether the references object is a linear
     ObjectPtr anObject = aRefAttr->object();
 
-    const ModelAPI_AttributeValidator* anEdgeValidator = 
-      dynamic_cast<const GeomValidators_Edge*>(aFactory->validator("GeomValidators_Edge"));
+    const ModelAPI_AttributeValidator* aShapeValidator = 
+      dynamic_cast<const GeomValidators_ShapeType*>(aFactory->validator("GeomValidators_ShapeType"));
     std::list<std::string> anArguments;
     anArguments.push_back("circle");
-    bool anEdgeValid = anEdgeValidator->isValid(aRefAttr, anArguments);
+    bool aShapeValid = aShapeValidator->isValid(aRefAttr, anArguments);
     // the circle line is not a valid case
-    if (anEdgeValid)
+    if (aShapeValid)
       return false;
       
     anArguments.clear();
     anArguments.push_back("line");
-    anEdgeValid = anEdgeValidator->isValid(aRefAttr, anArguments);
+    aShapeValid = aShapeValidator->isValid(aRefAttr, anArguments);
     // if the attribute value is not a line, that means it is a vertex. A vertex is always valid
-    if (!anEdgeValid)
+    if (!aShapeValid)
       return true;
 
     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
@@ -236,3 +237,80 @@ bool SketchPlugin_MirrorAttrValidator::isValid(
   return true;
 }
 
+
+bool SketchPlugin_CoincidenceAttrValidator::isValid(
+  const AttributePtr& theAttribute, const std::list<std::string>& theArguments ) const
+{
+  // there is a check whether the feature contains a point and a linear edge or two point values
+  std::string aParamA = theArguments.front();
+  SessionPtr aMgr = ModelAPI_Session::get();
+  ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
+
+  FeaturePtr aConstraint = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+  AttributeRefAttrPtr aRefAttrA = aConstraint->data()->refattr(aParamA);
+  if (!aRefAttrA)
+    return false;
+
+  AttributeRefAttrPtr aRefAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
+  if (!aRefAttrB)
+    return false;
+
+  // first attribute is a point, it may coincide with any object
+  if (!aRefAttrA->isObject())
+    return true;
+  else {
+    FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttrA->object());
+    if (!aFeature)
+      return false;
+    if (aFeature->getKind() == SketchPlugin_Point::ID())
+      return true;
+  }
+
+  // second attribute is a point, it may coincide with any object
+  if (!aRefAttrB->isObject())
+    return true;
+  else {
+    FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttrB->object());
+    if (!aFeature)
+      return false;
+    if (aFeature->getKind() == SketchPlugin_Point::ID())
+      return true;
+  }
+
+  return false;
+}
+
+
+bool SketchPlugin_CopyValidator::isValid(
+  const AttributePtr& theAttribute, const std::list<std::string>& theArguments ) const
+{
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+  AttributeSelectionListPtr aSelAttr = 
+    std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+  if (!aSelAttr)
+    return false;
+
+  AttributeRefListPtr aRefListOfInitial = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+      aFeature->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  AttributeRefListPtr aRefListOfCopied = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+      aFeature->attribute(SketchPlugin_Constraint::ENTITY_B()));
+  std::list<ObjectPtr> anInitialObjects = aRefListOfInitial->list();
+  std::list<ObjectPtr> aCopiedObjects = aRefListOfCopied->list();
+
+  std::list<ObjectPtr>::iterator anObjIter;
+  for(int anInd = 0; anInd < aSelAttr->size(); anInd++) {
+    std::shared_ptr<ModelAPI_AttributeSelection> aSelect = aSelAttr->value(anInd);
+    anObjIter = anInitialObjects.begin();
+    for (; anObjIter != anInitialObjects.end(); anObjIter++)
+      if (aSelect->context() == *anObjIter)
+        break;
+    if (anObjIter != anInitialObjects.end())
+      continue;
+    anObjIter = aCopiedObjects.begin();
+    for (; anObjIter != aCopiedObjects.end(); anObjIter++)
+      if (aSelect->context() == *anObjIter)
+        return false;
+  }
+  return true;
+}
+
index e4f6d36d6904eefabf32e44a0b30e4f9ade5e169..cd7a7d5336dba141f1df7bb9b44f8302130aad57 100644 (file)
@@ -93,4 +93,38 @@ class SketchPlugin_MirrorAttrValidator : public ModelAPI_AttributeValidator
 };
 
 
+/**\class SketchPlugin_CoincidenceAttrValidator
+ * \ingroup Validators
+ * \brief Validator for the coincidence constraint input.
+ *
+ * It checks that attributes of the Coincidence constraint are correct.
+ */
+class SketchPlugin_CoincidenceAttrValidator : public ModelAPI_AttributeValidator
+{
+ public:
+  //! returns true if attribute is valid
+  //! \param theAttribute the checked attribute
+  //! \param theArguments arguments of the attribute (not used)
+  virtual bool isValid(const AttributePtr& theAttribute,
+                       const std::list<std::string>& theArguments) const;
+};
+
+
+/**\class SketchPlugin_CopyValidator
+ * \ingroup Validators
+ * \brief Validator for the constraints which create features.
+ *
+ * Applicable only for features, which creates another features. It verifies the produced
+ * features of current constraint don't become into the list of initial features
+ */
+class SketchPlugin_CopyValidator : public ModelAPI_AttributeValidator
+{
+ public:
+  //! returns true if attribute is valid
+  //! \param theAttribute the checked attribute
+  //! \param theArguments arguments of the attribute (not used)
+  virtual bool isValid(const AttributePtr& theAttribute,
+                       const std::list<std::string>& theArguments) const;
+};
+
 #endif
index 87f4cf32482a9f7df50a48bb90fe7c743f5aa536..97830f944a99f256685bb442bf106db239ecf5f0 100644 (file)
@@ -5,7 +5,7 @@
     <group id="Basic">
       <feature
         id="Sketch"
-        nested="SketchPoint SketchLine SketchCircle SketchArc SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintParallel SketchConstraintPerpendicular SketchConstraintRigid SketchConstraintHorizontal SketchConstraintVertical SketchConstraintEqual SketchConstraintTangent SketchConstraintFillet SketchConstraintCoincidence SketchConstraintMirror"
+        nested="SketchPoint SketchLine SketchCircle SketchArc SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintParallel SketchConstraintPerpendicular SketchConstraintRigid SketchConstraintHorizontal SketchConstraintVertical SketchConstraintEqual SketchConstraintTangent SketchConstraintFillet SketchConstraintCoincidence SketchConstraintMirror SketchMultiRotation SketchMultiTranslation"
         when_nested="accept abort"
         title="Sketch"
         tooltip="Create sketch"
@@ -54,7 +54,7 @@
               shape_types="edge vertex">
           <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
           <validator id="PartSet_DifferentObjects"/>
-          <validator id="GeomValidators_EdgeOrVertex"/>
+          <validator id="GeomValidators_ShapeType" parameters="vertex,line"/>
         </sketch_shape_selector>/>
         <sketch_shape_selector 
           id="ConstraintEntityB" 
@@ -64,7 +64,7 @@
           <validator id="PartSet_DifferentObjects"/>
           <validator id="SketchPlugin_DistanceAttr" parameters="ConstraintEntityA"/>
           <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
-          <validator id="GeomValidators_EdgeOrVertex"/>
+          <validator id="GeomValidators_ShapeType" parameters="vertex,line"/>
         </sketch_shape_selector>
         <sketch-2dpoint_selector id="ConstraintFlyoutValuePnt"  default="computed" internal="1" obligatory="0"/>
         
@@ -80,7 +80,7 @@
         <label title="Select a line on which to calculate length" tooltip="Select a line on which to calculate length"/>
         <shape_selector id="ConstraintEntityA" label="Line" tooltip="Select an line" 
             shape_types="edge" >
-        <validator id="GeomValidators_Edge" parameters="line"/>
+        <validator id="GeomValidators_ShapeType" parameters="line"/>
     </shape_selector>
         <sketch-2dpoint_selector id="ConstraintFlyoutValuePnt" default="computed" internal="1" obligatory="0"/>
         <doublevalue_editor label="Value" tooltip="Length" id="ConstraintValue" default="computed">
@@ -94,7 +94,7 @@
         <label title="Select a circle or an arc on which to calculate radius" tooltip="Select a circle or an arc on which to calculate radius"/>
         <shape_selector id="ConstraintEntityA" label="Circle or Arc" tooltip="Select a circle or an arc" 
             shape_types="edge">
-            <validator id="GeomValidators_Edge" parameters="circle"/>
+            <validator id="GeomValidators_ShapeType" parameters="circle"/>
         </shape_selector>
         <sketch-2dpoint_selector id="ConstraintFlyoutValuePnt"  default="computed" internal="1" obligatory="0"/>
         <doublevalue_editor label="Value" tooltip="Radius" id="ConstraintValue" default="computed"/>
       <feature id="SketchConstraintParallel" title="Parallel" tooltip="Create constraint defining two parallel lines" icon=":icons/parallel.png">
         <sketch_shape_selector id="ConstraintEntityA" 
             label="First line" tooltip="Select a line" shape_types="edge">
-          <validator id="GeomValidators_Edge" parameters="line"/>
+          <validator id="GeomValidators_ShapeType" parameters="line"/>
           <validator id="PartSet_DifferentObjects"/>
           <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
         </sketch_shape_selector>
         
         <sketch_shape_selector id="ConstraintEntityB" label="Second line" tooltip="Select a line" 
             shape_types="edge">
-            <validator id="GeomValidators_Edge" parameters="line"/>
+            <validator id="GeomValidators_ShapeType" parameters="line"/>
             <validator id="PartSet_DifferentObjects"/>
             <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
         </sketch_shape_selector>
             shape_types="edge">
           <validator id="PartSet_DifferentObjects"/>
           <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
-            <validator id="GeomValidators_Edge" parameters="line"/>
+            <validator id="GeomValidators_ShapeType" parameters="line"/>
         </sketch_shape_selector>
         
         <sketch_shape_selector id="ConstraintEntityB" 
             shape_types="edge">
             <validator id="PartSet_DifferentObjects"/>
           <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
-            <validator id="GeomValidators_Edge" parameters="line"/>
+            <validator id="GeomValidators_ShapeType" parameters="line"/>
         </sketch_shape_selector>
         <validator id="PartSet_PerpendicularSelection"/>
       </feature>
 
       <!--  SketchConstraintCoincedence  -->
-      <feature id="SketchConstraintCoincidence" title="Coincident" tooltip="Create constraint for the coincidence of two points" icon=":icons/coincedence.png">
-        <sketch_shape_selector id="ConstraintEntityA" label="First point" tooltip="Select a first point" shape_types="vertex">
+      <feature id="SketchConstraintCoincidence" title="Coincident" tooltip="Create constraint for the coincidence of two points or point on line or circle" icon=":icons/coincedence.png">
+        <sketch_shape_selector id="ConstraintEntityA" label="First object" tooltip="Select a first object" shape_types="vertex edge">
           <validator id="PartSet_DifferentObjects"/>
           <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
         </sketch_shape_selector>
-        <sketch_shape_selector id="ConstraintEntityB" label="Second point" tooltip="Select a second point" shape_types="vertex">
+        <sketch_shape_selector id="ConstraintEntityB" label="Second object" tooltip="Select a second object" shape_types="vertex edge">
           <validator id="PartSet_DifferentObjects"/>
           <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
+          <validator id="SketchPlugin_CoincidenceAttr" parameters="ConstraintEntityA"/>
         </sketch_shape_selector>
         <validator id="PartSet_CoincidentSelection"/>
       </feature>
 
       <!--  SketchConstraintRigid  -->
       <feature id="SketchConstraintRigid" title="Fixed" tooltip="Fix an object" icon=":icons/fixed.png">
-        <shape_selector id="ConstraintEntityA" label="Object" tooltip="Select an object" 
-            shape_types="edge vertex">
-          <validator id="PartSet_SketchEntityValidator" parameters="SketchPoint,SketchLine,SketchCircle,SketchArc"/>
+        <sketch_shape_selector id="ConstraintEntityA" label="Object"
+                        tooltip="Select point, line end point, line, center of circle or arc."
+                        shape_types="edge vertex">
+          <validator id="GeomValidators_ShapeType" parameters="vertex,line,circle"/>
           <validator id="SketchPlugin_NotFixed"/>
-        </shape_selector>
+        </sketch_shape_selector>
         <validator id="PartSet_RigidSelection"/>
       </feature>
-      
-    <!--  SketchConstraintHorizontal  -->
+
+      <!--  SketchConstraintHorizontal  -->
       <feature id="SketchConstraintHorizontal" title="Horizontal" tooltip="Create constraint defining horizontal line" icon=":icons/horisontal.png">
         <sketch_shape_selector id="ConstraintEntityA" 
             label="Line" tooltip="Select a line" shape_types="edge" use_external="false">
-            <validator id="GeomValidators_Edge" parameters="line"/>
+            <validator id="GeomValidators_ShapeType" parameters="line"/>
         </sketch_shape_selector>
         <validator id="PartSet_HVDirSelection"/>
       </feature>
       <feature id="SketchConstraintVertical" title="Vertical" tooltip="Create constraint defining vertical line" icon=":icons/vertical.png">
         <sketch_shape_selector id="ConstraintEntityA" 
             label="Line" tooltip="Select a line" shape_types="edge" use_external="false">
-            <validator id="GeomValidators_Edge" parameters="line"/>
+            <validator id="GeomValidators_ShapeType" parameters="line"/>
         </sketch_shape_selector>
         <validator id="PartSet_HVDirSelection"/>
       </feature>
         tooltip="Create constraint, mirroring group of objects">
         <sketch_shape_selector id="ConstraintEntityA"
             label="Mirror line" tooltip="Select mirror line" shape_types="edge">
-            <validator id="GeomValidators_Edge" parameters="line"/>
+            <validator id="GeomValidators_ShapeType" parameters="line"/>
         </sketch_shape_selector>
         <sketch_multi_selector id="ConstraintMirrorList"
             label="List of objects"
             <validator id="SketchPlugin_MirrorAttr" />
         </sketch_multi_selector>
       </feature>
+      <!--  SketchMultiTranslation  -->
+      <feature
+        id="SketchMultiTranslation"
+        title="Translation" icon=":icons/translate.png"
+        tooltip="Make a number of shifted copies of a group of objects">
+        <sketch_multi_selector id="MultiTranslationList"
+            label="List of objects"
+            tooltip="Select list of translating objects"
+            type_choice="Edges"
+            use_external="true">
+          <validator id="SketchPlugin_CopyValidator" />
+        </sketch_multi_selector>
+        <groupbox title="Direction">
+          <sketch-2dpoint_selector
+              id="MultiTranslationStartPoint"
+              title="Start point"
+              tooltip="Start point of translation"/>
+          <sketch-2dpoint_selector
+              id="MultiTranslationEndPoint"
+              title="End point"
+              tooltip="Final point of translation"/>
+        </groupbox>
+        <integervalue id="MultiTranslationCopies"
+            label="Number of copies"
+            tooltip="Number of copies" 
+            default="1" min="1">
+          <validator id="GeomValidators_Positive"/>
+        </integervalue>
+      </feature>
+      <!--  SketchMultiRotation  -->
+      <feature
+        id="SketchMultiRotation"
+        title="Rotation" icon=":icons/rotate.png"
+        tooltip="Make a number of rotated copies of a group of objects">
+        <sketch_multi_selector id="MultiRotationList"
+            label="List of objects"
+            tooltip="Select list of rotating objects"
+            type_choice="Edges"
+            use_external="true">
+          <validator id="SketchPlugin_CopyValidator" />
+        </sketch_multi_selector>
+        <sketch-2dpoint_selector
+            id="MultiRotationCenter"
+            title="Center of rotation"
+            tooltip="Center of rotation"/>
+        <point2dangle id="MultiRotationAngle"
+                         first_point="MultiRotationCenter"
+                         label="Angle"
+                         icon=":icons/angle.png"
+                         tooltip="Rotation angle"
+                         default="90"/>
+        <integervalue id="MultiRotationCopies"
+            label="Number of copies"
+            tooltip="Number of copies" 
+            default="1" min="1">
+          <validator id="GeomValidators_Positive"/>
+        </integervalue>
+      </feature>
     </group>
   </workbench>
 </plugin>
index d8070e05f68e641d867a06d03615301154c05efe..29e2ef1e754a4f95fe9c0444c418fe843fb60d5f 100644 (file)
@@ -16,6 +16,8 @@ SET(PROJECT_HEADERS
     SketchSolver_ConstraintMirror.h
     SketchSolver_ConstraintRigid.h
     SketchSolver_ConstraintTangent.h
+    SketchSolver_ConstraintMultiRotation.h
+    SketchSolver_ConstraintMultiTranslation.h
     SketchSolver_Builder.h
     SketchSolver_Group.h
     SketchSolver_ConstraintManager.h
@@ -34,6 +36,8 @@ SET(PROJECT_SOURCES
     SketchSolver_ConstraintMirror.cpp
     SketchSolver_ConstraintRigid.cpp
     SketchSolver_ConstraintTangent.cpp
+    SketchSolver_ConstraintMultiRotation.cpp
+    SketchSolver_ConstraintMultiTranslation.cpp
     SketchSolver_Builder.cpp
     SketchSolver_Group.cpp
     SketchSolver_ConstraintManager.cpp
index 77bb4029a701f8a8faa5e6174cad5cdba5e0195b..cc5013f6ed163cf32b89d7b19ac2f346652ab826 100644 (file)
@@ -20,4 +20,6 @@
 /// Tolerance for value of parameters
 const double tolerance = 1.e-10;
 
+#define PI 3.1415926535897932
+
 #endif
index 82cf9669c37a143123ad6413c4487984076c78bc..bc992f26d297cc9aff2e36d65ebaacd98186e0a2 100644 (file)
@@ -13,6 +13,8 @@
 #include <SketchSolver_ConstraintMirror.h>
 #include <SketchSolver_ConstraintRigid.h>
 #include <SketchSolver_ConstraintTangent.h>
+#include <SketchSolver_ConstraintMultiRotation.h>
+#include <SketchSolver_ConstraintMultiTranslation.h>
 #include <SketchSolver_Error.h>
 
 #include <GeomAPI_Edge.h>
@@ -43,6 +45,8 @@
 #include <SketchPlugin_ConstraintRigid.h>
 #include <SketchPlugin_ConstraintTangent.h>
 #include <SketchPlugin_ConstraintVertical.h>
+#include <SketchPlugin_MultiRotation.h>
+#include <SketchPlugin_MultiTranslation.h>
 
 #include <math.h>
 
@@ -118,6 +122,10 @@ SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theCons
     return SolverConstraintPtr(new SketchSolver_ConstraintVertical(theConstraint));
   } else if (theConstraint->getKind() == SketchPlugin_ConstraintRigid::ID()) {
     return SolverConstraintPtr(new SketchSolver_ConstraintRigid(theConstraint));
+  } else if (theConstraint->getKind() == SketchPlugin_MultiTranslation::ID()) {
+    return SolverConstraintPtr(new SketchSolver_ConstraintMultiTranslation(theConstraint));
+  } else if (theConstraint->getKind() == SketchPlugin_MultiRotation::ID()) {
+    return SolverConstraintPtr(new SketchSolver_ConstraintMultiRotation(theConstraint));
   }
   return aResult;
 }
index ce0fc9797ba9ebba75042cc6369036538ab758d9..2a4c36f8f7dada5503b0c0c55875144e3c55344c 100644 (file)
@@ -7,6 +7,7 @@
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_Point.h>
 
+#include <GeomAPI_Dir2d.h>
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Point2D.h>
 #include <ModelAPI_AttributeDouble.h>
@@ -85,6 +86,8 @@ void SketchSolver_Constraint::process()
   getAttributes(aValue, anAttributes);
   if (!myErrorMsg.empty())
     return;
+  if (aConstrType == SLVS_C_UNKNOWN)
+    aConstrType = getType();
 
   Slvs_hGroup aGroupID = myGroup->getId();
   Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
@@ -677,61 +680,16 @@ void SketchSolver_Constraint::calculateMiddlePoint(
       return;
     }
 
-    double xStart = anArcPoint[1][0] / aRad, xEnd = anArcPoint[2][0] / aRad;
-    double yStart = anArcPoint[1][1] / aRad, yEnd = anArcPoint[2][1] / aRad;
-    double aTanStart = abs(xStart) < tolerance ? yStart : yStart / xStart;
-    double aTanEnd   = abs(xEnd) < tolerance   ? yEnd   : yEnd / xEnd;
-    double aCotStart = abs(yStart) < tolerance ? xStart : xStart / yStart;
-    double aCotEnd   = abs(yEnd) < tolerance   ? xEnd   : xEnd / yEnd;
-    if (anArcPoint[1][0] * anArcPoint[2][0] < 0.0) {
-      if (anArcPoint[1][0] > 0.0)
-        yEnd = 2.0 - yEnd;
-      else
-        yStart = -2.0 - yStart;
-    } else {
-      if (aTanStart > aTanEnd) {
-        if (yStart > yEnd) {
-          yStart = 2.0 - yStart;
-          yEnd = -2.0 - yEnd;
-        } else {
-          yStart = -2.0 - yStart;
-          yEnd = 2.0 - yEnd;
-        }
-      }
-    }
-    if (anArcPoint[1][1] * anArcPoint[2][1] < 0.0) {
-      if (anArcPoint[1][1] > 0.0)
-        xEnd = 2.0 - xEnd;
-      else
-        xStart = -2.0 - xStart;
-    } else {
-      if (aCotStart < aCotEnd) {
-        if (xStart > xEnd) {
-          xStart = 2.0 - xStart;
-          xEnd = -2.0 - xEnd;
-        } else {
-          xStart = -2.0 - xStart;
-          xEnd = 2.0 - xEnd;
-        }
-      }
-    }
-    x = (1.0 - theCoeff) * xStart + theCoeff * xEnd;
-    y = (1.0 - theCoeff) * yStart + theCoeff * yEnd;
-    if (x > 1.0) x = 2.0 - x;
-    if (x < -1.0) x = -2.0 - x;
-    if (y > 1.0) y = 2.0 - y;
-    if (y < -1.0) y = -2.0 - y;
-
-    aNorm = sqrt(x*x + y*y);
-    if (aNorm >= tolerance) {
-      x *= aRad / aNorm;
-      y *= aRad / aNorm;
-    } else {
-      x = -0.5 * (anArcPoint[2][1] + anArcPoint[1][1]);
-      y = -0.5 * (anArcPoint[2][0] + anArcPoint[1][0]);
-    }
-    theX = anArcPoint[0][0] + x;
-    theY = anArcPoint[0][1] + y;
+    std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
+    std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
+    double anAngle = aStartDir->angle(aEndDir);
+    if (anAngle < 0)
+      anAngle += 2.0 * PI;
+    anAngle *= theCoeff;
+    double aCos = cos(anAngle);
+    double aSin = sin(anAngle);
+    theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
+    theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
   }
 }
 
index 2afdbcf0d9ac9d8c67f85b0da750f878cfd81fa1..04e6db8d21c62e7c460d973106f8c830f7c4b664 100644 (file)
@@ -4,6 +4,30 @@
 
 #include <map>
 
+void SketchSolver_ConstraintCoincidence::getAttributes(
+    double& theValue,
+    std::vector<Slvs_hEntity>& theAttributes)
+{
+  SketchSolver_Constraint::getAttributes(theValue, theAttributes);
+  if (!myErrorMsg.empty() || theAttributes[0] == SLVS_E_UNKNOWN)
+    return;
+
+  if (theAttributes[1] != SLVS_E_UNKNOWN)
+    myType = SLVS_C_POINTS_COINCIDENT;
+  else if (theAttributes[2] != SLVS_E_UNKNOWN) {
+    // check the type of entity (line or circle)
+    Slvs_Entity anEnt = myStorage->getEntity(theAttributes[2]);
+    if (anEnt.type == SLVS_E_LINE_SEGMENT)
+      myType = SLVS_C_PT_ON_LINE;
+    else if (anEnt.type == SLVS_E_CIRCLE || anEnt.type == SLVS_E_ARC_OF_CIRCLE)
+      myType = SLVS_C_PT_ON_CIRCLE;
+    else
+      myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+  } else
+    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+}
+
+
 bool SketchSolver_ConstraintCoincidence::hasConstraint(ConstraintPtr theConstraint) const
 {
   if (myBaseConstraint == theConstraint)
@@ -28,6 +52,10 @@ std::list<ConstraintPtr> SketchSolver_ConstraintCoincidence::constraints() const
 bool SketchSolver_ConstraintCoincidence::isCoincide(
     std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const
 {
+  // Multi-coincidence allowed for two points only
+  if (getType() != theConstraint->getType() || getType() != SLVS_C_POINTS_COINCIDENT)
+    return false;
+
   std::set<AttributePtr>::const_iterator anAttrIter = theConstraint->myCoincidentPoints.begin();
   for (; anAttrIter != theConstraint->myCoincidentPoints.end(); anAttrIter++)
     if (myCoincidentPoints.find(*anAttrIter) != myCoincidentPoints.end())
index a5c885ade5863fccdce77842f18904c6acb5ff5a..c1d1124af4ecdd30641c5884d21688a5767ac7a0 100644 (file)
@@ -19,11 +19,12 @@ class SketchSolver_ConstraintCoincidence : public SketchSolver_Constraint
 {
 public:
   SketchSolver_ConstraintCoincidence(ConstraintPtr theConstraint) :
-      SketchSolver_Constraint(theConstraint)
+      SketchSolver_Constraint(theConstraint),
+      myType(SLVS_C_UNKNOWN)
   {}
 
   virtual int getType() const
-  { return SLVS_C_POINTS_COINCIDENT; }
+  { return myType; }
 
   /// \brief Tries to remove constraint
   /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
@@ -45,6 +46,11 @@ protected:
   /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
   virtual void process();
 
+  /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
+  /// \param[out] theValue      numerical characteristic of constraint (e.g. distance)
+  /// \param[out] theAttributes list of attributes to be filled
+  virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
+
 private:
   /// \brief Creates new coincidence constraint
   Slvs_hConstraint addConstraint(Slvs_hEntity thePoint1, Slvs_hEntity thePoint2);
@@ -53,6 +59,7 @@ private:
   void addConstraint(ConstraintPtr theConstraint);
 
 private:
+  int myType; ///< type of constraint (applicable SLVS_C_POINTS_COINCIDENT or SLVS_C_PT_ON_LINE or SLVS_C_PT_ON_CIRCLE)
   std::map<Slvs_hConstraint, ConstraintPtr> myExtraCoincidence; ///< multiple coincidence of points
   std::set<AttributePtr> myCoincidentPoints; ///< list of points under the Coincidence constraint
 };
index 50d578a668826c4350b8cc690afa629b087117b6..591fa555e4e3d47b7ab0478934939f264baf9306 100644 (file)
@@ -10,6 +10,7 @@
 #include <GeomAPI_Dir2d.h>
 #include <GeomAPI_XY.h>
 
+#include <cmath>
 
 void SketchSolver_ConstraintMirror::getAttributes(
     Slvs_Entity& theMirrorLine,
@@ -192,17 +193,6 @@ void SketchSolver_ConstraintMirror::process()
       }
     }
   }
-
-  // Set the mirror line unchanged during constraint recalculation
-  for (int i = 0; i < 2; i++) {
-    if (myStorage->isPointFixed(aMirrorLine.point[i], aConstraint.h, true))
-      continue;
-    aConstraint = Slvs_MakeConstraint(
-        SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
-        aMirrorLine.point[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
-    aConstraint.h = myStorage->addConstraint(aConstraint);
-    mySlvsConstraints.push_back(aConstraint.h);
-  }
 }
 
 
@@ -293,6 +283,7 @@ void SketchSolver_ConstraintMirror::makeMirrorEntity(
     Slvs_hEntity aTmp = aMirrorPoint[2];
     aMirrorPoint[2] = aMirrorPoint[1];
     aMirrorPoint[1] = aTmp;
+    adjustArcPoints(theBase);
   }
   if (theBase.type == SLVS_E_POINT_IN_2D || theBase.type == SLVS_E_POINT_IN_3D) {
     aBasePoint[0] = theBase.h;
@@ -310,9 +301,14 @@ void SketchSolver_ConstraintMirror::makeMirrorEntity(
   // orthogonal direction
   aDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aDir->y(), -aDir->x()));
 
+  Slvs_hConstraint aFixed; // transient variable
   for (int i = 0; i < 4; i++) {
     if (aBasePoint[i] == SLVS_E_UNKNOWN || aMirrorPoint[i] == SLVS_E_UNKNOWN)
       continue;
+    // check the mirror point is not fixed
+    if (myStorage->isPointFixed(aMirrorPoint[i], aFixed, true))
+      continue;
+
     Slvs_Entity aPointEnt = myStorage->getEntity(aBasePoint[i]);
     double aBaseX = myStorage->getParameter(aPointEnt.param[0]).val;
     double aBaseY = myStorage->getParameter(aPointEnt.param[1]).val;
@@ -331,13 +327,41 @@ void SketchSolver_ConstraintMirror::makeMirrorEntity(
   }
 }
 
-void SketchSolver_ConstraintMirror::adjustConstraint()
+void SketchSolver_ConstraintMirror::adjustArcPoints(const Slvs_Entity& theArc) const
 {
-  // Search mirror between middle points on the arcs and recompute their coordinates
-  std::list<Slvs_Constraint> aPonCirc = myStorage->getConstraintsByType(SLVS_C_PT_ON_CIRCLE);
-  if (aPonCirc.empty())
-    return;
+  Slvs_Param aParam;
+  Slvs_Entity aPoint;
+  double anArcParams[3][2];
+  for (int i = 0; i < 3; i++) {
+    aPoint = myStorage->getEntity(theArc.point[i]);
+    for (int j = 0; j < 2; j++) {
+      aParam = myStorage->getParameter(aPoint.param[j]);
+      anArcParams[i][j] = aParam.val;
+      if (i > 0)
+        anArcParams[i][j] -= anArcParams[0][j];
+    }
+  }
+  double aRad2 = anArcParams[1][0] * anArcParams[1][0] + anArcParams[1][1] * anArcParams[1][1];
+  double aDist2 = anArcParams[2][0] * anArcParams[2][0] + anArcParams[2][1] * anArcParams[2][1];
+  if (std::fabs(aRad2 - aDist2) < tolerance)
+    return; // nothing to update (last point already on the arc)
+  if (aDist2 < tolerance)
+    return; // unable to update
+  double aCoeff = std::sqrt(aRad2 / aDist2);
+  anArcParams[2][0] *= aCoeff;
+  anArcParams[2][1] *= aCoeff;
+
+  // Update last point
+  aPoint = myStorage->getEntity(theArc.point[2]);
+  for (int i = 0; i < 2; i++) {
+    aParam = Slvs_MakeParam(aPoint.param[i], myGroup->getId(),
+        anArcParams[0][i] + anArcParams[2][i]);
+    myStorage->updateParameter(aParam);
+  }
+}
 
+void SketchSolver_ConstraintMirror::adjustConstraint()
+{
   AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
       myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
   if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) {
@@ -353,6 +377,7 @@ void SketchSolver_ConstraintMirror::adjustConstraint()
     return;
   Slvs_Entity aMirrorLine = myStorage->getEntity(aMirLineIter->second);
 
+  Slvs_Constraint aMirror;
   double aStartEnd[4];
   for (int i = 0; i < 2; i++) {
     Slvs_Entity aPoint = myStorage->getEntity(aMirrorLine.point[i]);
@@ -360,7 +385,10 @@ void SketchSolver_ConstraintMirror::adjustConstraint()
       aStartEnd[2*i+j] = myStorage->getParameter(aPoint.param[j]).val;
   }
 
-  Slvs_Constraint aMirror;
+  // Search mirror between middle points on the arcs and recompute their coordinates
+  std::map<Slvs_hEntity, Slvs_hEntity> aPointsOnCircles;
+  std::list<Slvs_Constraint> aMirrorPonCirc;
+  std::list<Slvs_Constraint> aPonCirc = myStorage->getConstraintsByType(SLVS_C_PT_ON_CIRCLE);
   std::vector<Slvs_hConstraint>::iterator aConstrIter = mySlvsConstraints.begin();
   for (; aConstrIter != mySlvsConstraints.end(); aConstrIter++) {
     aMirror = myStorage->getConstraint(*aConstrIter);
@@ -378,24 +406,45 @@ void SketchSolver_ConstraintMirror::adjustConstraint()
     }
     if (aPonCircA.h == SLVS_E_UNKNOWN || aPonCircB.h == SLVS_E_UNKNOWN)
       continue;
+    aMirrorPonCirc.push_back(aMirror);
+    // Store point IDs to avoid their recalculation twice
+    aPointsOnCircles[aPonCircA.ptA] = aPonCircA.entityA;
+    aPointsOnCircles[aPonCircB.ptA] = aPonCircB.entityA;
+  }
+
+  // Recalculate positions of mirroring points
+  std::list<Slvs_Constraint> aMirrorList = myStorage->getConstraintsByType(SLVS_C_SYMMETRIC_LINE);
+  std::list<Slvs_Constraint>::iterator aMirIter = aMirrorList.begin();
+  for (; aMirIter != aMirrorList.end(); aMirIter++) {
+    if (aPointsOnCircles.find(aMirIter->ptA) != aPointsOnCircles.end())
+      continue; // Avoid mirroring points on circles
+    Slvs_Entity aBase = myStorage->getEntity(aMirIter->ptA);
+    Slvs_Entity aMirror = myStorage->getEntity(aMirIter->ptB);
+    makeMirrorEntity(aBase, aMirror, aStartEnd);
+  }
 
-    bool aNeedToResolve = myStorage->isNeedToResolve();
+  bool aNeedToResolve = myStorage->isNeedToResolve();
+  for (aMirIter = aMirrorPonCirc.begin(); aMirIter != aMirrorPonCirc.end(); aMirIter++) {
     // Calculate middle point for base arc and mirrored point on mirror arc
-    Slvs_Entity aBaseArc = myStorage->getEntity(aPonCircA.entityA);
-    Slvs_Entity aBasePoint = myStorage->getEntity(aPonCircA.ptA);
+    Slvs_Entity aBaseArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptA]);
+    Slvs_Entity aBasePoint = myStorage->getEntity(aMirIter->ptA);
     Slvs_Param aParamX = myStorage->getParameter(aBasePoint.param[0]);
     Slvs_Param aParamY = myStorage->getParameter(aBasePoint.param[1]);
     calculateMiddlePoint(aBaseArc, 0.5, aParamX.val, aParamY.val);
     myStorage->updateParameter(aParamX);
     myStorage->updateParameter(aParamY);
-    Slvs_Entity aMirrorArc = myStorage->getEntity(aPonCircB.entityA);
-    Slvs_Entity aMirrorPoint = myStorage->getEntity(aPonCircB.ptA);
+    Slvs_Entity aMirrorArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptB]);
+    Slvs_Entity aMirrorPoint = myStorage->getEntity(aMirIter->ptB);
     aParamX = myStorage->getParameter(aMirrorPoint.param[0]);
     aParamY = myStorage->getParameter(aMirrorPoint.param[1]);
     calculateMiddlePoint(aMirrorArc, 0.5, aParamX.val, aParamY.val);
     myStorage->updateParameter(aParamX);
     myStorage->updateParameter(aParamY);
-    // To avoid looped recalculations of sketch
-    myStorage->setNeedToResolve(aNeedToResolve);
+    // make centers of arcs symmetric
+    aBasePoint = myStorage->getEntity(aBaseArc.point[0]);
+    aMirrorPoint = myStorage->getEntity(aMirrorArc.point[0]);
+    makeMirrorEntity(aBasePoint, aMirrorPoint, aStartEnd);
   }
+  // Restore previous value to avoid looped recalculations of sketch
+  myStorage->setNeedToResolve(aNeedToResolve);
 }
index e65dcb90bc77363098636fda0ef710fb3c07a52b..26d97ff983889e358e457f29d523839ad979b19a 100644 (file)
@@ -66,6 +66,9 @@ private:
                         const Slvs_Entity& theMirror,
                         const double theMirrorLine[]) const;
 
+  /// \brief Precisely update last point to be on arc
+  void adjustArcPoints(const Slvs_Entity& theArc) const;
+
 private:
   size_t myNumberOfObjects; ///< number of previously mirrored objects
 };
diff --git a/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp b/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp
new file mode 100644 (file)
index 0000000..ab3a4e5
--- /dev/null
@@ -0,0 +1,303 @@
+#include <SketchSolver_ConstraintMultiRotation.h>
+#include <SketchSolver_Group.h>
+#include <SketchSolver_Error.h>
+
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_MultiRotation.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_ResultConstruction.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+
+#include <math.h>
+
+void SketchSolver_ConstraintMultiRotation::getAttributes(
+    Slvs_hEntity& theCenter, double& theAngle,
+    std::vector<std::vector<Slvs_hEntity> >& thePoints,
+    std::vector<std::vector<Slvs_hEntity> >& theCircular)
+{
+  DataPtr aData = myBaseConstraint->data();
+  theAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+      aData->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value();
+
+  AttributePtr aCenterAttr = aData->attribute(SketchPlugin_MultiRotation::CENTER_ID());
+  if (!aCenterAttr || !aCenterAttr->isInitialized()) {
+    myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+    return;
+  }
+  int aType = SLVS_E_UNKNOWN; // type of created entity
+  Slvs_hEntity anEntityID = myGroup->getAttributeId(aCenterAttr);
+  if (anEntityID == SLVS_E_UNKNOWN)
+    anEntityID = changeEntity(aCenterAttr, aType);
+  theCenter = anEntityID;
+
+  // Lists of objects and number of copies
+  AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+      aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  myNumberOfObjects = anInitialRefList->size();
+  myNumberOfCopies = (size_t) aData->integer(SketchPlugin_MultiRotation::NUMBER_OF_COPIES_ID())->value();
+  AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+  if (!aRefList) {
+    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+    return;
+  }
+
+  // Obtain all points of initial features and store them into separate lists
+  // containing their translated copies.
+  // Also all circles and arc collected too, because they will be constrained by equal radii.
+  FeaturePtr aFeature;
+  ResultConstructionPtr aRC;
+  std::vector<Slvs_hEntity> aPoints[2]; // lists of points of features
+  std::vector<Slvs_hEntity> aCircs;     // list of circular objects
+  std::list<ObjectPtr> anObjectList = aRefList->list();
+  std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
+  while (anObjectIter != anObjectList.end()) {
+    aPoints[0].clear();
+    aPoints[1].clear();
+    aCircs.clear();
+
+    for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
+      aFeature = ModelAPI_Feature::feature(*anObjectIter);
+      if (!aFeature)
+        continue;
+      anEntityID = changeEntity(aFeature, aType);
+      Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
+      switch (aType) {
+      case SLVS_E_POINT_IN_2D:
+      case SLVS_E_POINT_IN_3D:
+        aPoints[0].push_back(anEntityID);
+        break;
+      case SLVS_E_LINE_SEGMENT:
+        aPoints[0].push_back(anEntity.point[0]); // start point of line
+        aPoints[1].push_back(anEntity.point[1]); // end point of line
+        break;
+      case SLVS_E_CIRCLE:
+        aPoints[0].push_back(anEntity.point[0]); // center of circle
+        aCircs.push_back(anEntityID);
+        break;
+      case SLVS_E_ARC_OF_CIRCLE:
+        aPoints[0].push_back(anEntity.point[1]); // start point of arc
+        aPoints[1].push_back(anEntity.point[2]); // end point of arc
+        aCircs.push_back(anEntityID);
+        break;
+      default:
+        myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+        return;
+      }
+    }
+
+    if (!aPoints[0].empty())
+      thePoints.push_back(aPoints[0]);
+    if (!aPoints[1].empty())
+      thePoints.push_back(aPoints[1]);
+    if (!aCircs.empty())
+      theCircular.push_back(aCircs);
+  }
+}
+
+void SketchSolver_ConstraintMultiRotation::process()
+{
+  cleanErrorMsg();
+  if (!myBaseConstraint || !myStorage || myGroup == 0) {
+    /// TODO: Put error message here
+    return;
+  }
+  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+    update(myBaseConstraint);
+
+  Slvs_hEntity aCenter;
+  std::vector<std::vector<Slvs_hEntity> > aPointsAndCopies;
+  std::vector<std::vector<Slvs_hEntity> > aCircsAndCopies;
+  getAttributes(aCenter, myAngle, aPointsAndCopies, aCircsAndCopies);
+  if (!myErrorMsg.empty())
+    return;
+
+  // Create lines between neighbor rotated points and make angle between them equal to anAngle.
+  // Also these lines should have equal lengths.
+  Slvs_Constraint aConstraint;
+  myRotationCenter = aCenter;
+  Slvs_Entity aPrevLine;
+  std::vector<std::vector<Slvs_hEntity> >::iterator aCopyIter = aPointsAndCopies.begin();
+  for (; aCopyIter != aPointsAndCopies.end(); aCopyIter++) {
+    size_t aSize = aCopyIter->size();
+    if (aSize <= 1) continue;
+
+    aPrevLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
+          myGroup->getWorkplaneId(), aCenter, (*aCopyIter)[0]);
+    aPrevLine.h = myStorage->addEntity(aPrevLine);
+    for (size_t i = 1; i < aSize; i++) {
+      Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
+          myGroup->getWorkplaneId(), aCenter, (*aCopyIter)[i]);
+      aLine.h = myStorage->addEntity(aLine);
+      // Equal length constraint
+      aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+          SLVS_C_EQUAL_LENGTH_LINES, myGroup->getWorkplaneId(), 0.0,
+          SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aPrevLine.h, aLine.h);
+      aConstraint.h = myStorage->addConstraint(aConstraint);
+      mySlvsConstraints.push_back(aConstraint.h);
+      // Angle constraint
+      aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+          SLVS_C_ANGLE, myGroup->getWorkplaneId(), fabs(myAngle), SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
+          aPrevLine.h, aLine.h);
+      if (myAngle < 0.0) // clockwise rotation
+        aConstraint.other = true;
+      aConstraint.h = myStorage->addConstraint(aConstraint);
+      mySlvsConstraints.push_back(aConstraint.h);
+
+      aPrevLine = aLine;
+    }
+  }
+  // Equal radii constraints
+  for (aCopyIter = aCircsAndCopies.begin(); aCopyIter != aCircsAndCopies.end(); aCopyIter++) {
+    size_t aSize = aCopyIter->size();
+    for (size_t i = 0; i < aSize - 1; i++) {
+      aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+          SLVS_C_EQUAL_RADIUS, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
+          (*aCopyIter)[i], (*aCopyIter)[i+1]);
+      aConstraint.h = myStorage->addConstraint(aConstraint);
+      mySlvsConstraints.push_back(aConstraint.h);
+    }
+  }
+
+  // Set the rotation center unchanged during constraint recalculation
+  if (!myStorage->isPointFixed(myRotationCenter, aConstraint.h, true)) {
+    aConstraint = Slvs_MakeConstraint(
+        SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
+        myRotationCenter, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+    aConstraint.h = myStorage->addConstraint(aConstraint);
+    mySlvsConstraints.push_back(aConstraint.h);
+  }
+
+  adjustConstraint();
+}
+
+void SketchSolver_ConstraintMultiRotation::update(ConstraintPtr theConstraint)
+{
+  cleanErrorMsg();
+  if (!theConstraint || theConstraint == myBaseConstraint) {
+    AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+        myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+    AttributeIntegerPtr aNbCopies = myBaseConstraint->integer(SketchPlugin_MultiRotation::NUMBER_OF_COPIES_ID());
+    if (anInitialRefList->size() != myNumberOfObjects || aNbCopies->value() != myNumberOfCopies) {
+      remove(myBaseConstraint);
+      process();
+      return;
+    }
+  }
+
+  // update angle value
+  myAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+      myBaseConstraint->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value();
+
+  SketchSolver_Constraint::update();
+}
+
+bool SketchSolver_ConstraintMultiRotation::remove(ConstraintPtr theConstraint)
+{
+  cleanErrorMsg();
+  if (theConstraint && theConstraint != myBaseConstraint)
+    return false;
+  bool isFullyRemoved = true;
+  std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
+  for (; aCIter != mySlvsConstraints.end(); aCIter++)
+   isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
+  mySlvsConstraints.clear();
+
+  std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
+  for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
+    myStorage->removeEntity(aFeatIt->second);
+
+  if (isFullyRemoved) {
+    myFeatureMap.clear();
+    myAttributeMap.clear();
+    myValueMap.clear();
+  } else
+    cleanRemovedEntities();
+  return true;
+}
+
+void SketchSolver_ConstraintMultiRotation::adjustConstraint()
+{
+  if (abs(myAngle) < tolerance) {
+    myStorage->setNeedToResolve(false);
+    return;
+  }
+
+  // Obtain coordinates of rotation center
+  Slvs_Entity aRotCenter = myStorage->getEntity(myRotationCenter);
+  double aCenterXY[2];
+  for (int i = 0; i < 2; i++)
+    aCenterXY[i] = myStorage->getParameter(aRotCenter.param[i]).val;
+
+  double cosA = cos(myAngle * PI / 180.0);
+  double sinA = sin(myAngle * PI / 180.0);
+
+  // Update positions of all points to satisfy angles
+  std::list<Slvs_Constraint> aConstrAngle = myStorage->getConstraintsByType(SLVS_C_ANGLE);
+  std::list<Slvs_Constraint>::iterator anAngIt = aConstrAngle.begin();
+  std::vector<Slvs_hConstraint>::iterator aCIt;
+  Slvs_hConstraint aFixed; // temporary variable
+  double aVec[2]; // coordinates of vector defining a line
+  Slvs_Param aTarget[2]; // parameter to be changed
+  for (; anAngIt != aConstrAngle.end(); anAngIt++) {
+    for (aCIt = mySlvsConstraints.begin(); aCIt != mySlvsConstraints.end(); aCIt++)
+      if (anAngIt->h == *aCIt)
+        break;
+    if (aCIt == mySlvsConstraints.end())
+      continue;
+    Slvs_Entity aLineA = myStorage->getEntity(anAngIt->entityA);
+    Slvs_Entity aLineB = myStorage->getEntity(anAngIt->entityB);
+    if (myStorage->isPointFixed(aLineB.point[1], aFixed))
+      continue;
+    Slvs_Entity aPointA = myStorage->getEntity(aLineA.point[1]);
+    Slvs_Entity aPointB = myStorage->getEntity(aLineB.point[1]);
+    for (int i = 0; i < 2; i++) {
+      aVec[i] = myStorage->getParameter(aPointA.param[i]).val - aCenterXY[i];
+      aTarget[i] = myStorage->getParameter(aPointB.param[i]);
+    }
+    aTarget[0].val = aCenterXY[0] + aVec[0] * cosA - aVec[1] * sinA;
+    aTarget[1].val = aCenterXY[1] + aVec[0] * sinA + aVec[1] * cosA;
+    myStorage->updateParameter(aTarget[0]);
+    myStorage->updateParameter(aTarget[1]);
+
+    anAngIt->valA = myAngle;
+    myStorage->updateConstraint(*anAngIt);
+  }
+
+  // update positions of centers of arcs for correct radius calculation
+  std::list<Slvs_Constraint> aRadii = myStorage->getConstraintsByType(SLVS_C_EQUAL_RADIUS);
+  std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt;
+  for (anAngIt = aRadii.begin(); anAngIt != aRadii.end(); anAngIt++) {
+    int aNbFound = 0; // number of arcs used in translation
+    for (aFeatIt = myFeatureMap.begin(); aFeatIt != myFeatureMap.end(); aFeatIt++)
+      if (aFeatIt->second == anAngIt->entityA || aFeatIt->second == anAngIt->entityB) {
+        if (aFeatIt->first->getKind() == SketchPlugin_Arc::ID())
+          aNbFound++;
+        else
+          break;
+      }
+    if (aNbFound != 2)
+      continue;
+    // two arcs were found, update their centers
+    Slvs_Entity anArcA = myStorage->getEntity(anAngIt->entityA);
+    Slvs_Entity anArcB = myStorage->getEntity(anAngIt->entityB);
+    if (myStorage->isPointFixed(anArcB.point[0], aFixed))
+      continue;
+    Slvs_Entity aCenterA = myStorage->getEntity(anArcA.point[0]);
+    Slvs_Entity aCenterB = myStorage->getEntity(anArcB.point[0]);
+    for (int i = 0; i < 2; i++) {
+      aVec[i] = myStorage->getParameter(aCenterA.param[i]).val - aCenterXY[i];
+      aTarget[i] = myStorage->getParameter(aCenterB.param[i]);
+    }
+    aTarget[0].val = aCenterXY[0] + aVec[0] * cosA - aVec[1] * sinA;
+    aTarget[1].val = aCenterXY[1] + aVec[0] * sinA + aVec[1] * cosA;
+    myStorage->updateParameter(aTarget[0]);
+    myStorage->updateParameter(aTarget[1]);
+  }
+}
diff --git a/src/SketchSolver/SketchSolver_ConstraintMultiRotation.h b/src/SketchSolver/SketchSolver_ConstraintMultiRotation.h
new file mode 100644 (file)
index 0000000..e9d0bd1
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    SketchSolver_ConstraintMultiRotation.h
+// Created: 1 Apr 2015
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintMultiRotation_H_
+#define SketchSolver_ConstraintMultiRotation_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_Constraint.h>
+
+/** \class   SketchSolver_ConstraintMultiRotation
+ *  \ingroup Plugins
+ *  \brief   Convert rotated features to the list of SolveSpace constraints
+ */
+class SketchSolver_ConstraintMultiRotation : public SketchSolver_Constraint
+{
+public:
+  SketchSolver_ConstraintMultiRotation(ConstraintPtr theConstraint) :
+      SketchSolver_Constraint(theConstraint),
+      myNumberOfObjects(0),
+      myNumberOfCopies(0)
+  {}
+
+  virtual int getType() const
+  { return SLVS_C_MULTI_ROTATION; }
+
+  /// \brief Update constraint
+  virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
+
+  /// \brief Tries to remove constraint
+  /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+  virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
+
+protected:
+  /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+  virtual void process();
+
+  /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
+  /// \param[out] theValue      numerical characteristic of constraint (e.g. distance)
+  /// \param[out] theAttributes list of attributes to be filled
+  virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes)
+  { /* do nothing here */ }
+
+  /// \brief Generate list of rotated entities
+  /// \param[out] theCenter   ID of central point of rotation
+  /// \param[out] theAngle    rotation angle
+  /// \param[out] thePoints   list of IDs of initial points and their rotated copies
+  /// \param[out] theCircular list of IDs of arcs and circles and their copies
+  void getAttributes(Slvs_hEntity& theCenter, double& theAngle,
+                     std::vector<std::vector<Slvs_hEntity> >& thePoints,
+                     std::vector<std::vector<Slvs_hEntity> >& theCircular);
+
+  /// \brief This method is used in derived objects to check consistence of constraint.
+  virtual void adjustConstraint();
+
+private:
+  size_t myNumberOfObjects; ///< number of previous initial objects
+  size_t myNumberOfCopies;  ///< number of previous copies of initial objects
+  Slvs_hEntity myRotationCenter; ///< ID of center of rotation
+  double myAngle;           ///< angle of rotation
+};
+
+#endif
diff --git a/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp b/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp
new file mode 100644 (file)
index 0000000..2e5bafb
--- /dev/null
@@ -0,0 +1,290 @@
+#include <SketchSolver_ConstraintMultiTranslation.h>
+#include <SketchSolver_Group.h>
+#include <SketchSolver_Error.h>
+
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_MultiTranslation.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Data.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_XY.h>
+
+#include <math.h>
+
+
+void SketchSolver_ConstraintMultiTranslation::getAttributes(
+    Slvs_hEntity& theStartPoint, Slvs_hEntity& theEndPoint,
+    std::vector<std::vector<Slvs_hEntity> >& thePoints,
+    std::vector<std::vector<Slvs_hEntity> >& theCircular)
+{
+  DataPtr aData = myBaseConstraint->data();
+  AttributePtr aStartPointAttr = aData->attribute(SketchPlugin_MultiTranslation::START_POINT_ID());
+  AttributePtr aEndPointAttr = aData->attribute(SketchPlugin_MultiTranslation::END_POINT_ID());
+  if (!aStartPointAttr || !aStartPointAttr->isInitialized() ||
+      !aEndPointAttr || !aEndPointAttr->isInitialized()) {
+    myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+    return;
+  }
+
+  int aType = SLVS_E_UNKNOWN; // type of created entity
+  Slvs_hEntity anEntityID = myGroup->getAttributeId(aStartPointAttr);
+  if (anEntityID == SLVS_E_UNKNOWN)
+    anEntityID = changeEntity(aStartPointAttr, aType);
+  theStartPoint = anEntityID;
+  anEntityID = myGroup->getAttributeId(aEndPointAttr);
+  if (anEntityID == SLVS_E_UNKNOWN)
+    anEntityID = changeEntity(aEndPointAttr, aType);
+  theEndPoint = anEntityID;
+
+  // Lists of objects and number of copies
+  AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+      aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  myNumberOfObjects = anInitialRefList->size();
+  myNumberOfCopies = (size_t) aData->integer(SketchPlugin_MultiTranslation::NUMBER_OF_COPIES_ID())->value();
+  AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+      myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+  if (!aRefList) {
+    myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+    return;
+  }
+
+  // Obtain all points of initial features and store them into separate lists
+  // containing their translated copies.
+  // Also all circles and arc collected too, because they will be constrained by equal radii.
+  FeaturePtr aFeature;
+  ResultConstructionPtr aRC;
+  std::vector<Slvs_hEntity> aPoints[2]; // lists of points of features
+  std::vector<Slvs_hEntity> aCircs;     // list of circular objects
+  std::list<ObjectPtr> anObjectList = aRefList->list();
+  std::list<ObjectPtr>::iterator anObjectIter = anObjectList.begin();
+  while (anObjectIter != anObjectList.end()) {
+    aPoints[0].clear();
+    aPoints[1].clear();
+    aCircs.clear();
+
+    for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) {
+      aFeature = ModelAPI_Feature::feature(*anObjectIter);
+      if (!aFeature)
+        continue;
+      anEntityID = changeEntity(aFeature, aType);
+      Slvs_Entity anEntity = myStorage->getEntity(anEntityID);
+      switch (aType) {
+      case SLVS_E_POINT_IN_2D:
+      case SLVS_E_POINT_IN_3D:
+        aPoints[0].push_back(anEntityID);
+        break;
+      case SLVS_E_LINE_SEGMENT:
+        aPoints[0].push_back(anEntity.point[0]); // start point of line
+        aPoints[1].push_back(anEntity.point[1]); // end point of line
+        break;
+      case SLVS_E_CIRCLE:
+        aPoints[0].push_back(anEntity.point[0]); // center of circle
+        aCircs.push_back(anEntityID);
+        break;
+      case SLVS_E_ARC_OF_CIRCLE:
+        aPoints[0].push_back(anEntity.point[1]); // start point of arc
+        aPoints[1].push_back(anEntity.point[2]); // end point of arc
+        aCircs.push_back(anEntityID);
+        break;
+      default:
+        myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+        return;
+      }
+    }
+
+    if (!aPoints[0].empty())
+      thePoints.push_back(aPoints[0]);
+    if (!aPoints[1].empty())
+      thePoints.push_back(aPoints[1]);
+    if (!aCircs.empty())
+      theCircular.push_back(aCircs);
+  }
+}
+
+void SketchSolver_ConstraintMultiTranslation::process()
+{
+  cleanErrorMsg();
+  if (!myBaseConstraint || !myStorage || myGroup == 0) {
+    /// TODO: Put error message here
+    return;
+  }
+  if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+    update(myBaseConstraint);
+
+  Slvs_hEntity aStartPoint, aEndPoint;
+  std::vector<std::vector<Slvs_hEntity> > aPointsAndCopies;
+  std::vector<std::vector<Slvs_hEntity> > aCircsAndCopies;
+  getAttributes(aStartPoint, aEndPoint, aPointsAndCopies, aCircsAndCopies);
+  if (!myErrorMsg.empty())
+    return;
+
+  // Create lines between neighbor translated points and make them parallel to the translation line.
+  // Also these lines should have equal lengths.
+  Slvs_Constraint aConstraint;
+  Slvs_Entity aTranslationLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
+      myGroup->getWorkplaneId(), aStartPoint, aEndPoint);
+  aTranslationLine.h = myStorage->addEntity(aTranslationLine);
+  myTranslationLine = aTranslationLine.h;
+  std::vector<std::vector<Slvs_hEntity> >::iterator aCopyIter = aPointsAndCopies.begin();
+  for (; aCopyIter != aPointsAndCopies.end(); aCopyIter++) {
+    size_t aSize = aCopyIter->size();
+    for (size_t i = 0; i < aSize - 1; i++) {
+      Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
+          myGroup->getWorkplaneId(), (*aCopyIter)[i], (*aCopyIter)[i+1]);
+      aLine.h = myStorage->addEntity(aLine);
+      // Equal length constraint
+      aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+          SLVS_C_EQUAL_LENGTH_LINES, myGroup->getWorkplaneId(), 0.0,
+          SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aTranslationLine.h, aLine.h);
+      aConstraint.h = myStorage->addConstraint(aConstraint);
+      mySlvsConstraints.push_back(aConstraint.h);
+      // Parallel constraint
+      aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+          SLVS_C_PARALLEL, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
+          aTranslationLine.h, aLine.h);
+      aConstraint.h = myStorage->addConstraint(aConstraint);
+      mySlvsConstraints.push_back(aConstraint.h);
+    }
+  }
+  // Equal radii constraints
+  for (aCopyIter = aCircsAndCopies.begin(); aCopyIter != aCircsAndCopies.end(); aCopyIter++) {
+    size_t aSize = aCopyIter->size();
+    for (size_t i = 0; i < aSize - 1; i++) {
+      aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+          SLVS_C_EQUAL_RADIUS, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
+          (*aCopyIter)[i], (*aCopyIter)[i+1]);
+      aConstraint.h = myStorage->addConstraint(aConstraint);
+      mySlvsConstraints.push_back(aConstraint.h);
+    }
+  }
+
+  // Set the translation line unchanged during constraint recalculation
+  for (int i = 0; i < 2; i++) {
+    if (myStorage->isPointFixed(aTranslationLine.point[i], aConstraint.h, true))
+      continue;
+    aConstraint = Slvs_MakeConstraint(
+        SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
+        aTranslationLine.point[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+    aConstraint.h = myStorage->addConstraint(aConstraint);
+    mySlvsConstraints.push_back(aConstraint.h);
+  }
+
+  adjustConstraint();
+}
+
+void SketchSolver_ConstraintMultiTranslation::update(ConstraintPtr theConstraint)
+{
+  cleanErrorMsg();
+  if (!theConstraint || theConstraint == myBaseConstraint) {
+    AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+        myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+    AttributeIntegerPtr aNbCopies = myBaseConstraint->integer(SketchPlugin_MultiTranslation::NUMBER_OF_COPIES_ID());
+    if (anInitialRefList->size() != myNumberOfObjects ||
+        (size_t)aNbCopies->value() != myNumberOfCopies) {
+      remove(myBaseConstraint);
+      process();
+      return;
+    }
+  }
+  SketchSolver_Constraint::update();
+}
+
+bool SketchSolver_ConstraintMultiTranslation::remove(ConstraintPtr theConstraint)
+{
+  cleanErrorMsg();
+  if (theConstraint && theConstraint != myBaseConstraint)
+    return false;
+  bool isFullyRemoved = true;
+  std::vector<Slvs_hEntity>::iterator aCIter = mySlvsConstraints.begin();
+  for (; aCIter != mySlvsConstraints.end(); aCIter++)
+   isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved;
+  mySlvsConstraints.clear();
+
+  std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
+  for (; aFeatIt != myFeatureMap.end(); aFeatIt++)
+    myStorage->removeEntity(aFeatIt->second);
+
+  if (isFullyRemoved) {
+    myFeatureMap.clear();
+    myAttributeMap.clear();
+    myValueMap.clear();
+  } else
+    cleanRemovedEntities();
+  return true;
+}
+
+void SketchSolver_ConstraintMultiTranslation::adjustConstraint()
+{
+  Slvs_Entity aTranslationLine = myStorage->getEntity(myTranslationLine);
+  // Check if the distance between point is 0, no need to resolve constraints (just wait another values)
+  double aXY[4];
+  for (int i = 0; i < 2; i++) {
+    Slvs_Entity aPnt = myStorage->getEntity(aTranslationLine.point[i]);
+    aXY[2*i] = myStorage->getParameter(aPnt.param[0]).val;
+    aXY[2*i+1] = myStorage->getParameter(aPnt.param[1]).val;
+  }
+  double aDelta[2] = {aXY[2] - aXY[0], aXY[3] - aXY[1]};
+  if (fabs(aDelta[0]) + fabs(aDelta[1]) < tolerance) {
+    myStorage->setNeedToResolve(false);
+    return;
+  }
+
+  // Update positions of all points to satisfy distances
+  std::list<Slvs_Constraint> aParallel = myStorage->getConstraintsByType(SLVS_C_PARALLEL);
+  std::list<Slvs_Constraint>::iterator aParIt = aParallel.begin();
+  std::vector<Slvs_hConstraint>::iterator aCIt;
+  Slvs_hConstraint aFixed; // temporary variable
+  for (; aParIt != aParallel.end(); aParIt++) {
+    for (aCIt = mySlvsConstraints.begin(); aCIt != mySlvsConstraints.end(); aCIt++)
+      if (aParIt->h == *aCIt)
+        break;
+    if (aCIt == mySlvsConstraints.end())
+      continue;
+    Slvs_Entity aLine = myStorage->getEntity(aParIt->entityB);
+    if (myStorage->isPointFixed(aLine.point[1], aFixed))
+      continue;
+    Slvs_Entity aStart = myStorage->getEntity(aLine.point[0]);
+    Slvs_Entity aEnd = myStorage->getEntity(aLine.point[1]);
+    for (int i = 0; i < 2; i++) {
+      Slvs_Param aFrom = myStorage->getParameter(aStart.param[i]);
+      Slvs_Param aTo = myStorage->getParameter(aEnd.param[i]);
+      aTo.val = aFrom.val + aDelta[i];
+      myStorage->updateParameter(aTo);
+    }
+  }
+
+  // update positions of centers of arcs for correct radius calculation
+  std::list<Slvs_Constraint> aRadii = myStorage->getConstraintsByType(SLVS_C_EQUAL_RADIUS);
+  std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt;
+  for (aParIt = aRadii.begin(); aParIt != aRadii.end(); aParIt++) {
+    int aNbFound = 0; // number of arcs used in translation
+    for (aFeatIt = myFeatureMap.begin(); aFeatIt != myFeatureMap.end(); aFeatIt++)
+      if (aFeatIt->second == aParIt->entityA || aFeatIt->second == aParIt->entityB) {
+        if (aFeatIt->first->getKind() == SketchPlugin_Arc::ID())
+          aNbFound++;
+        else
+          break;
+      }
+    if (aNbFound != 2)
+      continue;
+    // two arcs were found, update their centers
+    Slvs_Entity anArcA = myStorage->getEntity(aParIt->entityA);
+    Slvs_Entity anArcB = myStorage->getEntity(aParIt->entityB);
+    if (myStorage->isPointFixed(anArcB.point[0], aFixed))
+      continue;
+    Slvs_Entity aCenterA = myStorage->getEntity(anArcA.point[0]);
+    Slvs_Entity aCenterB = myStorage->getEntity(anArcB.point[0]);
+    for (int i = 0; i < 2; i++) {
+      Slvs_Param aFrom = myStorage->getParameter(aCenterA.param[i]);
+      Slvs_Param aTo = myStorage->getParameter(aCenterB.param[i]);
+      aTo.val = aFrom.val + aDelta[i];
+      myStorage->updateParameter(aTo);
+    }
+  }
+}
diff --git a/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.h b/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.h
new file mode 100644 (file)
index 0000000..b02551f
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:    SketchSolver_ConstraintMultiTranslation.h
+// Created: 1 Apr 2015
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintMultiTranslation_H_
+#define SketchSolver_ConstraintMultiTranslation_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_Constraint.h>
+
+/** \class   SketchSolver_ConstraintMultiTranslation
+ *  \ingroup Plugins
+ *  \brief   Convert translated features to the list of SolveSpace constraints
+ */
+class SketchSolver_ConstraintMultiTranslation : public SketchSolver_Constraint
+{
+public:
+  SketchSolver_ConstraintMultiTranslation(ConstraintPtr theConstraint) :
+      SketchSolver_Constraint(theConstraint),
+      myNumberOfObjects(0),
+      myNumberOfCopies(0)
+  {}
+
+  virtual int getType() const
+  { return SLVS_C_MULTI_TRANSLATION; }
+
+  /// \brief Update constraint
+  virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
+
+  /// \brief Tries to remove constraint
+  /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+  virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr());
+
+protected:
+  /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+  virtual void process();
+
+  /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
+  /// \param[out] theValue      numerical characteristic of constraint (e.g. distance)
+  /// \param[out] theAttributes list of attributes to be filled
+  virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes)
+  { /* do nothing here */ }
+
+  /// \brief Generate list of translated entities
+  /// \param[out] theStartPoint ID of start point of translation
+  /// \param[out] theEndPoint   ID of final point of translation
+  /// \param[out] thePoints     list of IDs of initial points and their translated copies
+  /// \param[out] theCircular   list of IDs of arcs and circles and their copies
+  void getAttributes(Slvs_hEntity& theStartPoint, Slvs_hEntity& theEndPoint,
+                     std::vector<std::vector<Slvs_hEntity> >& thePoints,
+                     std::vector<std::vector<Slvs_hEntity> >& theCircular);
+
+  /// \brief This method is used in derived objects to check consistence of constraint.
+  virtual void adjustConstraint();
+
+private:
+  size_t myNumberOfObjects; ///< number of previous initial objects
+  size_t myNumberOfCopies;  ///< number of previous copies of initial objects
+  Slvs_hEntity myTranslationLine; ///< ID of translation line
+};
+
+#endif
index 7247553ae345d4adcf618b0340f43f348f0e2c7d..735412dde8706158efc1cfe6ca2dfdfdb9def8cb 100644 (file)
@@ -35,28 +35,38 @@ void SketchSolver_ConstraintRigid::process()
   double aValue;
   std::vector<Slvs_hEntity> anEntities;
   getAttributes(aValue, anEntities);
-  if (!myErrorMsg.empty() || myFeatureMap.empty())
+  if (!myErrorMsg.empty() || (myFeatureMap.empty() && myAttributeMap.empty()))
     return;
 
-  Slvs_hEntity anEntID = myFeatureMap.begin()->second;
+  Slvs_hEntity anEntID; 
+  if (!myFeatureMap.empty())
+    anEntID = myFeatureMap.begin()->second;
+  else
+    anEntID = myAttributeMap.begin()->second;
   if (myStorage->isEntityFixed(anEntID, true)) {
     myErrorMsg = SketchSolver_Error::ALREADY_FIXED();
     return;
   }
 
-  if (myFeatureMap.begin()->first->getKind() == SketchPlugin_Line::ID()) {
+  std::string aKind;
+  if (!myFeatureMap.empty())
+    aKind = myFeatureMap.begin()->first->getKind();
+  else
+    aKind = myAttributeMap.begin()->first->attributeType();
+
+  if (aKind == SketchPlugin_Line::ID()) {
     Slvs_Entity aLine = myStorage->getEntity(anEntID);
     fixLine(aLine);
   }
-  else if (myFeatureMap.begin()->first->getKind() == SketchPlugin_Arc::ID()) {
+  else if (aKind == SketchPlugin_Arc::ID()) {
     Slvs_Entity anArc = myStorage->getEntity(anEntID);
     fixArc(anArc);
   }
-  else if (myFeatureMap.begin()->first->getKind() == SketchPlugin_Circle::ID()) {
+  else if (aKind == SketchPlugin_Circle::ID()) {
     Slvs_Entity aCirc = myStorage->getEntity(anEntID);
     fixCircle(aCirc);
   }
-  else if (myFeatureMap.begin()->first->getKind() == SketchPlugin_Point::ID()) {
+  else if (aKind == SketchPlugin_Point::ID() || aKind == GeomDataAPI_Point2D::typeId()) {
     fixPoint(anEntID);
   }
 }
index 8a5267be2c6fb42a56f027737ec2fe34e580f743..419cc3e87b51241c5d45d1db49fd0020d4c70aac 100644 (file)
@@ -236,12 +236,21 @@ bool SketchSolver_Group::changeConstraint(
       setTemporary(aConstraint);
     }
   }
-  //// Fix base features for mirror
-  //if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
-  //  AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
-  //      theConstraint->attribute(SketchPlugin_ConstraintMirror::ENTITY_B()));
-  //  fixFeaturesList(aRefList);
-  //}
+  // Fix mirror line
+  if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
+    AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+        theConstraint->attribute(SketchPlugin_ConstraintMirror::ENTITY_A()));
+    if (aRefAttr && aRefAttr->isObject()) {
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+      SolverConstraintPtr aConstraint =
+          SketchSolver_Builder::getInstance()->createRigidConstraint(aFeature);
+      if (aConstraint) {
+        aConstraint->setGroup(this);
+        aConstraint->setStorage(myStorage);
+        setTemporary(aConstraint);
+      }
+    }
+  }
 
   if (!myFeatureStorage)
     myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage);
@@ -272,8 +281,7 @@ bool SketchSolver_Group::updateFeature(std::shared_ptr<SketchPlugin_Feature> the
 
 void SketchSolver_Group::moveFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
 {
-  updateFeature(theFeature);
-  // Temporary rigid constraint
+  // Firstly, create temporary rigid constraint
   SolverConstraintPtr aConstraint =
       SketchSolver_Builder::getInstance()->createRigidConstraint(theFeature);
   if (!aConstraint)
@@ -282,6 +290,8 @@ void SketchSolver_Group::moveFeature(std::shared_ptr<SketchPlugin_Feature> theFe
   aConstraint->setStorage(myStorage);
   if (aConstraint->error().empty())
     setTemporary(aConstraint);
+  // Secondly, update the feature
+  updateFeature(theFeature);
 }
 
 // ============================================================================
index bdc23ce288182adff99c5752d3f0befc5d06e60f..46e83afd0bf8f6b9eaffdbab6f8bccde08cde368 100644 (file)
@@ -25,7 +25,11 @@ typedef unsigned int UINT32;
 // Unknown constraint (for error reporting)
 #define SLVS_C_UNKNOWN 0
 // Fillet constraint identifier
-#define SLVS_C_FILLET 100100
+#define SLVS_C_FILLET            100100
+// Multi-rotation constraint identifier
+#define SLVS_C_MULTI_ROTATION    100101
+// Multi-translation constraint identifier
+#define SLVS_C_MULTI_TRANSLATION 100102
 // Unknown entity
 #define SLVS_E_UNKNOWN 0
 // Unknown group
index 963c7e54244d171e682de90299662e95c52283bf..fb508fed714d25e78555e2b5c2dc50e2a7cb611c 100644 (file)
@@ -17,6 +17,7 @@ SET(PROJECT_HEADERS
        SketcherPrs_Radius.h
        SketcherPrs_LengthDimension.h
        SketcherPrs_Mirror.h
+       SketcherPrs_Transformation.h
 )
 
 SET(PROJECT_SOURCES
@@ -35,12 +36,14 @@ SET(PROJECT_SOURCES
        SketcherPrs_Radius.cpp
        SketcherPrs_LengthDimension.cpp
        SketcherPrs_Mirror.cpp
+       SketcherPrs_Transformation.cpp
 )
 
 SET(PROJECT_LIBRARIES
     Config
     ModelAPI
     GeomAPI
+       Events
     ${CAS_KERNEL} 
     ${CAS_MODELER} 
     ${CAS_VIEWER}
@@ -65,6 +68,8 @@ SET(PROJECT_PICTURES
        icons/equal.png
        icons/tangent.png
        icons/mirror.png
+       icons/rotate.png
+       icons/translate.png
 )
 
 ADD_DEFINITIONS(-DSKETCHERPRS_EXPORTS ${CAS_DEFINITIONS})
@@ -72,6 +77,7 @@ ADD_LIBRARY(SketcherPrs SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS})
 
 INCLUDE_DIRECTORIES(
   ${PROJECT_SOURCE_DIR}/src/Config
+  ${PROJECT_SOURCE_DIR}/src/Events
   ${PROJECT_SOURCE_DIR}/src/ModelAPI
   ${PROJECT_SOURCE_DIR}/src/GeomAPI
   ${PROJECT_SOURCE_DIR}/src/GeomDataAPI
index b85d018b361da4502cfa8bbbc51b465261de0799..7bd3d30ef4f347eeef10d7302de8dc3929fe1962 100644 (file)
@@ -46,6 +46,8 @@ void SketcherPrs_Coincident::Compute(const Handle(PrsMgr_PresentationManager3d)&
 {
   std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(myConstraint, 
                                                                     SketchPlugin_Constraint::ENTITY_A());
+  if (aPnt.get() == NULL)
+    aPnt = SketcherPrs_Tools::getPoint(myConstraint, SketchPlugin_Constraint::ENTITY_B());
   if (aPnt.get() == NULL)
     return;
 
@@ -55,15 +57,27 @@ void SketcherPrs_Coincident::Compute(const Handle(PrsMgr_PresentationManager3d)&
   static Handle(Graphic3d_AspectMarker3d) aPtA;
   if (aPtA.IsNull()) {
     aPtA = new Graphic3d_AspectMarker3d ();
-    aPtA->SetType(Aspect_TOM_RING1);
-    aPtA->SetScale(2.);
-    aPtA->SetColor(myOwnColor);
   }
+  aPtA->SetType(Aspect_TOM_RING3);
+  aPtA->SetScale(2.);
+  aPtA->SetColor(Quantity_NOC_YELLOW);
+
   Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup(thePresentation);
   aGroup->SetPrimitivesAspect(aPtA);
   Handle(Graphic3d_ArrayOfPoints) aPntArray = new Graphic3d_ArrayOfPoints(1);
   aPntArray->AddVertex (aPoint->x(), aPoint->y(), aPoint->z());
   aGroup->AddPrimitiveArray (aPntArray);
+
+  aPtA->SetType(Aspect_TOM_RING1);
+  aPtA->SetScale(1.);
+  aPtA->SetColor(Quantity_NOC_BLACK);
+  aGroup->SetPrimitivesAspect(aPtA);
+  aGroup->AddPrimitiveArray (aPntArray);
+
+  aPtA->SetType(Aspect_TOM_POINT);
+  aPtA->SetScale(5.);
+  aGroup->SetPrimitivesAspect(aPtA);
+  aGroup->AddPrimitiveArray (aPntArray);
 }
 
 
index 39ce4d6e0ce01385eba019c200cec8431ea4c742..b855929ab16f7513ffb86b1fe71fd7761c31a492 100644 (file)
@@ -16,6 +16,7 @@
 #include "SketcherPrs_Radius.h"
 #include "SketcherPrs_LengthDimension.h"
 #include "SketcherPrs_Mirror.h"
+#include "SketcherPrs_Transformation.h"
 
 #define CONSTRAINT_PRS_IMPL(NAME, CLASS) \
 AISObjectPtr SketcherPrs_Factory::NAME(ModelAPI_Feature* theConstraint, \
@@ -55,3 +56,21 @@ AISObjectPtr SketcherPrs_Factory::verticalConstraint(ModelAPI_Feature* theConstr
   aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aPrs)); 
   return aAISObj; 
 }
+
+AISObjectPtr SketcherPrs_Factory::translateConstraint(ModelAPI_Feature* theConstraint,
+                                       const std::shared_ptr<GeomAPI_Ax3>& thePlane)
+{ 
+  std::shared_ptr<GeomAPI_AISObject> aAISObj = AISObjectPtr(new GeomAPI_AISObject()); 
+  Handle(SketcherPrs_Transformation) aPrs = new SketcherPrs_Transformation(theConstraint, thePlane, true); 
+  aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aPrs)); 
+  return aAISObj; 
+}
+
+AISObjectPtr SketcherPrs_Factory::rotateConstraint(ModelAPI_Feature* theConstraint,
+                                       const std::shared_ptr<GeomAPI_Ax3>& thePlane)
+{ 
+  std::shared_ptr<GeomAPI_AISObject> aAISObj = AISObjectPtr(new GeomAPI_AISObject()); 
+  Handle(SketcherPrs_Transformation) aPrs = new SketcherPrs_Transformation(theConstraint, thePlane, false); 
+  aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aPrs)); 
+  return aAISObj; 
+}
index 9b627b940650c0d30720e5c5b2a7e807621a43a8..291484d3b491e53960406d4d28462de3e29db618 100644 (file)
@@ -30,7 +30,7 @@ public:
   /// \param thePlane the current sketch plane
   GET_CONSTRAINT_PRS(coincidentConstraint)
 
-  /// Creates coincedent parallel presentation
+  /// Creates parallel constraint presentation
   /// \param theConstraint the constraint
   /// \param thePlane the current sketch plane
   GET_CONSTRAINT_PRS(parallelConstraint)
@@ -40,45 +40,55 @@ public:
   /// \param thePlane the current sketch plane
   GET_CONSTRAINT_PRS(perpendicularConstraint)
 
-  /// Creates coincedent perpendicular presentation
+  /// Creates rigid constraint presentation
   /// \param theConstraint the constraint
   /// \param thePlane the current sketch plane
   GET_CONSTRAINT_PRS(rigidConstraint)
 
-  /// Creates coincedent perpendicular presentation
+  /// Creates horizontal constraint presentation
   /// \param theConstraint the constraint
   /// \param thePlane the current sketch plane
   GET_CONSTRAINT_PRS(horisontalConstraint)
 
-  /// Creates coincedent perpendicular presentation
+  /// Creates vertical constraint presentation
   /// \param theConstraint the constraint
   /// \param thePlane the current sketch plane
   GET_CONSTRAINT_PRS(verticalConstraint)
 
-  /// Creates coincedent perpendicular presentation
+  /// Creates equal constraint presentation
   /// \param theConstraint the constraint
   /// \param thePlane the current sketch plane
   GET_CONSTRAINT_PRS(equalConstraint)
 
-  /// Creates coincedent perpendicular presentation
+  /// Creates tangent constraiont presentation
   /// \param theConstraint the constraint
   /// \param thePlane the current sketch plane
   GET_CONSTRAINT_PRS(tangentConstraint)
 
-  /// Creates coincedent perpendicular presentation
+  /// Creates radius dimension presentation
   /// \param theConstraint the constraint
   /// \param thePlane the current sketch plane
   GET_CONSTRAINT_PRS(radiusConstraint)
 
-  /// Creates coincedent perpendicular presentation
+  /// Creates length dimension presentation
   /// \param theConstraint the constraint
   /// \param thePlane the current sketch plane
   GET_CONSTRAINT_PRS(lengthDimensionConstraint)
 
-  /// Creates coincedent perpendicular presentation
+  /// Creates mirror constraint presentation
   /// \param theConstraint the constraint
   /// \param thePlane the current sketch plane
   GET_CONSTRAINT_PRS(mirrorConstraint)
+
+  /// Creates translate constraint presentation
+  /// \param theConstraint the constraint
+  /// \param thePlane the current sketch plane
+  GET_CONSTRAINT_PRS(translateConstraint)
+
+  /// Creates rotate constraint presentation
+  /// \param theConstraint the constraint
+  /// \param thePlane the current sketch plane
+  GET_CONSTRAINT_PRS(rotateConstraint)
 };
 
 #endif
index 2c05d225f25b00bf593763291f38d9ab833a6f55..2c680a64aaf7aae5a882f65c920772e048a3b382 100644 (file)
@@ -10,8 +10,6 @@
 
 #include <SketchPlugin_Constraint.h>
 
-#include <ModelAPI_AttributeRefList.h>
-
 #include <Graphic3d_AspectLine3d.hxx>
 #include <Prs3d_Root.hxx>
 
@@ -76,7 +74,6 @@ void SketcherPrs_Mirror::drawLines(const Handle(Prs3d_Presentation)& thePrs, Qua
   if (anAttrC.get() == NULL)
     return;
 
-  SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
   int aNb = anAttrB->size();
   if (aNb != anAttrC->size())
     return;
@@ -90,20 +87,9 @@ void SketcherPrs_Mirror::drawLines(const Handle(Prs3d_Presentation)& thePrs, Qua
   addLine(aGroup, SketchPlugin_Constraint::ENTITY_A());
 
   // Draw source objects
-  int i;
-  ObjectPtr aObj;
-  for (i = 0; i < aNb; i++) {
-    aObj = anAttrB->object(i);
-    std::shared_ptr<GeomAPI_Shape> aShape = SketcherPrs_Tools::getShape(aObj);
-    if (aShape.get() != NULL)
-      drawShape(aShape, thePrs);
-  }
+  drawListOfShapes(anAttrB, thePrs);
+
   // draw mirrored objects
-  for (i = 0; i < aNb; i++) {
-    aObj = anAttrC->object(i);
-    std::shared_ptr<GeomAPI_Shape> aShape = SketcherPrs_Tools::getShape(aObj);
-    if (aShape.get() != NULL)
-      drawShape(aShape, thePrs);
-  }
+  drawListOfShapes(anAttrC, thePrs);
 }
 
index 73963b7fed11d3dce7c4356effe22da7981756d3..109d3a6871ebfed7df2f125f35850feaff856562 100644 (file)
@@ -13,6 +13,8 @@
 #include <GeomAPI_Curve.h>
 #include <GeomAPI_Vertex.h>
 
+#include <ModelAPI_AttributeRefAttr.h>
+
 #include <SketchPlugin_Constraint.h>
 
 #include <AIS_Drawer.hxx>
@@ -47,13 +49,24 @@ SketcherPrs_Rigid::SketcherPrs_Rigid(ModelAPI_Feature* theConstraint,
 
 bool SketcherPrs_Rigid::updatePoints(double theStep) const 
 {
-  ObjectPtr aObj = SketcherPrs_Tools::getResult(myConstraint, SketchPlugin_Constraint::ENTITY_A());
-  if (SketcherPrs_Tools::getShape(aObj).get() == NULL)
-    return false;
-
-  SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
-  gp_Pnt aP1 = aMgr->getPosition(aObj, this, theStep);
-  myPntArray->SetVertice(1, aP1);
+  std::shared_ptr<ModelAPI_Data> aData = myConstraint->data();
+  std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = aData->refattr(SketchPlugin_Constraint::ENTITY_A());
+  AttributePtr aRefAttr = anAttr->attr();
+  if (anAttr->isObject()) {
+    ObjectPtr aObj = anAttr->object();
+    if (SketcherPrs_Tools::getShape(aObj).get() == NULL)
+      return false;
+
+    SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
+    gp_Pnt aP1 = aMgr->getPosition(aObj, this, theStep);
+    myPntArray->SetVertice(1, aP1);
+  } else {
+    std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(myConstraint, SketchPlugin_Constraint::ENTITY_A());
+    if (aPnt.get() == NULL)
+      return false;
+    std::shared_ptr<GeomAPI_Pnt> aPoint = myPlane->to3D(aPnt->x(), aPnt->y() + theStep);
+    myPntArray->SetVertice(1, aPoint->impl<gp_Pnt>());
+  }
   return true;
 }
 
@@ -61,7 +74,19 @@ bool SketcherPrs_Rigid::updatePoints(double theStep) const
 void SketcherPrs_Rigid::drawLines(const Handle(Prs3d_Presentation)& thePrs, Quantity_Color theColor) const
 {
   ObjectPtr aObj = SketcherPrs_Tools::getResult(myConstraint, SketchPlugin_Constraint::ENTITY_A());
-  std::shared_ptr<GeomAPI_Shape> aShape = SketcherPrs_Tools::getShape(aObj);
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
+  std::shared_ptr<GeomAPI_Shape> aShape;
+  if (aFeature.get()) {
+    const std::list<ResultPtr>& aResults = aFeature->results();
+    std::list<ResultPtr>::const_iterator aIt;
+    for (aIt = aResults.cbegin(); aIt != aResults.cend(); aIt++) {
+      aShape = (*aIt)->shape();
+      if (aShape->isEdge())
+        break;
+    }
+  } else {
+    aShape = SketcherPrs_Tools::getShape(aObj);
+  }
   if (aShape.get() == NULL)
     return;
 
index b4e646709886c7f327bb81be9f1a16afe0d7c578..224a4b1dc36bbfac20152273288ea4042be96ce0 100644 (file)
@@ -12,6 +12,8 @@
 #include <GeomAPI_Vertex.h>
 #include <GeomAPI_Curve.h>
 
+#include <Events_Error.h>
+
 #include <Graphic3d_ArrayOfSegments.hxx>
 #include <Graphic3d_BndBox4f.hxx>
 
@@ -247,14 +249,23 @@ Handle(Image_AlienPixMap) SketcherPrs_SymbolPrs::icon()
   if (myIconsMap.count(iconName()) == 1) {
     return myIconsMap[iconName()];
   }
-  TCollection_AsciiString aFile(getenv("NewGeomResources"));
-  aFile += FSEP;
-  aFile += iconName();
-  Handle(Image_AlienPixMap) aPixMap = new Image_AlienPixMap();
-  if (aPixMap->Load(aFile)) {
-    myIconsMap[iconName()] = aPixMap;
-    return aPixMap;
+  char* aEnv = getenv("NEWGEOM_ROOT_DIR");
+  if (aEnv != NULL) {
+    TCollection_AsciiString aFile(aEnv);
+    aFile+=FSEP;
+    aFile+="resources";
+    aFile += FSEP;
+    aFile += iconName();
+    Handle(Image_AlienPixMap) aPixMap = new Image_AlienPixMap();
+    if (aPixMap->Load(aFile)) {
+      myIconsMap[iconName()] = aPixMap;
+      return aPixMap;
+    }
   }
+  static const char aMsg[] = "Error! constraint images are not found";
+  cout<<aMsg<<endl;
+  Events_Error::send(aMsg);
+  myIconsMap[iconName()] = Handle(Image_AlienPixMap)();
   return Handle(Image_AlienPixMap)();
 }
 
@@ -269,7 +280,11 @@ void SketcherPrs_SymbolPrs::ClearSelected()
 void SketcherPrs_SymbolPrs::prepareAspect()
 {
   if (myAspect.IsNull()) {
-    myAspect = new Graphic3d_AspectMarker3d(icon());
+    Handle(Image_AlienPixMap) aIcon = icon();
+    if (aIcon.IsNull()) 
+      myAspect = new Graphic3d_AspectMarker3d();
+    else
+      myAspect = new Graphic3d_AspectMarker3d(aIcon);
   }
 }
 
@@ -335,10 +350,12 @@ void SketcherPrs_SymbolPrs::Compute(const Handle(PrsMgr_PresentationManager3d)&
   int aNbVertex = myPntArray->VertexNumber();
   if (myOwner.IsNull()) {
     myOwner = new SelectMgr_EntityOwner(this);
-    for (int i = 1; i <= aNbVertex; i++) {
-      Handle(SketcherPrs_SensitivePoint) aSP = new SketcherPrs_SensitivePoint(myOwner, myPntArray, i);
-      mySPoints.Append(aSP);
-    }
+  }
+
+  mySPoints.Clear();
+  for (int i = 1; i <= aNbVertex; i++) {
+    Handle(SketcherPrs_SensitivePoint) aSP = new SketcherPrs_SensitivePoint(myOwner, myPntArray, i);
+    mySPoints.Append(aSP);
   }
 
   Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup(thePresentation);
@@ -465,3 +482,20 @@ void SketcherPrs_SymbolPrs::drawShape(const std::shared_ptr<GeomAPI_Shape>& theS
     StdPrs_Point::Add(thePrs, aPoint, myDrawer);
   }
 }
+
+void SketcherPrs_SymbolPrs::drawListOfShapes(const std::shared_ptr<ModelAPI_AttributeRefList>& theListAttr, 
+                                             const Handle(Prs3d_Presentation)& thePrs) const
+{
+  int aNb = theListAttr->size();
+  if (aNb == 0)
+    return;
+  int i;
+  ObjectPtr aObj;
+  for (i = 0; i < aNb; i++) {
+    aObj = theListAttr->object(i);
+    std::shared_ptr<GeomAPI_Shape> aShape = SketcherPrs_Tools::getShape(aObj);
+    if (aShape.get() != NULL)
+      drawShape(aShape, thePrs);
+  }
+}
+
index b6c0cf66a2b8a6407dadf7ad6ee10dc9b29fb42b..d2202bacf6f84cbb6f3fa0838e41fde18d73b291 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "SketcherPrs_SensitivePoint.h"
 #include <ModelAPI_Feature.h>
+#include <ModelAPI_AttributeRefList.h>
 
 #include <AIS_InteractiveObject.hxx>
 #include <GeomAPI_Ax3.h>
@@ -115,6 +116,11 @@ protected:
   void drawShape(const std::shared_ptr<GeomAPI_Shape>& theShape, 
     const Handle(Prs3d_Presentation)& thePrs) const;
 
+  /// Draw a list of shapes stored in a RefListAttribute
+  /// \param theListAttr the attribute of reference3s list
+  /// \param thePrs the presentation scene
+  void drawListOfShapes(const std::shared_ptr<ModelAPI_AttributeRefList>& theListAttr, 
+                        const Handle(Prs3d_Presentation)& thePrs) const;
 
 protected:
   /// Constraint feature
index aeefdb8e7f867e6f1d80fccf3b08b20ca183941c..f8891b2253bdf2025369ea887e7c5e977ae99b4b 100644 (file)
@@ -58,10 +58,6 @@ std::shared_ptr<GeomAPI_Pnt2d> getPoint(ModelAPI_Feature* theFeature,
     aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
         aFeature->data()->attribute(SketchPlugin_Point::COORD_ID()));
 
-  else if (aFeature && aFeature->getKind() == SketchPlugin_Circle::ID())
-    aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-        aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID()));
-
   else if (anAttr->attr()) {
     aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
   }
@@ -89,10 +85,6 @@ std::shared_ptr<GeomDataAPI_Point2D> getFeaturePoint(DataPtr theData,
     aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
         aFeature->data()->attribute(SketchPlugin_Point::COORD_ID()));
 
-  else if (aFeature && aFeature->getKind() == SketchPlugin_Circle::ID())
-    aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-        aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID()));
-
   else if (anAttr->attr()) {
     aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
   }
diff --git a/src/SketcherPrs/SketcherPrs_Transformation.cpp b/src/SketcherPrs/SketcherPrs_Transformation.cpp
new file mode 100644 (file)
index 0000000..dcbe966
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        SketcherPrs_Transformation.cpp
+// Created:     16 February 2015
+// Author:      Vitaly SMETANNIKOV
+
+#include "SketcherPrs_Transformation.h"
+#include "SketcherPrs_Tools.h"
+#include "SketcherPrs_PositionMgr.h"
+
+#include <SketchPlugin_Constraint.h>
+#include <ModelAPI_AttributeRefList.h>
+
+#include <Graphic3d_AspectLine3d.hxx>
+#include <Prs3d_Root.hxx>
+
+
+
+IMPLEMENT_STANDARD_HANDLE(SketcherPrs_Transformation, SketcherPrs_SymbolPrs);
+IMPLEMENT_STANDARD_RTTIEXT(SketcherPrs_Transformation, SketcherPrs_SymbolPrs);
+
+static Handle(Image_AlienPixMap) MyPixMap;
+
+SketcherPrs_Transformation::SketcherPrs_Transformation(ModelAPI_Feature* theConstraint, 
+                                           const std::shared_ptr<GeomAPI_Ax3>& thePlane,
+                                           bool isTranslation) 
+ : SketcherPrs_SymbolPrs(theConstraint, thePlane), myIsTranslation(isTranslation)
+{
+}  
+
+bool SketcherPrs_Transformation::updatePoints(double theStep) const 
+{
+  std::shared_ptr<ModelAPI_Data> aData = myConstraint->data();
+  std::shared_ptr<ModelAPI_AttributeRefList> anAttrB = aData->reflist(SketchPlugin_Constraint::ENTITY_B());
+  if (anAttrB.get() == NULL)
+    return false;
+
+  int aNbB = anAttrB->size();
+  if (aNbB == 0)
+    return false;
+
+  SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
+  myPntArray = new Graphic3d_ArrayOfPoints(aNbB);
+
+  int i;
+  ObjectPtr aObj;
+  gp_Pnt aP1;
+  for (i = 0; i < aNbB; i++) {
+    aObj = anAttrB->object(i);
+    aP1 = aMgr->getPosition(aObj, this, theStep);
+    myPntArray->SetVertice(i + 1, aP1);
+  }  
+
+  return true;
+}
+
+void SketcherPrs_Transformation::drawLines(const Handle(Prs3d_Presentation)& thePrs, Quantity_Color theColor) const
+{
+  std::shared_ptr<ModelAPI_Data> aData = myConstraint->data();
+  std::shared_ptr<ModelAPI_AttributeRefList> anAttrB = aData->reflist(SketchPlugin_Constraint::ENTITY_B());
+  if (anAttrB.get() == NULL)
+    return;
+
+  Handle(Graphic3d_Group) aGroup = Prs3d_Root::NewGroup(thePrs);
+
+  Handle(Graphic3d_AspectLine3d) aLineAspect = new Graphic3d_AspectLine3d(theColor, Aspect_TOL_SOLID, 2);
+  aGroup->SetPrimitivesAspect(aLineAspect);
+
+  drawListOfShapes(anAttrB, thePrs);
+}
+
diff --git a/src/SketcherPrs/SketcherPrs_Transformation.h b/src/SketcherPrs/SketcherPrs_Transformation.h
new file mode 100644 (file)
index 0000000..6ba9bc8
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        SketcherPrs_Transformation.h
+// Created:     16 February 2015
+// Author:      Vitaly SMETANNIKOV
+
+#ifndef SketcherPrs_Transformation_H
+#define SketcherPrs_Transformation_H
+
+#include "SketcherPrs_SymbolPrs.h"
+#include <ModelAPI_Feature.h>
+
+
+DEFINE_STANDARD_HANDLE(SketcherPrs_Transformation, SketcherPrs_SymbolPrs)
+
+/**
+* \ingroup GUI
+* A redefinition of standard AIS Interactive Object in order to provide  
+* presentation of parallel constraint
+*/
+class SketcherPrs_Transformation: public SketcherPrs_SymbolPrs
+{
+public:
+  /// Constructor
+  /// \param theConstraint a constraint feature
+  /// \param thePlane a coordinate plane of current sketch
+  Standard_EXPORT SketcherPrs_Transformation(ModelAPI_Feature* theConstraint, 
+                                         const std::shared_ptr<GeomAPI_Ax3>& thePlane,
+                                         bool isTranslation);
+
+  DEFINE_STANDARD_RTTI(SketcherPrs_Transformation)
+protected:
+  virtual const char* iconName() const { return myIsTranslation? "translate.png" : "rotate.png"; }
+
+  /// Redefine this function in order to add additiona lines of constraint base
+  /// \param thePrs a presentation
+  /// \param theColor a color of additiona lines
+  virtual void drawLines(const Handle(Prs3d_Presentation)& thePrs, Quantity_Color theColor) const;
+
+  /// Update myPntArray according to presentation positions
+  /// \return true in case of success
+  virtual bool updatePoints(double theStep) const;
+
+private:
+  bool myIsTranslation;
+};
+
+#endif
\ No newline at end of file
diff --git a/src/SketcherPrs/icons/rotate.png b/src/SketcherPrs/icons/rotate.png
new file mode 100644 (file)
index 0000000..300121c
Binary files /dev/null and b/src/SketcherPrs/icons/rotate.png differ
diff --git a/src/SketcherPrs/icons/translate.png b/src/SketcherPrs/icons/translate.png
new file mode 100644 (file)
index 0000000..54be370
Binary files /dev/null and b/src/SketcherPrs/icons/translate.png differ
index bd843caa93b19576aab7c2eca61099108cc77a7c..d570650ef03b4c518907c4267795842249020178 100644 (file)
@@ -6,16 +6,14 @@ SET(CMAKE_AUTOMOC ON)
 SET(PROJECT_HEADERS
        XGUI.h
        XGUI_ActionsMgr.h
+       XGUI_ColorDialog.h
        XGUI_ContextMenuMgr.h
        XGUI_CustomPrs.h
-       XGUI_DataTreeModel.h
        XGUI_Displayer.h
-       XGUI_DocumentDataModel.h
        XGUI_ErrorDialog.h
        XGUI_ModuleConnector.h
        XGUI_ObjectsBrowser.h
        XGUI_OperationMgr.h
-       XGUI_PartDataModel.h
        XGUI_PropertyPanel.h
        XGUI_QtEvents.h
        XGUI_SalomeConnector.h
@@ -33,15 +31,14 @@ SET(PROJECT_AUTOMOC
 
 SET(PROJECT_SOURCES
        XGUI_ActionsMgr.cpp
+       XGUI_ColorDialog.cpp
        XGUI_ContextMenuMgr.cpp
        XGUI_CustomPrs.cpp
        XGUI_Displayer.cpp
-       XGUI_DocumentDataModel.cpp
        XGUI_ErrorDialog.cpp
        XGUI_ModuleConnector.cpp
        XGUI_ObjectsBrowser.cpp
        XGUI_OperationMgr.cpp
-       XGUI_PartDataModel.cpp
        XGUI_PropertyPanel.cpp
        XGUI_QtEvents.cpp
        XGUI_Selection.cpp
diff --git a/src/XGUI/XGUI_ColorDialog.cpp b/src/XGUI/XGUI_ColorDialog.cpp
new file mode 100644 (file)
index 0000000..e91d3cc
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        XGUI_ColorDialog.cpp
+// Created:     27 Apr 2015
+// Author:      Natalia ERMOLAEVA
+
+#include <XGUI_ColorDialog.h>
+
+#include <ModelAPI_Tools.h>
+
+#include <QtxColorButton.h>
+
+#include <QLabel>
+#include <QButtonGroup>
+#include <QGridLayout>
+#include <QRadioButton>
+#include <QDialogButtonBox>
+
+XGUI_ColorDialog::XGUI_ColorDialog(QWidget* theParent)
+  : QDialog(theParent)
+{
+  setWindowTitle("Color");
+  QGridLayout* aLay = new QGridLayout(this);
+
+  QRadioButton* aRandomChoiceBtn = new QRadioButton(this);
+  QRadioButton* aColorChoiceBtn = new QRadioButton(this);
+  aColorChoiceBtn->setChecked(true);
+  myButtonGroup = new QButtonGroup(this);
+  myButtonGroup->setExclusive(true);
+  myButtonGroup->addButton(aColorChoiceBtn, 0);
+  myButtonGroup->addButton(aRandomChoiceBtn, 1);
+
+  aLay->addWidget(aColorChoiceBtn, 0, 0);
+  aLay->addWidget(aRandomChoiceBtn, 1, 0);
+
+  myColorButton = new QtxColorButton(this);
+  myColorButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+  aLay->addWidget(myColorButton, 0, 1);
+
+  QLabel* aRandomLabel = new QLabel("Random", this);
+  aLay->addWidget(aRandomLabel, 1, 1);
+
+  QDialogButtonBox* aButtons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
+                                                    Qt::Horizontal, this);
+  connect(aButtons, SIGNAL(accepted()), this, SLOT(accept()));
+  connect(aButtons, SIGNAL(rejected()), this, SLOT(reject()));
+  aLay->addWidget(aButtons, 2, 0, 1, 2);
+}
+
+bool XGUI_ColorDialog::isRandomColor() const
+{
+  int anId = myButtonGroup->checkedId();
+
+  return myButtonGroup->checkedId() == 1;
+}
+
+void XGUI_ColorDialog::setColor(const std::vector<int>& theValue)
+{
+  if (theValue.size() != 3)
+    return;
+
+  myColorButton->setColor(QColor(theValue[0], theValue[1], theValue[2]));
+}
+
+std::vector<int> XGUI_ColorDialog::getColor() const
+{
+  std::vector<int> aValues;
+  if (isRandomColor()) {
+    ModelAPI_Tools::findRandomColor(aValues);
+  }
+  else {
+    QColor aColorResult = myColorButton->color();
+    aValues.push_back(aColorResult.red());
+    aValues.push_back(aColorResult.green());
+    aValues.push_back(aColorResult.blue());
+  }
+  return aValues;
+}
diff --git a/src/XGUI/XGUI_ColorDialog.h b/src/XGUI/XGUI_ColorDialog.h
new file mode 100644 (file)
index 0000000..e5bc381
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File:        XGUI_ColorDialog.hxx
+// Created:     27 Apr 2015
+// Author:      Natalia ERMOLAEVA
+
+#ifndef XGUI_ColorDialog_H
+#define XGUI_ColorDialog_H
+
+#include "XGUI.h"
+
+#include <QDialog>
+
+class QButtonGroup;
+class QtxColorButton;
+
+/**
+* \ingroup GUI
+* A class of dialog to chose a color. The color can be set in two ways: use a random value or
+* a certain color. There is a radio button to provide this choice. The color button is visualized to
+* select a certain color.
+*/ 
+class XGUI_ColorDialog : public QDialog
+{
+  Q_OBJECT
+public:
+  /// Constructor
+  /// \param theParent a parent widget for the dialog
+  XGUI_EXPORT XGUI_ColorDialog(QWidget* theParent);
+
+  XGUI_EXPORT virtual ~XGUI_ColorDialog() {};
+
+  /// Returns whether the random state of color is chosen
+  /// \return a boolean value
+  bool isRandomColor() const;
+
+  /// Initializes the dialog with the given value. Set choice on certain value and fill it by.
+  /// \param theValue an RGB components value
+  void setColor(const std::vector<int>& theValue);
+
+  /// Returns a container with the current color value. These are tree int values for RGB definition.
+  /// These value is depend on the random choice and eighter a next random color or a certain color.
+  /// \return a vector of values
+  std::vector<int> getColor() const;
+
+private:
+  QButtonGroup* myButtonGroup; /// a group, contained random and certain color radio button choice
+  QtxColorButton* myColorButton; /// a control to select a color
+};
+
+#endif
index 494ecf28d011cf8dcf54d04dae64ac496ebd843e..88f167b96b0471363ac67017334f9b17a4bcb912 100644 (file)
@@ -8,7 +8,6 @@
 #include "XGUI_ViewerProxy.h"
 #include "XGUI_Selection.h"
 #include "XGUI_SalomeConnector.h"
-#include "XGUI_Tools.h"
 
 #include <AppElements_MainWindow.h>
 
 #include <ModelAPI_Data.h>
 #include <ModelAPI_AttributeDocRef.h>
 #include <ModelAPI_Object.h>
-#include <ModelAPI_ResultPart.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_ResultGroup.h>
 #include <ModelAPI_ResultParameter.h>
 
 #include <ModuleBase_IModule.h>
+#include <ModuleBase_Tools.h>
 
 #include <QAction>
 #include <QContextMenuEvent>
@@ -41,16 +40,7 @@ XGUI_ContextMenuMgr::~XGUI_ContextMenuMgr()
 
 void XGUI_ContextMenuMgr::createActions()
 {
-  QAction* aAction = new QAction(QIcon(":pictures/edit.png"), tr("Edit..."), this);
-  addAction("EDIT_CMD", aAction);
-
-  aAction = new QAction(QIcon(":pictures/activate.png"), tr("Activate"), this);
-  addAction("ACTIVATE_PART_CMD", aAction);
-
-  aAction = new QAction(QIcon(":pictures/assembly.png"), tr("Deactivate"), this);
-  addAction("DEACTIVATE_PART_CMD", aAction);
-
-  aAction = new QAction(QIcon(":pictures/delete.png"), tr("Delete"), this);
+  QAction* aAction = new QAction(QIcon(":pictures/delete.png"), tr("Delete"), this);
   QMainWindow* aDesktop = myWorkshop->mainWindow();
   if (!aDesktop)
     aDesktop = myWorkshop->salomeConnector()->desktop();
@@ -155,22 +145,14 @@ QMenu* XGUI_ContextMenuMgr::objectBrowserMenu() const
     bool hasResult = false;
     bool hasFeature = false;
     bool hasParameter = false;
-    XGUI_Tools::checkObjects(aObjects, hasResult, hasFeature, hasParameter);
+    ModuleBase_Tools::checkObjects(aObjects, hasResult, hasFeature, hasParameter);
 
     //Process Feature
     if (aSelected == 1) {
       ObjectPtr aObject = aObjects.first();
       if (aObject) {
-        ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
-        if (aPart) {
-          if (aMgr->activeDocument() == aPart->partDoc())
-            aMenu->addAction(action("DEACTIVATE_PART_CMD"));
-          else
-            aMenu->addAction(action("ACTIVATE_PART_CMD"));
-        } else if (hasFeature && aObject->document() == aMgr->activeDocument()) {
-          aMenu->addAction(action("EDIT_CMD"));
-        } else {
-          if (aDisplayer->isVisible(aObject)) {
+        if (!hasFeature) {
+          if (aObject->isDisplayed()) {
             if (aDisplayer->canBeShaded(aObject)) {
               if (aDisplayer->displayMode(aObject) == XGUI_Displayer::Shading)
                 aMenu->addAction(action("WIREFRAME_CMD"));
@@ -179,18 +161,13 @@ QMenu* XGUI_ContextMenuMgr::objectBrowserMenu() const
             }
             aMenu->addSeparator();
             aMenu->addAction(action("HIDE_CMD"));
-          } else if (!hasParameter) {
+          } else if (hasResult && (!hasParameter)) {
             aMenu->addAction(action("SHOW_CMD"));
           }
-          if (hasParameter)
-            aMenu->addAction(action("EDIT_CMD"));
-          else
+          if (!(hasParameter || hasFeature))
             aMenu->addAction(action("SHOW_ONLY_CMD"));
         }
-      } else {  // If feature is 0 the it means that selected root object (document)
-        if (aMgr->activeDocument() != aMgr->moduleDocument())
-          aMenu->addAction(action("ACTIVATE_PART_CMD"));
-      }
+      } 
     } else {
       if (hasResult && (!hasParameter)) {
         aMenu->addAction(action("SHOW_CMD"));
@@ -208,11 +185,13 @@ QMenu* XGUI_ContextMenuMgr::objectBrowserMenu() const
     aMenu->addAction(action("COLOR_CMD"));
 
   aMenu->addSeparator();
+  ModuleBase_IModule* aModule = myWorkshop->module();
+  if (aModule) {
+    aModule->addObjectBrowserMenu(aMenu);
+    aMenu->addSeparator();
+  }
   aMenu->addActions(myWorkshop->objectBrowser()->actions());
 
-  ModuleBase_IModule* aModule = myWorkshop->module();
-  if (aModule)
-    aModule->addObjectBrowserItems(aMenu);
 
   if (aMenu->actions().size() > 0) {
     return aMenu;
@@ -224,7 +203,7 @@ QMenu* XGUI_ContextMenuMgr::objectBrowserMenu() const
 QMenu* XGUI_ContextMenuMgr::viewerMenu() const
 {
   QMenu* aMenu = new QMenu();
-  addViewerItems(aMenu);
+  addViewerMenu(aMenu);
   if (aMenu->actions().size() > 0) {
     return aMenu;
   }
@@ -232,26 +211,24 @@ QMenu* XGUI_ContextMenuMgr::viewerMenu() const
   return 0;
 }
 
-void XGUI_ContextMenuMgr::addViewerItems(QMenu* theMenu) const
+void XGUI_ContextMenuMgr::addViewerMenu(QMenu* theMenu) const
 {
   bool aIsDone = false;
   ModuleBase_IModule* aModule = myWorkshop->module();
   if (aModule) 
-    aIsDone = aModule->addViewerItems(theMenu, myActions);
+    aIsDone = aModule->addViewerMenu(theMenu, myActions);
 
   if (!aIsDone) {
     XGUI_SelectionMgr* aSelMgr = myWorkshop->selector();
     QObjectPtrList aObjects = aSelMgr->selection()->selectedObjects();
     if (aObjects.size() > 0) {
-      //if (aObjects.size() == 1)
-      //  theMenu->addAction(action("EDIT_CMD"));
       bool isVisible = false;
       bool isShading = false;
       bool canBeShaded = false;
       foreach(ObjectPtr aObject, aObjects)
       {
         ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObject);
-        if (aRes && myWorkshop->displayer()->isVisible(aRes)) {
+        if (aRes && aRes->isDisplayed()) {
           isVisible = true;
           canBeShaded = myWorkshop->displayer()->canBeShaded(aObject);
           isShading = (myWorkshop->displayer()->displayMode(aObject) == XGUI_Displayer::Shading);      
@@ -270,7 +247,6 @@ void XGUI_ContextMenuMgr::addViewerItems(QMenu* theMenu) const
         theMenu->addAction(action("HIDE_CMD"));
       } else
         theMenu->addAction(action("SHOW_CMD"));
-      //theMenu->addAction(action("DELETE_CMD"));
     }
     if (myWorkshop->displayer()->objectsCount() > 0)
       theMenu->addAction(action("HIDEALL_CMD"));
index 5098ca1bbd63116d2066e9260cc0e37f4fb95af8..3f490a59b22d0450ab458c975df741c58b63766f 100644 (file)
@@ -51,7 +51,7 @@ Q_OBJECT
 
   /// Add menu atems for viewer into the given menu (used in SALOME mode)
   /// \param theMenu a popup menu to be shown in the viewer
-  void addViewerItems(QMenu* theMenu) const;
+  void addViewerMenu(QMenu* theMenu) const;
 
 signals:
   /// Signal aabout triggered action
index c074a841e4ab3af76f0b33dee705234510d38f74..171baa8465bb73e8b61291b7743a9eb0a7558db5 100644 (file)
@@ -7,11 +7,13 @@
 #include <XGUI_CustomPrs.h>
 
 #include <ModelAPI_AttributeIntArray.h>
+#include <ModelAPI_Session.h>
 #include <Config_PropManager.h>
 
 #include <Events_Error.h>
 
 #include <vector>
+#include <QColor>
 
 
 void getColor(ResultPtr theResult, std::vector<int>& theColor)
@@ -56,5 +58,13 @@ bool XGUI_CustomPrs::customisePresentation(ResultPtr theResult, AISObjectPtr the
   if (aColor.empty())
     getDefaultColor(theResult, thePrs, aColor);
 
+  SessionPtr aMgr = ModelAPI_Session::get();
+  if (aMgr->activeDocument() != theResult->document()) {
+    QColor aQColor(aColor[0], aColor[1], aColor[2]);
+    QColor aNewColor = QColor::fromHsvF(aQColor.hueF(), aQColor.saturationF()/3., aQColor.valueF());
+    aColor[0] = aNewColor.red();
+    aColor[1] = aNewColor.green();
+    aColor[2] = aNewColor.blue();
+  }
   return !aColor.empty() && thePrs->setColor(aColor[0], aColor[1], aColor[2]);
 }
diff --git a/src/XGUI/XGUI_DataTreeModel.h b/src/XGUI/XGUI_DataTreeModel.h
deleted file mode 100644 (file)
index fb28e59..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
-
-#ifndef XGUI_DataTreeModel_H
-#define XGUI_DataTreeModel_H
-
-#include "XGUI.h"
-
-#include <ModelAPI_Document.h>
-#include <ModelAPI_Feature.h>
-#include <ModelAPI_ResultPart.h>
-
-#include <QAbstractItemModel>
-#include <QColor>
-
-/**\class XGUI_FeaturesModel
- * \ingroup GUI
- * \brief Abstaract class of model object which operates with features data.
- */
-class XGUI_EXPORT XGUI_FeaturesModel : public QAbstractItemModel
-{
- public:
-   /// Constructor
-   /// \param theParent a parent object
-  XGUI_FeaturesModel(QObject* theParent)
-      : QAbstractItemModel(theParent),
-        myItemsColor(Qt::black)
-  {
-  }
-
-  //! Returns Feature object by the given Model index.
-  //! Returns 0 if the given index is not index of a feature
-  /// \param theIndex a model index
-  virtual ObjectPtr object(const QModelIndex& theIndex) const = 0;
-
-  //! Returns QModelIndex which corresponds to the given feature
-  //! If the feature is not found then index is not valid
-  virtual QModelIndex objectIndex(const ObjectPtr& theFeature) const = 0;
-
-  //! Returns parent index of the given feature
-  virtual QModelIndex findParent(const ObjectPtr& theObject) const = 0;
-
-  //! Returns index corresponded to the group
-  //! \param theGroup a group name
-  virtual QModelIndex findGroup(const std::string& theGroup) const = 0;
-
-  //! Set color of items
-  void setItemsColor(const QColor& theColor)
-  {
-    myItemsColor = theColor;
-  }
-
-  //! Returns color of items
-  QColor itemsColor() const
-  {
-    return myItemsColor;
-  }
-
- protected:
-   /// Color of items
-  QColor myItemsColor;
-};
-
-/**\class XGUI_PartModel
- * \ingroup GUI
- * \brief Abstaract class of model object which operates with parts data.
- */
-class XGUI_PartModel : public XGUI_FeaturesModel
-{
- public:
-   /// Constructor
-   /// \param theParent a parent object
-  XGUI_PartModel(QObject* theParent)
-      : XGUI_FeaturesModel(theParent)
-  {
-  }
-
-  /// Set part id
-  /// \param theId a new id
-  void setPartId(int theId)
-  {
-    myId = theId;
-  }
-
-  //! Returns true if the given document is a sub-document of this tree
-  //! \param theDoc a document to check
-  virtual bool hasDocument(const DocumentPtr& theDoc) const = 0;
-
-  //! Return a Part object
-  virtual ResultPartPtr part() const = 0;
-
- protected:
-  //! Id of the current part object in the document
-  int myId;
-};
-
-#endif
index dd564aba08280ce8f647e08a38eadbda7f37a1d4..83fa8010dd1dce83aedec88d74947ef59887dbd6 100644 (file)
@@ -47,6 +47,7 @@ const int MOUSE_SENSITIVITY_IN_PIXEL = 10;  ///< defines the local context mouse
 //#define DEBUG_ACTIVATE
 //#define DEBUG_FEATURE_REDISPLAY
 //#define DEBUG_SELECTION_FILTERS
+//#define DEBUG_USE_CLEAR_OUTDATED_SELECTION
 
 // Workaround for bug #25637
 void displayedObjects(const Handle(AIS_InteractiveContext)& theAIS, AIS_ListOfInteractive& theList)
@@ -272,6 +273,10 @@ void XGUI_Displayer::deactivate(ObjectPtr theObject)
     AISObjectPtr anObj = myResult2AISObjectMap[theObject];
     Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
     aContext->Deactivate(anAIS);
+#ifdef DEBUG_USE_CLEAR_OUTDATED_SELECTION
+    aContext->LocalContext()->ClearOutdatedSelection(anAIS, true);
+    updateViewer();
+#endif
   }
 }
 
@@ -388,6 +393,10 @@ void XGUI_Displayer::deactivateObjects()
   for(aLIt.Initialize(aPrsList); aLIt.More(); aLIt.Next()){
     anAISIO = aLIt.Value();
     aContext->Deactivate(anAISIO);
+#ifdef DEBUG_USE_CLEAR_OUTDATED_SELECTION
+    aContext->LocalContext()->ClearOutdatedSelection(anAISIO, true);
+    updateViewer();
+#endif
   }
 }
 
@@ -407,7 +416,7 @@ bool XGUI_Displayer::isActive(ObjectPtr theObject) const
   return aModes.Extent() > 0;
 }
 
-void XGUI_Displayer::setSelected(const QObjectPtrList& theResults, const bool isUpdateViewer)
+void XGUI_Displayer::setSelected(const  QList<ModuleBase_ViewerPrs>& theValues, bool isUpdateViewer)
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
   if (aContext.IsNull())
@@ -415,19 +424,35 @@ void XGUI_Displayer::setSelected(const QObjectPtrList& theResults, const bool is
   if (aContext->HasOpenedContext()) {
     aContext->UnhilightSelected();
     aContext->ClearSelected();
-    foreach(ObjectPtr aResult, theResults) {
-      if (isVisible(aResult)) {
-        AISObjectPtr anObj = myResult2AISObjectMap[aResult];
-        Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
-        if (!anAIS.IsNull())
-          aContext->SetSelected(anAIS, false);
+    //if (aSelected.size() > 0) {
+    foreach (ModuleBase_ViewerPrs aPrs, theValues) {
+      const TopoDS_Shape& aShape = aPrs.shape();
+      if (!aShape.IsNull()) {
+        aContext->AddOrRemoveSelected(aShape, false);
+      } else {
+        ObjectPtr anObject = aPrs.object();
+        ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
+        if (aResult.get() && isVisible(aResult)) {
+          AISObjectPtr anObj = myResult2AISObjectMap[aResult];
+          Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
+          if (!anAIS.IsNull()) {
+            // The methods are replaced in order to provide multi-selection, e.g. restore selection
+            // by activating multi selector widget. It also gives an advantage that the multi
+            // selection in OB gives multi-selection in the viewer
+            //aContext->SetSelected(anAIS, false);
+            // The selection in the context was cleared, so the method sets the objects are selected
+            aContext->AddOrRemoveSelected(anAIS, false);
+          }
+        }
       }
     }
   } else {
     aContext->UnhilightCurrents();
     aContext->ClearCurrents();
-    foreach(ObjectPtr aResult, theResults) {
-      if (isVisible(aResult)) {
+    foreach (ModuleBase_ViewerPrs aPrs, theValues) {
+      ObjectPtr anObject = aPrs.object();
+      ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
+      if (aResult.get() && isVisible(aResult)) {
         AISObjectPtr anObj = myResult2AISObjectMap[aResult];
         Handle(AIS_InteractiveObject) anAIS = anObj->impl<Handle(AIS_InteractiveObject)>();
         if (!anAIS.IsNull())
@@ -439,7 +464,6 @@ void XGUI_Displayer::setSelected(const QObjectPtrList& theResults, const bool is
     updateViewer();
 }
 
-
 void XGUI_Displayer::clearSelected()
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
@@ -588,7 +612,7 @@ bool XGUI_Displayer::enableUpdateViewer(const bool isEnabled)
   return aWasEnabled;
 }
 
-void XGUI_Displayer::updateViewer()
+void XGUI_Displayer::updateViewer() const
 {
   Handle(AIS_InteractiveContext) aContext = AISContext();
   if (!aContext.IsNull() && myEnableUpdateViewer)
@@ -788,6 +812,7 @@ void XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO,
   aContext->ActivatedModes(theIO, aTColModes);
   TColStd_ListIteratorOfListOfInteger itr( aTColModes );
   QIntList aModesActivatedForIO;
+  //bool isDeactivated = false;
   for (; itr.More(); itr.Next() ) {
     Standard_Integer aMode = itr.Value();
     if (!theModes.contains(aMode)) {
@@ -795,6 +820,7 @@ void XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO,
       qDebug(QString("deactivate: %1").arg(aMode).toStdString().c_str());
 #endif
       aContext->Deactivate(theIO, aMode);
+      //isDeactivated = true;
     }
     else {
       aModesActivatedForIO.append(aMode);
@@ -803,6 +829,12 @@ void XGUI_Displayer::activate(const Handle(AIS_InteractiveObject)& theIO,
 #endif
     }
   }
+#ifdef DEBUG_USE_CLEAR_OUTDATED_SELECTION
+  if (isDeactivated) {
+    aContext->LocalContext()->ClearOutdatedSelection(theIO, true);
+    updateViewer();
+  }
+#endif
   // loading the interactive object allowing the decomposition
   if (aTColModes.IsEmpty())
     aContext->Load(theIO, -1, true);
index 89f693d522c1c58bd8fa21dc955326260fea6498..493a077a204aa1d1c72e1e39530e71322c653faa 100644 (file)
@@ -79,11 +79,13 @@ class XGUI_EXPORT XGUI_Displayer: public QObject
   void redisplay(ObjectPtr theObject, bool isUpdateViewer = true);
 
   /**
-   * Add presentations which corresponds to the given features to current selection
-   * \param theFeatures a list of features to be selected
+   * Add presentations to current selection. It unhighlight and deselect the current selection.
+   * The shape and result components are processed in the values. If the presentation shape is not
+   * empty, select it, otherwise select the result.
+   * \param theValues a list of presentation to be selected
    * \param isUpdateViewer the parameter whether the viewer should be update immediatelly
    */
-  void setSelected(const QObjectPtrList& theFeatures, bool isUpdateViewer = true);
+  void setSelected(const  QList<ModuleBase_ViewerPrs>& theValues, bool isUpdateViewer = true);
 
 
   /// Unselect all objects
@@ -126,7 +128,7 @@ class XGUI_EXPORT XGUI_Displayer: public QObject
   bool enableUpdateViewer(const bool isEnabled);
 
   /// Updates the viewer
-  void updateViewer();
+  void updateViewer() const;
 
   /// Searches the interactive object by feature
   /// \param theObject the object or presentable feature
diff --git a/src/XGUI/XGUI_DocumentDataModel.cpp b/src/XGUI/XGUI_DocumentDataModel.cpp
deleted file mode 100644 (file)
index 2443426..0000000
+++ /dev/null
@@ -1,592 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
-
-#include "XGUI_DocumentDataModel.h"
-#include "XGUI_PartDataModel.h"
-#include "XGUI_Workshop.h"
-#include "XGUI_Tools.h"
-
-#include <ModelAPI_Session.h>
-#include <ModelAPI_Document.h>
-#include <ModelAPI_Feature.h>
-#include <ModelAPI_Data.h>
-#include <ModelAPI_ResultPart.h>
-#include <ModelAPI_Events.h>
-#include <ModelAPI_Object.h>
-
-#include <Events_Loop.h>
-
-#include <Config_FeatureMessage.h>
-
-#include <QIcon>
-#include <QString>
-#include <QBrush>
-
-#include <set>
-
-#define ACTIVE_COLOR QColor(0,72,140)
-#define PASSIVE_COLOR Qt::black
-
-XGUI_DocumentDataModel::XGUI_DocumentDataModel(QObject* theParent)
-    : QAbstractItemModel(theParent),
-      myActivePart(0)
-{
-  // Register in event loop
-  //Events_Loop* aLoop = Events_Loop::loop();
-  //aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
-  //aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
-  //aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
-
-  // Create a top part of data tree model
-  myModel = new XGUI_TopDataModel(this);
-  myModel->setItemsColor(ACTIVE_COLOR);
-}
-
-XGUI_DocumentDataModel::~XGUI_DocumentDataModel()
-{
-  clearModelIndexes();
-  clearSubModels();
-}
-
-void XGUI_DocumentDataModel::processEvent(const std::shared_ptr<Events_Message>& theMessage)
-{
-  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-
-  // Created object event *******************
-  if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
-    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
-    std::set<ObjectPtr> aObjects = aUpdMsg->objects();
-
-    std::set<ObjectPtr>::const_iterator aIt;
-    for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
-      ObjectPtr aObject = (*aIt);
-      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
-      if (aFeature && (!aFeature->isInHistory()))
-        continue;
-
-      DocumentPtr aDoc = aObject->document();
-      if (aDoc == aRootDoc) {  // If root objects
-        if (aObject->groupName() == ModelAPI_ResultPart::group()) {  // Update only Parts group
-            // Add a new part
-          int aStart = myPartModels.size();
-          XGUI_PartDataModel* aModel = new XGUI_PartDataModel(this);
-          aModel->setPartId(myPartModels.count());
-          myPartModels.append(aModel);
-          insertRow(aStart, partFolderNode());
-        } else {  // Update top groups (other except parts
-          QModelIndex aIndex = myModel->findParent(aObject);
-          int aStart = myModel->rowCount(aIndex) - 1;
-          if (aStart < 0)
-            aStart = 0;
-          aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
-          insertRow(aStart, aIndex);
-        }
-      } else {  // if sub-objects of first level nodes
-        XGUI_PartModel* aPartModel = 0;
-        foreach (XGUI_PartModel* aPart, myPartModels) {
-          if (aPart->hasDocument(aDoc)) {
-            aPartModel = aPart;
-            break;
-          }
-        }
-        if (aPartModel) {
-          QModelIndex aIndex = aPartModel->findParent(aObject);
-          int aStart = aPartModel->rowCount(aIndex);  // check this index
-          aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
-          insertRow(aStart, aIndex);
-        } else
-          reset();
-      }
-    }
-    // Deleted object event ***********************
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
-    std::shared_ptr<ModelAPI_ObjectDeletedMessage> aUpdMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
-    DocumentPtr aDoc = aUpdMsg->document();
-    std::set<std::string> aGroups = aUpdMsg->groups();
-
-    std::set<std::string>::const_iterator aIt;
-    for (aIt = aGroups.begin(); aIt != aGroups.end(); ++aIt) {
-      std::string aGroup = (*aIt);
-      if (aDoc == aRootDoc) {  // If root objects
-        if (aGroup == ModelAPI_ResultPart::group()) {  // Update only Parts group
-          int aStart = myPartModels.size() - 1;
-          if (aStart >= 0) {// MPV: this could be reproduced on close
-            removeSubModel(aStart);
-            removeRow(aStart, partFolderNode());
-            if (myActivePart && (!isPartSubModel(myActivePart))) {
-              myActivePart = 0;
-              myActivePartIndex = QModelIndex();
-              myModel->setItemsColor(ACTIVE_COLOR);
-            }
-          }
-        } else {  // Update top groups (other except parts
-          QModelIndex aIndex = myModel->findGroup(aGroup);
-          int aStart = myModel->rowCount(aIndex);
-          aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
-          removeRow(aStart, aIndex);
-        }
-      } else {
-        XGUI_PartModel* aPartModel = 0;
-        foreach (XGUI_PartModel* aPart, myPartModels) {
-          if (aPart->hasDocument(aDoc)) {
-            aPartModel = aPart;
-            break;
-          }
-        }
-        if (aPartModel) {
-          QModelIndex aIndex = aPartModel->findGroup(aGroup);
-          int aStart = aPartModel->rowCount(aIndex);
-          aIndex = createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex));
-          removeRow(aStart, aIndex);
-        }
-      }
-    }
-    // Deleted object event ***********************
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)) {
-    //std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg = std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
-    //ObjectPtr aFeature = aUpdMsg->feature();
-    //DocumentPtr aDoc = aFeature->document();
-
-    // TODO: Identify the necessary index by the modified feature
-    QModelIndex aIndex;
-    emit dataChanged(aIndex, aIndex);
-
-    // Reset whole tree **************************
-  } else {
-    rebuildDataTree();
-  }
-}
-
-void XGUI_DocumentDataModel::rebuildDataTree()
-{
-  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-
-  beginResetModel();
-  clearModelIndexes();
-
-  int aNbParts = aRootDoc->size(ModelAPI_ResultPart::group());
-  if (myPartModels.size() != aNbParts) {  // resize internal models
-    while (myPartModels.size() > aNbParts) {
-      delete myPartModels.last();
-      myPartModels.removeLast();
-    }
-    while (myPartModels.size() < aNbParts) {
-      myPartModels.append(new XGUI_PartDataModel(this));
-    }
-    for (int i = 0; i < myPartModels.size(); i++)
-      myPartModels.at(i)->setPartId(i);
-  }
-  endResetModel();
-}
-
-QVariant XGUI_DocumentDataModel::data(const QModelIndex& theIndex, int theRole) const
-{
-  if (!theIndex.isValid())
-    return QVariant();
-  switch (theIndex.internalId()) {
-    case PartsFolder:
-      switch (theRole) {
-        case Qt::DisplayRole:
-          return tr("Parts") + QString(" (%1)").arg(rowCount(theIndex));
-        case Qt::DecorationRole:
-          return QIcon(":pictures/constr_folder.png");
-        case Qt::ToolTipRole:
-          return tr("Parts folder");
-        case Qt::ForegroundRole:
-          if (myActivePart)
-            return QBrush(PASSIVE_COLOR);
-            else
-            return QBrush(ACTIVE_COLOR);
-            default:
-            return QVariant();
-          }
-          break;
-          case HistoryNode:
-          {
-            int aOffset = historyOffset();
-            DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-            ObjectPtr aObj = aRootDoc->object(ModelAPI_Feature::group(), theIndex.row() - aOffset);
-            FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
-            if (!aFeature)
-            return QVariant();
-            switch (theRole) {
-              case Qt::DisplayRole:
-              if (aFeature)
-              return aFeature->data()->name().c_str();
-              else
-              return QVariant();
-              case Qt::DecorationRole:
-              return XGUI_Workshop::featureIcon(aFeature);
-              case Qt::ToolTipRole:
-              return tr("Feature object");
-              case Qt::ForegroundRole:
-              if (myActivePart)
-              return QBrush(PASSIVE_COLOR);
-              else
-              return QBrush(ACTIVE_COLOR);
-              default:
-              return QVariant();
-            }
-          }
-          break;
-        }
-  QModelIndex aParent = theIndex.parent();
-  if (aParent.isValid() && (aParent.internalId() == PartsFolder)) {
-    return myPartModels.at(theIndex.row())->data(QModelIndex(), theRole);
-  }
-  return toSourceModelIndex(theIndex)->data(theRole);
-}
-
-QVariant XGUI_DocumentDataModel::headerData(int theSection, Qt::Orientation theOrient,
-                                            int theRole) const
-{
-  return QVariant();
-}
-
-int XGUI_DocumentDataModel::rowCount(const QModelIndex& theParent) const
-{
-  if (!theParent.isValid()) {
-    DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-    // Size of external models
-    int aVal = historyOffset();
-    // Plus history size
-    aVal += aRootDoc->size(ModelAPI_Feature::group());
-    return aVal;
-  }
-  if (theParent.internalId() == PartsFolder) {
-    int aSize = myPartModels.size();
-    return myPartModels.size();
-  }
-  if (theParent.internalId() == HistoryNode) {
-    return 0;
-  }
-  QModelIndex* aParent = toSourceModelIndex(theParent);
-  const QAbstractItemModel* aModel = aParent->model();
-  if (!isSubModel(aModel))
-    return 0;
-
-  /*if (isPartSubModel(aModel)) {
-   if (aModel != myActivePart)
-   return 0;
-   }*/
-  return aModel->rowCount(*aParent);
-}
-
-int XGUI_DocumentDataModel::columnCount(const QModelIndex& theParent) const
-{
-  return 1;
-}
-
-QModelIndex XGUI_DocumentDataModel::index(int theRow, int theColumn,
-                                          const QModelIndex& theParent) const
-{
-  QModelIndex aIndex;
-  if (!theParent.isValid()) {
-    int aOffs = myModel->rowCount();
-    if (theRow < aOffs) {
-      aIndex = myModel->index(theRow, theColumn, theParent);
-      aIndex = createIndex(theRow, theColumn, (void*) getModelIndex(aIndex));
-    } else {
-      if (theRow == aOffs)  // Create Parts node
-        aIndex = partFolderNode();
-      else
-        // create history node
-        aIndex = createIndex(theRow, theColumn, HistoryNode);
-    }
-  } else {
-    if (theParent.internalId() == PartsFolder) {
-      aIndex = myPartModels.at(theRow)->index(0, theColumn, QModelIndex());
-    } else {
-      QModelIndex* aParent = (QModelIndex*) theParent.internalPointer();
-      aIndex = aParent->model()->index(theRow, theColumn, (*aParent));
-    }
-    aIndex = createIndex(theRow, theColumn, (void*) getModelIndex(aIndex));
-  }
-  return aIndex;
-}
-
-QModelIndex XGUI_DocumentDataModel::parent(const QModelIndex& theIndex) const
-{
-  if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
-    return QModelIndex();
-
-  QModelIndex* aIndex = toSourceModelIndex(theIndex);
-  const QAbstractItemModel* aModel = aIndex->model();
-  if (!isSubModel(aModel))
-    return QModelIndex();
-
-  if (isPartSubModel(aModel)) {
-    if (!aModel->parent(*aIndex).isValid()) {
-      return partFolderNode();
-    }
-  }
-
-  QModelIndex aIndex1 = aModel->parent(*aIndex);
-  if (aIndex1.isValid())
-    return createIndex(aIndex1.row(), aIndex1.column(), (void*) getModelIndex(aIndex1));
-  return aIndex1;
-}
-
-bool XGUI_DocumentDataModel::hasChildren(const QModelIndex& theParent) const
-{
-  if (!theParent.isValid())
-    return true;
-  return rowCount(theParent) > 0;
-}
-
-QModelIndex* XGUI_DocumentDataModel::toSourceModelIndex(const QModelIndex& theProxy) const
-{
-  QModelIndex* aIndexPtr = static_cast<QModelIndex*>(theProxy.internalPointer());
-  return aIndexPtr;
-}
-
-QModelIndex* XGUI_DocumentDataModel::findModelIndex(const QModelIndex& theIndex) const
-{
-  QList<QModelIndex*>::const_iterator aIt;
-  for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt) {
-    QModelIndex* aIndex = (*aIt);
-    if ((*aIndex) == theIndex)
-      return aIndex;
-  }
-  return 0;
-}
-
-QModelIndex* XGUI_DocumentDataModel::getModelIndex(const QModelIndex& theIndex) const
-{
-  QModelIndex* aIndexPtr = findModelIndex(theIndex);
-  if (!aIndexPtr) {
-    aIndexPtr = new QModelIndex(theIndex);
-    XGUI_DocumentDataModel* that = (XGUI_DocumentDataModel*) this;
-    that->myIndexes.append(aIndexPtr);
-  }
-  return aIndexPtr;
-}
-
-void XGUI_DocumentDataModel::clearModelIndexes()
-{
-  foreach (QModelIndex* aIndex, myIndexes) 
-    delete aIndex;
-  myIndexes.clear();
-}
-
-void XGUI_DocumentDataModel::clearSubModels()
-{
-  foreach (XGUI_PartModel* aPart, myPartModels) 
-    delete aPart;
-  myPartModels.clear();
-}
-
-ObjectPtr XGUI_DocumentDataModel::object(const QModelIndex& theIndex) const
-{
-  if (theIndex.internalId() == PartsFolder)
-    return ObjectPtr();
-  if (theIndex.internalId() == HistoryNode) {
-    DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-    int aOffset = historyOffset();
-    return aRootDoc->object(ModelAPI_Feature::group(), theIndex.row() - aOffset);
-  }
-  QModelIndex* aIndex = toSourceModelIndex(theIndex);
-  if (!isSubModel(aIndex->model()))
-    return ObjectPtr();
-
-  const XGUI_FeaturesModel* aModel = dynamic_cast<const XGUI_FeaturesModel*>(aIndex->model());
-  return aModel->object(*aIndex);
-}
-
-bool XGUI_DocumentDataModel::insertRows(int theRow, int theCount, const QModelIndex& theParent)
-{
-  beginInsertRows(theParent, theRow, theRow + theCount - 1);
-  //endInsertRows();
-
-  // Update history
-  QModelIndex aRoot;
-  int aRow = rowCount(aRoot);
-  beginInsertRows(aRoot, aRow, aRow);
-  endInsertRows();
-
-  return true;
-}
-
-bool XGUI_DocumentDataModel::removeRows(int theRow, int theCount, const QModelIndex& theParent)
-{
-  beginRemoveRows(theParent, theRow, theRow + theCount - 1);
-  endRemoveRows();
-  return true;
-}
-
-void XGUI_DocumentDataModel::removeSubModel(int theModelId)
-{
-  XGUI_PartModel* aModel = myPartModels.at(theModelId);
-  QIntList aToRemove;
-  for (int i = 0; i < myIndexes.size(); i++) {
-    if (myIndexes.at(i)->model() == aModel)
-      aToRemove.append(i);
-  }
-  int aId;
-  while (aToRemove.size() > 0) {
-    aId = aToRemove.last();
-    delete myIndexes.at(aId);
-    myIndexes.removeAt(aId);
-    aToRemove.removeLast();
-  }
-  delete aModel;
-  myPartModels.removeAt(theModelId);
-}
-
-bool XGUI_DocumentDataModel::isSubModel(const QAbstractItemModel* theModel) const
-{
-  if (theModel == myModel)
-    return true;
-  return isPartSubModel(theModel);
-}
-
-bool XGUI_DocumentDataModel::isPartSubModel(const QAbstractItemModel* theModel) const
-{
-  return myPartModels.contains((XGUI_PartModel*) theModel);
-}
-
-QModelIndex XGUI_DocumentDataModel::partFolderNode() const
-{
-  int aPos = myModel->rowCount(QModelIndex());
-  return createIndex(aPos, columnCount() - 1, PartsFolder);
-}
-
-int XGUI_DocumentDataModel::historyOffset() const
-{
-  // Nb of rows of top model + Parts folder
-  return myModel->rowCount(QModelIndex()) + 1;
-}
-
-bool XGUI_DocumentDataModel::activatedIndex(const QModelIndex& theIndex)
-{
-  if ((theIndex.internalId() == PartsFolder) || (theIndex.internalId() == HistoryNode))
-    return false;
-
-  QModelIndex* aIndex = toSourceModelIndex(theIndex);
-  if (!aIndex)
-    return false;
-
-  const QAbstractItemModel* aModel = aIndex->model();
-
-  if (isPartSubModel(aModel)) {
-    // if this is root node (Part item index)
-    if (!aIndex->parent().isValid()) {
-      if (myActivePart)
-        myActivePart->setItemsColor(PASSIVE_COLOR);
-
-        if (myActivePart == aModel) {
-          myActivePart = 0;
-          myActivePartIndex = QModelIndex();
-        } else {
-          myActivePart = (XGUI_PartModel*)aModel;
-          myActivePartIndex = theIndex;
-        }
-
-        if (myActivePart) {
-          myActivePart->setItemsColor(ACTIVE_COLOR);
-          myModel->setItemsColor(PASSIVE_COLOR);
-        } else
-          myModel->setItemsColor(ACTIVE_COLOR);
-        return true;
-      }
-    }
-  return false;
-}
-
-ResultPartPtr XGUI_DocumentDataModel::activePart() const
-{
-  if (myActivePart)
-    return myActivePart->part();
-  return ResultPartPtr();
-}
-
-void XGUI_DocumentDataModel::deactivatePart()
-{
-  if (myActivePart)
-    myActivePart->setItemsColor(PASSIVE_COLOR);
-    myActivePart = 0;
-    myActivePartIndex = QModelIndex();
-    myModel->setItemsColor(ACTIVE_COLOR);
-  }
-
-Qt::ItemFlags XGUI_DocumentDataModel::flags(const QModelIndex& theIndex) const
-{
-  Qt::ItemFlags aFlags = QAbstractItemModel::flags(theIndex);
-  if (object(theIndex)) {
-    aFlags |= Qt::ItemIsEditable;
-  }
-  return aFlags;
-}
-
-QModelIndex XGUI_DocumentDataModel::partIndex(const ResultPartPtr& theObject) const
-{
-  int aRow = -1;
-  XGUI_PartModel* aModel = 0;
-  foreach (XGUI_PartModel* aPartModel, myPartModels)
-  {
-    aRow++;
-    if (aPartModel->part() == theObject) {
-      aModel = aPartModel;
-      break;
-    }
-  }
-  if (aModel) {
-    return createIndex(aRow, 0, (void*) getModelIndex(aModel->index(0, 0, QModelIndex())));
-  }
-  return QModelIndex();
-}
-
-QModelIndex XGUI_DocumentDataModel::objectIndex(const ObjectPtr theObject) const
-{
-  // Check that this feature belongs to root document
-  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-  DocumentPtr aDoc = theObject->document();
-  if (aDoc == aRootDoc) {
-    // This feature belongs to histrory or top model
-    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
-    if (aFeature) {
-      int aId;
-      int aNb = aRootDoc->size(ModelAPI_Feature::group());
-      for (aId = 0; aId < aNb; aId++) {
-        if (theObject == aRootDoc->object(ModelAPI_Feature::group(), aId))
-          break;
-      }
-      if (aId < aNb)
-        return index(aId + historyOffset(), 0, QModelIndex());
-    } else {
-      QModelIndex aIndex = myModel->objectIndex(theObject);
-      return
-          aIndex.isValid() ?
-              createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex)) :
-              QModelIndex();
-    }
-  } else {
-    XGUI_PartModel* aPartModel = 0;
-    foreach(XGUI_PartModel* aModel, myPartModels)
-    {
-      if (aModel->hasDocument(aDoc)) {
-        aPartModel = aModel;
-        break;
-      }
-    }
-    if (aPartModel) {
-      QModelIndex aIndex = aPartModel->objectIndex(theObject);
-      return
-          aIndex.isValid() ?
-              createIndex(aIndex.row(), aIndex.column(), (void*) getModelIndex(aIndex)) :
-              QModelIndex();
-    }
-  }
-  return QModelIndex();
-}
-
-
-void XGUI_DocumentDataModel::clear()
-{
-  clearModelIndexes();
-  clearSubModels();
-  myActivePart = 0;
-  myActivePartIndex = QModelIndex();
-  myModel->setItemsColor(ACTIVE_COLOR);
-}
diff --git a/src/XGUI/XGUI_DocumentDataModel.h b/src/XGUI/XGUI_DocumentDataModel.h
deleted file mode 100644 (file)
index 63fa17a..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
-
-#ifndef XGUI_DocumentDataModel_H
-#define XGUI_DocumentDataModel_H
-
-#include "XGUI.h"
-#include <ModuleBase_Definitions.h>
-#include <ModelAPI_ResultPart.h>
-
-#include <Events_Listener.h>
-
-#include <QAbstractItemModel>
-#include <QList>
-
-class ModelAPI_Document;
-class XGUI_PartModel;
-class XGUI_TopDataModel;
-
-/**\class XGUI_DocumentDataModel
- * \ingroup GUI
- * \brief This is a proxy data model for Object Browser (QTreeView).
- * It contains several sub-models for generation of each sub-part of data tree.
- */
-class XGUI_EXPORT XGUI_DocumentDataModel : public QAbstractItemModel, public Events_Listener
-{
-Q_OBJECT
- public:
-   /// Constructor
-   /// \param theParent a parent object
-  XGUI_DocumentDataModel(QObject* theParent);
-  virtual ~XGUI_DocumentDataModel();
-
-  /// Event Listener method
-  /// \param theMessage an event message
-  virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
-
-  /// Returns the data stored under the given role for the item referred to by the index.
-  /// \param theIndex a model index
-  /// \param theRole a data role (see Qt::ItemDataRole)
-  virtual QVariant data(const QModelIndex& theIndex, int theRole) const;
-
-  /// Returns the data for the given role and section in the header with the specified orientation.
-  /// \param theSection a section
-  /// \param theOrient an orientation
-  /// \param theRole a data role (see Qt::ItemDataRole)
-  virtual QVariant headerData(int theSection, Qt::Orientation theOrient, int theRole =
-                                  Qt::DisplayRole) const;
-
-  /// Returns the number of rows under the given parent. When the parent is valid it means that 
-  /// rowCount is returning the number of children of parent.
-  /// \param theParent a parent model index
-  virtual int rowCount(const QModelIndex& theParent = QModelIndex()) const;
-
-  /// Returns the number of columns for the children of the given parent.
-  /// It has a one column
-  /// \param theParent a parent model index
-  virtual int columnCount(const QModelIndex& theParent = QModelIndex()) const;
-
-  /// Returns the index of the item in the model specified by the given row, column and parent index.
-  /// \param theRow a row
-  /// \param theColumn a column
-  /// \param theParent a parent model index
-  virtual QModelIndex index(int theRow, int theColumn, const QModelIndex &theParent =
-                                QModelIndex()) const;
-
-  /// Returns the parent of the model item with the given index. 
-  /// If the item has no parent, an invalid QModelIndex is returned.
-  /// \param theIndex a model index
-  virtual QModelIndex parent(const QModelIndex& theIndex) const;
-
-  /// Returns true if parent has any children; otherwise returns false.
-  /// \param theParent a parent model index
-  virtual bool hasChildren(const QModelIndex& theParent = QModelIndex()) const;
-
-  /// Inserts count rows into the model before the given row. 
-  /// Items in the new row will be children of the item represented by the parent model index.
-  /// \param theRow a start row
-  /// \param theCount a nember of rows to insert
-  /// \param theParent a parent model index
-  bool insertRows(int theRow, int theCount, const QModelIndex& theParent = QModelIndex());
-
-  /// Removes count rows starting with the given row under parent parent from the model.
-  /// \param theRow a start row
-  /// \param theCount a nember of rows to remove
-  /// \param theParent a parent model index
-  bool removeRows(int theRow, int theCount, const QModelIndex& theParent = QModelIndex());
-
-  /// Returns the item flags for the given index.
-  /// \param theIndex a model index
-  Qt::ItemFlags flags(const QModelIndex& theIndex) const;
-
-  //! Returns an object by the given Model index.
-  //! Returns 0 if the given index is not index of an object
-  ObjectPtr object(const QModelIndex& theIndex) const;
-
-  //! Returns index of the object
-  //! \param theObject object to find
-  QModelIndex objectIndex(const ObjectPtr theObject) const;
-
-  //! Returns QModelIndex which corresponds to the given part
-  //! If the object is not found then index is not valid
-  //! \param thePart a part for analysis
-  QModelIndex partIndex(const ResultPartPtr& thePart) const;
-
-  //! Activates a part data model if the index is a Part node index. 
-  //! Returns true if active part changed.
-  //! \param theIndex a model index
-  bool activatedIndex(const QModelIndex& theIndex);
-
-  //! Retrurns active part
-  ResultPartPtr activePart() const;
-
-  //! Retrurns QModelIndex of active part
-  QModelIndex activePartIndex() const
-  {
-    return myActivePartIndex;
-  }
-
-  //! Deactivates a Part
-  void deactivatePart();
-
-  //! Rebuild data tree
-  void rebuildDataTree();
-
-  //! Clear internal data
-  void clear();
-
-
- private:
-
-  enum
-  {
-    PartsFolder,
-    HistoryNode
-  };
-
-  //! Converts QModelIndex of this model to QModelIndex of a one of sub-models.
-  QModelIndex* toSourceModelIndex(const QModelIndex& theProxy) const;
-
-  //! Finds a pointer on QModelIndex which is equal to the given one
-  QModelIndex* findModelIndex(const QModelIndex& theIndex) const;
-
-  //! Returns pointer on QModelIndex which is equal to the given one.
-  QModelIndex* getModelIndex(const QModelIndex& theIndex) const;
-
-  //! Deletes all saved pointers on QModelIndex objects.
-  void clearModelIndexes();
-
-  //! Deletes all saved pointers on QModelIndex objects.
-  void clearSubModels();
-
-  //! Removes sub-model on removing a part object. Also it removes QModelIndex-es which refer to this model
-  void removeSubModel(int theModelId);
-
-  //! Returns true if the given model is a one of sub-models (of both types)
-  bool isSubModel(const QAbstractItemModel* theModel) const;
-
-  //! Returns true if the given model is a one of sub-models of Part type
-  bool isPartSubModel(const QAbstractItemModel* theModel) const;
-
-  //! Returns Parts Folder node
-  QModelIndex partFolderNode() const;
-
-  int historyOffset() const;
-
-  //! Data model of top part of data tree (not parts object)
-  XGUI_TopDataModel* myModel;
-
-  //! Data models for Parts data tree representation (one data model per a one part)
-  QList<XGUI_PartModel*> myPartModels;
-
-  //! Active part in part editing mode
-  XGUI_PartModel* myActivePart;
-
-  QModelIndex myActivePartIndex;
-
-  //! List of saved QModelIndexes created by sub-models
-  QList<QModelIndex*> myIndexes;
-
-};
-
-#endif
index d3a057beb5111d865a7f09285d809bc1d5460c20..1405ba5d620fb6d7da7997fa9a59a24b169597aa 100644 (file)
@@ -13,6 +13,8 @@
 #include "XGUI_Displayer.h"
 #include "XGUI_PropertyPanel.h"
 
+#include <ModuleBase_IModule.h>
+
 #include <AIS_Shape.hxx>
 
 
@@ -83,6 +85,14 @@ void XGUI_ModuleConnector::deactivateSubShapesSelection()
   XGUI_Displayer* aDisp = myWorkshop->displayer();
   // Clear selection modes
   QIntList aModes;
+  // TODO: check on OCC6.9.0
+  // the module current active modes should not be deactivated in order to save the objects selected
+  // the deactivate object in the mode of selection leads to the object is deselected in the viewer.
+  // But, in OCC6.8.0 this deselection does not happened automatically. It is necessary to call
+  // ClearOutdatedSelection, but this method has an error in the realization, which should be fixed in
+  // the OCC6.9.0 release. Moreother, it is possible that ClearOutdatedSelection will be called inside
+  // Deactivate method of AIS_InteractiveContext. In this case, we need not call it.
+  module()->activeSelectionModes(aModes);
   aDisp->activateObjects(aModes);
   // The document limitation selection has to be only during operation
   //aDisp->removeSelectionFilter(myDocumentShapeFilter);
@@ -101,13 +111,13 @@ ObjectPtr XGUI_ModuleConnector::findPresentedObject(const AISObjectPtr& theAIS)
   return aDisp->getObject(theAIS);
 }
 
-void XGUI_ModuleConnector::setSelected(const QObjectPtrList& theFeatures)
+void XGUI_ModuleConnector::setSelected(const QList<ModuleBase_ViewerPrs>& theValues)
 {
   XGUI_Displayer* aDisp = myWorkshop->displayer();
-  if (theFeatures.isEmpty()) {
+  if (theValues.isEmpty()) {
     myWorkshop->selector()->clearSelection();
   } else {
-    aDisp->setSelected(theFeatures);
+    aDisp->setSelected(theValues);
   }    
 }
 
index e78228378bebf0f455857e6850215cb7fbfc9001..d2348e101018e6672460988ccb5113075127ae02 100644 (file)
@@ -63,7 +63,7 @@ Q_OBJECT
 
   //! Select features clearing previous selection. 
   //! If the list is empty then selection will be cleared
-  virtual void setSelected(const QObjectPtrList& theFeatures);
+  virtual void setSelected(const QList<ModuleBase_ViewerPrs>& theValues);
 
   //! Returns workshop
   XGUI_Workshop* workshop() const { return myWorkshop; }
index 75f6c32a9d86d2f0c27e7bc1fd6793ef5bde89ea..25e2db0f5b448054571199ca4a484a273d1509ce 100644 (file)
@@ -1,15 +1,14 @@
 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
 
 #include "XGUI_ObjectsBrowser.h"
-#include "XGUI_DocumentDataModel.h"
 #include "XGUI_Tools.h"
 
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Document.h>
-#include <ModelAPI_Object.h>
 
 #include <ModuleBase_Tools.h>
+#include <ModuleBase_IDocumentDataModel.h>
 
 #include <QLayout>
 #include <QLabel>
 #include <QAction>
 #include <QStyledItemDelegate>
 
+
+/// Width of second column (minimum acceptable = 27)
+#define SECOND_COL_WIDTH 30
+
+
 /**
 * \ingroup GUI
 * Tree item delegate for definition of data in column items editor
@@ -38,7 +42,7 @@ public:
   {
     QLineEdit* aEditor = dynamic_cast<QLineEdit*>(editor);
     if (aEditor) {
-      XGUI_DocumentDataModel* aModel = myTreedView->dataModel();
+      ModuleBase_IDocumentDataModel* aModel = myTreedView->dataModel();
       ObjectPtr aObj = aModel->object(index);
       if (aObj.get() != NULL) {
         aEditor->setText(aObj->data()->name().c_str());
@@ -57,53 +61,20 @@ XGUI_DataTree::XGUI_DataTree(QWidget* theParent)
     : QTreeView(theParent)
 {
   setHeaderHidden(true);
-  setModel(new XGUI_DocumentDataModel(this));
   setEditTriggers(QAbstractItemView::NoEditTriggers);
   setSelectionBehavior(QAbstractItemView::SelectRows);
   setSelectionMode(QAbstractItemView::ExtendedSelection);
 
   setItemDelegateForColumn(0, new XGUI_TreeViewItemDelegate(this));
-
-  connect(selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
-          this, SLOT(onSelectionChanged(const QItemSelection&, const QItemSelection&)));
 }
 
 XGUI_DataTree::~XGUI_DataTree()
 {
 }
 
-XGUI_DocumentDataModel* XGUI_DataTree::dataModel() const
-{
-  return static_cast<XGUI_DocumentDataModel*>(model());
-}
-
-void XGUI_DataTree::onSelectionChanged(const QItemSelection& theSelected,
-                                       const QItemSelection& theDeselected)
-{
-  mySelectedData.clear();
-  QModelIndexList aIndexes = selectionModel()->selectedIndexes();
-  XGUI_DocumentDataModel* aModel = dataModel();
-  QModelIndexList::const_iterator aIt;
-  for (aIt = aIndexes.constBegin(); aIt != aIndexes.constEnd(); ++aIt) {
-    ObjectPtr aObject = aModel->object(*aIt);
-    if (aObject)
-      mySelectedData.append(aObject);
-  }
-  emit selectionChanged();
-}
-
-void XGUI_DataTree::mouseDoubleClickEvent(QMouseEvent* theEvent)
+ModuleBase_IDocumentDataModel* XGUI_DataTree::dataModel() const
 {
-  if (theEvent->button() == Qt::LeftButton) {
-    QModelIndex aIndex = currentIndex();
-    XGUI_DocumentDataModel* aModel = dataModel();
-    ObjectPtr aObject = aModel->object(aIndex);
-    ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
-    if (aPart) {
-      aPart->activate();
-    }
-  } else
-    QTreeView::mouseDoubleClickEvent(theEvent);
+  return static_cast<ModuleBase_IDocumentDataModel*>(model());
 }
 
 void XGUI_DataTree::contextMenuEvent(QContextMenuEvent* theEvent)
@@ -116,27 +87,38 @@ void XGUI_DataTree::commitData(QWidget* theEditor)
   QLineEdit* aEditor = dynamic_cast<QLineEdit*>(theEditor);
   if (aEditor) {
     QString aRes = aEditor->text();
-    ObjectPtr aFeature = mySelectedData.first();
+    QModelIndexList aIndexList = selectionModel()->selectedIndexes();
+    ModuleBase_IDocumentDataModel* aModel = dataModel();
+    ObjectPtr aObj = aModel->object(aIndexList.first());
     SessionPtr aMgr = ModelAPI_Session::get();
     aMgr->startOperation("Rename");
-    aFeature->data()->setName(qPrintable(aRes));
+    aObj->data()->setName(qPrintable(aRes));
     aMgr->finishOperation();
   }
 }
 
 void XGUI_DataTree::clear() 
 {
-  mySelectedData.clear();
-  XGUI_DocumentDataModel* aModel = dataModel();
+  ModuleBase_IDocumentDataModel* aModel = dataModel();
   aModel->clear();
   reset();
 }
 
+void XGUI_DataTree::resizeEvent(QResizeEvent* theEvent)
+{
+  QSize aSize = theEvent->size();
+  if (aSize.isValid()) {
+    setColumnWidth(0, aSize.width() - SECOND_COL_WIDTH);
+    setColumnWidth(1, SECOND_COL_WIDTH);
+  }
+}
+
+
 //********************************************************************
 //********************************************************************
 //********************************************************************
 XGUI_ObjectsBrowser::XGUI_ObjectsBrowser(QWidget* theParent)
-    : QWidget(theParent)
+    : QWidget(theParent), myDocModel(0)
 {
   QVBoxLayout* aLayout = new QVBoxLayout(this);
   ModuleBase_Tools::zeroMargins(aLayout);
@@ -179,24 +161,14 @@ XGUI_ObjectsBrowser::XGUI_ObjectsBrowser(QWidget* theParent)
   myTreeView = new XGUI_DataTree(this);
   aLayout->addWidget(myTreeView);
 
-  myDocModel = myTreeView->dataModel();
-
   aLabelWgt->setFrameShape(myTreeView->frameShape());
   aLabelWgt->setFrameShadow(myTreeView->frameShadow());
 
-  connect(myTreeView, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
-  connect(myTreeView, SIGNAL(activePartChanged(ObjectPtr)), this,
-          SLOT(onActivePartChanged(ObjectPtr)));
-  connect(myTreeView, SIGNAL(activePartChanged(ObjectPtr)), this,
-          SIGNAL(activePartChanged(ObjectPtr)));
-
   connect(myActiveDocLbl, SIGNAL(customContextMenuRequested(const QPoint&)), this,
           SLOT(onLabelContextMenuRequested(const QPoint&)));
   connect(myTreeView, SIGNAL(contextMenuRequested(QContextMenuEvent*)), this,
           SLOT(onContextMenuRequested(QContextMenuEvent*)));
 
-  onActivePartChanged(ObjectPtr());
-
   // Create internal actions
   QAction* aAction = new QAction(QIcon(":pictures/rename_edit.png"), tr("Rename"), this);
   aAction->setData("RENAME_CMD");
@@ -209,32 +181,11 @@ XGUI_ObjectsBrowser::~XGUI_ObjectsBrowser()
 {
 }
 
-//***************************************************
-void XGUI_ObjectsBrowser::onActivePartChanged(ObjectPtr thePart)
-{
-  QPalette aPalet = myActiveDocLbl->palette();
-  if (thePart) {
-    aPalet.setColor(QPalette::Text, Qt::black);
-  } else {
-    aPalet.setColor(QPalette::Text, QColor(0, 72, 140));
-  }
-  myActiveDocLbl->setPalette(aPalet);
-}
-
 //***************************************************
 bool XGUI_ObjectsBrowser::eventFilter(QObject* obj, QEvent* theEvent)
 {
   if (obj == myActiveDocLbl) {
-    if (myActiveDocLbl->isReadOnly()) {
-      if (theEvent->type() == QEvent::MouseButtonDblClick) {
-        if (myDocModel->activePartIndex().isValid()) {
-          myTreeView->setExpanded(myDocModel->activePartIndex(), false);
-        }
-        myDocModel->deactivatePart();
-        onActivePartChanged(ObjectPtr());
-        emit activePartChanged(ObjectPtr());
-      }
-    } else {
+    if (!myActiveDocLbl->isReadOnly()) {
       // End of editing by mouse click
       if (theEvent->type() == QEvent::MouseButtonRelease) {
         QMouseEvent* aEvent = (QMouseEvent*) theEvent;
@@ -275,42 +226,12 @@ void XGUI_ObjectsBrowser::closeDocNameEditing(bool toSave)
   }
 }
 
-//***************************************************
-void XGUI_ObjectsBrowser::activatePart(const ResultPartPtr& thePart)
-{
-  if (thePart) {
-    QModelIndex aIndex = myDocModel->partIndex(thePart);
-
-    if ((myDocModel->activePartIndex() != aIndex) && myDocModel->activePartIndex().isValid()) {
-      myTreeView->setExpanded(myDocModel->activePartIndex(), false);
-    }
-    bool isChanged = myDocModel->activatedIndex(aIndex);
-    if (isChanged) {
-      if (myDocModel->activePartIndex().isValid()) {
-        myTreeView->setExpanded(aIndex.parent(), true);
-        myTreeView->setExpanded(aIndex, true);
-        onActivePartChanged(myDocModel->object(aIndex));
-      } else {
-        onActivePartChanged(ObjectPtr());
-      }
-    }
-  } else {
-    QModelIndex aIndex = myDocModel->activePartIndex();
-    if (aIndex.isValid()) {
-      myDocModel->activatedIndex(aIndex);
-      myTreeView->setExpanded(aIndex, false);
-      onActivePartChanged(ObjectPtr());
-    }
-  }
-}
-
 //***************************************************
 void XGUI_ObjectsBrowser::onContextMenuRequested(QContextMenuEvent* theEvent)
 {
-  myObjectsList = myTreeView->selectedObjects();
-  bool toEnable = myObjectsList.size() == 1;
-  foreach(QAction* aCmd, actions())
-  {
+  QObjectPtrList aSelectedData = selectedObjects();
+  bool toEnable = aSelectedData.size() == 1;
+  foreach(QAction* aCmd, actions()) {
     aCmd->setEnabled(toEnable);
   }
   emit contextMenuRequested(theEvent);
@@ -319,12 +240,9 @@ void XGUI_ObjectsBrowser::onContextMenuRequested(QContextMenuEvent* theEvent)
 //***************************************************
 void XGUI_ObjectsBrowser::onLabelContextMenuRequested(const QPoint& thePnt)
 {
-  myObjectsList.clear();
+  myTreeView->selectionModel()->clearSelection();
   //Empty feature pointer means that selected root document
-  myObjectsList.append(ObjectPtr());
-
-  foreach(QAction* aCmd, actions())
-  {
+  foreach(QAction* aCmd, actions()) {
     aCmd->setEnabled(true);
   }
   QContextMenuEvent aEvent(QContextMenuEvent::Mouse, thePnt, myActiveDocLbl->mapToGlobal(thePnt));
@@ -334,13 +252,13 @@ void XGUI_ObjectsBrowser::onLabelContextMenuRequested(const QPoint& thePnt)
 //***************************************************
 void XGUI_ObjectsBrowser::onEditItem()
 {
-  if (myObjectsList.size() > 0) {
-    ObjectPtr aFeature = myObjectsList.first();
+  QObjectPtrList aSelectedData = selectedObjects();
+  if (aSelectedData.size() > 0) {
+    ObjectPtr aFeature = aSelectedData.first();
     if (aFeature) {  // Selection happens in TreeView
       // Find index which corresponds the feature
       QModelIndex aIndex;
-      foreach(QModelIndex aIdx, selectedIndexes())
-      {
+      foreach(QModelIndex aIdx, selectedIndexes()) {
         ObjectPtr aFea = dataModel()->object(aIdx);
         if (dataModel()->object(aIdx)->isSame(aFeature)) {
           aIndex = aIdx;
@@ -351,21 +269,15 @@ void XGUI_ObjectsBrowser::onEditItem()
         myTreeView->setCurrentIndex(aIndex);
         myTreeView->edit(aIndex);
       }
-    } else {  //Selection happens in Upper label
-      myActiveDocLbl->setReadOnly(false);
-      myActiveDocLbl->setFocus();
-      myActiveDocLbl->selectAll();
-      myActiveDocLbl->grabMouse();
-      myActiveDocLbl->setProperty("OldText", myActiveDocLbl->text());
+      return;
     }
   }
-}
-
-//***************************************************
-void XGUI_ObjectsBrowser::onSelectionChanged()
-{
-  myObjectsList = myTreeView->selectedObjects();
-  emit selectionChanged();
+  //Selection happens in Upper label
+  myActiveDocLbl->setReadOnly(false);
+  myActiveDocLbl->setFocus();
+  myActiveDocLbl->selectAll();
+  myActiveDocLbl->grabMouse();
+  myActiveDocLbl->setProperty("OldText", myActiveDocLbl->text());
 }
 
 //***************************************************
@@ -392,15 +304,38 @@ void XGUI_ObjectsBrowser::setObjectsSelected(const QObjectPtrList& theObjects)
 }
 
 //***************************************************
-void XGUI_ObjectsBrowser::processEvent(const std::shared_ptr<Events_Message>& theMessage)
+void XGUI_ObjectsBrowser::clearContent()  
 { 
-  myDocModel->processEvent(theMessage); 
+  myTreeView->clear(); 
 }
 
+void XGUI_ObjectsBrowser::setDataModel(ModuleBase_IDocumentDataModel* theModel)
+{
+  myDocModel = theModel;
+  myTreeView->setModel(myDocModel);
+  QItemSelectionModel* aSelMod = myTreeView->selectionModel();
+  connect(aSelMod, SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
+          this, SLOT(onSelectionChanged(const QItemSelection&, const QItemSelection&)));
+}
 
-//***************************************************
-void XGUI_ObjectsBrowser::clearContent()  
-{ 
-  myObjectsList.clear();
-  myTreeView->clear(); 
+void XGUI_ObjectsBrowser::onSelectionChanged(const QItemSelection& theSelected,
+                                       const QItemSelection& theDeselected)
+{
+  emit selectionChanged();
 }
+
+QObjectPtrList XGUI_ObjectsBrowser::selectedObjects() const
+{
+  QObjectPtrList aList;
+  QModelIndexList aIndexes = selectedIndexes();
+  ModuleBase_IDocumentDataModel* aModel = dataModel();
+  QModelIndexList::const_iterator aIt;
+  for (aIt = aIndexes.constBegin(); aIt != aIndexes.constEnd(); ++aIt) {
+    if ((*aIt).column() == 0) {
+      ObjectPtr aObject = aModel->object(*aIt);
+      if (aObject)
+        aList.append(aObject);
+    }
+  }
+  return aList;
+}
\ No newline at end of file
index 93cc131be4f458eb27428306fca6400e2696549f..e5965b0ddf8e934838be9146eaaf447aa3957fcf 100644 (file)
@@ -12,7 +12,7 @@
 #include <QWidget>
 #include <QTreeView>
 
-class XGUI_DocumentDataModel;
+class ModuleBase_IDocumentDataModel;
 class QLineEdit;
 
 /**
@@ -26,24 +26,13 @@ Q_OBJECT
    /// Constructor
    /// \param theParent a parent widget
   XGUI_DataTree(QWidget* theParent);
-  virtual ~XGUI_DataTree();
 
-  //! Returns list of currently selected objects
-  QObjectPtrList selectedObjects() const
-  {
-    return mySelectedData;
-  }
+  virtual ~XGUI_DataTree();
 
   /// Returns current data model
-  XGUI_DocumentDataModel* dataModel() const;
+  ModuleBase_IDocumentDataModel* dataModel() const;
 
 signals:
-  //! Emited when selection is changed
-  void selectionChanged();
-
-  //! Emited when active part changed
-  void activePartChanged(ObjectPtr thePart);
-
   //! Emited on context menu request
   void contextMenuRequested(QContextMenuEvent* theEvent);
 
@@ -52,23 +41,16 @@ public slots:
   virtual void clear();
 
  protected slots:
-   /// Commit modified data (used for renaming of objects)
+  /// Commit modified data (used for renaming of objects)
   virtual void commitData(QWidget* theEditor);
 
  protected:
-   /// Redefinition of virtual method
-  virtual void mouseDoubleClickEvent(QMouseEvent* theEvent);
-
    /// Redefinition of virtual method
   virtual void contextMenuEvent(QContextMenuEvent* theEvent);
 
- private slots:
-  //! Called when selection in Data Tree is changed
-  void onSelectionChanged(const QItemSelection& theSelected, const QItemSelection& theDeselected);
+   /// Redefinition of virtual method
+  virtual void resizeEvent(QResizeEvent* theEvent);
 
- private:
-  //! List of currently selected data
-  QObjectPtrList mySelectedData;
 };
 
 /**\class XGUI_ObjectsBrowser
@@ -85,16 +67,13 @@ Q_OBJECT
   virtual ~XGUI_ObjectsBrowser();
 
   //! Returns Model which provides access to data objects
-  XGUI_DocumentDataModel* dataModel() const
+  ModuleBase_IDocumentDataModel* dataModel() const
   {
     return myDocModel;
   }
 
   //! Returns list of currently selected objects
-  QObjectPtrList selectedObjects() const
-  {
-    return myObjectsList;
-  }
+  QObjectPtrList selectedObjects() const;
 
   /// Set selected list of objects
   /// \param theObjects list of objects to select
@@ -112,26 +91,22 @@ Q_OBJECT
     return myTreeView;
   }
 
-  //! Activates currently selected part. Signal activePartChanged will not be sent
-  void activatePart(const ResultPartPtr& thePart);
+  /// Returns active doc label object
+  QLineEdit* activeDocLabel() const { return myActiveDocLbl; }
 
   /// Rebuild data tree
   void rebuildDataTree();
 
-  /// Process application event
-  /// \param theMessage an event message
-  void processEvent(const std::shared_ptr<Events_Message>& theMessage);
-
   /// Resets the object browser into initial state
   void clearContent();
 
+  /// Set Data Model for the Object Browser
+  void setDataModel(ModuleBase_IDocumentDataModel* theModel);
+
 signals:
   //! Emited when selection is changed
   void selectionChanged();
 
-  //! Emited when current active document is changed
-  void activePartChanged(ObjectPtr thePart);
-
   //! Emited on context menu request
   void contextMenuRequested(QContextMenuEvent* theEvent);
 
@@ -140,10 +115,6 @@ signals:
   virtual bool eventFilter(QObject* obj, QEvent* theEvent);
 
  private slots:
-   /// Activate part
-   /// \param thePart a part to activate
-  void onActivePartChanged(ObjectPtr thePart);
-
   /// Show context menu
   /// \param theEvent a context menu event
   void onContextMenuRequested(QContextMenuEvent* theEvent);
@@ -155,19 +126,17 @@ signals:
   //! Called on Edit command request
   void onEditItem();
 
-  /// Process selection changed event
-  void onSelectionChanged();
+  //! Called when selection in Data Tree is changed
+  void onSelectionChanged(const QItemSelection& theSelected, const QItemSelection& theDeselected);
 
  private:
   void closeDocNameEditing(bool toSave);
 
   //! Internal model
-  XGUI_DocumentDataModel* myDocModel;
+  ModuleBase_IDocumentDataModel* myDocModel;
 
   QLineEdit* myActiveDocLbl;
   XGUI_DataTree* myTreeView;
-
-  QObjectPtrList myObjectsList;
 };
 
 #endif
diff --git a/src/XGUI/XGUI_PartDataModel.cpp b/src/XGUI/XGUI_PartDataModel.cpp
deleted file mode 100644 (file)
index bbf0ef9..0000000
+++ /dev/null
@@ -1,573 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
-
-#include "XGUI_PartDataModel.h"
-#include "XGUI_Workshop.h"
-
-#include <ModelAPI_Session.h>
-#include <ModelAPI_Document.h>
-#include <ModelAPI_Feature.h>
-#include <ModelAPI_Result.h>
-#include <ModelAPI_Data.h>
-#include <ModelAPI_AttributeDocRef.h>
-#include <ModelAPI_Object.h>
-#include <ModelAPI_ResultPart.h>
-#include <ModelAPI_ResultConstruction.h>
-#include <ModelAPI_ResultParameter.h>
-#include <ModelAPI_ResultBody.h>
-#include <ModelAPI_ResultGroup.h>
-#include <ModelAPI_AttributeDouble.h>
-
-#include <QIcon>
-#include <QBrush>
-
-//ObjectPtr featureObj(const ObjectPtr& theFeature)
-//{
-//  ObjectPtr aObject = std::dynamic_pointer_cast<ModelAPI_Object>(theFeature);
-//  if (aObject)
-//    return aObject->featureRef();
-//  return theFeature;
-//}
-
-XGUI_TopDataModel::XGUI_TopDataModel(QObject* theParent)
-    : XGUI_FeaturesModel(theParent)
-{
-}
-
-XGUI_TopDataModel::~XGUI_TopDataModel()
-{
-}
-
-QVariant XGUI_TopDataModel::data(const QModelIndex& theIndex, int theRole) const
-{
-  switch (theRole) {
-    case Qt::DisplayRole:
-      // return a name
-      switch (theIndex.internalId()) {
-        case ParamsFolder:
-          return tr("Parameters") + QString(" (%1)").arg(rowCount(theIndex));
-        case ParamObject: {
-          DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-          ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultParameter::group(), theIndex.row());
-          if (aObject) {
-            ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObject);
-            AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
-            QString aVal = QString::number(aValueAttribute->value());
-            QString aTitle = QString(aObject->data()->name().c_str());
-            return aTitle + " = " + aVal;
-          }
-        }
-          break;
-        case ConstructFolder:
-          return tr("Constructions") + QString(" (%1)").arg(rowCount(theIndex));
-        case ConstructObject: {
-          DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-          ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultConstruction::group(),
-                                               theIndex.row());
-          if (aObject)
-            return aObject->data()->name().c_str();
-        }
-          break;
-        //case GroupsFolder:
-        //  return tr("Groups") + QString(" (%1)").arg(rowCount(theIndex));
-        //case GroupObject: {
-        //  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-        //  ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultGroup::group(),
-        //                                       theIndex.row());
-        //  if (aObject)
-        //    return aObject->data()->name().c_str();
-        //}
-        //  break;
-      }
-      break;
-
-    case Qt::DecorationRole:
-      {
-      // return an Icon
-      switch (theIndex.internalId()) {
-        case ParamsFolder:
-          return QIcon(":pictures/params_folder.png");
-        case ConstructFolder:
-          return QIcon(":pictures/constr_folder.png");
-        case ConstructObject:
-          return QIcon(":pictures/constr_object.png");
-        //case GroupsFolder:
-        //  return QIcon(":pictures/constr_folder.png");
-        }
-      }
-      break;
-
-    case Qt::ToolTipRole:
-      // return Tooltip
-      break;
-    case Qt::ForegroundRole:
-      return QBrush(myItemsColor);
-      break;
-  }
-  return QVariant();
-}
-
-QVariant XGUI_TopDataModel::headerData(int section, Qt::Orientation orientation, int role) const
-{
-  return QVariant();
-}
-
-int XGUI_TopDataModel::rowCount(const QModelIndex& theParent) const
-{
-  if (!theParent.isValid())
-    return 2;  // In case of groups using it has to be +1
-
-  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-  if (theParent.internalId() == ParamsFolder)
-    return aRootDoc->size(ModelAPI_ResultParameter::group());
-
-  if (theParent.internalId() == ConstructFolder)
-    return aRootDoc->size(ModelAPI_ResultConstruction::group());
-
-  //if (theParent.internalId() == GroupsFolder)
-  //  return aRootDoc->size(ModelAPI_ResultGroup::group());
-
-  return 0;
-}
-
-int XGUI_TopDataModel::columnCount(const QModelIndex &parent) const
-{
-  return 1;
-}
-
-QModelIndex XGUI_TopDataModel::index(int theRow, int theColumn, const QModelIndex& theParent) const
-{
-  if (!theParent.isValid()) {
-    switch (theRow) {
-      case 0:
-        return createIndex(theRow, theColumn, (qint32) ParamsFolder);
-      case 1:
-        return createIndex(theRow, theColumn, (qint32) ConstructFolder);
-      //case 2:
-      //  return createIndex(theRow, theColumn, (qint32) GroupsFolder);
-    }
-  } else {
-    if (theParent.internalId() == ParamsFolder)
-      return createIndex(theRow, theColumn, (qint32) ParamObject);
-
-    if (theParent.internalId() == ConstructFolder)
-      return createIndex(theRow, theColumn, (qint32) ConstructObject);
-
-    //if (theParent.internalId() == GroupsFolder)
-    //  return createIndex(theRow, theColumn, (qint32) GroupObject);
-  }
-  return QModelIndex();
-}
-
-QModelIndex XGUI_TopDataModel::parent(const QModelIndex& theIndex) const
-{
-  int aId = (int) theIndex.internalId();
-  switch (aId) {
-    case ParamsFolder:
-    case ConstructFolder:
-    //case GroupsFolder:
-      return QModelIndex();
-    case ParamObject:
-      return createIndex(0, 0, (qint32) ParamsFolder);
-    case ConstructObject:
-      return createIndex(1, 0, (qint32) ConstructFolder);
-    //case GroupObject:
-    //  return createIndex(2, 0, (qint32) GroupsFolder);
-  }
-  return QModelIndex();
-}
-
-bool XGUI_TopDataModel::hasChildren(const QModelIndex& theParent) const
-{
-  return rowCount(theParent) > 0;
-}
-
-ObjectPtr XGUI_TopDataModel::object(const QModelIndex& theIndex) const
-{
-  switch (theIndex.internalId()) {
-    case ParamsFolder:
-    case ConstructFolder:
-      return ObjectPtr();
-    case ParamObject: {
-      DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-      return aRootDoc->object(ModelAPI_ResultParameter::group(), theIndex.row());
-    }
-    case ConstructObject: {
-      DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-      return aRootDoc->object(ModelAPI_ResultConstruction::group(), theIndex.row());
-    }
-    //case GroupObject: {
-    //  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-    //  return aRootDoc->object(ModelAPI_ResultGroup::group(), theIndex.row());
-    //}
-  }
-  return ObjectPtr();
-}
-
-QModelIndex XGUI_TopDataModel::findParent(const ObjectPtr& theObject) const
-{
-  return findGroup(theObject->groupName().c_str());
-}
-
-QModelIndex XGUI_TopDataModel::findGroup(const std::string& theGroup) const
-{
-  if (theGroup == ModelAPI_ResultParameter::group())
-    return createIndex(0, 0, (qint32) ParamsFolder);
-  if (theGroup == ModelAPI_ResultConstruction::group())
-    return createIndex(1, 0, (qint32) ConstructFolder);
-  //if (theGroup == ModelAPI_ResultGroup::group())
-  //  return createIndex(2, 0, (qint32) ConstructFolder);
-  return QModelIndex();
-}
-
-QModelIndex XGUI_TopDataModel::objectIndex(const ObjectPtr& theObject) const
-{
-  QModelIndex aIndex;
-  if (theObject) {
-    DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-    std::string aGroup = theObject->groupName();
-    int aNb = aRootDoc->size(aGroup);
-    int aRow = -1;
-    for (int i = 0; i < aNb; i++) {
-      if (aRootDoc->object(aGroup, i) == theObject) {
-        aRow = i;
-        break;
-      }
-    }
-    if (aRow != -1) {
-      if (aGroup == ModelAPI_ResultParameter::group())
-        return createIndex(aRow, 0, (qint32) ParamObject);
-      if (aGroup == ModelAPI_ResultConstruction::group())
-        return createIndex(aRow, 0, (qint32) ConstructObject);
-      //if (aGroup == ModelAPI_ResultGroup::group())
-      //  return createIndex(aRow, 0, (qint32) GroupObject);
-    }
-  }
-  return aIndex;
-}
-
-//******************************************************************
-//******************************************************************
-//******************************************************************
-XGUI_PartDataModel::XGUI_PartDataModel(QObject* theParent)
-    : XGUI_PartModel(theParent)
-{
-}
-
-XGUI_PartDataModel::~XGUI_PartDataModel()
-{
-}
-
-QVariant XGUI_PartDataModel::data(const QModelIndex& theIndex, int theRole) const
-{
-  switch (theRole) {
-    case Qt::DisplayRole:
-      // return a name
-      switch (theIndex.internalId()) {
-        case MyRoot: {
-          DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-          ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), myId);
-          if (aObject)
-            return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
-        }
-        case ParamsFolder:
-          return tr("Parameters") + QString(" (%1)").arg(rowCount(theIndex));
-        case ConstructFolder:
-          return tr("Constructions") + QString(" (%1)").arg(rowCount(theIndex));
-        case BodiesFolder:
-          return tr("Bodies") + QString(" (%1)").arg(rowCount(theIndex));
-        case GroupsFolder:
-          return tr("Groups") + QString(" (%1)").arg(rowCount(theIndex));
-        case ParamObject: {
-          ObjectPtr aObject = partDocument()->object(ModelAPI_ResultParameter::group(),
-                                                     theIndex.row());
-          if (aObject) {
-            ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObject);
-            AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
-            QString aVal = QString::number(aValueAttribute->value());
-            QString aTitle = QString(aObject->data()->name().c_str());
-            return aTitle + " = " + aVal;
-          }
-        }
-          break;
-        case ConstructObject: {
-          ObjectPtr aObject = partDocument()->object(ModelAPI_ResultConstruction::group(),
-                                                     theIndex.row());
-          if (aObject)
-            return std::dynamic_pointer_cast<ModelAPI_Object>(aObject)->data()->name().c_str();
-        }
-          break;
-        case BodiesObject: {
-          ObjectPtr aObject = partDocument()->object(ModelAPI_ResultBody::group(), theIndex.row());
-          if (aObject)
-            return aObject->data()->name().c_str();
-        }
-          break;
-        case GroupObject: {
-          ObjectPtr aObject = partDocument()->object(ModelAPI_ResultGroup::group(), theIndex.row());
-          if (aObject)
-            return aObject->data()->name().c_str();
-        }
-        case HistoryObject: {
-          ObjectPtr aObject = partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
-          if (aObject)
-            return aObject->data()->name().c_str();
-        }
-      }
-      break;
-    case Qt::DecorationRole:
-      // return an Icon
-      switch (theIndex.internalId()) {
-        case MyRoot:
-          return QIcon(":pictures/part_ico.png");
-        case ParamsFolder:
-          return QIcon(":pictures/params_folder.png");
-        case ConstructFolder:
-        case BodiesFolder:
-          return QIcon(":pictures/constr_folder.png");
-        case GroupsFolder:
-          return QIcon(":pictures/constr_folder.png");
-        case ConstructObject:
-        case GroupObject:
-        case BodiesObject: {
-          std::string aGroup = theIndex.internalId() == ConstructObject ?
-            ModelAPI_ResultConstruction::group() : ModelAPI_ResultBody::group();
-          ObjectPtr anObject = partDocument()->object(aGroup, theIndex.row());
-          if (anObject && anObject->data() && 
-              anObject->data()->execState() == ModelAPI_StateMustBeUpdated) {
-            return QIcon(":pictures/constr_object_modified.png");
-          }
-          return QIcon(":pictures/constr_object.png");
-        }
-        case HistoryObject: {
-          ObjectPtr aObject = partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
-          FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
-          if (aFeature)
-            return XGUI_Workshop::featureIcon(aFeature);
-        }
-      }
-      break;
-    case Qt::ToolTipRole:
-      // return Tooltip
-      break;
-    case Qt::ForegroundRole:
-      return QBrush(myItemsColor);
-      break;
-  }
-  return QVariant();
-}
-
-QVariant XGUI_PartDataModel::headerData(int section, Qt::Orientation orientation, int role) const
-{
-  return QVariant();
-}
-
-int XGUI_PartDataModel::rowCount(const QModelIndex& parent) const
-{
-  if (!parent.isValid()) {
-    DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-    if (aRootDoc->object(ModelAPI_ResultPart::group(), myId))
-      return 1;
-    else
-      return 0;
-  }
-  switch (parent.internalId()) {
-    case MyRoot:
-      {
-        DocumentPtr aDoc = partDocument();
-        if (aDoc) {
-          return getRowsNumber() + aDoc->size(ModelAPI_Feature::group());
-        } else 
-          return 0;
-      }
-    case ParamsFolder:
-      return partDocument()->size(ModelAPI_ResultParameter::group());
-    case ConstructFolder:
-      return partDocument()->size(ModelAPI_ResultConstruction::group());
-    case BodiesFolder:
-      return partDocument()->size(ModelAPI_ResultBody::group());
-    case GroupsFolder:
-      return partDocument()->size(ModelAPI_ResultGroup::group());
-  }
-  return 0;
-}
-
-int XGUI_PartDataModel::columnCount(const QModelIndex &parent) const
-{
-  return 1;
-}
-
-QModelIndex XGUI_PartDataModel::index(int theRow, int theColumn, const QModelIndex &theParent) const
-{
-  if (!theParent.isValid())
-    return createIndex(theRow, 0, (qint32) MyRoot);
-
-  int aId = (int) theParent.internalId();
-  switch (aId) {
-    case MyRoot:
-      switch (theRow) {
-        case 0:
-          return createIndex(theRow, 0, (qint32) ParamsFolder);
-        case 1:
-          return createIndex(theRow, 0, (qint32) ConstructFolder);
-        case 2:
-          return createIndex(theRow, 0, (qint32) BodiesFolder);
-        case 3:
-          {
-          int aSize = partDocument()->size(ModelAPI_ResultGroup::group());
-          if (aSize > 0)
-            return createIndex(theRow, 0, (qint32) GroupsFolder);
-          else
-            return createIndex(theRow, theColumn, (qint32) HistoryObject);
-          }
-        default:
-          return createIndex(theRow, theColumn, (qint32) HistoryObject);
-      }
-    case ParamsFolder:
-      return createIndex(theRow, 0, (qint32) ParamObject);
-    case ConstructFolder:
-      return createIndex(theRow, 0, (qint32) ConstructObject);
-    case BodiesFolder:
-      return createIndex(theRow, 0, (qint32) BodiesObject);
-    case GroupsFolder:
-      return createIndex(theRow, 0, (qint32) GroupObject);
-  }
-  return QModelIndex();
-}
-
-QModelIndex XGUI_PartDataModel::parent(const QModelIndex& theIndex) const
-{
-  switch (theIndex.internalId()) {
-    case MyRoot:
-      return QModelIndex();
-    case ParamsFolder:
-    case ConstructFolder:
-    case BodiesFolder:
-    case GroupsFolder:
-    case HistoryObject:
-      return createIndex(0, 0, (qint32) MyRoot);
-
-    case ParamObject:
-      return createIndex(0, 0, (qint32) ParamsFolder);
-    case ConstructObject:
-      return createIndex(1, 0, (qint32) ConstructFolder);
-    case BodiesObject:
-      return createIndex(2, 0, (qint32) BodiesFolder);
-    case GroupObject:
-      return createIndex(3, 0, (qint32) GroupsFolder);
-  }
-  return QModelIndex();
-}
-
-bool XGUI_PartDataModel::hasChildren(const QModelIndex& theParent) const
-{
-  return rowCount(theParent) > 0;
-}
-
-DocumentPtr XGUI_PartDataModel::partDocument() const
-{
-  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-  ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), myId);
-  ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
-  if (aPart)
-    return aPart->partDoc();
-  return DocumentPtr(); // null if not found
-}
-
-ObjectPtr XGUI_PartDataModel::object(const QModelIndex& theIndex) const
-{
-  switch (theIndex.internalId()) {
-    case MyRoot: {
-      DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-      return aRootDoc->object(ModelAPI_ResultPart::group(), myId);
-    }
-    case ParamsFolder:
-    case ConstructFolder:
-    case BodiesFolder:
-    case GroupsFolder:
-      return ObjectPtr();
-
-    case ParamObject:
-      return partDocument()->object(ModelAPI_ResultParameter::group(), theIndex.row());
-    case ConstructObject:
-      return partDocument()->object(ModelAPI_ResultConstruction::group(), theIndex.row());
-    case BodiesObject:
-      return partDocument()->object(ModelAPI_ResultBody::group(), theIndex.row());
-    case GroupObject:
-      return partDocument()->object(ModelAPI_ResultGroup::group(), theIndex.row());
-    case HistoryObject:
-      return partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - getRowsNumber());
-  }
-  return ObjectPtr();
-}
-
-bool XGUI_PartDataModel::hasDocument(const DocumentPtr& theDoc) const
-{
-  return (partDocument() == theDoc);
-}
-
-QModelIndex XGUI_PartDataModel::findParent(const ObjectPtr& theObject) const
-{
-  return findGroup(theObject->groupName().c_str());
-}
-
-QModelIndex XGUI_PartDataModel::findGroup(const std::string& theGroup) const
-{
-  if (theGroup == ModelAPI_ResultParameter::group())
-    return createIndex(0, 0, (qint32) ParamsFolder);
-  if (theGroup == ModelAPI_ResultConstruction::group())
-    return createIndex(1, 0, (qint32) ConstructFolder);
-  if (theGroup == ModelAPI_ResultBody::group())
-    return createIndex(2, 0, (qint32) BodiesFolder);
-  if (theGroup == ModelAPI_ResultGroup::group())
-    return createIndex(3, 0, (qint32) GroupsFolder);
-  return QModelIndex();
-}
-
-ResultPartPtr XGUI_PartDataModel::part() const
-{
-  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
-  ObjectPtr aObj = aRootDoc->object(ModelAPI_ResultPart::group(), myId);
-  return std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObj);
-}
-
-QModelIndex XGUI_PartDataModel::objectIndex(const ObjectPtr& theObject) const
-{
-  QModelIndex aIndex;
-  if (theObject) {
-    if (part() == theObject)
-      return aIndex;
-
-    std::string aGroup = theObject->groupName();
-    DocumentPtr aDoc = theObject->document();
-    int aNb = aDoc->size(aGroup);
-    int aRow = -1;
-    for (int i = 0; i < aNb; i++) {
-      if (aDoc->object(aGroup, i) == theObject) {
-        aRow = i;
-        break;
-      }
-    }
-    if (aRow == -1)
-      return aIndex;
-    if (aGroup == ModelAPI_ResultParameter::group())
-      return createIndex(aRow, 0, (qint32) ParamObject);
-    else if (aGroup == ModelAPI_ResultConstruction::group())
-      return createIndex(aRow, 0, (qint32) ConstructObject);
-    else if (aGroup == ModelAPI_ResultBody::group())
-      return createIndex(aRow, 0, (qint32) BodiesObject);
-    else if (aGroup == ModelAPI_ResultGroup::group())
-      return createIndex(aRow, 0, (qint32) GroupObject);
-    else
-      return createIndex(aRow + getRowsNumber(), 0, (qint32) HistoryObject);
-  }
-  return aIndex;
-}
-
-
-int XGUI_PartDataModel::getRowsNumber() const
-{
-  int aSize = partDocument()->size(ModelAPI_ResultGroup::group());
-  if (aSize == 0) // If there are no groups then do not show group folder
-    return 3;
-  return 4;
-}
\ No newline at end of file
diff --git a/src/XGUI/XGUI_PartDataModel.h b/src/XGUI/XGUI_PartDataModel.h
deleted file mode 100644 (file)
index 56f28ad..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
-
-#ifndef XGUI_PartDataModel_H
-#define XGUI_PartDataModel_H
-
-#include "XGUI.h"
-#include "XGUI_DataTreeModel.h"
-
-/**\class XGUI_TopDataModel
- * \ingroup GUI
- * \brief This is a data model for Object Browser (QTreeView).
- * It represents only upper part of data tree (non-parts tree items)
- */
-class XGUI_EXPORT XGUI_TopDataModel : public XGUI_FeaturesModel
-{
-Q_OBJECT
- public:
-   /// Constructor
-   /// \param theParent a parent object
-  XGUI_TopDataModel(QObject* theParent);
-  virtual ~XGUI_TopDataModel();
-
-  // Reimpl from QAbstractItemModel
-
-  /// Returns the data stored under the given role for the item referred to by the index.
-  /// \param theIndex a model index
-  /// \param theRole a data role (see Qt::ItemDataRole)
-  virtual QVariant data(const QModelIndex& theIndex, int theRole) const;
-
-  /// Returns the data for the given role and section in the header with the specified orientation.
-  /// \param theSection a section
-  /// \param theOrient an orientation
-  /// \param theRole a data role (see Qt::ItemDataRole)
-  virtual QVariant headerData(int theSection, Qt::Orientation theOrient,
-                              int theRole = Qt::DisplayRole) const;
-
-  /// Returns the number of rows under the given parent. When the parent is valid it means that 
-  /// rowCount is returning the number of children of parent.
-  /// \param theParent a parent model index
-  virtual int rowCount(const QModelIndex &theParent = QModelIndex()) const;
-
-  /// Returns the number of columns for the children of the given parent.
-  /// It has a one column
-  /// \param theParent a parent model index
-  virtual int columnCount(const QModelIndex &theParent = QModelIndex()) const;
-
-
-  /// Returns the index of the item in the model specified by the given row, column and parent index.
-  /// \param theRow a row
-  /// \param theColumn a column
-  /// \param theParent a parent model index
-  virtual QModelIndex index(int theRow, int theColumn, const QModelIndex& theParent =
-                                QModelIndex()) const;
-
-  /// Returns the parent of the model item with the given index. 
-  /// If the item has no parent, an invalid QModelIndex is returned.
-  /// \param theIndex a model index
-  virtual QModelIndex parent(const QModelIndex& theIndex) const;
-
-  /// Returns true if parent has any children; otherwise returns false.
-  /// \param theParent a parent model index
-  virtual bool hasChildren(const QModelIndex& theParent = QModelIndex()) const;
-
-  //! Returns object by the given Model index.
-  //! Returns 0 if the given index is not index of a object
-  virtual ObjectPtr object(const QModelIndex& theIndex) const;
-
-  //! Returns QModelIndex which corresponds to the given object
-  //! If the object is not found then index is not valid
-  virtual QModelIndex objectIndex(const ObjectPtr& theObject) const;
-
-  //! Returns parent index of the given object
-  virtual QModelIndex findParent(const ObjectPtr& theObject) const;
-
-  //! Returns index corresponded to the group
-  virtual QModelIndex findGroup(const std::string& theGroup) const;
-
- private:
-  //! Types of QModelIndexes
-  enum DataIds
-  {
-    ParamsFolder,
-    ParamObject,
-    ConstructFolder,
-    ConstructObject
-    //GroupsFolder,
-    //GroupObject
-  };
-
-};
-
-/**\class XGUI_PartDataModel
- * \ingroup GUI
- * \brief This is a data model for Object Browser (QTreeView).
- * It represents data tree only of a one part
- */
-class XGUI_PartDataModel : public XGUI_PartModel
-{
-Q_OBJECT
- public:
-   /// Constructor
-   /// \param theParent a parent object
-  XGUI_PartDataModel(QObject* theParent);
-  virtual ~XGUI_PartDataModel();
-
-  // Reimpl from QAbstractItemModel
-
-  /// Returns the data stored under the given role for the item referred to by the index.
-  /// \param theIndex a model index
-  /// \param theRole a data role (see Qt::ItemDataRole)
-  virtual QVariant data(const QModelIndex& theIndex, int theRole) const;
-
-  /// Returns the data for the given role and section in the header with the specified orientation.
-  /// \param theSection a section
-  /// \param theOrient an orientation
-  /// \param theRole a data role (see Qt::ItemDataRole)
-  virtual QVariant headerData(int theSection, Qt::Orientation theOrient,
-                              int theRole = Qt::DisplayRole) const;
-
-  /// Returns the number of rows under the given parent. When the parent is valid it means that 
-  /// rowCount is returning the number of children of parent.
-  /// \param theParent a parent model index
-  virtual int rowCount(const QModelIndex &theParent = QModelIndex()) const;
-
-  /// Returns the number of columns for the children of the given parent.
-  /// It has a one column
-  /// \param theParent a parent model index
-  virtual int columnCount(const QModelIndex &theParent = QModelIndex()) const;
-
-  /// Returns the index of the item in the model specified by the given row, column and parent index.
-  /// \param theRow a row
-  /// \param theColumn a column
-  /// \param theParent a parent model index
-  virtual QModelIndex index(int theRow, int theColumn, const QModelIndex& theParent =
-                                QModelIndex()) const;
-
-  /// Returns the parent of the model item with the given index. 
-  /// If the item has no parent, an invalid QModelIndex is returned.
-  /// \param theIndex a model index
-  virtual QModelIndex parent(const QModelIndex& theIndex) const;
-
-  /// Returns true if parent has any children; otherwise returns false.
-  /// \param theParent a parent model index
-  virtual bool hasChildren(const QModelIndex& theParent = QModelIndex()) const;
-
-  //! Returns object by the given Model index.
-  //! Returns 0 if the given index is not index of a object
-  virtual ObjectPtr object(const QModelIndex& theIndex) const;
-
-  //! Returns QModelIndex which corresponds to the given object
-  //! If the object is not found then index is not valid
-  virtual QModelIndex objectIndex(const ObjectPtr& theObject) const;
-
-  //! Returns true if the given document is a sub-document of this tree
-  virtual bool hasDocument(const DocumentPtr& theDoc) const;
-
-  //! Returns parent index of the given object
-  virtual QModelIndex findParent(const ObjectPtr& theObject) const;
-
-  //! Returns index corresponded to the group
-  virtual QModelIndex findGroup(const std::string& theGroup) const;
-
-  //! Return a Part object
-  virtual ResultPartPtr part() const;
-
- private:
-
-  //! Returns document of the current part
-  DocumentPtr partDocument() const;
-
-  //! Returns defult number of rows
-  int getRowsNumber() const;
-
-  //! Types of QModelIndexes
-  enum DataIds
-  {
-    MyRoot,
-    ParamsFolder,
-    ParamObject,
-    ConstructFolder,
-    ConstructObject,
-    BodiesFolder,
-    BodiesObject,
-    GroupsFolder,
-    GroupObject,
-    HistoryObject
-  };
-
-};
-
-#endif
index cc9ba8aeb45453793c1b5cf1f08d4e9c64cedfa1..bc0934af53f26d7cc31e7aeecf190622bff259da 100644 (file)
@@ -62,7 +62,7 @@ Q_OBJECT
   virtual const QList<ModuleBase_ModelWidget*>& modelWidgets() const;
 
   /// Removes all widgets in the widget area of the property panel
-  void cleanContent();
+  virtual void cleanContent();
 
   /// Returns currently active widget
   virtual ModuleBase_ModelWidget* activeWidget() const { return myActiveWidget; }
index 84d03259006a4f449ebae4ce90457ab97101ddd2..517f248668f0d0404773a0af6a2de7d610c0157a 100644 (file)
@@ -87,8 +87,10 @@ void XGUI_SelectionMgr::updateSelectedOwners(bool isUpdateViewer)
 void XGUI_SelectionMgr::onObjectBrowserSelection()
 {
   QObjectPtrList aObjects = myWorkshop->objectBrowser()->selectedObjects();
+  QList<ModuleBase_ViewerPrs> aSelectedPrs = ModuleBase_ISelection::getViewerPrs(aObjects);
+
   XGUI_Displayer* aDisplayer = myWorkshop->displayer();
-  aDisplayer->setSelected(aObjects);
+  aDisplayer->setSelected(aSelectedPrs);
   emit selectionChanged();
 }
 
@@ -117,9 +119,10 @@ void XGUI_SelectionMgr::clearSelection()
   bool aBlocked = myWorkshop->objectBrowser()->blockSignals(true);
   myWorkshop->objectBrowser()->setObjectsSelected(aFeatures);
   myWorkshop->objectBrowser()->blockSignals(aBlocked);
+  QList<ModuleBase_ViewerPrs> aSelectedPrs = ModuleBase_ISelection::getViewerPrs(aFeatures);
 
   XGUI_Displayer* aDisplayer = myWorkshop->displayer();
-  aDisplayer->setSelected(aFeatures);
+  aDisplayer->setSelected(aSelectedPrs);
 
   emit selectionChanged();
 }
index 4ffac6dc7ba28294cd40733b3bcc26344f92004d..42ddf7318fdcc02e4f6521763f192386bd5dc4b9 100644 (file)
@@ -75,23 +75,5 @@ std::string featureInfo(FeaturePtr theFeature)
  }*/
 
 
-void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFeature, bool& hasParameter)
-{
-  hasResult = false;
-  hasFeature = false;
-  hasParameter = false;
-  foreach(ObjectPtr aObj, theObjects) {
-    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
-    ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
-    ResultParameterPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aResult);
-
-    hasResult = (aResult.get() != NULL);
-    hasFeature = (aFeature.get() != NULL);
-    hasParameter = (aConstruction.get() != NULL);
-    if (hasFeature && hasResult  && hasParameter)
-      break;
-  }
-}
-
 
 }
index e541ba2f0418e8fcef741ece0fd46eb62e0433f8..1a5c7b05f2b2103dc91e33dcc25025ef9a47742f 100644 (file)
@@ -8,7 +8,6 @@
 #include <QRect>
 
 #include <ModelAPI_Feature.h>
-#include <ModuleBase_Definitions.h>
 
 #include <memory>
 
@@ -66,15 +65,6 @@ bool XGUI_EXPORT isModelObject(FeaturePtr theFeature);
 std::string XGUI_EXPORT featureInfo(FeaturePtr theFeature);
 
 
-/*!
-Check types of objects which are in the given list
-\param theObjects the list of objects
-\param hasResult will be set to true if list contains Result objects
-\param hasFeature will be set to true if list contains Feature objects
-\param hasParameter will be set to true if list contains Parameter objects
-*/
-void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFeature, bool& hasParameter);
-
 };
 
 #endif
index c32ceab8a045bdd84474e6a1ee69623944c680eb..cf300615a91fcd56eec14c96019b28c163a98cdd 100644 (file)
@@ -105,10 +105,11 @@ void XGUI_ViewerProxy::connectToViewer()
       this, SIGNAL(keyRelease(ModuleBase_IViewWindow*, QKeyEvent*)));
 
     connect(aViewer, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged()));
+    
+    connect(aViewer, SIGNAL(viewTransformed(int)), this, SIGNAL(viewTransformed(int)));
+
     connect(aViewer, SIGNAL(contextMenuRequested(QContextMenuEvent*)), this,
             SIGNAL(contextMenuRequested(QContextMenuEvent*)));
-
-    // TODO: Connect to ViewTransformation signal
   } else {
     AppElements_Viewer* aViewer = myWorkshop->mainWindow()->viewer();
 
@@ -300,7 +301,9 @@ bool XGUI_ViewerProxy::canDragByMouse() const
   }
 }
 
+//***************************************
 void XGUI_ViewerProxy::onViewTransformed(AppElements_ViewWindow::OperationType theType)
 {
   emit viewTransformed((int) theType);
-}
\ No newline at end of file
+}
+
index 71f296c1a83e647b216296b78376dbcbfb0cd224..8774bbf917c3de5619be7cabed1909d1e41eaab7 100644 (file)
@@ -11,6 +11,7 @@
 #include "XGUI_SalomeConnector.h"
 #include "XGUI_ActionsMgr.h"
 #include "XGUI_ErrorDialog.h"
+#include "XGUI_ColorDialog.h"
 #include "XGUI_ViewerProxy.h"
 #include "XGUI_PropertyPanel.h"
 #include "XGUI_ContextMenuMgr.h"
 #include <QMenu>
 #include <QToolButton>
 #include <QAction>
-#include <QDialog>
-#include <QDialogButtonBox>
-#include <QHBoxLayout>
-#include <QtxColorButton.h>
 
 #ifdef _DEBUG
 #include <QDebug>
 //#define DEBUG_FEATURE_CREATED
 //#define DEBUG_FEATURE_REDISPLAY
 
-QMap<QString, QString> XGUI_Workshop::myIcons;
-
-
-QIcon XGUI_Workshop::featureIcon(const FeaturePtr& theFeature)
-{
-  QIcon anIcon;
-
-  std::string aKind = theFeature->getKind();
-  QString aId(aKind.c_str());
-  if (!myIcons.contains(aId))
-    return anIcon;
-
-  QString anIconString = myIcons[aId];
-
-  ModelAPI_ExecState aState = theFeature->data()->execState();
-  switch(aState) {
-    case ModelAPI_StateDone:
-    case ModelAPI_StateNothing: {
-      anIcon = QIcon(anIconString);
-    }
-    break;
-    case ModelAPI_StateMustBeUpdated: {
-      anIcon = ModuleBase_Tools::lighter(anIconString);
-    }
-    break;
-    case ModelAPI_StateExecFailed: {
-      anIcon = ModuleBase_Tools::composite(":pictures/exec_state_failed.png", anIconString);
-    }
-    break;
-    case ModelAPI_StateInvalidArgument: {
-      anIcon = ModuleBase_Tools::composite(":pictures/exec_state_invalid_parameters.png",
-                                           anIconString);
-    }
-    break;
-    default: break;  
-  }
-  return anIcon;  
-}
 
 XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
     : QObject(),
@@ -204,12 +163,8 @@ void XGUI_Workshop::startApplication()
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
   aLoop->registerListener(this, Events_LongOp::eventID());
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_PLUGIN_LOADED));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TOSHOW));
-  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TOHIDE));
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_SELFILTER_LOADED));
 
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED));
@@ -385,34 +340,12 @@ void XGUI_Workshop::processEvent(const std::shared_ptr<Events_Message>& theMessa
     std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
         std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
     onFeatureUpdatedMsg(anUpdateMsg);
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
-    std::shared_ptr<ModelAPI_ObjectDeletedMessage> aDelMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
-    onObjectDeletedMsg(aDelMsg);
   } else if (theMessage->eventID() == Events_LongOp::eventID()) {
     if (Events_LongOp::isPerformed()) {
       QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
     } else {
       QApplication::restoreOverrideCursor();
     }
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TOSHOW)) {
-    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
-    const std::set<ObjectPtr>& aObjList = anUpdateMsg->objects();
-    QObjectPtrList aList;
-    std::set<ObjectPtr>::const_iterator aIt;
-    for (aIt = aObjList.cbegin(); aIt != aObjList.cend(); ++aIt)
-      aList.append(*aIt);
-    showObjects(aList, true);
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TOHIDE)) {
-    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
-        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
-    const std::set<ObjectPtr>& aObjList = anUpdateMsg->objects();
-    QObjectPtrList aList;
-    std::set<ObjectPtr>::const_iterator aIt;
-    for (aIt = aObjList.cbegin(); aIt != aObjList.cend(); ++aIt)
-      aList.append(*aIt);
-    showObjects(aList, false);
   }
   //An operation passed by message. Start it, process and commit.
   else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OPERATION_LAUNCHED)) {
@@ -428,30 +361,7 @@ void XGUI_Workshop::processEvent(const std::shared_ptr<Events_Message>& theMessa
           updateCommandStatus();
       }
     }
-  } else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOCUMENT_CHANGED)) {
-    myActionsMgr->update();
-    // Find and Activate active part
-    if (myPartActivating)
-      return;
-    SessionPtr aMgr = ModelAPI_Session::get();
-    DocumentPtr aActiveDoc = aMgr->activeDocument();
-    DocumentPtr aDoc = aMgr->moduleDocument();
-    if (aActiveDoc == aDoc) {
-      activatePart(ResultPartPtr()); 
-      return;
-    }
-    std::string aGrpName = ModelAPI_ResultPart::group();
-    for (int i = 0; i < aDoc->size(aGrpName); i++) {
-      ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aDoc->object(aGrpName, i));
-      if (aPart->partDoc() == aActiveDoc) {
-        activatePart(aPart); // Activate a part which corresponds to active Doc
-        return;
-      }
-    }
-    // If not found then activate global document
-    activatePart(ResultPartPtr()); 
-
-  }
+  } 
   else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_SELFILTER_LOADED)) {
     std::shared_ptr<Config_SelectionFilterMessage> aMsg = 
       std::dynamic_pointer_cast<Config_SelectionFilterMessage>(theMessage);
@@ -513,8 +423,8 @@ void XGUI_Workshop::onFeatureUpdatedMsg(const std::shared_ptr<ModelAPI_ObjectUpd
     }
   }
   myOperationMgr->onValidateOperation();
-  if (myObjectBrowser)
-    myObjectBrowser->processEvent(theMsg);
+  //if (myObjectBrowser)
+  //  myObjectBrowser->processEvent(theMsg);
 }
 
 //******************************************************
@@ -536,7 +446,8 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptr<ModelAPI_ObjectU
     ObjectPtr aObj = (*aIt);
 
     // Hide the object if it is invalid or concealed one
-    bool aHide = !aObj->data() || !aObj->data()->isValid();
+    bool aHide = !aObj->data() || !aObj->data()->isValid() || 
+      aObj->isDisabled() || (!aObj->isDisplayed());
     if (!aHide) { // check that this is not hidden result
       ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
       aHide = aRes && aRes->isConcealed();
@@ -564,14 +475,14 @@ void XGUI_Workshop::onFeatureRedisplayMsg(const std::shared_ptr<ModelAPI_ObjectU
             myDisplayer->deactivate(aObj);
         }
       } else { // display object if the current operation has it
-        ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
-        if (aOperation && aOperation->hasObject(aObj)) {
+        if (displayObject(aObj)) {
           ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
-          #ifdef DEBUG_FEATURE_REDISPLAY
-            QString anObjInfo = ModuleBase_Tools::objectInfo((aObj));
-            qDebug(QString("  display object = %1").arg(anObjInfo).toStdString().c_str());
-          #endif
-          if (displayObject(aObj)) {
+          if (aOperation && aOperation->hasObject(aObj)) {
+            ModuleBase_Operation* aOperation = myOperationMgr->currentOperation();
+            #ifdef DEBUG_FEATURE_REDISPLAY
+              QString anObjInfo = ModuleBase_Tools::objectInfo((aObj));
+              qDebug(QString("  display object = %1").arg(anObjInfo).toStdString().c_str());
+            #endif
             // Deactivate object of current operation from selection
             if (myDisplayer->isActive(aObj))
               myDisplayer->deactivate(aObj);
@@ -614,8 +525,8 @@ void XGUI_Workshop::onFeatureCreatedMsg(const std::shared_ptr<ModelAPI_ObjectUpd
     isDisplayed = displayObject(*aIt);
     //}
   }
-  if (myObjectBrowser)
-    myObjectBrowser->processEvent(theMsg);
+  //if (myObjectBrowser)
+  //  myObjectBrowser->processEvent(theMsg);
   if (isDisplayed)
     myDisplayer->updateViewer();
   //if (aHasPart) { // TODO: Avoid activate last part on loading of document
@@ -623,14 +534,6 @@ void XGUI_Workshop::onFeatureCreatedMsg(const std::shared_ptr<ModelAPI_ObjectUpd
   //}
 }
 
-//******************************************************
-void XGUI_Workshop::onObjectDeletedMsg(const std::shared_ptr<ModelAPI_ObjectDeletedMessage>& theMsg)
-{
-  if (myObjectBrowser)
-    myObjectBrowser->processEvent(theMsg);
-  //std::set<ObjectPtr> aFeatures = theMsg->objects();
-}
-
 //******************************************************
 void XGUI_Workshop::onOperationStarted(ModuleBase_Operation* theOperation)
 {
@@ -678,11 +581,20 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation)
   //myDisplayer->activateObjects(aModes);
   myModule->operationStopped(theOperation);
 
-  if (myOperationMgr->operationsCount() == 0) {
+  // if the operation is nested, do not deactivate objects
+  //if (myOperationMgr->operationsCount() == 0) {
     // Activate selection mode for all objects
-    QIntList aModes;
-    myDisplayer->activateObjects(aModes);
-  }
+  QIntList aModes;
+  // TODO: check on OCC_6.9.0
+  // the module current active modes should not be deactivated in order to save the objects selected
+  // the deactivate object in the mode of selection leads to the object is deselected in the viewer.
+  // But, in OCC_6.8.0 this deselection does not happened automatically. It is necessary to call
+  // ClearOutdatedSelection, but this method has an error in the realization, which should be fixed in
+  // the OCC_6.9.0 release. Moreother, it is possible that ClearOutdatedSelection will be called inside
+  // Deactivate method of AIS_InteractiveContext. In this case, we need not call it.
+  module()->activeSelectionModes(aModes);
+  myDisplayer->activateObjects(aModes);
+  //}
 }
 
 
@@ -755,8 +667,6 @@ void XGUI_Workshop::addFeature(const std::shared_ptr<Config_FeatureMessage>& the
   }
   ActionInfo aFeatureInfo;
   aFeatureInfo.initFrom(theMessage);
-  // Remember features icons
-  myIcons[QString::fromStdString(theMessage->id())] = aFeatureInfo.iconFile;
 
   QString aWchName = QString::fromStdString(theMessage->workbenchId());
   QStringList aNestedFeatures =
@@ -918,7 +828,6 @@ void XGUI_Workshop::onOpen()
     } else if (anAnswer == QMessageBox::Cancel) {
       return;
     }
-    aSession->closeAll();
     myCurrentDir = "";
   }
 
@@ -934,6 +843,7 @@ void XGUI_Workshop::onOpen()
   }
   QApplication::setOverrideCursor(Qt::WaitCursor);
   myIsLoadingData = true;
+  aSession->closeAll();
   aSession->load(myCurrentDir.toLatin1().constData());
   myObjectBrowser->rebuildDataTree();
   displayAllResults();
@@ -1209,8 +1119,8 @@ QDockWidget* XGUI_Workshop::createObjectBrowser(QWidget* theParent)
   aObjDock->setStyleSheet(
       "::title { position: relative; padding-left: 5px; text-align: left center }");
   myObjectBrowser = new XGUI_ObjectsBrowser(aObjDock);
-  connect(myObjectBrowser, SIGNAL(activePartChanged(ObjectPtr)), this,
-          SLOT(changeCurrentDocument(ObjectPtr)));
+  myObjectBrowser->setDataModel(myModule->dataModel());
+  myModule->customizeObjectBrowser(myObjectBrowser);
   aObjDock->setWidget(myObjectBrowser);
 
   myContextMenuMgr->connectObjectBrowser();
@@ -1293,23 +1203,6 @@ void XGUI_Workshop::onFeatureTriggered()
   }
 }
 
-//******************************************************
-void XGUI_Workshop::changeCurrentDocument(ObjectPtr theObj)
-{
-  SessionPtr aMgr = ModelAPI_Session::get();
-  if (theObj) {
-    ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(theObj);
-    if (aPart) {
-      DocumentPtr aPartDoc = aPart->partDoc();
-      if (aPartDoc) {
-        aMgr->setActiveDocument(aPartDoc);
-        return;
-      }
-    }
-  }
-  aMgr->setActiveDocument(aMgr->moduleDocument());
-}
-
 //******************************************************
 void XGUI_Workshop::salomeViewerSelectionChanged()
 {
@@ -1326,12 +1219,7 @@ ModuleBase_IViewer* XGUI_Workshop::salomeViewer() const
 void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
 {
   QObjectPtrList aObjects = mySelector->selection()->selectedObjects();
-  if ((theId == "ACTIVATE_PART_CMD") && (aObjects.size() > 0)) {
-    ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObjects.first());
-    activatePart(aPart);
-  } else if (theId == "DEACTIVATE_PART_CMD")
-    activatePart(ResultPartPtr());
-  else if (theId == "DELETE_CMD")
+  if (theId == "DELETE_CMD")
     deleteObjects();
   else if (theId == "COLOR_CMD")
     changeColor(aObjects);
@@ -1345,49 +1233,14 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
     setDisplayMode(aObjects, XGUI_Displayer::Shading);
   else if (theId == "WIREFRAME_CMD")
     setDisplayMode(aObjects, XGUI_Displayer::Wireframe);
-  else if (theId == "HIDEALL_CMD")
-    myDisplayer->eraseAll();
-  else if (theId == "EDIT_CMD") {
-    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObjects.first());
-    if (aFeature == NULL) {
-      ResultParameterPtr aParam = 
-        std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aObjects.first());
-      if (aParam.get() != NULL) {
-        aFeature = ModelAPI_Feature::feature(aParam);
-      }
-    }
-    if (aFeature.get() != NULL)
-      myModule->editFeature(aFeature);
+  else if (theId == "HIDEALL_CMD") {
+    QObjectPtrList aList = myDisplayer->displayedObjects();
+    foreach (ObjectPtr aObj, aList)
+      aObj->setDisplayed(false);
+    Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
   }
 }
 
-//**************************************************************
-void XGUI_Workshop::activatePart(ResultPartPtr theFeature)
-{
-  if (!myPartActivating) {
-    myPartActivating = true;
-    if (theFeature)
-      theFeature->activate();
-    changeCurrentDocument(theFeature);
-    myObjectBrowser->activatePart(theFeature);
-    myPartActivating = false;
-  }
-  updateCommandStatus();
-}
-
-//**************************************************************
-//void XGUI_Workshop::activateLastPart()
-//{
-//  SessionPtr aMgr = ModelAPI_Session::get();
-//  DocumentPtr aDoc = aMgr->moduleDocument();
-//  std::string aGrpName = ModelAPI_ResultPart::group();
-//  ObjectPtr aLastPart = aDoc->object(aGrpName, aDoc->size(aGrpName) - 1);
-//  ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aLastPart);
-//  if (aPart) {
-//    activatePart(aPart);
-//  }
-//}
-
 //**************************************************************
 void XGUI_Workshop::deleteObjects()
 {
@@ -1404,7 +1257,7 @@ void XGUI_Workshop::deleteObjects()
   bool hasResult = false;
   bool hasFeature = false;
   bool hasParameter = false;
-  XGUI_Tools::checkObjects(anObjects, hasResult, hasFeature, hasParameter);
+  ModuleBase_Tools::checkObjects(anObjects, hasResult, hasFeature, hasParameter);
   if (!(hasFeature || hasParameter))
     return;
 
@@ -1525,18 +1378,64 @@ bool XGUI_Workshop::canChangeColor() const
   aTypes.insert(ModelAPI_ResultGroup::group());
   aTypes.insert(ModelAPI_ResultConstruction::group());
   aTypes.insert(ModelAPI_ResultBody::group());
+  aTypes.insert(ModelAPI_ResultPart::group());
+
   return hasResults(aObjects, aTypes);
 }
 
+void setColor(ResultPtr theResult, std::vector<int>& theColor)
+{
+  if (!theResult.get())
+    return;
+
+  AttributeIntArrayPtr aColorAttr = theResult->data()->intArray(ModelAPI_Result::COLOR_ID());
+  if (aColorAttr.get() != NULL) {
+    if (!aColorAttr->size()) {
+      aColorAttr->setSize(3);
+    }
+    aColorAttr->setValue(0, theColor[0]);
+    aColorAttr->setValue(1, theColor[1]);
+    aColorAttr->setValue(2, theColor[2]);
+  }
+}
+
 //**************************************************************
 void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects)
 {
+  AttributeIntArrayPtr aColorAttr;
+  // 1. find the current color of the object. This is a color of AIS presentation
+  // The objects are iterated until a first valid color is found 
   std::vector<int> aColor;
   foreach(ObjectPtr anObject, theObjects) {
-
-    AISObjectPtr anAISObj = myDisplayer->getAISObject(anObject);
-    aColor.resize(3);
-    anAISObj->getColor(aColor[0], aColor[1], aColor[2]);
+    if (anObject->groupName() == ModelAPI_ResultPart::group()) {
+      ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(anObject);
+      DocumentPtr aPartDoc = aPart->partDoc();
+      // the document should be checked on null, because in opened document if the part
+      // has not been activated yet, the part document is empty
+      if (!aPartDoc.get()) {
+        emit errorOccurred(QString::fromLatin1("Color can not be changed on a part with an empty document"));
+      }
+      else {
+        if (aPartDoc->size(ModelAPI_ResultBody::group()) > 0) {
+          ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultBody::group(), 0);
+          ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aObject);
+          if (aBody.get()) {
+            std::string aSection, aName, aDefault;
+            aBody->colorConfigInfo(aSection, aName, aDefault);
+            if (!aSection.empty() && !aName.empty()) {
+              aColor = Config_PropManager::color(aSection, aName, aDefault);
+            }
+          }
+        }
+      }
+    }
+    else {
+      AISObjectPtr anAISObj = myDisplayer->getAISObject(anObject);
+      if (anAISObj.get()) {
+        aColor.resize(3);
+        anAISObj->getColor(aColor[0], aColor[1], aColor[2]);
+      }
+    }
     if (!aColor.empty())
       break;
   }
@@ -1544,55 +1443,44 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects)
     return;
 
   // 2. show the dialog to change the value
-  QDialog* aDlg = new QDialog();
-  QVBoxLayout* aLay = new QVBoxLayout(aDlg);
-
-  QtxColorButton* aColorBtn = new QtxColorButton(aDlg);
-  aColorBtn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
-
-  aLay->addWidget(aColorBtn);
-  aColorBtn->setColor(QColor(aColor[0], aColor[1], aColor[2]));
-
-  QDialogButtonBox* aButtons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
-                                                    Qt::Horizontal, aDlg);
-  connect(aButtons, SIGNAL(accepted()), aDlg, SLOT(accept()));
-  connect(aButtons, SIGNAL(rejected()), aDlg, SLOT(reject()));
-  aLay->addWidget(aButtons);
-
+  XGUI_ColorDialog* aDlg = new XGUI_ColorDialog(mainWindow());
+  aDlg->setColor(aColor);
   aDlg->move(QCursor::pos());
   bool isDone = aDlg->exec() == QDialog::Accepted;
   if (!isDone)
     return;
 
-  QColor aColorResult = aColorBtn->color();
-  int aRedResult = aColorResult.red(),
-      aGreenResult = aColorResult.green(),
-      aBlueResult = aColorResult.blue();
-
-  if (aRedResult == aColor[0] && aGreenResult == aColor[1] && aBlueResult == aColor[2])
-    return;
+  bool isRandomColor = aDlg->isRandomColor();
 
   // 3. abort the previous operation and start a new one
   SessionPtr aMgr = ModelAPI_Session::get();
   bool aWasOperation = aMgr->isOperation(); // keep this value
   if (!aWasOperation) {
-    QString aDescription = contextMenuMgr()->action("DELETE_CMD")->text();
+    QString aDescription = contextMenuMgr()->action("COLOR_CMD")->text();
     aMgr->startOperation(aDescription.toStdString());
   }
 
   // 4. set the value to all results
-  AttributeIntArrayPtr aColorAttr;
   foreach(ObjectPtr anObj, theObjects) {
     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObj);
     if (aResult.get() != NULL) {
-      aColorAttr = aResult->data()->intArray(ModelAPI_Result::COLOR_ID());
-      if (aColorAttr.get() != NULL) {
-        if (!aColorAttr->size()) {
-          aColorAttr->setSize(3);
+      if (aResult->groupName() == ModelAPI_ResultPart::group()) {
+        ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aResult);
+        DocumentPtr aPartDoc = aPart->partDoc();
+        // the document should be checked on null, because in opened document if the part
+        // has not been activated yet, the part document is empty
+        if (aPartDoc.get()) {
+          for (int i = 0; i < aPartDoc->size(ModelAPI_ResultBody::group()); i++) {
+            ObjectPtr aObject = aPartDoc->object(ModelAPI_ResultBody::group(), i);
+            ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aObject);
+            std::vector<int> aColorResult = aDlg->getColor();
+            setColor(aBody, aColorResult);
+          }
         }
-        aColorAttr->setValue(0, aRedResult);
-        aColorAttr->setValue(1, aGreenResult);
-        aColorAttr->setValue(2, aBlueResult);
+      }
+      else {
+        std::vector<int> aColorResult = aDlg->getColor();
+        setColor(aResult, aColorResult);
       }
     }
   }
@@ -1604,21 +1492,29 @@ void XGUI_Workshop::changeColor(const QObjectPtrList& theObjects)
 //**************************************************************
 void XGUI_Workshop::showObjects(const QObjectPtrList& theList, bool isVisible)
 {
-  foreach (ObjectPtr aObj, theList)
-  {
+  foreach (ObjectPtr aObj, theList) {
     if (isVisible) {
-      displayObject(aObj);
+      aObj->setDisplayed(true);
+      //displayObject(aObj);
     } else {
-      myDisplayer->erase(aObj, false);
+      aObj->setDisplayed(false);
+      //myDisplayer->erase(aObj, false);
     }
   }
-  myDisplayer->updateViewer();
+  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+  //myDisplayer->updateViewer();
 }
 
 //**************************************************************
 void XGUI_Workshop::showOnlyObjects(const QObjectPtrList& theList)
 {
-  myDisplayer->showOnly(theList);
+  QObjectPtrList aList = myDisplayer->displayedObjects();
+  foreach (ObjectPtr aObj, aList)
+    aObj->setDisplayed(false);
+  foreach (ObjectPtr aObj, theList)
+    aObj->setDisplayed(true);
+  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+
 }
 
 
@@ -1655,8 +1551,10 @@ void XGUI_Workshop::displayDocumentResults(DocumentPtr theDoc)
 //**************************************************************
 void XGUI_Workshop::displayGroupResults(DocumentPtr theDoc, std::string theGroup)
 {
-  for (int i = 0; i < theDoc->size(theGroup); i++)
-    displayObject(theDoc->object(theGroup, i));
+  for (int i = 0; i < theDoc->size(theGroup); i++) 
+    theDoc->object(theGroup, i)->setDisplayed(true);
+    //displayObject(theDoc->object(theGroup, i));
+  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
 }
 
 //**************************************************************
index 37c04437fdc18426d5a0527af068e7ae500853ce..d4fd4a3689e68937bed3d2dd26206f59745892c5 100644 (file)
@@ -156,13 +156,6 @@ Q_OBJECT
   /// \return a desktop instance
   QMainWindow* desktop() const;
 
-  //! Returns icon name according to feature
-  static QIcon featureIcon(const FeaturePtr& theFeature);
-
-  //! Activates or deactivates a part
-  //! If PartPtr is Null pointer then PartSet will be activated
-  void activatePart(std::shared_ptr<ModelAPI_ResultPart> theFeature);
-
   //! Delete features
   void deleteObjects();
 
@@ -293,12 +286,6 @@ signals:
   /// Reaction on command call
   void onFeatureTriggered();
 
-  /// Change active document
-  /// \param theObj a part object. If it is NULL then active document is a main document
-  void changeCurrentDocument(ObjectPtr theObj);
-
-  //void activateLastPart();
-
   /// Close document
   void closeDocument();
 
@@ -333,9 +320,6 @@ signals:
   /// Process feature redisplay message
   void onFeatureRedisplayMsg(const std::shared_ptr<ModelAPI_ObjectUpdatedMessage>& );
 
-  /// Process feature delete message
-  void onObjectDeletedMsg(const std::shared_ptr<ModelAPI_ObjectDeletedMessage>& );
-
   /// Display all results
   void displayAllResults();
 
@@ -435,7 +419,6 @@ private:
   XGUI_ModuleConnector* myModuleConnector;
 
   QString myCurrentDir;
-  static QMap<QString, QString> myIcons;
 
   bool myUpdatePrefs;
 
index 085837a9202a09c47140df20fd6b85a2fdc5cc19..1f53d95360ab50ac557cc9ed0ae0205426241f9a 100644 (file)
      <file>pictures/button_help.png</file>
      <file>pictures/button_ok.png</file>
    
-     <file>pictures/edit.png</file>
-     <file>pictures/exec_state_failed.png</file>
-     <file>pictures/exec_state_invalid_parameters.png</file>
      <file>pictures/assembly.png</file>
-     <file>pictures/activate.png</file>
      <file>pictures/delete.png</file>
      <file>pictures/rename_edit.png</file>
      <file>pictures/eye_pencil.png</file>
@@ -46,5 +42,6 @@
      <file>pictures/shading.png</file>
      <file>pictures/wireframe.png</file>
      <file>pictures/expression.png</file>
+     <file>pictures/arrow.png</file>
  </qresource>
  </RCC>
diff --git a/src/XGUI/pictures/activate.png b/src/XGUI/pictures/activate.png
deleted file mode 100644 (file)
index f829179..0000000
Binary files a/src/XGUI/pictures/activate.png and /dev/null differ
diff --git a/src/XGUI/pictures/arrow.png b/src/XGUI/pictures/arrow.png
new file mode 100644 (file)
index 0000000..47cc73d
Binary files /dev/null and b/src/XGUI/pictures/arrow.png differ
diff --git a/src/XGUI/pictures/edit.png b/src/XGUI/pictures/edit.png
deleted file mode 100644 (file)
index 43a3174..0000000
Binary files a/src/XGUI/pictures/edit.png and /dev/null differ
diff --git a/src/XGUI/pictures/exec_state_failed.png b/src/XGUI/pictures/exec_state_failed.png
deleted file mode 100644 (file)
index 738f303..0000000
Binary files a/src/XGUI/pictures/exec_state_failed.png and /dev/null differ
diff --git a/src/XGUI/pictures/exec_state_invalid_parameters.png b/src/XGUI/pictures/exec_state_invalid_parameters.png
deleted file mode 100644 (file)
index 1346f97..0000000
Binary files a/src/XGUI/pictures/exec_state_invalid_parameters.png and /dev/null differ