]> SALOME platform Git repositories - modules/geom.git/commitdiff
Salome HOME
21854: Add persistent dimensions BR_imps_2013
authorapl <apl@opencascade.com>
Thu, 26 Dec 2013 06:19:13 +0000 (06:19 +0000)
committerapl <apl@opencascade.com>
Thu, 26 Dec 2013 06:19:13 +0000 (06:19 +0000)
- Implementation of dimension dialogs, displaying, persistence.

40 files changed:
resources/CMakeLists.txt
resources/SalomeApp.xml.in
resources/managedimensions.png [new file with mode: 0644]
src/EntityGUI/EntityGUI_3DSketcherDlg.cxx
src/GEOMGUI/CMakeLists.txt
src/GEOMGUI/GEOM_Displayer.cxx
src/GEOMGUI/GEOM_Displayer.h
src/GEOMGUI/GEOM_images.ts
src/GEOMGUI/GEOM_msg_en.ts
src/GEOMGUI/GEOM_msg_fr.ts
src/GEOMGUI/GEOM_msg_ja.ts
src/GEOMGUI/GeometryGUI.cxx
src/GEOMGUI/GeometryGUI_Operations.h
src/GEOMUtils/CMakeLists.txt
src/GEOMUtils/GEOMUtils_DimensionProperty.cxx [new file with mode: 0644]
src/GEOMUtils/GEOMUtils_DimensionProperty.hxx [new file with mode: 0644]
src/MeasureGUI/CMakeLists.txt
src/MeasureGUI/MeasureGUI.cxx
src/MeasureGUI/MeasureGUI_1Sel_Frame_QTD.ui [new file with mode: 0644]
src/MeasureGUI/MeasureGUI_1TreeWidget_4Button_QTD.ui [new file with mode: 0644]
src/MeasureGUI/MeasureGUI_2Sel_Frame_QTD.ui [new file with mode: 0644]
src/MeasureGUI/MeasureGUI_3Sel_Frame_QTD.ui [new file with mode: 0644]
src/MeasureGUI/MeasureGUI_AngleDlg.cxx
src/MeasureGUI/MeasureGUI_CreateDimensionDlg.cxx [new file with mode: 0644]
src/MeasureGUI/MeasureGUI_CreateDimensionDlg.h [new file with mode: 0644]
src/MeasureGUI/MeasureGUI_DimensionCreateTool.cxx [new file with mode: 0644]
src/MeasureGUI/MeasureGUI_DimensionCreateTool.h [new file with mode: 0644]
src/MeasureGUI/MeasureGUI_DimensionFilter.cxx [new file with mode: 0644]
src/MeasureGUI/MeasureGUI_DimensionFilter.h [new file with mode: 0644]
src/MeasureGUI/MeasureGUI_DimensionInteractor.cxx [new file with mode: 0644]
src/MeasureGUI/MeasureGUI_DimensionInteractor.h [new file with mode: 0644]
src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx [new file with mode: 0644]
src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.h [new file with mode: 0644]
src/MeasureGUI/MeasureGUI_Widgets.cxx
src/MeasureGUI/MeasureGUI_Widgets.h
src/OBJECT/CMakeLists.txt
src/OBJECT/GEOM_AISDimension.cxx [new file with mode: 0755]
src/OBJECT/GEOM_AISDimension.hxx [new file with mode: 0755]
src/OBJECT/GEOM_Constants.cxx
src/OBJECT/GEOM_Constants.h

index 7e9c9aa48457df4851fe6eb2fcf10aa4c3e7333a..973310af6bc78e1de7aaa9bb8ef168b8fbe8d5a1 100755 (executable)
@@ -107,6 +107,7 @@ SET( _res_files
   line.png
   line2points.png
   line2faces.png
+  managedimensions.png
   mindist.png
   mirrorPoint.png
   mirrorAxe.png
index af5f33ef5dad888ba099ea0935f554badf90ba96..2fb47511b3119f38e8ddfe8a1a842aa1a4bd6f86 100644 (file)
     <parameter name="iso_number_u"        value="0" />
     <parameter name="iso_number_v"        value="0" />
 
+    <!-- Dimension presentation properties -->
+    <parameter name="dimensions_color"         value="#00ff21" />
+    <parameter name="dimensions_line_width"    value="1" />
+    <parameter name="dimensions_font_height"   value="10" />
+    <parameter name="dimensions_arrow_length"  value="5" />
+    <parameter name="dimensions_show_units"    value="0" />
+    <parameter name="dimensions_length_units"  value="m" />
+    <parameter name="dimensions_angle_units"   value="deg" />
+
     <!-- Scalar bar for field step presentation -->
     <parameter name="scalar_bar_x_position"   value="0.05" />
     <parameter name="scalar_bar_y_position"   value="0.1" />
diff --git a/resources/managedimensions.png b/resources/managedimensions.png
new file mode 100644 (file)
index 0000000..1600ecb
Binary files /dev/null and b/resources/managedimensions.png differ
index 64e1e5e12c2594b49ac9bbc075674acc0bb91339..c486ce48cee5eef71085459ddb5836eca74a83c6 100755 (executable)
@@ -1696,36 +1696,8 @@ Handle(AIS_AngleDimension) EntityGUI_3DSketcherDlg::createAISAngleDimension(doub
   if (Abs(theAngle) < Precision::Angular() ||
       aLength < Precision::Confusion())
     return NULL;
-  
-  // Convert angles to string
-  std::string Angle_str = doubleToString(theAngle);
-  
-  // Construction of the plane
-  gce_MakePln gce_MP2(P0, P1, P2);
-  Handle(Geom_Plane) aPlane = new Geom_Plane(gce_MP2.Value());
-  
-  TopoDS_Vertex V0 = BRepBuilderAPI_MakeVertex(P0);
-  TopoDS_Vertex V1 = BRepBuilderAPI_MakeVertex(P1);
-  TopoDS_Vertex V2 = BRepBuilderAPI_MakeVertex(P2);
-  
-  TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(V0, V1);
-  TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(V0, V2);
-
-  //Handle(AIS_AngleDimension) anIO =
-  //  new AIS_AngleDimension(anEdge1, anEdge2, aPlane, theAngle * M_PI / 180.,
-  //                         TCollection_ExtendedString(Angle_str.c_str()));
-  //  
-  //anIO->SetArrowSize((theAngle * M_PI / 180) * (aLength/20));
-  //
-  //SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
-  //int w = resMgr->integerValue("Geometry", "measures_line_width", 1);
-  //Handle(Prs3d_AngleAspect) asp = new Prs3d_AngleAspect();
-  //asp->LineAspect()->SetWidth(w);
-  //anIO->Attributes()->SetAngleAspect(asp);
-
-  // todo : port
-
-  Handle(AIS_AngleDimension) anIO = new AIS_AngleDimension( anEdge1, anEdge2, aPlane->Pln() );
+
+  Handle(AIS_AngleDimension) anIO = new AIS_AngleDimension( P1, P0, P2 );
 
   anIO->SetCustomValue( theAngle );
 
index ed1bf4cf1d64c6b4b4f8e46d6f2f1c331cf3b6ea..fa56d9185c208957a2219800c52b6766ce94b19f 100755 (executable)
@@ -38,6 +38,7 @@ INCLUDE_DIRECTORIES(
   ${PROJECT_SOURCE_DIR}/src/Material
   ${PROJECT_SOURCE_DIR}/src/GEOMClient
   ${PROJECT_SOURCE_DIR}/src/GEOMImpl
+  ${PROJECT_SOURCE_DIR}/src/GEOMUtils
   ${CMAKE_CURRENT_SOURCE_DIR}
   )
 
@@ -56,6 +57,7 @@ SET(_link_LIBRARIES
   GEOMFiltersSelection
   Material
   GEOMImpl
+  GEOMUtils
   ${KERNEL_SALOMELocalTrace}
   ${KERNEL_SalomeDS}
   ${KERNEL_SalomeDSClient}
index 25ad93b5a499797965365a51d99df7d77e412365..2ba012082664d69f0eb6225262b6b0335e3868c8 100644 (file)
 
 #include <GEOM_Actor.h>
 #include <GEOM_AISShape.hxx>
+#include <GEOM_AISDimension.hxx>
 #include <GEOM_TopWireframeShape.hxx>
 #include <GEOM_AISVector.hxx>
 #include <GEOM_AISTrihedron.hxx>
 #include <GEOM_VTKTrihedron.hxx>
 #include <GEOM_VTKPropertyMaterial.hxx>
 
+#include <GEOMUtils.hxx>
+#include <GEOMUtils_DimensionProperty.hxx>
+
 #include <Material_Model.h>
 
 #include <SUIT_Desktop.h>
 
 // OCCT Includes
 #include <AIS_Drawer.hxx>
+#include <AIS_Dimension.hxx>
+#include <AIS_LengthDimension.hxx>
+#include <AIS_DiameterDimension.hxx>
+#include <AIS_AngleDimension.hxx>
 #include <AIS_ListIteratorOfListOfInteractive.hxx>
+#include <Aspect_PolygonOffsetMode.hxx>
 #include <Aspect_ColorScale.hxx>
 #include <Prs3d_IsoAspect.hxx>
 #include <Prs3d_PointAspect.hxx>
@@ -520,8 +529,7 @@ void GEOM_Displayer::Redisplay( const Handle(SALOME_InteractiveObject)& theIO,
           {
             if ( view->isVisible( theIO ) || ( checkActiveViewer && view == GetActiveView() ) )
             {
-              Erase( theIO, true, false, view );
-              Display( theIO, updateViewer, view );
+              Redisplay( theIO, updateViewer, view );
             }
           }
         }
@@ -530,6 +538,27 @@ void GEOM_Displayer::Redisplay( const Handle(SALOME_InteractiveObject)& theIO,
   }
 }
 
+//=================================================================
+/*!
+ *  GEOM_Displayer::Redisplay
+ *  Redisplay (erase and then display again) interactive object
+ *  in the specified view
+ */
+//=================================================================
+void GEOM_Displayer::Redisplay( const Handle(SALOME_InteractiveObject)& theIO,
+                                const bool theUpdateViewer,
+                                SALOME_View* theViewFrame )
+{
+  SALOME_View* vf = theViewFrame ? theViewFrame : GetActiveView();
+  if ( !vf )
+  {
+    return;
+  }
+
+  Erase( theIO, true, false, theViewFrame );
+  Display( theIO, theUpdateViewer, theViewFrame );
+}
+
 //=================================================================
 /*!
  *  GEOM_Displayer::Display
@@ -930,6 +959,144 @@ void GEOM_Displayer::updateActorProperties( GEOM_Actor* actor, bool create )
   }
 }
 
+//=================================================================
+/*!
+ *  GEOM_Displayer::updateDimensions
+ *  Creates or renews dimension presentation for the IO.
+ */
+//=================================================================
+void GEOM_Displayer::updateDimensions( const Handle(SALOME_InteractiveObject)& theIO,
+                                       SALOME_OCCPrs* thePrs,
+                                       const gp_Ax3& theShapeLCS )
+{
+  SalomeApp_Study* aStudy = getStudy();
+  if ( !aStudy )
+  {
+    return;
+  }
+
+  if ( theIO.IsNull() )
+  {
+    return;
+  }
+
+  SOCC_Prs* anOccPrs = dynamic_cast<SOCC_Prs*>( thePrs );
+
+  AIS_ListOfInteractive aListOfIO;
+
+  anOccPrs->GetObjects( aListOfIO );
+
+  AIS_ListIteratorOfListOfInteractive aIterateIO( aListOfIO );
+
+  // remove outdated presentations of dimensions
+  for ( ; aIterateIO.More(); aIterateIO.Next() )
+  {
+    const Handle(AIS_InteractiveObject)& anIO = aIterateIO.Value();
+    if ( !anIO->IsKind( STANDARD_TYPE( AIS_Dimension ) ) )
+    {
+      continue;
+    }
+
+    aListOfIO.Remove( aIterateIO );
+  }
+
+  // prepare dimension styling
+  SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
+
+  QColor  aQColor       = aResMgr->colorValue  ( "Geometry", "dimensions_color", QColor( 0, 255, 0 ) );
+  int     aLineWidth    = aResMgr->integerValue( "Geometry", "dimensions_line_width", 1 );
+  double  aFontHeight   = aResMgr->doubleValue ( "Geometry", "dimensions_font_height", 10 );
+  double  anArrowLength = aResMgr->doubleValue ( "Geometry", "dimensions_arrow_length", 5 );
+  bool    isUnitsShown  = aResMgr->booleanValue( "Geometry", "dimensions_show_units", false );
+  QString aUnitsLength  = aResMgr->stringValue ( "Geometry", "dimensions_length_units", "m" );
+  QString aUnitsAngle   = aResMgr->stringValue ( "Geometry", "dimensions_angle_units", "deg" );
+
+  // restore dimension presentation from saved attribute or property data
+  AIS_ListOfInteractive aRestoredDimensions;
+
+  QVariant aProperty = aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+                                                  theIO->getEntry(),
+                                                  GEOM::propertyName( GEOM::Dimensions ),
+                                                  QVariant() );
+
+  GEOMUtils_DimensionProperty aRecords;
+
+  if ( aProperty.isValid() && aProperty.canConvert<GEOMUtils_DimensionProperty>() )
+  {
+    aRecords = aProperty.value<GEOMUtils_DimensionProperty>();
+  }
+  else
+  {
+    aRecords.LoadFromAttribute( getStudy(), theIO->getEntry() );
+  }
+  
+  // create up-to-date dimension presentations
+  for ( int aPrsIt = 0; aPrsIt < aRecords.GetNumber(); ++aPrsIt )
+  {
+    if ( !aRecords.IsVisible( aPrsIt ) )
+    {
+      continue;
+    }
+
+    // init dimension by type
+    Handle(AIS_Dimension) aPrs;
+    switch( aRecords.GetType( aPrsIt ) )
+    {
+      case GEOMUtils_DimensionProperty::DimensionType_Length :
+      {
+        Handle(GEOM_AISLength) aLength = new GEOM_AISLength( aPrsIt );
+        aRecords.GetRecord( aPrsIt )->AsLength()->Update( aLength, theShapeLCS );
+        aPrs = aLength;
+        break;
+      }
+
+      case GEOMUtils_DimensionProperty::DimensionType_Diameter :
+      {
+        Handle(GEOM_AISDiameter) aDiam = new GEOM_AISDiameter( aPrsIt );
+        aRecords.GetRecord( aPrsIt )->AsDiameter()->Update( aDiam, theShapeLCS );
+        aPrs = aDiam;
+        break;
+      }
+
+      case GEOMUtils_DimensionProperty::DimensionType_Angle :
+      {
+        Handle(GEOM_AISAngle) anAng = new GEOM_AISAngle( aPrsIt );
+        aRecords.GetRecord( aPrsIt )->AsAngle()->Update( anAng, theShapeLCS );
+        aPrs = anAng;
+        break;
+      }
+    }
+
+    aPrs->SetOwner( theIO );
+
+    Quantity_Color aColor( aQColor.redF(), aQColor.greenF(), aQColor.blueF(), Quantity_TOC_RGB );
+
+    Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect();
+
+    aStyle->SetCommonColor( aColor );
+    aStyle->MakeUnitsDisplayed( (Standard_Boolean) isUnitsShown );
+    aStyle->MakeText3d( Standard_True );
+    aStyle->MakeTextShaded( Standard_True );
+    aStyle->TextAspect()->SetHeight( aFontHeight );
+    aStyle->ArrowAspect()->SetLength( anArrowLength );
+    aStyle->LineAspect()->SetWidth( aLineWidth );
+    aStyle->SetTextHorizontalPosition( aPrs->DimensionAspect()->TextHorizontalPosition() );
+    aStyle->SetTextVerticalPosition( aPrs->DimensionAspect()->TextVerticalPosition() );
+    aPrs->SetDimensionAspect( aStyle );
+    aPrs->SetPolygonOffsets( Aspect_POM_Fill, -1.0, -1.0 );
+
+    aListOfIO.Append( aPrs );
+  }
+
+  // update presentation
+  anOccPrs->Clear();
+
+  for ( aIterateIO.Initialize( aListOfIO ); aIterateIO.More(); aIterateIO.Next() )
+  {
+    anOccPrs->AddObject( aIterateIO.Value() );
+  }
+}
+
 //=================================================================
 /*!
  *  GEOM_Displayer::Erase
@@ -966,6 +1133,28 @@ void GEOM_Displayer::Redisplay( const SALOME_ListIO& theIOList,
     UpdateViewer();
 }
 
+//=================================================================
+/*!
+ *  GEOM_Displayer::Redisplay
+ *  Calls Redisplay() method for each object in the given list
+ */
+//=================================================================
+void GEOM_Displayer::Redisplay( const SALOME_ListIO& theIOList,
+                                const bool theUpdateViewer,
+                                SALOME_View* theViewFrame )
+{
+  SALOME_ListIteratorOfListIO anIter( theIOList );
+  for ( ; anIter.More(); anIter.Next() )
+  {
+    Redisplay( anIter.Value(), false, theViewFrame );
+  }
+
+  if ( theUpdateViewer )
+  {
+    UpdateViewer();
+  }
+}
+
 //=================================================================
 /*!
  *  GEOM_Displayer::Update
@@ -1096,6 +1285,8 @@ void GEOM_Displayer::Update( SALOME_OCCPrs* prs )
         AISShape->SetToUpdate();
       }
     }
+
+    updateDimensions( myIO, occPrs, GEOMUtils::GetPosition( myShape ) );
   }
 }
 
index 6d3f0321697a74a75b87c5ac07a402dbca56633c..4e8df530beb199c3230ba0889191c0081d061dc3 100644 (file)
@@ -66,6 +66,7 @@ class SalomeApp_Study;
 class SalomeApp_Application;
 class SUIT_SelectionFilter;
 class Handle_GEOM_AISShape;
+class gp_Ax3;
 //class SALOME_Selection;
 
 class GEOMGUI_EXPORT GEOM_Displayer : public LightApp_Displayer
@@ -93,6 +94,10 @@ public:
                             const bool updateViewer = true,
                             const bool checkActiveViewer = true );
 
+  void          Redisplay ( const Handle(SALOME_InteractiveObject)& theIO,
+                            const bool theUpdateViewer,
+                            SALOME_View* theViewFrame );
+
   void          Erase     ( const Handle(SALOME_InteractiveObject)& theIO,
                             const bool forced = false,
                             const bool updateViewer = true,
@@ -118,6 +123,10 @@ public:
                             const bool updateViewer = true,
                             const bool checkActiveViewer = true );
 
+  void          Redisplay ( const SALOME_ListIO& theIOList,
+                            const bool theUpdateViewer,
+                            SALOME_View* theViewFrame );
+
   /* build presentation accordint to the current viewer type*/
   SALOME_Prs*   BuildPrs  ( GEOM::GEOM_Object_ptr );
   SALOME_Prs*   BuildPrs  ( const TopoDS_Shape& );
@@ -226,6 +235,7 @@ protected:
   QColor         colorFromResources( const QString&, const QColor& );
   void           updateShapeProperties( const Handle(GEOM_AISShape)&, bool );
   void           updateActorProperties( GEOM_Actor*, bool );
+  void           updateDimensions( const Handle(SALOME_InteractiveObject)&, SALOME_OCCPrs*, const gp_Ax3& );
 
   PropMap getObjectProperties( SalomeApp_Study*, const QString&, SALOME_View* = 0 );
   PropMap getDefaultPropertyMap();
index 1e27166a65a4cac2c9ef95d3502c3c0f47270c8b..467cc55de488a8b12bf93038c412367362d6be3b 100644 (file)
             <source>ICO_MEASURE_ANGLE</source>
             <translation>angle.png</translation>
         </message>
+        <message>
+            <source>ICO_MANAGE_DIMENSIONS</source>
+            <translation>managedimensions.png</translation>
+        </message>
         <message>
             <source>ICO_POINT</source>
             <translation>point2.png</translation>
index a56f0efd878b62eddd25bae60ade1a15f8df9b13..8f02e9aba6541fb140c091df4038eb22e3551f5f 100644 (file)
@@ -3240,6 +3240,38 @@ Please, select face, shell or solid and try again</translation>
         <source>PREF_AUTO_BRING_TO_FRONT</source>
         <translation>Automatic bring to front</translation>
     </message>
+    <message>
+        <source>PREF_DIMENSIONS</source>
+        <translation>Dimensions (Measurements)</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_COLOR</source>
+        <translation>Color</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_LINE_WIDTH</source>
+        <translation>Line width</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_FONT_HEIGHT</source>
+        <translation>Font height</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_ARROW_LENGTH</source>
+        <translation>Length of arrows</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_LENGTH_UNITS</source>
+        <translation>Length measurement units</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_ANGLE_UNITS</source>
+        <translation>Angle measurement units</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_SHOW_UNITS</source>
+        <translation>Show units of measurement</translation>
+    </message>
     <message>
         <source>PREF_ISOS</source>
         <translation>Number of isolines</translation>
@@ -4681,6 +4713,18 @@ Please, select face, shell or solid and try again</translation>
         <source>STB_MEASURE_ANGLE</source>
         <translation>Compute angle between two lines or linear edges</translation>
     </message>
+    <message>
+      <source>TOP_MANAGE_DIMENSIONS</source>
+      <translation>Manage dimensions</translation>
+    </message>
+    <message>
+      <source>MEN_MANAGE_DIMENSIONS</source>
+      <translation>Manage dimensions</translation>
+    </message>
+    <message>
+      <source>STB_MANAGE_DIMENSIONS</source>
+      <translation>Manage measurement dimensions of an object</translation>
+    </message>
     <message>
         <source>TOP_POP_AUTO_COLOR</source>
         <translation>Auto color</translation>
@@ -6073,6 +6117,154 @@ Number of sketch points too small</translation>
         <translation>Z</translation>
     </message>
 </context>
+<context>
+    <name>MeasureGUI_ManageDimensionsDlg</name>
+    <message>
+        <source>MANAGE_DIMENSIONS_TITLE</source>
+        <translation>Manage dimensions</translation>
+    </message>
+    <message>
+        <source>OBJECT_LABEL</source>
+        <translation>Object</translation>
+    </message>
+    <message>
+        <source>DIMENSIONS_GROUP</source>
+        <translation>Dimensions</translation>
+    </message>
+    <message>
+        <source>ADD_BTN</source>
+        <translation>Add</translation>
+    </message>
+    <message>
+        <source>REMOVE_BTN</source>
+        <translation>Remove</translation>
+    </message>
+    <message>
+        <source>SHOW_ALL_BTN</source>
+        <translation>Show all</translation>
+    </message>
+    <message>
+      <source>HIDE_ALL_BTN</source>
+      <translation>Hide all</translation>
+    </message>
+    <message>
+      <source>DISTANCE_ITEM</source>
+      <translation>Distance</translation>
+    </message>
+    <message>
+      <source>DIAMETER_ITEM</source>
+      <translation>Diameter</translation>
+    </message>
+    <message>
+      <source>ANGLE_ITEM</source>
+      <translation>Angle</translation>
+    </message>
+    <message>
+      <source>WRN_TITLE_UNSAVED</source>
+      <translation>Unsaved changes</translation>
+    </message>
+    <message>
+      <source>WRN_MSG_UNSAVED</source>
+      <translation>The unsaved changes will be lost.
+Do you want to continue?</translation>
+    </message>
+</context>
+<context>
+    <name>MeasureGUI_CreateDimensionDlg</name>
+    <message>
+        <source>CREATE_DIMENSION_TITLE</source>
+        <translation>Add dimension</translation>
+    </message>
+    <message>
+        <source>DIMENSIONS</source>
+        <translation>Dimensions</translation>
+    </message>
+    <message>
+        <source>LENGTH</source>
+        <translation>Length</translation>
+    </message>
+    <message>
+        <source>DIAMETER</source>
+        <translation>Diameter</translation>
+    </message>
+    <message>
+        <source>ANGLE</source>
+        <translation>Angle</translation>
+    </message>
+    <message>
+        <source>ARGUMENTS</source>
+        <translation>Arguments</translation>
+    </message>
+    <message>
+        <source>EDGE_LENGTH</source>
+        <translation>Edge length</translation>
+    </message>
+    <message>
+        <source>TWO_POINTS</source>
+        <translation>Two points</translation>
+    </message>
+    <message>
+        <source>PARALLEL_EDGES</source>
+        <translation>Parallel edges</translation>
+    </message>
+    <message>
+        <source>TWO_EDGES</source>
+        <translation>Two edges</translation>
+    </message>
+    <message>
+        <source>THREE_POINTS</source>
+        <translation>Three points</translation>
+    </message>
+    <message>
+        <source>EDGE</source>
+        <translation>Edge</translation>
+    </message>
+    <message>
+        <source>EDGE_1</source>
+        <translation>Edge 1</translation>
+    </message>
+    <message>
+        <source>EDGE_2</source>
+        <translation>Edge 2</translation>
+    </message>
+    <message>
+        <source>POINT_1</source>
+        <translation>Point 1</translation>
+    </message>
+    <message>
+        <source>POINT_2</source>
+        <translation>Point 2</translation>
+    </message>
+    <message>
+        <source>POINT_3</source>
+        <translation>Point 3</translation>
+    </message>
+    <message>
+        <source>OBJECT</source>
+        <translation>Object</translation>
+    </message>
+    <message>
+        <source>NAME_LENGTH</source>
+        <translation>Length</translation>
+    </message>
+    <message>
+        <source>NAME_DIAMETER</source>
+        <translation>Diameter</translation>
+    </message>
+    <message>
+        <source>NAME_ANGLE</source>
+        <translation>Angle</translation>
+    </message>
+    <message>
+        <source>WARNING_TITLE_CANNOT_CREATE_DIMENSION</source>
+        <translation>Can not create dimension</translation>
+    </message>
+    <message>
+        <source>WARNING_MSG_INVALID_ARGUMENTS</source>
+        <translation>The dimension can not be created for the specified arguments.
+Please specify suitable arguments.</translation>
+    </message>
+</context>
 <context>
     <name>OperationGUI_ChamferDlg</name>
     <message>
index 371635ac41fed253595fde7220a2487a4937a794..b0515a893b3443c5fc82e1bcb0d4bc43cc603645 100644 (file)
@@ -3242,6 +3242,38 @@ Choisissez une face, une coque ou un solide et essayez de nouveau</translation>
         <source>PREF_AUTO_BRING_TO_FRONT</source>
         <translation>Afficher au premier plan automatiquement</translation>
     </message>
+    <message>
+        <source>PREF_DIMENSIONS</source>
+        <translation type="unfinished">Dimensions (Measurements)</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_COLOR</source>
+        <translation type="unfinished">Color</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_LINE_WIDTH</source>
+        <translation type="unfinished">Line width</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_FONT_HEIGHT</source>
+        <translation type="unfinished">Font height</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_ARROW_LENGTH</source>
+        <translation type="unfinished">Length of arrows</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_LENGTH_UNITS</source>
+        <translation type="unfinished">Length measurement units</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_ANGLE_UNITS</source>
+        <translation type="unfinished">Angle measurement units</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_SHOW_UNITS</source>
+        <translation type="unfinished">Show units of measurement</translation>
+    </message>
     <message>
         <source>PREF_ISOS</source>
         <translation>Nombre d&apos;isolignes</translation>
@@ -4658,6 +4690,18 @@ Choisissez une face, une coque ou un solide et essayez de nouveau</translation>
         <source>STB_MEASURE_ANGLE</source>
         <translation>Calculer l&apos;angle entre deux lignes ou arêtes linéaires</translation>
     </message>
+    <message>
+      <source>TOP_MANAGE_DIMENSIONS</source>
+      <translation type="unfinished">Manage dimensions</translation>
+    </message>
+    <message>
+      <source>MEN_MANAGE_DIMENSIONS</source>
+      <translation type="unfinished">Manage dimensions</translation>
+    </message>
+    <message>
+      <source>STB_MANAGE_DIMENSIONS</source>
+      <translation type="unfinished">Manage measurement dimensions of an object</translation>
+    </message>
     <message>
         <source>TOP_POP_AUTO_COLOR</source>
         <translation>Couleur automatique</translation>
@@ -6050,6 +6094,154 @@ Le nombre de points n&apos;est pas suffisant</translation>
         <translation>Z</translation>
     </message>
 </context>
+<context>
+    <name>MeasureGUI_ManageDimensionsDlg</name>
+    <message>
+        <source>MANAGE_DIMENSIONS_TITLE</source>
+        <translation type="unfinished">Manage dimensions</translation>
+    </message>
+    <message>
+        <source>OBJECT_LABEL</source>
+        <translation type="unfinished">Object</translation>
+    </message>
+    <message>
+        <source>DIMENSIONS_GROUP</source>
+        <translation type="unfinished">Dimensions</translation>
+    </message>
+    <message>
+        <source>ADD_BTN</source>
+        <translation type="unfinished">Add</translation>
+    </message>
+    <message>
+        <source>REMOVE_BTN</source>
+        <translation type="unfinished">Remove</translation>
+    </message>
+    <message>
+        <source>SHOW_ALL_BTN</source>
+        <translation type="unfinished">Show all</translation>
+    </message>
+    <message>
+      <source>HIDE_ALL_BTN</source>
+      <translation type="unfinished">Hide all</translation>
+    </message>
+    <message>
+      <source>DISTANCE_ITEM</source>
+      <translation type="unfinished">Distance</translation>
+    </message>
+    <message>
+      <source>DIAMETER_ITEM</source>
+      <translation type="unfinished">Diameter</translation>
+    </message>
+    <message>
+      <source>ANGLE_ITEM</source>
+      <translation type="unfinished">Angle</translation>
+    </message>
+    <message>
+      <source>WRN_TITLE_UNSAVED</source>
+      <translation type="unfinished">Unsaved changes</translation>
+    </message>
+    <message>
+      <source>WRN_MSG_UNSAVED</source>
+      <translation type="unfinished">The unsaved changes will be lost.
+Do you want to continue?</translation>
+    </message>
+</context>
+<context>
+    <name>MeasureGUI_CreateDimensionDlg</name>
+    <message>
+        <source>CREATE_DIMENSION_TITLE</source>
+        <translation type="unfinished">Add dimension</translation>
+    </message>
+    <message>
+        <source>DIMENSIONS</source>
+        <translation type="unfinished">Dimensions</translation>
+    </message>
+    <message>
+        <source>LENGTH</source>
+        <translation type="unfinished">Length</translation>
+    </message>
+    <message>
+        <source>DIAMETER</source>
+        <translation type="unfinished">Diameter</translation>
+    </message>
+    <message>
+        <source>ANGLE</source>
+        <translation type="unfinished">Angle</translation>
+    </message>
+    <message>
+        <source>ARGUMENTS</source>
+        <translation type="unfinished">Arguments</translation>
+    </message>
+    <message>
+        <source>EDGE_LENGTH</source>
+        <translation type="unfinished">Edge length</translation>
+    </message>
+    <message>
+        <source>TWO_POINTS</source>
+        <translation type="unfinished">Two points</translation>
+    </message>
+    <message>
+        <source>PARALLEL_EDGES</source>
+        <translation type="unfinished">Parallel edges</translation>
+    </message>
+    <message>
+        <source>TWO_EDGES</source>
+        <translation type="unfinished">Two edges</translation>
+    </message>
+    <message>
+        <source>THREE_POINTS</source>
+        <translation type="unfinished">Three points</translation>
+    </message>
+    <message>
+        <source>EDGE</source>
+        <translation type="unfinished">Edge</translation>
+    </message>
+    <message>
+        <source>EDGE_1</source>
+        <translation type="unfinished">Edge 1</translation>
+    </message>
+    <message>
+        <source>EDGE_2</source>
+        <translation type="unfinished">Edge 2</translation>
+    </message>
+    <message>
+        <source>POINT_1</source>
+        <translation type="unfinished">Point 1</translation>
+    </message>
+    <message>
+        <source>POINT_2</source>
+        <translation type="unfinished">Point 2</translation>
+    </message>
+    <message>
+        <source>POINT_3</source>
+        <translation type="unfinished">Point 3</translation>
+    </message>
+    <message>
+        <source>OBJECT</source>
+        <translation type="unfinished">Object</translation>
+    </message>
+    <message>
+        <source>NAME_LENGTH</source>
+        <translation type="unfinished">Length</translation>
+    </message>
+    <message>
+        <source>NAME_DIAMETER</source>
+        <translation type="unfinished">Diameter</translation>
+    </message>
+    <message>
+        <source>NAME_ANGLE</source>
+        <translation type="unfinished">Angle</translation>
+    </message>
+    <message>
+        <source>WARNING_TITLE_CANNOT_CREATE_DIMENSION</source>
+        <translation type="unfinished">Can not create dimension</translation>
+    </message>
+    <message>
+        <source>WARNING_MSG_INVALID_ARGUMENTS</source>
+        <translation type="unfinished">The dimension can not be created for the specified arguments.
+Please specify suitable arguments.</translation>
+    </message>
+</context>
 <context>
     <name>OperationGUI_ChamferDlg</name>
     <message>
index 77b266efce34a1c0f580a3b831b5286b436ae82e..313d43c1d06e0c5829e37a31dc13cd049ed05bc7 100644 (file)
       <source>PREF_AUTO_BRING_TO_FRONT</source>
       <translation>PREF_AUTO_BRING_TO_FRONT</translation>
     </message>
+    <message>
+        <source>PREF_DIMENSIONS</source>
+        <translation type="unfinished">Dimensions (Measurements)</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_COLOR</source>
+        <translation type="unfinished">Color</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_LINE_WIDTH</source>
+        <translation type="unfinished">Line width</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_FONT_HEIGHT</source>
+        <translation type="unfinished">Font height</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_ARROW_LENGTH</source>
+        <translation type="unfinished">Length of arrows</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_LENGTH_UNITS</source>
+        <translation type="unfinished">Length measurement units</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_ANGLE_UNITS</source>
+        <translation type="unfinished">Angle measurement units</translation>
+    </message>
+    <message>
+        <source>PREF_DIMENSIONS_SHOW_UNITS</source>
+        <translation type="unfinished">Show units of measurement</translation>
+    </message>
     <message>
       <source>PREF_ISOS</source>
       <translation>PREF_ISOS</translation>
       <source>STB_MEASURE_ANGLE</source>
       <translation>2つのラインまたはエッジ間の角度を計算</translation>
     </message>
+    <message>
+      <source>TOP_MANAGE_DIMENSIONS</source>
+      <translation type="unfinished">Manage dimensions</translation>
+    </message>
+    <message>
+      <source>MEN_MANAGE_DIMENSIONS</source>
+      <translation type="unfinished">Manage dimensions</translation>
+    </message>
+    <message>
+      <source>STB_MANAGE_DIMENSIONS</source>
+      <translation type="unfinished">Manage measurement dimensions of an object</translation>
+    </message>
     <message>
       <source>TOP_POP_AUTO_COLOR</source>
       <translation>自動色</translation>
       <translation>Z</translation>
     </message>
   </context>
+  <context>
+    <name>MeasureGUI_ManageDimensionsDlg</name>
+    <message>
+        <source>MANAGE_DIMENSIONS_TITLE</source>
+        <translation type="unfinished">Manage dimensions</translation>
+    </message>
+    <message>
+        <source>OBJECT_LABEL</source>
+        <translation type="unfinished">Object</translation>
+    </message>
+    <message>
+        <source>DIMENSIONS_GROUP</source>
+        <translation type="unfinished">Dimensions</translation>
+    </message>
+    <message>
+        <source>ADD_BTN</source>
+        <translation type="unfinished">Add</translation>
+    </message>
+    <message>
+        <source>REMOVE_BTN</source>
+        <translation type="unfinished">Remove</translation>
+    </message>
+    <message>
+        <source>SHOW_ALL_BTN</source>
+        <translation type="unfinished">Show all</translation>
+    </message>
+    <message>
+      <source>HIDE_ALL_BTN</source>
+      <translation type="unfinished">Hide all</translation>
+    </message>
+    <message>
+      <source>DISTANCE_ITEM</source>
+      <translation type="unfinished">Distance</translation>
+    </message>
+    <message>
+      <source>DIAMETER_ITEM</source>
+      <translation type="unfinished">Diameter</translation>
+    </message>
+    <message>
+      <source>ANGLE_ITEM</source>
+      <translation type="unfinished">Angle</translation>
+    </message>
+    <message>
+      <source>WRN_TITLE_UNSAVED</source>
+      <translation type="unfinished">Unsaved changes</translation>
+    </message>
+    <message>
+      <source>WRN_MSG_UNSAVED</source>
+      <translation type="unfinished">The unsaved changes will be lost.
+Do you want to continue?</translation>
+    </message>
+  </context>
+  <context>
+    <name>MeasureGUI_CreateDimensionDlg</name>
+    <message>
+        <source>CREATE_DIMENSION_TITLE</source>
+        <translation type="unfinished">Add dimension</translation>
+    </message>
+    <message>
+        <source>DIMENSIONS</source>
+        <translation type="unfinished">Dimensions</translation>
+    </message>
+    <message>
+        <source>LENGTH</source>
+        <translation type="unfinished">Length</translation>
+    </message>
+    <message>
+        <source>DIAMETER</source>
+        <translation type="unfinished">Diameter</translation>
+    </message>
+    <message>
+        <source>ANGLE</source>
+        <translation type="unfinished">Angle</translation>
+    </message>
+    <message>
+        <source>ARGUMENTS</source>
+        <translation type="unfinished">Arguments</translation>
+    </message>
+    <message>
+        <source>EDGE_LENGTH</source>
+        <translation type="unfinished">Edge length</translation>
+    </message>
+    <message>
+        <source>TWO_POINTS</source>
+        <translation type="unfinished">Two points</translation>
+    </message>
+    <message>
+        <source>PARALLEL_EDGES</source>
+        <translation type="unfinished">Parallel edges</translation>
+    </message>
+    <message>
+        <source>TWO_EDGES</source>
+        <translation type="unfinished">Two edges</translation>
+    </message>
+    <message>
+        <source>THREE_POINTS</source>
+        <translation type="unfinished">Three points</translation>
+    </message>
+    <message>
+        <source>EDGE</source>
+        <translation type="unfinished">Edge</translation>
+    </message>
+    <message>
+        <source>EDGE_1</source>
+        <translation type="unfinished">Edge 1</translation>
+    </message>
+    <message>
+        <source>EDGE_2</source>
+        <translation type="unfinished">Edge 2</translation>
+    </message>
+    <message>
+        <source>POINT_1</source>
+        <translation type="unfinished">Point 1</translation>
+    </message>
+    <message>
+        <source>POINT_2</source>
+        <translation type="unfinished">Point 2</translation>
+    </message>
+    <message>
+        <source>POINT_3</source>
+        <translation type="unfinished">Point 3</translation>
+    </message>
+    <message>
+        <source>OBJECT</source>
+        <translation type="unfinished">Object</translation>
+    </message>
+    <message>
+        <source>NAME_LENGTH</source>
+        <translation type="unfinished">Length</translation>
+    </message>
+    <message>
+        <source>NAME_DIAMETER</source>
+        <translation type="unfinished">Diameter</translation>
+    </message>
+    <message>
+        <source>NAME_ANGLE</source>
+        <translation type="unfinished">Angle</translation>
+    </message>
+    <message>
+        <source>WARNING_TITLE_CANNOT_CREATE_DIMENSION</source>
+        <translation type="unfinished">Can not create dimension</translation>
+    </message>
+    <message>
+        <source>WARNING_MSG_INVALID_ARGUMENTS</source>
+        <translation type="unfinished">The dimension can not be created for the specified arguments.
+Please specify suitable arguments.</translation>
+    </message>
+  </context>
   <context>
     <name>OperationGUI_ChamferDlg</name>
     <message>
index bdf31b9688c0c77ed4ce5a4b191bb9ad1344c321..5e392c88f0312c9d0161c35f59d3b53249ca180b 100644 (file)
@@ -633,6 +633,7 @@ void GeometryGUI::OnGUIEvent( int id, const QVariant& theParam )
   case GEOMOp::OpGetNonBlocks:       // MENU MEASURE - Get NON BLOCKS
   case GEOMOp::OpPointCoordinates:   // MENU MEASURE - POINT COORDINATES
   case GEOMOp::OpCheckSelfInters:    // MENU MEASURE - CHECK SELF INTERSECTIONS
+  case GEOMOp::OpManageDimensions:   // MENU MEASURE - MANAGE DIMENSIONS
     libName = "MeasureGUI";
     break;
   case GEOMOp::OpGroupCreate:        // MENU GROUP - CREATE
@@ -1003,6 +1004,7 @@ void GeometryGUI::initialize( CAM_Application* app )
   createGeomAction( GEOMOp::OpBoundingBox,      "BND_BOX" );
   createGeomAction( GEOMOp::OpMinDistance,      "MIN_DIST" );
   createGeomAction( GEOMOp::OpAngle,            "MEASURE_ANGLE" );
+  createGeomAction( GEOMOp::OpManageDimensions, "MANAGE_DIMENSIONS" );
 
   createGeomAction( GEOMOp::OpTolerance,        "TOLERANCE" );
   createGeomAction( GEOMOp::OpWhatIs,           "WHAT_IS" );
@@ -1261,9 +1263,10 @@ void GeometryGUI::initialize( CAM_Application* app )
   createMenu( separator(),                measurId, -1 );
 
   int dimId = createMenu( tr( "MEN_DIMENSIONS" ), measurId, -1 );
-  createMenu( GEOMOp::OpBoundingBox, dimId, -1 );
-  createMenu( GEOMOp::OpMinDistance, dimId, -1 );
-  createMenu( GEOMOp::OpAngle,       dimId, -1 );
+  createMenu( GEOMOp::OpBoundingBox,      dimId, -1 );
+  createMenu( GEOMOp::OpMinDistance,      dimId, -1 );
+  createMenu( GEOMOp::OpAngle,            dimId, -1 );
+  createMenu( GEOMOp::OpManageDimensions, dimId, -1 );
 
   createMenu( separator(),               measurId, -1 );
   createMenu( GEOMOp::OpTolerance,       measurId, -1 );
@@ -2352,6 +2355,47 @@ void GeometryGUI::createPreferences()
   addPreference( tr( "PREF_AUTO_BRING_TO_FRONT" ), genGroup,
                  LightApp_Preferences::Bool, "Geometry", "auto_bring_to_front" );
 
+  int aDimGroupId = addPreference( tr( "PREF_DIMENSIONS" ), tabId );
+  setPreferenceProperty( aDimGroupId, "columns", 2 );
+
+  addPreference( tr( "PREF_DIMENSIONS_COLOR" ), aDimGroupId,
+                 LightApp_Preferences::Color, "Geometry", "dimensions_color" );
+
+  int aDimLineWidthId = addPreference( tr( "PREF_DIMENSIONS_LINE_WIDTH" ), aDimGroupId, 
+                                       LightApp_Preferences::IntSpin, "Geometry", "dimensions_line_width" );
+
+  setPreferenceProperty( aDimLineWidthId, "min", 1 );
+  setPreferenceProperty( aDimLineWidthId, "max", 5 );
+
+  addPreference( tr( "PREF_DIMENSIONS_FONT_HEIGHT" ), aDimGroupId,
+                 LightApp_Preferences::DblSpin, "Geometry", "dimensions_font_height" );
+
+  addPreference( tr( "PREF_DIMENSIONS_ARROW_LENGTH" ), aDimGroupId,
+                 LightApp_Preferences::IntSpin, "Geometry", "dimensions_arrow_length" );
+
+  int aLengthUnitsId = addPreference( tr( "PREF_DIMENSIONS_LENGTH_UNITS" ), aDimGroupId,
+                                      LightApp_Preferences::Selector, "Geometry", "dimensions_length_units" );
+
+  int anAngUnitsId = addPreference( tr( "PREF_DIMENSIONS_ANGLE_UNITS" ), aDimGroupId,
+                                   LightApp_Preferences::Selector, "Geometry", "dimensions_angle_units" );
+
+  addPreference( tr( "PREF_DIMENSIONS_SHOW_UNITS" ), aDimGroupId,
+                 LightApp_Preferences::Bool, "Geometry", "dimensions_show_units" );
+
+  QStringList aListOfLengthUnits;
+  aListOfLengthUnits << "m";
+  aListOfLengthUnits << "cm";
+  aListOfLengthUnits << "mm";
+  aListOfLengthUnits << "in.";
+  aListOfLengthUnits << "ft.";
+
+  QStringList aListOfAngUnits;
+  aListOfAngUnits << "rad";
+  aListOfAngUnits << "deg";
+
+  setPreferenceProperty( aLengthUnitsId, "strings", aListOfLengthUnits );
+  setPreferenceProperty( anAngUnitsId,   "strings", aListOfAngUnits );
+
   int isoGroup = addPreference( tr( "PREF_ISOS" ), tabId );
   setPreferenceProperty( isoGroup, "columns", 2 );
   int isoU = addPreference( tr( "PREF_ISOS_U" ), isoGroup,
@@ -2561,6 +2605,46 @@ void GeometryGUI::preferencesChanged( const QString& section, const QString& par
         aDisplayer.UpdateColorScale( anIsRedisplayFieldSteps, true );
       }
     }
+    else if ( param == QString("dimensions_color")        ||
+              param == QString("dimensions_line_width")   ||
+              param == QString("dimensions_font_height")  ||
+              param == QString("dimensions_arrow_length") ||
+              param == QString("dimensions_show_units")   ||
+              param == QString("dimensions_length_units") ||
+              param == QString("dimensions_angle_units") )
+    {
+      SalomeApp_Application* anApp = getApp();
+      if ( !anApp )
+      {
+        return;
+      }
+
+      SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( anApp->activeStudy() );
+      if ( !aStudy )
+      {
+        return;
+      }
+
+      GEOM_Displayer aDisplayer( aStudy );
+
+      ViewManagerList aVMs;
+      anApp->viewManagers( OCCViewer_Viewer::Type(), aVMs );
+      ViewManagerList::Iterator anIt = aVMs.begin();
+      for ( ; anIt != aVMs.end(); ++anIt )
+      {
+        SOCC_Viewer* aViewer = dynamic_cast<SOCC_Viewer*>( (*anIt)->getViewModel() );
+        if ( !aViewer )
+        {
+          continue;
+        }
+
+        SALOME_ListIO aVisible;
+        aViewer->GetVisible( aVisible );
+        aDisplayer.Redisplay( aVisible, false, aViewer );
+      }
+
+      aDisplayer.UpdateViewer();
+    }
   }
 }
 
index 965e9e44509b7bd002ce55428d0178cd41e12da2..d0476898594ed7a3a8e44be286a8e534ec87e483 100644 (file)
@@ -188,6 +188,7 @@ namespace GEOMOp {
     OpPointCoordinates    = 5011,   // MENU MEASURES - POINT COORDINATES
     OpCheckSelfInters     = 5012,   // MENU MEASURES - CHECK SELF INTERSECTIONS
     OpGetNonBlocks        = 5013,   // MENU MEASURES - GET NON BLOCKS
+    OpManageDimensions    = 5014,   // MENU MEASURES - MANAGE DIMENSIONS
     // GroupGUI --------------------//--------------------------------
     OpGroupCreate         = 6000,   // MENU GROUP - CREATE
     OpGroupEdit           = 6001,   // MENU GROUP - EDIT
index 7402b7d5438237382c5f2c3fe0a9f37e9893654e..49b348a47b43b0572346112015daf89ba148d723 100755 (executable)
@@ -30,6 +30,7 @@ INCLUDE_DIRECTORIES(
 # additional preprocessor / compiler flags
 ADD_DEFINITIONS(
   ${CAS_DEFINITIONS}
+  ${OMNIORB_DEFINITIONS}
   )
 
 # libraries to link to
@@ -40,7 +41,10 @@ SET(_link_LIBRARIES
   ${CAS_TKG3d}
   ${CAS_TKV3d}
   ${CAS_TKGeomBase}
+  ${GUI_SalomeApp}
   ${KERNEL_SALOMELocalTrace}
+  ${KERNEL_SalomeDS}
+  ${KERNEL_SalomeDSClient}
   )
 
 # --- headers ---
@@ -48,12 +52,14 @@ SET(_link_LIBRARIES
 SET(GEOMUtils_HEADERS
   GEOMUtils.hxx
   GEOMUtils_Hatcher.hxx
+  GEOMUtils_DimensionProperty.hxx
   )
 # --- sources ---
 
 SET(GEOMUtils_SOURCES
   GEOMUtils.cxx
   GEOMUtils_Hatcher.cxx
+  GEOMUtils_DimensionProperty.cxx
   )
 
 # --- rules ---
diff --git a/src/GEOMUtils/GEOMUtils_DimensionProperty.cxx b/src/GEOMUtils/GEOMUtils_DimensionProperty.cxx
new file mode 100644 (file)
index 0000000..e9089a6
--- /dev/null
@@ -0,0 +1,918 @@
+// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMUTILS : Utilities for Geometry component
+// File   : GEOMUtils_DimensionProperty.cxx
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+//
+
+// GEOMUtils includes
+#include "GEOMUtils_DimensionProperty.hxx"
+
+// OCCT includes
+#include <Standard_ProgramError.hxx>
+#include <gp_Trsf.hxx>
+
+//=================================================================================
+// function : Length::Init
+// purpose  : 
+//=================================================================================
+void GEOMUtils_DimensionProperty::Length::Init( const Handle(AIS_LengthDimension)& theIO, const gp_Ax3& theLCS )
+{
+  gp_Trsf aFromLCS;
+  aFromLCS.SetTransformation( gp_Ax3(), theLCS );
+
+  FirstPoint  = theIO->FirstPoint().Transformed( aFromLCS );
+  SecondPoint = theIO->SecondPoint().Transformed( aFromLCS );
+  Plane       = theIO->GetPlane().Transformed( aFromLCS );
+  Flyout      = theIO->GetFlyout();
+  TextHPos    = theIO->DimensionAspect()->TextHorizontalPosition();
+  TextVPos    = theIO->DimensionAspect()->TextVerticalPosition();
+}
+
+//=================================================================================
+// function : Length::Update
+// purpose  : 
+//=================================================================================
+void GEOMUtils_DimensionProperty::Length::Update( Handle(AIS_LengthDimension)& theIO, const gp_Ax3& theLCS )
+{
+  gp_Trsf aToLCS;
+  aToLCS.SetTransformation( theLCS, gp_Ax3() );
+
+  gp_Pnt aPoint1 = FirstPoint.Transformed( aToLCS );
+  gp_Pnt aPoint2 = SecondPoint.Transformed( aToLCS );
+  gp_Pln aPlane  = Plane.Transformed( aToLCS );
+
+  theIO->SetMeasuredGeometry( aPoint1, aPoint2, aPlane );
+  theIO->SetFlyout( Flyout );
+
+  Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect();
+  aStyle->SetTextHorizontalPosition( TextHPos );
+  aStyle->SetTextVerticalPosition( TextVPos );
+  theIO->SetDimensionAspect( aStyle );
+}
+
+//=================================================================================
+// function : Length::operator == 
+// purpose  : 
+//=================================================================================
+bool GEOMUtils_DimensionProperty::Length::operator == (const Length& theOther) const
+{
+  if ( FirstPoint.X()  != theOther.FirstPoint.X()
+    || FirstPoint.Y()  != theOther.FirstPoint.Y()
+    || FirstPoint.Z()  != theOther.FirstPoint.Z()
+    || SecondPoint.X() != theOther.SecondPoint.X()
+    || SecondPoint.Y() != theOther.SecondPoint.Y()
+    || SecondPoint.Z() != theOther.SecondPoint.Z() )
+  {
+    return false;
+  }
+
+  if ( Plane.Location().X() != theOther.Plane.Location().X()
+    || Plane.Location().Y() != theOther.Plane.Location().Y()
+    || Plane.Location().Z() != theOther.Plane.Location().Z()
+    || Plane.Axis().Direction().X() != theOther.Plane.Axis().Direction().X()
+    || Plane.Axis().Direction().Y() != theOther.Plane.Axis().Direction().Y()
+    || Plane.Axis().Direction().Z() != theOther.Plane.Axis().Direction().Z() )
+  {
+    return false;
+  }
+
+  if ( Flyout   != theOther.Flyout 
+    || TextHPos != theOther.TextHPos 
+    || TextVPos != theOther.TextVPos )
+  {
+    return false;
+  }
+
+  return true;
+}
+
+//=================================================================================
+// function : Diameter::Init
+// purpose  : 
+//=================================================================================
+void GEOMUtils_DimensionProperty::Diameter::Init( const Handle(AIS_DiameterDimension)& theIO, const gp_Ax3& theLCS )
+{
+  gp_Trsf aFromLCS;
+  aFromLCS.SetTransformation( gp_Ax3(), theLCS );
+
+  Circle   = theIO->Circle().Transformed( aFromLCS );
+  Plane    = theIO->GetPlane().Transformed( aFromLCS );
+  Flyout   = theIO->GetFlyout();
+  TextHPos = theIO->DimensionAspect()->TextHorizontalPosition();
+  TextVPos = theIO->DimensionAspect()->TextVerticalPosition();
+}
+
+//=================================================================================
+// function : Diameter::Update
+// purpose  : 
+//=================================================================================
+void GEOMUtils_DimensionProperty::Diameter::Update( Handle(AIS_DiameterDimension)& theIO, const gp_Ax3& theLCS )
+{
+  gp_Trsf aToLCS;
+  aToLCS.SetTransformation( theLCS, gp_Ax3() );
+
+  gp_Circ aCircle = Circle.Transformed( aToLCS );
+  gp_Pln  aPlane  = Plane.Transformed( aToLCS );
+
+  Standard_Boolean isParallel = 
+    aCircle.Axis().Direction().IsParallel( aPlane.Axis().Direction(), Precision::Angular() );
+
+  if ( isParallel )
+  {
+    theIO->UnsetCustomPlane();
+    theIO->SetMeasuredGeometry( aCircle );
+  }
+  else
+  {
+    theIO->SetCustomPlane( aPlane );
+    theIO->SetMeasuredGeometry( aCircle );
+  }
+
+  theIO->SetFlyout( Flyout );
+
+  Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect();
+  aStyle->SetTextHorizontalPosition( TextHPos );
+  aStyle->SetTextVerticalPosition( TextVPos );
+  theIO->SetDimensionAspect( aStyle );
+}
+
+//=================================================================================
+// function : Diameter::operator == 
+// purpose  : 
+//=================================================================================
+bool GEOMUtils_DimensionProperty::Diameter::operator == (const Diameter& theOther) const
+{
+  if ( Circle.Location().X()  != theOther.Circle.Location().X()
+    || Circle.Location().Y()  != theOther.Circle.Location().Y()
+    || Circle.Location().Z()  != theOther.Circle.Location().Z()
+    || Circle.Axis().Direction().X() != theOther.Circle.Axis().Direction().X()
+    || Circle.Axis().Direction().Y() != theOther.Circle.Axis().Direction().Y()
+    || Circle.Axis().Direction().Z() != theOther.Circle.Axis().Direction().Z()
+    || Circle.XAxis().Direction().X() != theOther.Circle.XAxis().Direction().X()
+    || Circle.XAxis().Direction().Y() != theOther.Circle.XAxis().Direction().Y()
+    || Circle.XAxis().Direction().Z() != theOther.Circle.XAxis().Direction().Z() 
+    || Circle.Radius() != theOther.Circle.Radius() )
+  {
+    return false;
+  }
+
+  if ( Plane.Location().X() != theOther.Plane.Location().X()
+    || Plane.Location().Y() != theOther.Plane.Location().Y()
+    || Plane.Location().Z() != theOther.Plane.Location().Z()
+    || Plane.Axis().Direction().X() != theOther.Plane.Axis().Direction().X()
+    || Plane.Axis().Direction().Y() != theOther.Plane.Axis().Direction().Y()
+    || Plane.Axis().Direction().Z() != theOther.Plane.Axis().Direction().Z() )
+  {
+    return false;
+  }
+
+  if ( Flyout   != theOther.Flyout 
+    || TextHPos != theOther.TextHPos 
+    || TextVPos != theOther.TextVPos )
+  {
+    return false;
+  }
+
+  return true;
+}
+
+//=================================================================================
+// function : Angle::Init
+// purpose  : 
+//=================================================================================
+void GEOMUtils_DimensionProperty::Angle::Init( const Handle(AIS_AngleDimension)& theIO, const gp_Ax3& theLCS )
+{
+  gp_Trsf aFromLCS;
+  aFromLCS.SetTransformation( gp_Ax3(), theLCS );
+
+  FirstPoint  = theIO->FirstPoint().Transformed( aFromLCS );
+  SecondPoint = theIO->SecondPoint().Transformed( aFromLCS );
+  CenterPoint = theIO->CenterPoint().Transformed( aFromLCS );
+  Flyout      = theIO->GetFlyout();
+  TextHPos    = theIO->DimensionAspect()->TextHorizontalPosition();
+  TextVPos    = theIO->DimensionAspect()->TextVerticalPosition();
+}
+
+//=================================================================================
+// function : Angle::Update
+// purpose  : 
+//=================================================================================
+void GEOMUtils_DimensionProperty::Angle::Update( Handle(AIS_AngleDimension)& theIO, const gp_Ax3& theLCS )
+{
+  gp_Trsf aToLCS;
+  aToLCS.SetTransformation( theLCS, gp_Ax3() );
+
+  gp_Pnt aPoint1 = FirstPoint.Transformed( aToLCS );
+  gp_Pnt aPoint2 = CenterPoint.Transformed( aToLCS );
+  gp_Pnt aPoint3 = SecondPoint.Transformed( aToLCS );
+
+  theIO->SetMeasuredGeometry( aPoint1, aPoint2, aPoint3 );
+  theIO->SetFlyout( Flyout );
+
+  Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect();
+  aStyle->SetTextHorizontalPosition( TextHPos );
+  aStyle->SetTextVerticalPosition( TextVPos );
+  theIO->SetDimensionAspect( aStyle );
+}
+
+//=================================================================================
+// function : Angle::operator == 
+// purpose  : 
+//=================================================================================
+bool GEOMUtils_DimensionProperty::Angle::operator == (const Angle& theOther) const
+{
+  if ( FirstPoint.X()  != theOther.FirstPoint.X()
+    || FirstPoint.Y()  != theOther.FirstPoint.Y()
+    || FirstPoint.Z()  != theOther.FirstPoint.Z()
+    || SecondPoint.X() != theOther.SecondPoint.X()
+    || SecondPoint.Y() != theOther.SecondPoint.Y()
+    || SecondPoint.Z() != theOther.SecondPoint.Z()
+    || CenterPoint.X() != theOther.CenterPoint.X()
+    || CenterPoint.Y() != theOther.CenterPoint.Y()
+    || CenterPoint.Z() != theOther.CenterPoint.Z() )
+  {
+    return false;
+  }
+
+  if ( Flyout   != theOther.Flyout 
+    || TextHPos != theOther.TextHPos 
+    || TextVPos != theOther.TextVPos )
+  {
+    return false;
+  }
+
+  return true;
+}
+
+//=================================================================================
+// function : Constructor
+// purpose  : 
+//=================================================================================
+GEOMUtils_DimensionProperty::GEOMUtils_DimensionProperty()
+{
+}
+
+//=================================================================================
+// function : Copy constructor
+// purpose  : 
+//=================================================================================
+GEOMUtils_DimensionProperty::GEOMUtils_DimensionProperty( const GEOMUtils_DimensionProperty& theOther )
+{
+  const VectorOfVisibility& aOtherVis   = theOther.myVisibility;
+  const VectorOfNames& aOtherNames      = theOther.myNames;
+  const VectorOfRecords& aOtherRecords  = theOther.myRecords;
+
+  VectorOfVisibility::const_iterator aVisIt = aOtherVis.constBegin();
+  VectorOfNames::const_iterator   aNamesIt  = aOtherNames.constBegin();
+  VectorOfRecords::const_iterator aRecordIt = aOtherRecords.constBegin();
+  for ( ; aRecordIt != aOtherRecords.constEnd(); ++aVisIt, ++aNamesIt, ++aRecordIt )
+  {
+    RecordPtr aNewRecord;
+    const RecordPtr& aRecord = *aRecordIt;
+    switch( aRecord->Type() )
+    {
+      case DimensionType_Length :
+        aNewRecord = RecordPtr( new Length( *aRecord->AsLength() ) );
+        break;
+
+      case DimensionType_Diameter :
+        aNewRecord = RecordPtr( new Diameter( *aRecord->AsDiameter() ) );
+        break;
+
+      case DimensionType_Angle :
+        aNewRecord = RecordPtr( new Angle( *aRecord->AsAngle() ) );
+        break;
+    }
+
+    myVisibility.append( *aVisIt );
+    myNames.append( *aNamesIt );
+    myRecords.append( aNewRecord );
+  }
+}
+
+//=================================================================================
+// function : Destructor
+// purpose  : 
+//=================================================================================
+GEOMUtils_DimensionProperty::~GEOMUtils_DimensionProperty()
+{
+}
+
+//=================================================================================
+// function : operator QVariant()
+// purpose  : 
+//=================================================================================
+GEOMUtils_DimensionProperty::operator QVariant()
+{
+  QVariant aQVariant;
+  aQVariant.setValue( *this );
+  return aQVariant;
+}
+
+//=================================================================================
+// function : operator ==
+// purpose  : 
+//=================================================================================
+bool GEOMUtils_DimensionProperty::operator == (const GEOMUtils_DimensionProperty& theOther) const
+{
+  if ( myVisibility.size() != theOther.myVisibility.size()
+    || myNames.size() != theOther.myNames.size()
+    || myRecords.size() != theOther.myRecords.size() )
+  {
+    return false;
+  }
+
+  for ( int it = 0; it < myRecords.size(); ++it )
+  {
+    if ( myVisibility[it] != theOther.myVisibility[it] )
+    {
+      return false;
+    }
+
+    if ( myNames[it] != theOther.myNames[it] )
+    {
+      return false;
+    }
+
+    const RecordPtr& aRecord = myRecords[it];
+    const RecordPtr& aOtherRecord = theOther.myRecords[it];
+    if ( aRecord->Type() != aOtherRecord->Type() )
+    {
+      return false;
+    }
+
+    switch ( aRecord->Type() )
+    {
+      case DimensionType_Length:
+        if ( (*aRecord->AsLength()) != (*aOtherRecord->AsLength()) )
+        {
+          return false;
+        }
+        break;
+
+      case DimensionType_Diameter:
+        if ( (*aRecord->AsDiameter()) != (*aOtherRecord->AsDiameter()) )
+        {
+          return false;
+        }
+        break;
+
+      case DimensionType_Angle:
+        if ( (*aRecord->AsAngle()) != (*aOtherRecord->AsAngle()) )
+        {
+          return false;
+        }
+        break;
+    }
+  }
+
+  return true;
+}
+
+//=================================================================================
+// function : GetNumber
+// purpose  : 
+//=================================================================================
+int GEOMUtils_DimensionProperty::GetNumber() const
+{
+  return myRecords.size();
+}
+
+//=================================================================================
+// function : AddRecord
+// purpose  : 
+//=================================================================================
+void GEOMUtils_DimensionProperty::AddRecord( const Handle(AIS_Dimension)& theIO, const gp_Ax3& theLCS )
+{
+  RecordPtr aNewRecord;
+
+  int aType = TypeFromIO( theIO );
+
+  switch ( aType )
+  {
+    case DimensionType_Length :
+    {
+      Handle(AIS_LengthDimension) aLength = 
+        Handle(AIS_LengthDimension)::DownCast( theIO );
+
+      aNewRecord = RecordPtr( new Length() );
+      aNewRecord->AsLength()->Init( aLength, theLCS );
+      break;
+    }
+
+    case DimensionType_Diameter :
+    {
+      Handle(AIS_DiameterDimension) aDiam =
+        Handle(AIS_DiameterDimension)::DownCast( theIO );
+
+      aNewRecord = RecordPtr( new Diameter() );
+      aNewRecord->AsDiameter()->Init( aDiam, theLCS );
+      break;
+    }
+
+    case DimensionType_Angle :
+    {
+      Handle(AIS_AngleDimension) anAngle =
+        Handle(AIS_AngleDimension)::DownCast( theIO );
+
+      aNewRecord = RecordPtr( new Angle() );
+      aNewRecord->AsAngle()->Init( anAngle, theLCS );
+    }
+  }
+
+  myVisibility.append( true );
+  myNames.append( QString() );
+  myRecords.append( aNewRecord );
+}
+
+//=================================================================================
+// function : AddRecord
+// purpose  : 
+//=================================================================================
+void GEOMUtils_DimensionProperty::AddRecord( const RecordPtr& theRecord )
+{
+  myVisibility.append( true );
+  myNames.append( QString() );
+  myRecords.append( theRecord );
+}
+
+//=================================================================================
+// function : RemoveRecord
+// purpose  : 
+//=================================================================================
+void GEOMUtils_DimensionProperty::RemoveRecord( const int theIndex )
+{
+  myRecords.remove( theIndex );
+}
+
+//=================================================================================
+// function : Clear
+// purpose  : 
+//=================================================================================
+void GEOMUtils_DimensionProperty::Clear()
+{
+  myRecords.clear();
+}
+
+//=================================================================================
+// function : SetRecord
+// purpose  : 
+//=================================================================================
+void GEOMUtils_DimensionProperty::SetRecord( const int theIndex,
+                                             const Handle(AIS_Dimension)& theIO,
+                                             const gp_Ax3& theLCS )
+{
+  int aType = TypeFromIO( theIO );
+
+  RecordPtr& aChangeRecord = myRecords[theIndex];
+
+  switch ( aType )
+  {
+    case DimensionType_Length :
+    {
+      Handle(AIS_LengthDimension) aLength = 
+        Handle(AIS_LengthDimension)::DownCast( theIO );
+
+      aChangeRecord = RecordPtr( new Length() );
+      aChangeRecord->AsLength()->Init( aLength, theLCS );
+      break;
+    }
+
+    case DimensionType_Diameter :
+    {
+      Handle(AIS_DiameterDimension) aDiam =
+        Handle(AIS_DiameterDimension)::DownCast( theIO );
+
+      aChangeRecord = RecordPtr( new Diameter() );
+      aChangeRecord->AsDiameter()->Init( aDiam, theLCS );
+      break;
+    }
+
+    case DimensionType_Angle :
+    {
+      Handle(AIS_AngleDimension) anAngle =
+        Handle(AIS_AngleDimension)::DownCast( theIO );
+
+      aChangeRecord = RecordPtr( new Angle() );
+      aChangeRecord->AsAngle()->Init( anAngle, theLCS );
+    }
+  }
+}
+
+//=================================================================================
+// function : SetRecord
+// purpose  : 
+//=================================================================================
+void GEOMUtils_DimensionProperty::SetRecord( const int theIndex, const RecordPtr& theRecord )
+{
+  myRecords[theIndex] = theRecord;
+}
+
+//=================================================================================
+// function : GetRecord
+// purpose  : 
+//=================================================================================
+const GEOMUtils_DimensionProperty::RecordPtr& GEOMUtils_DimensionProperty::GetRecord( const int theIndex ) const
+{
+  return myRecords[theIndex];
+}
+
+//=================================================================================
+// function : IsVisible
+// purpose  : 
+//=================================================================================
+bool GEOMUtils_DimensionProperty::IsVisible( const int theIndex ) const
+{
+  return myVisibility[theIndex];
+}
+
+//=================================================================================
+// function : SetVisible
+// purpose  : 
+//=================================================================================
+void GEOMUtils_DimensionProperty::SetVisible( const int theIndex, const bool theIsVisible )
+{
+  myVisibility[theIndex] = theIsVisible;
+}
+
+//=================================================================================
+// function : GetName
+// purpose  : 
+//=================================================================================
+QString GEOMUtils_DimensionProperty::GetName( const int theIndex ) const
+{
+  return myNames[theIndex];
+}
+
+//=================================================================================
+// function : SetName
+// purpose  : 
+//=================================================================================
+void GEOMUtils_DimensionProperty::SetName( const int theIndex, const QString &theName )
+{
+  myNames[theIndex] = theName;
+}
+
+//=================================================================================
+// function : GetType
+// purpose  : 
+//=================================================================================
+int GEOMUtils_DimensionProperty::GetType( const int theIndex ) const
+{
+  return myRecords[theIndex]->Type();
+}
+
+//=================================================================================
+// function : LoadFromAttribute
+// purpose  : 
+//=================================================================================
+void GEOMUtils_DimensionProperty::LoadFromAttribute( SalomeApp_Study* theStudy,
+                                                     const std::string& theEntry )
+{
+  Clear();
+
+  _PTR(SObject) aSObj = theStudy->studyDS()->FindObjectID( theEntry );
+  if ( !aSObj )
+  {
+    return;
+  }
+
+  _PTR(StudyBuilder) aBuilder = theStudy->studyDS()->NewBuilder();
+
+  _PTR(GenericAttribute) aSeekAtt;
+  _PTR(AttributeTableOfReal) aRecordsAtt;
+
+  if ( !aSObj->FindAttribute( aSeekAtt, "AttributeTableOfReal" ) )
+  {
+    return;
+  }
+
+  aRecordsAtt = aSeekAtt;
+
+  for ( int aRecordIt = 1; aRecordIt <= aRecordsAtt->GetNbColumns(); ++aRecordIt )
+  {
+    std::vector<double> aPacked = aRecordsAtt->GetColumn( aRecordIt );
+
+    RecordPtr aRecord;
+
+    QString aName( aRecordsAtt->GetColumnTitle( aRecordIt ).c_str() );
+
+    // unpack records
+    int it = 0;
+
+    // visibility [0]
+    bool isVisible = (bool) aPacked[it++];
+
+    // type [1]
+    int aType = (int) aPacked[it++];
+
+    switch (aType)
+    {
+      case DimensionType_Length :
+      {
+        Length* aLength = new Length;
+
+        // custom plane [2,3,4,5]
+        Standard_Real A = (Standard_Real) aPacked[it++];
+        Standard_Real B = (Standard_Real) aPacked[it++];
+        Standard_Real C = (Standard_Real) aPacked[it++];
+        Standard_Real D = (Standard_Real) aPacked[it++];
+        aLength->Plane = gp_Pln( A, B, C, D );
+
+        // flyout size [6]
+        aLength->Flyout = (Standard_Real) aPacked[it++];
+
+        // text flags [7,8]
+        aLength->TextHPos = (Prs3d_DimensionTextHorizontalPosition)(int)aPacked[it++];
+        aLength->TextVPos = (Prs3d_DimensionTextVerticalPosition)  (int)aPacked[it++];
+
+        // point 1 [9,10,11]
+        Standard_Real aFirstX = aPacked[it++];
+        Standard_Real aFirstY = aPacked[it++];
+        Standard_Real aFirstZ = aPacked[it++];
+        aLength->FirstPoint = gp_Pnt( aFirstX, aFirstY, aFirstZ );
+
+        // point 2 [12,13,14]
+        Standard_Real aSecondX = aPacked[it++];
+        Standard_Real aSecondY = aPacked[it++];
+        Standard_Real aSecondZ = aPacked[it++];
+        aLength->SecondPoint = gp_Pnt( aSecondX, aSecondY, aSecondZ );
+
+        aRecord = RecordPtr( aLength );
+        break;
+      }
+
+      case DimensionType_Diameter :
+      {
+        Diameter* aDiam = new Diameter;
+
+        // custom plane [2,3,4,5]
+        Standard_Real A = (Standard_Real) aPacked[it++];
+        Standard_Real B = (Standard_Real) aPacked[it++];
+        Standard_Real C = (Standard_Real) aPacked[it++];
+        Standard_Real D = (Standard_Real) aPacked[it++];
+        aDiam->Plane = gp_Pln( A, B, C, D );
+
+        // flyout size [6]
+        aDiam->Flyout = (Standard_Real) aPacked[it++];
+
+        // text flags [7,8]
+        aDiam->TextHPos = (Prs3d_DimensionTextHorizontalPosition)(int)aPacked[it++];
+        aDiam->TextVPos = (Prs3d_DimensionTextVerticalPosition)  (int)aPacked[it++];
+
+        // circle location [9,10,11]
+        Standard_Real aLocX = (Standard_Real) aPacked[it++];
+        Standard_Real aLocY = (Standard_Real) aPacked[it++];
+        Standard_Real aLocZ = (Standard_Real) aPacked[it++];
+
+        // circle normal [12,13,14]
+        Standard_Real aNormX = (Standard_Real) aPacked[it++];
+        Standard_Real aNormY = (Standard_Real) aPacked[it++];
+        Standard_Real aNormZ = (Standard_Real) aPacked[it++];
+
+        // x-direction [15,16,17]
+        Standard_Real aXDirX = (Standard_Real) aPacked[it++];
+        Standard_Real aXDirY = (Standard_Real) aPacked[it++];
+        Standard_Real aXDirZ = (Standard_Real) aPacked[it++];
+
+        // radius [18]
+        Standard_Real aRadius = (Standard_Real) aPacked[it++];
+
+        gp_Ax2 anAx( gp_Pnt( aLocX, aLocY, aLocZ ),
+                     gp_Dir( aNormX, aNormY, aNormZ ),
+                     gp_Dir( aXDirX, aXDirY, aXDirZ ) );
+
+        aDiam->Circle = gp_Circ( anAx, aRadius );
+
+        aRecord = RecordPtr( aDiam );
+        break;
+      }
+
+      case DimensionType_Angle :
+      {
+        Angle* anAngle = new Angle;
+
+        // flyout [2]
+        anAngle->Flyout = (Standard_Real) aPacked[it++];
+
+        // text flags [3,4]
+        anAngle->TextHPos = (Prs3d_DimensionTextHorizontalPosition)(int)aPacked[it++];
+        anAngle->TextVPos = (Prs3d_DimensionTextVerticalPosition)  (int)aPacked[it++];
+
+        // point 1 [5,6,7]
+        Standard_Real aFirstX = (Standard_Real) aPacked[it++];
+        Standard_Real aFirstY = (Standard_Real) aPacked[it++];
+        Standard_Real aFirstZ = (Standard_Real) aPacked[it++];
+
+        // point 2 [8,9,10]
+        Standard_Real aSecondX = (Standard_Real) aPacked[it++];
+        Standard_Real aSecondY = (Standard_Real) aPacked[it++];
+        Standard_Real aSecondZ = (Standard_Real) aPacked[it++];
+
+        // center [11,12,13]
+        Standard_Real aCenterX = (Standard_Real) aPacked[it++];
+        Standard_Real aCenterY = (Standard_Real) aPacked[it++];
+        Standard_Real aCenterZ = (Standard_Real) aPacked[it++];
+
+        // points point 1 [4-6], point 2 [7-9], center [10-12]
+        anAngle->FirstPoint  = gp_Pnt( aFirstX, aFirstY, aFirstZ );
+        anAngle->SecondPoint = gp_Pnt( aSecondX, aSecondY, aSecondZ );
+        anAngle->CenterPoint = gp_Pnt( aCenterX, aCenterY, aCenterZ );
+
+        aRecord = RecordPtr( anAngle );
+        break;
+      }
+    }
+
+    myVisibility.append( isVisible );
+    myNames.append( aName );
+    myRecords.append( aRecord );
+  }
+}
+
+//=================================================================================
+// function : SaveToAttribute
+// purpose  : 
+//=================================================================================
+void GEOMUtils_DimensionProperty::SaveToAttribute( SalomeApp_Study *theStudy,
+                                                   const std::string &theEntry )
+{
+  _PTR(SObject) aSObj = theStudy->studyDS()->FindObjectID( theEntry );
+  if ( !aSObj )
+  {
+    return;
+  }
+
+  _PTR(StudyBuilder) aBuilder = theStudy->studyDS()->NewBuilder();
+
+  _PTR(AttributeTableOfReal) aRecordsAtt;
+
+  aRecordsAtt = aBuilder->FindOrCreateAttribute( aSObj, "AttributeTableOfReal" );
+  aRecordsAtt->SetNbColumns( 0 );
+
+  for ( int it = 0; it < myRecords.size(); ++it )
+  {
+    bool aVisibility   = myVisibility[it];
+    QString& aName     = myNames[it];
+    RecordPtr& aRecord = myRecords[it];
+
+    std::vector<double> aPacked;
+
+    // visibility [0]
+    aPacked.push_back( (double) aVisibility );
+
+    // type [1]
+    aPacked.push_back( (double) aRecord->Type() );
+
+    switch ( aRecord->Type() )
+    {
+      case DimensionType_Length:
+      {
+        Length* aProps = aRecord->AsLength();
+
+        // custom plane [2,3,4,5]
+        Standard_Real A, B, C, D;
+        aProps->Plane.Coefficients( A, B, C, D );
+        aPacked.push_back( (double) A );
+        aPacked.push_back( (double) B );
+        aPacked.push_back( (double) C );
+        aPacked.push_back( (double) D );
+
+        // flyout size [6]
+        aPacked.push_back( (double) aProps->Flyout );
+
+        // text flags [7,8]
+        aPacked.push_back( (double) aProps->TextHPos );
+        aPacked.push_back( (double) aProps->TextVPos );
+
+        // point 1 [9,10,11]
+        aPacked.push_back( (double) aProps->FirstPoint.X() );
+        aPacked.push_back( (double) aProps->FirstPoint.Y() );
+        aPacked.push_back( (double) aProps->FirstPoint.Z() );
+
+        // point 2 [12,13,14]
+        aPacked.push_back( (double) aProps->SecondPoint.X() );
+        aPacked.push_back( (double) aProps->SecondPoint.Y() );
+        aPacked.push_back( (double) aProps->SecondPoint.Z() );
+        break;
+      }
+
+      case DimensionType_Diameter:
+      {
+        Diameter* aProps = aRecord->AsDiameter();
+
+        // custom plane [2,3,4,5]
+        Standard_Real A, B, C, D;
+        aProps->Plane.Coefficients( A, B, C, D );
+        aPacked.push_back( (double) A );
+        aPacked.push_back( (double) B );
+        aPacked.push_back( (double) C );
+        aPacked.push_back( (double) D );
+
+        // flyout size [6]
+        aPacked.push_back( (double) aProps->Flyout );
+
+        // text flags [7,8]
+        aPacked.push_back( (double) aProps->TextHPos );
+        aPacked.push_back( (double) aProps->TextVPos );
+
+        // circle location [9,10,11]
+        aPacked.push_back( (double) aProps->Circle.Location().X() );
+        aPacked.push_back( (double) aProps->Circle.Location().Y() );
+        aPacked.push_back( (double) aProps->Circle.Location().Z() );
+
+        // circle normal [12,13,14]
+        aPacked.push_back( (double) aProps->Circle.Axis().Direction().X() );
+        aPacked.push_back( (double) aProps->Circle.Axis().Direction().Y() );
+        aPacked.push_back( (double) aProps->Circle.Axis().Direction().Z() );
+
+        // x-direction [15,16,17]
+        aPacked.push_back( (double) aProps->Circle.XAxis().Direction().X() );
+        aPacked.push_back( (double) aProps->Circle.XAxis().Direction().Y() );
+        aPacked.push_back( (double) aProps->Circle.XAxis().Direction().Z() );
+
+        // radius [18]
+        aPacked.push_back( (double) aProps->Circle.Radius() );
+        break;
+      }
+
+      case DimensionType_Angle:
+      {
+        Angle* aProps = aRecord->AsAngle();
+
+        // flyout [2]
+        aPacked.push_back( (double) aProps->Flyout );
+
+        // text flags [3,4]
+        aPacked.push_back( (double) aProps->TextHPos );
+        aPacked.push_back( (double) aProps->TextVPos );
+
+        // point 1 [5,6,7]
+        aPacked.push_back( (double) aProps->FirstPoint.X() );
+        aPacked.push_back( (double) aProps->FirstPoint.Y() );
+        aPacked.push_back( (double) aProps->FirstPoint.Z() );
+
+        // point 2 [8,9,10]
+        aPacked.push_back( (double) aProps->SecondPoint.X() );
+        aPacked.push_back( (double) aProps->SecondPoint.Y() );
+        aPacked.push_back( (double) aProps->SecondPoint.Z() );
+
+        // center [11,12,13]
+        aPacked.push_back( (double) aProps->CenterPoint.X() );
+        aPacked.push_back( (double) aProps->CenterPoint.Y() );
+        aPacked.push_back( (double) aProps->CenterPoint.Z() );
+        break;
+      }
+    }
+
+    aRecordsAtt->AddColumn( aPacked );
+    aRecordsAtt->SetColumnTitle( it + 1, aName.toStdString() );
+  }
+}
+
+//=================================================================================
+// function : TypeFromIO
+// purpose  : 
+//=================================================================================
+int GEOMUtils_DimensionProperty::TypeFromIO( const Handle(AIS_Dimension)& theIO ) const
+{
+  if ( theIO->IsKind( STANDARD_TYPE( AIS_LengthDimension ) ) )
+  {
+    return DimensionType_Length;
+  }
+
+  if ( theIO->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) )
+  {
+    return DimensionType_Diameter;
+  }
+
+  if ( theIO->IsKind( STANDARD_TYPE( AIS_AngleDimension ) ) )
+  {
+    return DimensionType_Angle;
+  }
+
+  Standard_ProgramError::Raise( "unsupported dimension type" );
+
+  return 0;
+}
diff --git a/src/GEOMUtils/GEOMUtils_DimensionProperty.hxx b/src/GEOMUtils/GEOMUtils_DimensionProperty.hxx
new file mode 100644 (file)
index 0000000..32b7adc
--- /dev/null
@@ -0,0 +1,422 @@
+// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMUTILS : Utilities for Geometry component
+// File   : GEOMUtils_DimensionProperty.hxx
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+//
+
+#ifndef GEOMUTILS_DIMENSIONPROPERTY_HXX
+#define GEOMUTILS_DIMENSIONPROPERTY_HXX
+
+// SUIT includes
+#include <SalomeApp_Study.h>
+
+// OCCT includes
+#include <AIS_DiameterDimension.hxx>
+#include <AIS_LengthDimension.hxx>
+#include <AIS_AngleDimension.hxx>
+#include <gp_Ax3.hxx>
+#include <QVariant>
+#include <QVector>
+#include <QDataStream>
+#include <QSharedPointer>
+
+#include <string>
+#include <vector>
+#include <list>
+
+/*!
+ * \brief Utility class to unpack/pack dimension presentations as object property of study.
+ *
+ * Dimension presentations are store in relative coordinate system (LCS).
+ * To ensure that dimension is bound to the equal shape irrespectively of its location
+ * transformation.
+ *
+ * The record is a list of qvariant, containing packed dimension properties and its attributes:
+ * (name);(is_visible);(dimension type);(dimension property list);
+ * 
+ * The following packing scheme is used to store dimension data:
+ * Length: (plane)[0-3] (flyout)[4] (text flags)[5-6] (p1)[7-9] (pnt2)[10-12]
+ * Diam:   (plane)[0-3] (flyout)[4] (text flags)[5-6] (circle loc, xdir, ydir, rad)[7-16]
+ * Angle:               (flyout)[0] (text flags)[1-2] (p1)[3-5] (p2)[6-8] (center)[9-11]
+ */
+class Standard_EXPORT GEOMUtils_DimensionProperty
+{
+public:
+
+  /*!
+   * \brief Type of packed presentation.
+   */
+  enum DimensionType
+  {
+    DimensionType_Length,
+    DimensionType_Diameter,
+    DimensionType_Angle
+  };
+
+  /*!
+   * \brief Base class for pointer-optimized records storing.
+   */
+  struct Length;
+  struct Diameter;
+  struct Angle;
+  struct Record
+  {
+  public:
+    Record( const DimensionType theType ) 
+      : myType( theType )
+      {}
+
+    DimensionType Type() const
+    {
+      return myType;
+    }
+
+    Length*   AsLength()   { return static_cast<Length*>( this ); }
+    Diameter* AsDiameter() { return static_cast<Diameter*>( this ); }
+    Angle*    AsAngle()    { return static_cast<Angle*>( this ); }
+
+  private:
+    DimensionType myType;
+  };
+
+  /*!
+   * \brief Declaration of properties for length dimensions.
+   */
+  struct Standard_EXPORT Length : public Record
+  {
+    Length() :
+      Record( DimensionType_Length ),
+      FirstPoint( gp::Origin() ),
+      SecondPoint( gp::Origin() ),
+      Plane( gp::XOY() ),
+      Flyout( 0.0 ),
+      TextHPos( Prs3d_DTHP_Fit ),
+      TextVPos( Prs3d_DTVP_Center )
+      {}
+
+    Length( const Length& theOther ) :
+      Record( DimensionType_Length ),
+      FirstPoint( theOther.FirstPoint ),
+      SecondPoint( theOther.SecondPoint ),
+      Plane( theOther.Plane ),
+      Flyout( theOther.Flyout ),
+      TextHPos( theOther.TextHPos ),
+      TextVPos( theOther.TextVPos )
+      {}
+
+    ~Length() {}
+
+    /*!
+     * \brief Inits property fields from the passed length object.
+     * \param theIO [in] the interactive presentation.
+     * \param theLCS [in] the local coordiante system of parent object.
+     */
+    void Init( const Handle(AIS_LengthDimension)& theIO, const gp_Ax3& theLCS );
+
+    /*!
+     * \brief Updates length object properties from the fields.
+     * \param theIO [in/out] the interactive presentation.
+     * \param theLCS [in] the local coordiante system of parent object.
+     */
+    void Update( Handle(AIS_LengthDimension)& theIO, const gp_Ax3& theLCS );
+
+    /*!
+     * \brief Overload comparsion.
+     */
+    bool operator == (const Length &theOther) const;
+    bool operator != (const Length &theOther) const { return !(operator == (theOther)); }
+
+    gp_Pnt FirstPoint;
+    gp_Pnt SecondPoint;
+    gp_Pln Plane;
+    double Flyout;
+    Prs3d_DimensionTextHorizontalPosition TextHPos;
+    Prs3d_DimensionTextVerticalPosition   TextVPos;
+  };
+
+  /*!
+   * \brief Declaration of properties for diameter dimensions.
+   */
+  struct Standard_EXPORT Diameter : public Record
+  {
+    Diameter() :
+      Record( DimensionType_Diameter ),
+      Plane( gp::XOY() ),
+      Flyout( 0.0 ),
+      TextHPos( Prs3d_DTHP_Fit ),
+      TextVPos( Prs3d_DTVP_Center )
+      {}
+
+     Diameter( const Diameter& theOther ) :
+       Record( DimensionType_Diameter ),
+       Circle( theOther.Circle ),
+       Plane( theOther.Plane ),
+       Flyout( theOther.Flyout ),
+       TextHPos( theOther.TextHPos ),
+       TextVPos( theOther.TextVPos )
+       {}
+
+    ~Diameter() {}
+
+    /*!
+     * \brief Inits property fields from the passed length object.
+     * \param theIO [in] the interactive presentation.
+     * \param theLCS [in] the local coordiante system of parent object.
+     */
+    void Init( const Handle(AIS_DiameterDimension)& theIO, const gp_Ax3& theLCS );
+
+    /*!
+     * \brief Updates length object properties from the fields.
+     * \param theIO [in/out] the interactive presentation.
+     * \param theLCS [in] the local coordiante system of parent object.
+     */
+    void Update( Handle(AIS_DiameterDimension)& theIO, const gp_Ax3& theLCS );
+
+    /*!
+     * \brief Overload comparsion.
+     */
+    bool operator == (const Diameter &theOther) const;
+    bool operator != (const Diameter &theOther) const { return !(operator == (theOther)); }
+
+    gp_Circ Circle;
+    gp_Pln  Plane;
+    double Flyout;
+    Prs3d_DimensionTextHorizontalPosition TextHPos;
+    Prs3d_DimensionTextVerticalPosition   TextVPos;
+  };
+
+  /*!
+   * \brief Declaration of properties for angle dimensions.
+   */
+  struct Standard_EXPORT Angle : public Record
+  {
+    Angle() :
+      Record( DimensionType_Angle ),
+      FirstPoint( gp::Origin() ),
+      SecondPoint( gp::Origin() ),
+      CenterPoint( gp::Origin() ),
+      Flyout( 0.0 ),
+      TextHPos( Prs3d_DTHP_Fit ),
+      TextVPos( Prs3d_DTVP_Center )
+      {}
+
+    Angle( const Angle& theOther ) :
+      Record( DimensionType_Angle ),
+      FirstPoint( theOther.FirstPoint ),
+      SecondPoint( theOther.SecondPoint ),
+      CenterPoint( theOther.CenterPoint ),
+      Flyout( theOther.Flyout ),
+      TextHPos( theOther.TextHPos ),
+      TextVPos( theOther.TextVPos )
+      {}
+
+    ~Angle() {}
+
+    /*!
+     * \brief Inits property fields from the passed length object.
+     * \param theIO [in] the interactive presentation.
+     * \param theLCS [in] the local coordiante system of parent object.
+     */
+    void Init( const Handle(AIS_AngleDimension)& theIO, const gp_Ax3& theLCS );
+
+    /*!
+     * \brief Updates length object properties from the fields.
+     * \param theIO [in/out] the interactive presentation.
+     * \param theLCS [in] the local coordiante system of parent object.
+     */
+    void Update( Handle(AIS_AngleDimension)& theIO, const gp_Ax3& theLCS );
+
+    /*!
+     * \brief Overload comparsion.
+     */
+    bool operator == (const Angle &theOther) const;
+    bool operator != (const Angle &theOther) const { return !(operator == (theOther)); }
+
+    gp_Pnt FirstPoint;
+    gp_Pnt SecondPoint;
+    gp_Pnt CenterPoint;
+    double Flyout;
+    Prs3d_DimensionTextHorizontalPosition TextHPos;
+    Prs3d_DimensionTextVerticalPosition   TextVPos;
+  };
+
+  typedef QSharedPointer<Record> RecordPtr;
+
+public:
+
+  /*!
+   * \brief Constructor. Inits empty property.
+   */
+  GEOMUtils_DimensionProperty();
+
+  /*!
+   * \brief Copy constructor.
+   */
+  GEOMUtils_DimensionProperty( const GEOMUtils_DimensionProperty& theOther );
+
+  /*!
+   * \brief Destructor.
+   */
+  ~GEOMUtils_DimensionProperty();
+
+  /*!
+   * \brief Overload QVariant cast operator.
+   */
+  operator QVariant();
+
+  /*!
+   * \brief Overload comparsion.
+   */
+  bool operator == (const GEOMUtils_DimensionProperty &theOther) const;
+
+public:
+
+  /*!
+   * \brief Returns number of dimension records.
+   */
+  int GetNumber() const;
+
+  /*!
+   * \brief Adds new record for the passed interactive object. Convenience method.
+   * \param theIO [in] the interactive dimension to append as new record.
+   * \param theLCS [in] the local coordinate system of parent object.
+   */
+  void AddRecord( const Handle(AIS_Dimension)& theIO, const gp_Ax3& theLCS );
+
+  /*!
+   * \brief Adds new dimension record.
+   * \param theRecord [in] the record to add.
+   */
+  void AddRecord( const RecordPtr& theRecord );
+
+  /*!
+   * \brief Update dimension record data.
+   * \param theIndex [in] the index of the record.
+   * \param theIO [in] the interactive dimension to update properties.
+   * \param theLCS [in] the local coordinate system of parent object.
+   */
+  void SetRecord( const int theIndex,
+                  const Handle(AIS_Dimension)& theIO,
+                  const gp_Ax3& theLCS );
+
+  /*!
+   * \brief Update dimension record data.
+   * \param theIndex [in] the index of the dimension record.
+   * \param theRecord [in] the record to replace with.
+   */
+  void SetRecord( const int theIndex, const RecordPtr& theRecord );
+
+  /*!
+   * \brief Access record by index.
+   * \param theIndex [in] the index of the dimension record.
+   */
+  const RecordPtr& GetRecord( const int theIndex ) const;
+
+  /*!
+   * \brief Removes record by its index.
+   * \param theIndex [in] the index of dimension record.
+   */
+  void RemoveRecord( const int theIndex );
+
+  /*!
+   * \brief Clears property data.
+   */
+  void Clear();
+
+public:
+
+  /*!
+   * \brief Returns visibility state of dimension record by its index.
+   *
+   * \param theIndex [in] the index of the dimension record.
+   */
+  bool IsVisible( const int theIndex ) const;
+
+  /*!
+   * \brief Changes visibility state of the dimension record.
+   *
+   * \param theIndex [in] the index of the dimension record.
+   * \param theIsVisible [in] the new visibility state.
+   */
+  void SetVisible( const int theIndex, const bool theIsVisible );
+
+  /*!
+   * \brief Returns name of dimension record by its index.
+   *
+   * \param theIndex [in] the index of the dimension record.
+   */
+  QString GetName( const int theIndex ) const;
+
+  /*!
+   * \brief Changes name of dimension record.
+   *
+   * \param theIndex [in] the index of the dimension record.
+   * \param theName [in] the new name.
+   */
+  void SetName( const int theIndex, const QString& theName );
+
+  /*!
+   * \brief Returns dimension type.
+   */
+  int GetType( const int theIndex ) const;
+
+public:
+
+  /*!
+   * \brief Loads properties data from attribute "AttributeTableOfReal".
+   * \param theStudy [in] the study.
+   * \param theEntry [in] the entry of GEOM object to operate with.
+   */
+  void LoadFromAttribute( SalomeApp_Study* theStudy, const std::string& theEntry );
+
+  /*!
+   * \brief Saves properties data to attribute "AttributeTableOfReal".
+   * \param theStudy [in] the study.
+   * \param theEntry [in] the entry of GEOM object to operate with.
+   */
+  void SaveToAttribute( SalomeApp_Study* theStudy, const std::string& theEntry );
+
+private:
+
+  /*!
+   * \brief Determines dimension type code.
+   */
+  int TypeFromIO( const Handle(AIS_Dimension)& theIO ) const;
+
+private:
+
+  typedef QVector<bool>      VectorOfVisibility;
+  typedef QVector<QString>   VectorOfNames;
+  typedef QVector<RecordPtr> VectorOfRecords;
+
+private:
+
+  VectorOfVisibility         myVisibility;
+  VectorOfNames              myNames;
+  VectorOfRecords            myRecords;
+};
+
+Q_DECLARE_METATYPE(GEOMUtils_DimensionProperty);
+
+#endif
index 809520ee87aca01a02b5fc1c39651586094f1f5f..2c6a39430b5b5b4d3fd197084a56e0770b5dad1b 100755 (executable)
@@ -41,6 +41,7 @@ INCLUDE_DIRECTORIES(
   ${PROJECT_SOURCE_DIR}/src/DlgRef
   ${PROJECT_BINARY_DIR}/src/DlgRef
   ${PROJECT_SOURCE_DIR}/src/GEOMAlgo
+  ${PROJECT_SOURCE_DIR}/src/GEOMUtils
   ${CMAKE_CURRENT_SOURCE_DIR}
   ${CMAKE_CURRENT_BINARY_DIR}
   )
@@ -55,6 +56,7 @@ ADD_DEFINITIONS(
 # libraries to link to
 SET(_link_LIBRARIES
   GEOMBase
+  GEOMUtils
   )
 
 # --- resources ---
@@ -67,7 +69,11 @@ SET(_uic_files
   MeasureGUI_1Sel1TextView_QTD.ui
   MeasureGUI_1Sel3LineEdit_QTD.ui
   MeasureGUI_1Sel6LineEdit_QTD.ui
+  MeasureGUI_1Sel_Frame_QTD.ui
+  MeasureGUI_1TreeWidget_4Button_QTD.ui
   MeasureGUI_2Sel1LineEdit_QTD.ui
+  MeasureGUI_2Sel_Frame_QTD.ui
+  MeasureGUI_3Sel_Frame_QTD.ui
   MeasureGUI_SkeletonBox_QTD.ui
   )
 
@@ -91,6 +97,11 @@ SET(MeasureGUI_HEADERS
   MeasureGUI_GetNonBlocksDlg.h
   MeasureGUI_CheckSelfIntersectionsDlg.h
   MeasureGUI_PointDlg.h
+  MeasureGUI_ManageDimensionsDlg.h
+  MeasureGUI_CreateDimensionDlg.h
+  MeasureGUI_DimensionCreateTool.h
+  MeasureGUI_DimensionInteractor.h
+  MeasureGUI_DimensionFilter.h
   )
 
 # header files / to be processed by moc
@@ -111,6 +122,9 @@ SET(_moc_HEADERS
   MeasureGUI_GetNonBlocksDlg.h
   MeasureGUI_CheckSelfIntersectionsDlg.h
   MeasureGUI_PointDlg.h
+  MeasureGUI_ManageDimensionsDlg.h
+  MeasureGUI_CreateDimensionDlg.h
+  MeasureGUI_DimensionInteractor.h
   )
 
 # header files / uic wrappings
@@ -139,6 +153,11 @@ SET(MeasureGUI_SOURCES
   MeasureGUI_GetNonBlocksDlg.cxx
   MeasureGUI_CheckSelfIntersectionsDlg.cxx
   MeasureGUI_PointDlg.cxx
+  MeasureGUI_ManageDimensionsDlg.cxx
+  MeasureGUI_CreateDimensionDlg.cxx
+  MeasureGUI_DimensionCreateTool.cxx
+  MeasureGUI_DimensionInteractor.cxx
+  MeasureGUI_DimensionFilter.cxx
   ${_moc_SOURCES}
   ${_uic_files}
   )
index 435a92a9fd3cf5412cab4a27d5aa49bb3dd963d0..e079e74bc0bcab5af1d5bb4f1490e81382968682 100644 (file)
 #include <SUIT_Desktop.h>
 #include <SalomeApp_Application.h>
 
-#include "MeasureGUI_PropertiesDlg.h"    // Method PROPERTIES
-#include "MeasureGUI_CenterMassDlg.h"    // Method CENTER MASS
-#include "MeasureGUI_NormaleDlg.h"       // Method NORMALE
-#include "MeasureGUI_InertiaDlg.h"       // Method INERTIA
-#include "MeasureGUI_BndBoxDlg.h"        // Method BNDBOX
-#include "MeasureGUI_DistanceDlg.h"      // Method DISTANCE
-#include "MeasureGUI_AngleDlg.h"         // Method ANGLE
-#include "MeasureGUI_MaxToleranceDlg.h"  // Method MAXTOLERANCE
-#include "MeasureGUI_WhatisDlg.h"        // Method WHATIS
-#include "MeasureGUI_CheckShapeDlg.h"    // Method CHECKSHAPE
-#include "MeasureGUI_CheckCompoundOfBlocksDlg.h" // Method CHECKCOMPOUND
-#include "MeasureGUI_GetNonBlocksDlg.h"  // Method GET NON BLOCKS
+#include "MeasureGUI_PropertiesDlg.h"             // Method PROPERTIES
+#include "MeasureGUI_CenterMassDlg.h"             // Method CENTER MASS
+#include "MeasureGUI_NormaleDlg.h"                // Method NORMALE
+#include "MeasureGUI_InertiaDlg.h"                // Method INERTIA
+#include "MeasureGUI_BndBoxDlg.h"                 // Method BNDBOX
+#include "MeasureGUI_DistanceDlg.h"               // Method DISTANCE
+#include "MeasureGUI_AngleDlg.h"                  // Method ANGLE
+#include "MeasureGUI_MaxToleranceDlg.h"           // Method MAXTOLERANCE
+#include "MeasureGUI_WhatisDlg.h"                 // Method WHATIS
+#include "MeasureGUI_CheckShapeDlg.h"             // Method CHECKSHAPE
+#include "MeasureGUI_CheckCompoundOfBlocksDlg.h"  // Method CHECKCOMPOUND
+#include "MeasureGUI_GetNonBlocksDlg.h"           // Method GET NON BLOCKS
 #include "MeasureGUI_CheckSelfIntersectionsDlg.h" // Method CHECK SELF INTERSCTIONS
-#include "MeasureGUI_PointDlg.h"         // Method POINTCOORDINATES
+#include "MeasureGUI_PointDlg.h"                  // Method POINTCOORDINATES
+#include "MeasureGUI_ManageDimensionsDlg.h"       // Method MANAGEDIMENSIONS
 
 #include <QApplication>
 
@@ -120,6 +121,9 @@ bool MeasureGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent )
   case GEOMOp::OpPointCoordinates:
     dlg = new MeasureGUI_PointDlg( getGeometryGUI(), parent );
     break; // POINT COORDINATES
+  case GEOMOp::OpManageDimensions:
+    dlg = new MeasureGUI_ManageDimensionsDlg( getGeometryGUI(), parent );
+    break; // MANAGE DIMENSIONS
   default: 
     app->putInfo( tr( "GEOM_PRP_COMMAND" ).arg( theCommandID ) ); 
     break;
diff --git a/src/MeasureGUI/MeasureGUI_1Sel_Frame_QTD.ui b/src/MeasureGUI/MeasureGUI_1Sel_Frame_QTD.ui
new file mode 100644 (file)
index 0000000..3d46ee1
--- /dev/null
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MeasureGUI_1Sel_Frame_QTD</class>
+ <widget class="QWidget" name="MeasureGUI_1Sel_Frame_QTD">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>155</width>
+    <height>45</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string/>
+  </property>
+  <layout class="QGridLayout">
+   <property name="margin">
+    <number>0</number>
+   </property>
+   <property name="spacing">
+    <number>0</number>
+   </property>
+   <item row="0" column="0">
+    <widget class="QFrame" name="Frame">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <layout class="QGridLayout">
+      <property name="margin">
+       <number>9</number>
+      </property>
+      <property name="spacing">
+       <number>6</number>
+      </property>
+      <item row="0" column="2">
+       <widget class="QLineEdit" name="LineEdit1"/>
+      </item>
+      <item row="0" column="1">
+       <widget class="QPushButton" name="PushButton1">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="0">
+       <widget class="QLabel" name="TextLabel1">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>TL1</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
+ <tabstops>
+  <tabstop>PushButton1</tabstop>
+  <tabstop>LineEdit1</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/MeasureGUI/MeasureGUI_1TreeWidget_4Button_QTD.ui b/src/MeasureGUI/MeasureGUI_1TreeWidget_4Button_QTD.ui
new file mode 100644 (file)
index 0000000..5aa2cbb
--- /dev/null
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MeasureGUI_1TreeWidget_4Button_QTD</class>
+ <widget class="QWidget" name="MeasureGUI_1TreeWidget_4Button_QTD">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>341</width>
+    <height>450</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string/>
+  </property>
+  <layout class="QGridLayout">
+   <property name="margin">
+    <number>0</number>
+   </property>
+   <property name="spacing">
+    <number>6</number>
+   </property>
+   <item row="0" column="0">
+    <widget class="QGroupBox" name="GroupBox">
+     <layout class="QGridLayout">
+      <property name="margin">
+       <number>9</number>
+      </property>
+      <property name="spacing">
+       <number>6</number>
+      </property>
+      <item row="0" column="0">
+       <layout class="QHBoxLayout" name="horizontalLayout">
+        <item>
+         <widget class="QTreeWidget" name="TreeWidget">
+          <column>
+           <property name="text">
+            <string/>
+           </property>
+          </column>
+         </widget>
+        </item>
+        <item>
+         <layout class="QVBoxLayout" name="verticalLayout">
+          <item>
+           <widget class="QPushButton" name="PushButton1">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="PushButton2">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="PushButton3">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="PushButton4">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <spacer name="verticalSpacer">
+            <property name="orientation">
+             <enum>Qt::Vertical</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>20</width>
+              <height>40</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/MeasureGUI/MeasureGUI_2Sel_Frame_QTD.ui b/src/MeasureGUI/MeasureGUI_2Sel_Frame_QTD.ui
new file mode 100644 (file)
index 0000000..76cd89d
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MeasureGUI_2Sel_Frame_QTD</class>
+ <widget class="QWidget" name="MeasureGUI_2Sel_Frame_QTD">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>156</width>
+    <height>74</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string/>
+  </property>
+  <layout class="QGridLayout">
+   <property name="margin">
+    <number>0</number>
+   </property>
+   <property name="spacing">
+    <number>6</number>
+   </property>
+   <item row="0" column="0">
+    <widget class="QFrame" name="Frame">
+     <layout class="QGridLayout">
+      <property name="margin">
+       <number>9</number>
+      </property>
+      <property name="spacing">
+       <number>6</number>
+      </property>
+      <item row="1" column="2">
+       <widget class="QLineEdit" name="LineEdit2"/>
+      </item>
+      <item row="1" column="1">
+       <widget class="QPushButton" name="PushButton2">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="0">
+       <widget class="QLabel" name="TextLabel1">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>TL1</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QPushButton" name="PushButton1">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="QLabel" name="TextLabel2">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>TL2</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="2">
+       <widget class="QLineEdit" name="LineEdit1"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
+ <tabstops>
+  <tabstop>PushButton1</tabstop>
+  <tabstop>LineEdit1</tabstop>
+  <tabstop>PushButton2</tabstop>
+  <tabstop>LineEdit2</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/MeasureGUI/MeasureGUI_3Sel_Frame_QTD.ui b/src/MeasureGUI/MeasureGUI_3Sel_Frame_QTD.ui
new file mode 100644 (file)
index 0000000..3d2787b
--- /dev/null
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MeasureGUI_3Sel_Frame_QTD</class>
+ <widget class="QWidget" name="MeasureGUI_3Sel_Frame_QTD">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>156</width>
+    <height>103</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string/>
+  </property>
+  <layout class="QGridLayout">
+   <property name="margin">
+    <number>0</number>
+   </property>
+   <property name="spacing">
+    <number>6</number>
+   </property>
+   <item row="0" column="0">
+    <widget class="QFrame" name="Frame">
+     <layout class="QGridLayout">
+      <property name="margin">
+       <number>9</number>
+      </property>
+      <property name="spacing">
+       <number>6</number>
+      </property>
+      <item row="0" column="2">
+       <widget class="QLineEdit" name="LineEdit1"/>
+      </item>
+      <item row="0" column="0">
+       <widget class="QLabel" name="TextLabel1">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>TL1</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="QLabel" name="TextLabel2">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>TL2</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1">
+       <widget class="QPushButton" name="PushButton3">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QPushButton" name="PushButton2">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="0">
+       <widget class="QLabel" name="TextLabel3">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string>TL3</string>
+        </property>
+        <property name="wordWrap">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="2">
+       <widget class="QLineEdit" name="LineEdit3"/>
+      </item>
+      <item row="0" column="1">
+       <widget class="QPushButton" name="PushButton1">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="2">
+       <widget class="QLineEdit" name="LineEdit2"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
+ <tabstops>
+  <tabstop>PushButton1</tabstop>
+  <tabstop>LineEdit1</tabstop>
+  <tabstop>PushButton2</tabstop>
+  <tabstop>LineEdit2</tabstop>
+  <tabstop>PushButton3</tabstop>
+  <tabstop>LineEdit3</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
index afb373a9d76f78d624f6fb8d7872865115e8e126..df482d067baf1e9e53a130781e1b93f10264e123 100644 (file)
@@ -320,34 +320,7 @@ SALOME_Prs* MeasureGUI_AngleDlg::buildPrs()
         TopoDS_Edge anEdge1 = TopoDS::Edge(S1);
         TopoDS_Edge anEdge2 = TopoDS::Edge(S2);
 
-        // Build a plane for angle dimension presentation {P11, P12, P3}
-        TopoDS_Vertex V11, V12, V21, V22;
-        TopExp::Vertices(anEdge1, V11, V12);
-        TopExp::Vertices(anEdge2, V21, V22);
-
-        gp_Pnt aP11 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge1));
-        gp_Pnt aP12 = BRep_Tool::Pnt(TopExp::LastVertex (anEdge1));
-
-        gp_Pnt aP21 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge2));
-        gp_Pnt aP22 = BRep_Tool::Pnt(TopExp::LastVertex (anEdge2));
-
-        //        *P3
-        //         \
-        //          \
-        //           *P22
-        //          /
-        //         /
-        // P11    /         P12
-        // *-----/----------*
-        //  \   /
-        //   \ /
-        //    *P21
-        gp_Pnt aP3 (aP22.XYZ() + aP11.XYZ() - aP21.XYZ());
-
-        gce_MakePln gce_MP(aP11, aP12, aP3);
-        Handle(Geom_Plane) aPlane = new Geom_Plane(gce_MP.Value());
-
-        Handle(AIS_AngleDimension) anIO = new AIS_AngleDimension( anEdge1, anEdge2, aPlane->Pln() );
+        Handle(AIS_AngleDimension) anIO = new AIS_AngleDimension( anEdge1, anEdge2 );
 
         Handle(Prs3d_DimensionAspect) aDimensionStyle = new Prs3d_DimensionAspect;
 
@@ -356,6 +329,7 @@ SALOME_Prs* MeasureGUI_AngleDlg::buildPrs()
         Standard_Boolean isInfinite1,isInfinite2;
         Handle(Geom_Curve) extCurv;
         Standard_Integer extShape;
+        Handle(Geom_Plane) aPlane;
         if (AIS::ComputeGeometry(anEdge1,
                                   anEdge2,
                                   extShape,
diff --git a/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.cxx b/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.cxx
new file mode 100644 (file)
index 0000000..378535a
--- /dev/null
@@ -0,0 +1,950 @@
+// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File   : MeasureGUI_CreateDimensionDlg.cxx
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+
+#include "MeasureGUI_CreateDimensionDlg.h"
+#include "MeasureGUI_DimensionCreateTool.h"
+
+#include <GEOM_Constants.h>
+#include <GeometryGUI.h>
+#include <GeomBase.h>
+#include <DlgRef.h>
+#include <GEOMUtils.hxx>
+#include <GEOMUtils_DimensionProperty.hxx>
+
+#include <LightApp_SelectionMgr.h>
+#include <SalomeApp_Application.h>
+#include <SalomeApp_DataObject.h>
+#include <SalomeApp_Study.h>
+#include <SOCC_ViewModel.h>
+#include <SOCC_Prs.h>
+#include <SUIT_ViewWindow.h>
+#include <SUIT_ViewManager.h>
+#include <SUIT_MessageBox.h>
+#include <SUIT_ResourceMgr.h>
+#include <SUIT_Session.h>
+#include <SUIT_Desktop.h>
+
+#include <Aspect_PolygonOffsetMode.hxx>
+
+//=================================================================================
+// function : Constructor
+// purpose  :
+//=================================================================================
+MeasureGUI_CreateDimensionDlg::MeasureGUI_CreateDimensionDlg( const GEOM::GeomObjPtr& theObj,
+                                                              GeometryGUI* theGUI,
+                                                              QWidget* theParent )
+: GEOMBase_Skeleton( theGUI, theParent ),
+  myParentObj( theObj ),
+  myEditingViewer( NULL )
+{
+  setWindowTitle( tr( "CREATE_DIMENSION_TITLE" ) );
+
+  // init "dimension type" radio buttons
+  QAbstractButton* aTypeButtonLength   = mainFrame()->RadioButton1;
+  QAbstractButton* aTypeButtonDiameter = mainFrame()->RadioButton2;
+  QAbstractButton* aTypeButtonAngle    = mainFrame()->RadioButton3;
+
+  mainFrame()->GroupConstructors->setTitle( tr( "DIMENSIONS" ) );
+  aTypeButtonDiameter->setText( tr( "DIAMETER" ) );
+  aTypeButtonLength->setText( tr( "LENGTH" ) );
+  aTypeButtonAngle->setText( tr( "ANGLE" ) );
+
+  // construct "arguments" pane
+  QGroupBox*   aGroupArgs       = new QGroupBox( tr( "ARGUMENTS" ), centralWidget() );
+  QVBoxLayout* aGroupArgsLayout = new QVBoxLayout( aGroupArgs );
+
+  myLengthArgs   = new LengthPane  ( centralWidget() );
+  myDiameterArgs = new DiameterPane( centralWidget() );
+  myAngleArgs    = new AnglePane   ( centralWidget() );
+
+  // connect selector pane signals
+  connect( myLengthArgs,   SIGNAL( StartSelection( const QList<TopAbs_ShapeEnum>& ) ),
+                           SLOT( OnStartSelection( const QList<TopAbs_ShapeEnum>& ) ) );
+  connect( myDiameterArgs, SIGNAL( StartSelection( const QList<TopAbs_ShapeEnum>& ) ),
+                           SLOT( OnStartSelection( const QList<TopAbs_ShapeEnum>& ) ) );
+  connect( myAngleArgs,    SIGNAL( StartSelection( const QList<TopAbs_ShapeEnum>& ) ), 
+                           SLOT( OnStartSelection( const QList<TopAbs_ShapeEnum>& ) ) );
+
+  connect( myLengthArgs,   SIGNAL( StopSelection() ), SLOT( OnStopSelection() ) );
+  connect( myDiameterArgs, SIGNAL( StopSelection() ), SLOT( OnStopSelection() ) );
+  connect( myAngleArgs,    SIGNAL( StopSelection() ), SLOT( OnStopSelection( ) ) );
+
+  connect( myLengthArgs,   SIGNAL( SelectionDone() ), SLOT( OnSelectionDone() ) );
+  connect( myDiameterArgs, SIGNAL( SelectionDone() ), SLOT( OnSelectionDone() ) );
+  connect( myAngleArgs,    SIGNAL( SelectionDone() ), SLOT( OnSelectionDone() ) );
+
+  aGroupArgsLayout->addWidget( myLengthArgs );
+  aGroupArgsLayout->addWidget( myDiameterArgs );
+  aGroupArgsLayout->addWidget( myAngleArgs );
+
+  // construct main layout
+  QVBoxLayout* aCustomWidLayout = new QVBoxLayout( centralWidget() );
+  aCustomWidLayout->setMargin( 0 ); 
+  aCustomWidLayout->setSpacing( 6 );
+  aCustomWidLayout->addWidget( aGroupArgs );
+
+  // add visibility rules for structural widgets
+  connect( aTypeButtonLength,   SIGNAL( toggled(bool) ), myLengthArgs,   SLOT( setVisible(bool) ) );
+  connect( aTypeButtonDiameter, SIGNAL( toggled(bool) ), myDiameterArgs, SLOT( setVisible(bool) ) );
+  connect( aTypeButtonAngle,    SIGNAL( toggled(bool) ), myAngleArgs,    SLOT( setVisible(bool) ) );
+
+  // signals and slots connections
+  connect( buttonOk(),    SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) );
+  connect( buttonApply(), SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
+
+  // map functional signals
+  myRBGroup->setId( aTypeButtonLength,   TypeButtonID_Length );
+  myRBGroup->setId( aTypeButtonDiameter, TypeButtonID_Diameter );
+  myRBGroup->setId( aTypeButtonAngle,    TypeButtonID_Angle );
+
+  connect( this, SIGNAL( constructorsClicked( int ) ), SLOT( ConstructTypeChanged( int ) ) );
+  connect( myLengthArgs,   SIGNAL( TabChanged() ), SLOT( OnArgumentTabChanged() ) );
+  connect( myDiameterArgs, SIGNAL( TabChanged() ), SLOT( OnArgumentTabChanged() ) );
+  connect( myAngleArgs,    SIGNAL( TabChanged() ), SLOT( OnArgumentTabChanged() ) );
+
+  myDimensionInteractor = new MeasureGUI_DimensionInteractor( theGUI, theParent );
+
+  Init();
+}
+
+//=================================================================================
+// function : Destructor
+// purpose  :
+//=================================================================================
+MeasureGUI_CreateDimensionDlg::~MeasureGUI_CreateDimensionDlg()
+{
+}
+
+//=================================================================================
+// function : ActiveArgs
+// purpose  : 
+//=================================================================================
+MeasureGUI_CreateDimensionDlg::BaseSelectorPane* MeasureGUI_CreateDimensionDlg::ActiveArgs()
+{
+  switch ( getConstructorId() )
+  {
+    case TypeButtonID_Length   : return myLengthArgs;
+    case TypeButtonID_Diameter : return myDiameterArgs;
+    case TypeButtonID_Angle    : return myAngleArgs;
+    default:
+      return NULL;
+  }
+}
+
+//=================================================================================
+// function : GenerateName
+// purpose  : 
+//=================================================================================
+QString MeasureGUI_CreateDimensionDlg::GenerateName( const QString& thePrefix )
+{
+  QRegExp anExtractIds( "^" + thePrefix + "_([0-9]+)$" );
+
+  QSet<int> anOccupiedIds;
+
+  GEOMUtils_DimensionProperty aProp =
+    getStudy()->getObjectProperty( GEOM::sharedPropertiesId(),
+                                   myParentObj->GetStudyEntry(),
+                                   GEOM::propertyName( GEOM::Dimensions ),
+                                   QVariant() )
+                                   .value<GEOMUtils_DimensionProperty>();
+
+  // get names and convert to QStrings to perform index matching
+  for( int anIt = 0; anIt < aProp.GetNumber(); ++anIt )
+  {
+    if ( anExtractIds.indexIn( aProp.GetName( anIt ) ) == -1 )
+    {
+      continue;
+    }
+
+    anOccupiedIds.insert( anExtractIds.cap( 1 ).toInt() );
+  }
+
+  int aSearchId = 1;
+  while ( true )
+  {
+    if ( !anOccupiedIds.contains( aSearchId ) )
+    {
+      break;
+    }
+
+    aSearchId++;
+  }
+
+  return QString( thePrefix + "_%1" ).arg( aSearchId );
+}
+
+//=================================================================================
+// function : ConstructTypeChanged
+// purpose  : 
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::ConstructTypeChanged( int theType )
+{
+  ActiveArgs()->Reset();
+
+  updateGeometry();
+
+  QString aName;
+  switch ( theType )
+  {
+    case TypeButtonID_Length   : aName = GenerateName( tr("NAME_LENGTH") );   break;
+    case TypeButtonID_Diameter : aName = GenerateName( tr("NAME_DIAMETER") ); break;
+    case TypeButtonID_Angle    : aName = GenerateName( tr("NAME_ANGLE") );    break;
+  }
+
+  myMainFrame->ResultName->setText( aName );
+
+  StopLocalEditing();
+  erasePreview();
+
+  updateGeometry();
+  resize( minimumSizeHint() );
+}
+
+//=================================================================================
+// function : OnArgumentTabChanged
+// purpose  : 
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::OnArgumentTabChanged()
+{
+  StopLocalEditing();
+  erasePreview();
+}
+
+//=================================================================================
+// function : OnStartSelection
+// purpose  :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::OnStartSelection( const QList<TopAbs_ShapeEnum>& theModes )
+{
+  OnStopSelection();
+
+  StopLocalEditing();
+
+  QList<TopAbs_ShapeEnum>::const_iterator aModeIt = theModes.constBegin();
+  for ( ; aModeIt != theModes.constEnd(); ++aModeIt )
+  {
+    localSelection( myParentObj.get(), *aModeIt );
+  }
+
+  mySelectionModes = theModes;
+
+  connect( myGeomGUI->getApp()->selectionMgr(),
+           SIGNAL( currentSelectionChanged() ),
+           SLOT( SelectionIntoArgument() ) );
+}
+
+//=================================================================================
+// function : OnStopSelection
+// purpose  :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::OnStopSelection()
+{
+  globalSelection();
+
+  disconnect( myGeomGUI->getApp()->selectionMgr(),
+              SIGNAL( currentSelectionChanged() ),
+              this,
+              SLOT( SelectionIntoArgument() ) );
+}
+
+//=================================================================================
+// function : SelectionIntoArgument
+// purpose  : Handle model selection by active selector pane
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::SelectionIntoArgument()
+{
+  LightApp_SelectionMgr* aSelectionMgr = myGeomGUI->getApp()->selectionMgr();
+  SALOME_ListIO aSelection;
+  aSelectionMgr->selectedObjects( aSelection );
+
+  if ( aSelection.Extent() != 1 )
+  {
+    ActiveArgs()->SelectionIntoArguments( GEOM::GeomObjPtr() );
+    return;
+  }
+
+  StopLocalEditing();
+
+  erasePreview();
+
+  ActiveArgs()->SelectionIntoArguments( getSelected( mySelectionModes ) );
+}
+
+//=================================================================================
+// function : OnSelectionDone
+// purpose  :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::OnSelectionDone()
+{
+  // create new dimension presentation
+  myDimension = CreateDimension();
+
+  if ( myDimension.IsNull() )
+  {
+    // can not create preview, repeat selection
+    SUIT_MessageBox::warning( this,
+                              tr( "WARNING_TITLE_CANNOT_CREATE_DIMENSION" ),
+                              tr( "WARNING_MSG_INVALID_ARGUMENTS" ) );
+
+    ActiveArgs()->Reset();
+
+    return;
+  }
+
+  // show preview of dimension object
+  SUIT_ViewWindow* aViewWindow = SUIT_Session::session()->activeApplication()->desktop()->activeWindow();
+
+  SOCC_Prs* aSalomePrs = dynamic_cast<SOCC_Prs*>( ( (SOCC_Viewer*)( aViewWindow->getViewManager()->getViewModel() ) )->CreatePrs( 0 ) );
+
+  aSalomePrs->AddObject( myDimension );
+
+  displayPreview( aSalomePrs );
+
+  StartLocalEditing();
+}
+
+//=================================================================================
+// function : ClickOnOk
+// purpose  : 
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::ClickOnOk()
+{
+  setIsApplyAndClose( true );
+  if ( ClickOnApply() )
+  {
+    ClickOnCancel();
+  }
+}
+
+//=================================================================================
+// function : ClickOnApply
+// purpose  : 
+//=================================================================================
+bool MeasureGUI_CreateDimensionDlg::ClickOnApply()
+{
+  StopLocalEditing();
+
+  if ( !AddDimensionToOwner() )
+  {
+    return false;
+  }
+
+  redisplay( myParentObj.get() );
+
+  if ( !isApplyAndClose() )
+  {
+    Init();
+  }
+
+  return true;
+}
+
+//=================================================================================
+// function : StartLocalEditing
+// purpose  : 
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::StartLocalEditing()
+{
+  StopLocalEditing();
+
+  myDimensionInteractor->Enable();
+
+  if ( myDimension.IsNull() )
+  {
+    return;
+  }
+
+  SalomeApp_Application* anApp = myGeomGUI->getApp();
+
+  SUIT_ViewManager* aViewMgr = anApp->activeViewManager();
+
+  if ( aViewMgr->getType() != OCCViewer_Viewer::Type() )
+  {
+    return;
+  }
+
+  SOCC_Viewer* anOCCViewer = dynamic_cast<SOCC_Viewer*>( aViewMgr->getViewModel() );
+
+  myEditingViewer = anOCCViewer;
+  if ( !myEditingViewer )
+  {
+    return;
+  }
+
+  Handle(AIS_InteractiveContext) anAISContext = myEditingViewer->getAISContext();
+  Handle(V3d_Viewer)             aViewer3d    = myEditingViewer->getViewer3d();
+
+  aViewer3d->AddZLayer( myEditingLayer );
+
+  anAISContext->OpenLocalContext( Standard_False, Standard_False );
+  anAISContext->Load( myDimension, AIS_DSM_All );
+  anAISContext->SetZLayer( myDimension, myEditingLayer );
+  anAISContext->Activate( myDimension, AIS_DSM_Line );
+  anAISContext->Activate( myDimension, AIS_DSM_Text );
+}
+
+//=================================================================================
+// function : StopLocalEditing
+// purpose  : 
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::StopLocalEditing()
+{
+  myDimensionInteractor->Disable();
+
+  if ( !myEditingViewer )
+  {
+    return;
+  }
+
+  Handle(AIS_InteractiveContext) anAISContext = myEditingViewer->getAISContext();
+  Handle(V3d_Viewer)             aViewer3d    = myEditingViewer->getViewer3d();
+
+  aViewer3d->RemoveZLayer( myEditingLayer );
+  anAISContext->CloseLocalContext();
+
+  myEditingViewer = NULL;
+}
+
+//=================================================================================
+// function : Init
+// purpose  : 
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::Init()
+{
+  StopLocalEditing();
+
+  erasePreview();
+
+  myDiameterArgs->setVisible( false );
+  myAngleArgs   ->setVisible( false );
+  myLengthArgs  ->setVisible( true );
+  myLengthArgs->Reset();
+
+  myRBGroup->button( TypeButtonID_Length )->click();
+}
+
+//=================================================================================
+// function : CreateDimensionPrs
+// purpose  : 
+//=================================================================================
+Handle(AIS_Dimension) MeasureGUI_CreateDimensionDlg::CreateDimension()
+{
+  Handle(AIS_Dimension) aDimensionIO;
+
+  // prepare dimension styling
+  SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
+
+  QColor  aQColor       = aResMgr->colorValue  ( "Geometry", "dimensions_color", QColor( 0, 255, 0 ) );
+  int     aLineWidth    = aResMgr->integerValue( "Geometry", "dimensions_line_width", 1 );
+  double  aFontHeight   = aResMgr->doubleValue ( "Geometry", "dimensions_font_height", 10 );
+  double  anArrowLength = aResMgr->doubleValue ( "Geometry", "dimensions_arrow_length", 5 );
+  bool    isUnitsShown  = aResMgr->booleanValue( "Geometry", "dimensions_show_units", false );
+  QString aUnitsLength  = aResMgr->stringValue ( "Geometry", "dimensions_length_units", "m" );
+  QString aUnitsAngle   = aResMgr->stringValue ( "Geometry", "dimensions_angle_units", "deg" );
+
+  MeasureGUI_DimensionCreateTool aTool( myGeomGUI );
+
+  switch ( getConstructorId() )
+  {
+    // create length dimension
+    case TypeButtonID_Length :
+    {
+      LengthPane* aLengthPane = qobject_cast<LengthPane*>( ActiveArgs() );
+
+      switch (aLengthPane->ActiveTab())
+      {
+        case LengthPane::TabID_SingleEdge:
+        {
+          const GEOM::GeomObjPtr& anEdge = aLengthPane->GetSingleEdge();
+
+          aDimensionIO = aTool.LengthOnEdge( anEdge );
+          break;
+        }
+
+        case LengthPane::TabID_TwoPoints:
+        {
+          const GEOM::GeomObjPtr& aPoint1 = aLengthPane->GetPoint1();
+          const GEOM::GeomObjPtr& aPoint2 = aLengthPane->GetPoint2();
+
+          aDimensionIO = aTool.LengthByPoints( aPoint1, aPoint2 );
+          break;
+        }
+
+        case LengthPane::TabID_ParallelEdges:
+        {
+          const GEOM::GeomObjPtr& anEdge1 = aLengthPane->GetEdge1();
+          const GEOM::GeomObjPtr& anEdge2 = aLengthPane->GetEdge2();
+
+          aDimensionIO = aTool.LengthByParallelEdges( anEdge1, anEdge2 );
+          break;
+        }
+      }
+    }
+    break;
+
+    // create diameter dimension
+    case TypeButtonID_Diameter :
+    {
+      DiameterPane* aDiameterPane = qobject_cast<DiameterPane*>( ActiveArgs() );
+
+      const GEOM::GeomObjPtr& aShape = aDiameterPane->GetShape();
+
+      aDimensionIO = aTool.Diameter( aShape );
+      break;
+    }
+
+    // create angle dimension
+    case TypeButtonID_Angle :
+    {
+      AnglePane* anAnglePane = qobject_cast<AnglePane*>( ActiveArgs() );
+
+      switch (ActiveArgs()->ActiveTab())
+      {
+        case AnglePane::TabID_TwoEdges:
+        {
+          const GEOM::GeomObjPtr& anEdge1 = anAnglePane->GetEdge1();
+          const GEOM::GeomObjPtr& anEdge2 = anAnglePane->GetEdge2();
+
+          aDimensionIO = aTool.AngleByTwoEdges( anEdge1, anEdge2 );
+          break;
+        }
+
+        case AnglePane::TabID_ThreePoints:
+        {
+          const GEOM::GeomObjPtr& aPoint1 = anAnglePane->GetPoint1();
+          const GEOM::GeomObjPtr& aPoint2 = anAnglePane->GetPoint2();
+          const GEOM::GeomObjPtr& aPoint3 = anAnglePane->GetPoint3();
+
+          aDimensionIO = aTool.AngleByThreePoints( aPoint1, aPoint2, aPoint3 );
+          break;
+        }
+      }
+      break;
+    }
+  }
+
+  if ( aDimensionIO.IsNull() )
+  {
+    return NULL;
+  }
+
+  Quantity_Color aColor( aQColor.redF(), aQColor.greenF(), aQColor.blueF(), Quantity_TOC_RGB );
+
+  Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect();
+
+  aStyle->SetCommonColor( aColor );
+  aStyle->MakeUnitsDisplayed( (Standard_Boolean) isUnitsShown );
+  aStyle->MakeText3d( Standard_True );
+  aStyle->MakeTextShaded( Standard_True );
+  aStyle->TextAspect()->SetHeight( aFontHeight );
+  aStyle->ArrowAspect()->SetLength( anArrowLength );
+  aStyle->LineAspect()->SetWidth( aLineWidth );
+  aDimensionIO->SetDimensionAspect( aStyle );
+  aDimensionIO->SetPolygonOffsets( Aspect_POM_Fill, -1.0, -1.0 );
+
+  return aDimensionIO;
+}
+
+//=================================================================================
+// class    : AddDimensionToOwner
+// purpose  : 
+//=================================================================================
+bool MeasureGUI_CreateDimensionDlg::AddDimensionToOwner()
+{
+  if ( myDimension.IsNull() )
+  {
+    return false;
+  }
+
+  gp_Ax3 aLCS;
+  TopoDS_Shape anParentSh;
+  if ( GEOMBase::GetShape( myParentObj.get(), anParentSh ) )
+  {
+    aLCS = GEOMUtils::GetPosition( anParentSh );
+  }
+
+  QString aName = getNewObjectName();
+
+  SalomeApp_Study* aStudy = getStudy();
+
+  GEOMUtils_DimensionProperty aProp =
+    aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+                               myParentObj->GetStudyEntry(),
+                               GEOM::propertyName( GEOM::Dimensions ),
+                               QVariant() )
+                               .value<GEOMUtils_DimensionProperty>();
+
+  // append new dimension record to data
+  aProp.AddRecord( myDimension, aLCS );
+  aProp.SetName( aProp.GetNumber() - 1, aName );
+  aProp.SetVisible( aProp.GetNumber() - 1, true );
+
+  // store modified property data
+  aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+                             myParentObj->GetStudyEntry(),
+                             GEOM::propertyName( GEOM::Dimensions ),
+                             aProp );
+
+  return true;
+}
+
+/* ------------------------------------------------------------------------------*
+ *                                                                               *
+ *                    Argument shape selector layout                             *
+ *                                                                               *
+ * ------------------------------------------------------------------------------*/
+
+//=================================================================================
+// class    : MeasureGUI_CreateDimensionDlg::LengthPane
+// purpose  : Constructor
+//=================================================================================
+MeasureGUI_CreateDimensionDlg::LengthPane::LengthPane( QWidget* theParent )
+: BaseSelectorPane( theParent )
+{
+  myTabs                   = new QTabWidget( this );
+  mySingleEdgeSelectors    = new MeasureGUI_1Sel_Frame( this );
+  myTwoPointsSelectors     = new MeasureGUI_2Sel_Frame( this );
+  myParallelEdgesSelectors = new MeasureGUI_2Sel_Frame( this );
+
+  myTabs->addTab( mySingleEdgeSelectors,    MeasureGUI_CreateDimensionDlg::tr( "EDGE_LENGTH" ) );
+  myTabs->addTab( myTwoPointsSelectors,     MeasureGUI_CreateDimensionDlg::tr( "TWO_POINTS" ) );
+  myTabs->addTab( myParallelEdgesSelectors, MeasureGUI_CreateDimensionDlg::tr( "PARALLEL_EDGES" ) );
+
+  mySingleEdgeSelectors->PushButton1->setIcon( mySelectorIcon );
+  mySingleEdgeSelectors->TextLabel1->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE" ) );
+  mySingleEdgeSelectors->LineEdit1->setReadOnly( true );
+
+  myTwoPointsSelectors->PushButton1->setIcon( mySelectorIcon );
+  myTwoPointsSelectors->PushButton2->setIcon( mySelectorIcon );
+  myTwoPointsSelectors->TextLabel1->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_1" ) );
+  myTwoPointsSelectors->TextLabel2->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_2" ) );
+  myTwoPointsSelectors->LineEdit1->setReadOnly( true );
+  myTwoPointsSelectors->LineEdit2->setReadOnly( true );
+
+  myParallelEdgesSelectors->PushButton1->setIcon( mySelectorIcon );
+  myParallelEdgesSelectors->PushButton2->setIcon( mySelectorIcon );
+  myParallelEdgesSelectors->TextLabel1 ->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE_1" ) );
+  myParallelEdgesSelectors->TextLabel2 ->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE_2" ) );
+  myParallelEdgesSelectors->LineEdit1->setReadOnly( true );
+  myParallelEdgesSelectors->LineEdit2->setReadOnly( true );
+
+  QVBoxLayout* aLayout = new QVBoxLayout( this );
+
+  aLayout->setMargin( 0 );
+  aLayout->addWidget( myTabs );
+
+  SelectionModes anEdgeModes;
+  SelectionModes aPointModes;
+  anEdgeModes << TopAbs_EDGE;
+  aPointModes << TopAbs_VERTEX;
+
+  SetTabWidget( myTabs );
+  RegisterSelector( mySingleEdgeSelectors->LineEdit1,    mySingleEdgeSelectors->PushButton1,    anEdgeModes, TabID_SingleEdge );
+  RegisterSelector( myTwoPointsSelectors->LineEdit1,     myTwoPointsSelectors->PushButton1,     aPointModes, TabID_TwoPoints );
+  RegisterSelector( myTwoPointsSelectors->LineEdit2,     myTwoPointsSelectors->PushButton2,     aPointModes, TabID_TwoPoints );
+  RegisterSelector( myParallelEdgesSelectors->LineEdit1, myParallelEdgesSelectors->PushButton1, anEdgeModes, TabID_ParallelEdges );
+  RegisterSelector( myParallelEdgesSelectors->LineEdit2, myParallelEdgesSelectors->PushButton2, anEdgeModes, TabID_ParallelEdges );
+}
+
+//=================================================================================
+// class    : MeasureGUI_CreateDimensionDlg::DiameterPane
+// purpose  : Constructor
+//=================================================================================
+MeasureGUI_CreateDimensionDlg::DiameterPane::DiameterPane( QWidget* theParent )
+: BaseSelectorPane( theParent )
+{
+  myShapeSelector = new MeasureGUI_1Sel_Frame( this );
+  myShapeSelector->PushButton1->setIcon( mySelectorIcon );
+  myShapeSelector->TextLabel1 ->setText( MeasureGUI_CreateDimensionDlg::tr( "OBJECT" ) );
+
+  QVBoxLayout* aLayout = new QVBoxLayout( this );
+
+  aLayout->setMargin( 0 );
+  aLayout->addWidget( myShapeSelector );
+
+  SelectionModes aDiamModes;
+  aDiamModes << TopAbs_SHAPE
+             << TopAbs_FACE
+             << TopAbs_EDGE;
+
+  RegisterSelector( myShapeSelector->LineEdit1, myShapeSelector->PushButton1, aDiamModes );
+}
+
+//=================================================================================
+// class    : MeasureGUI_CreateDimensionDlg::AnglePane
+// purpose  : Constructor
+//=================================================================================
+MeasureGUI_CreateDimensionDlg::AnglePane::AnglePane( QWidget* theParent )
+: BaseSelectorPane( theParent )
+{
+  myTabs                 = new QTabWidget( this );
+  myTwoEdgesSelectors    = new MeasureGUI_2Sel_Frame( this );
+  myThreePointsSelectors = new MeasureGUI_3Sel_Frame( this );
+
+  myTabs->addTab( myTwoEdgesSelectors,    MeasureGUI_CreateDimensionDlg::tr( "TWO_EDGES" ) );
+  myTabs->addTab( myThreePointsSelectors, MeasureGUI_CreateDimensionDlg::tr( "THREE_POINTS" ) );
+
+  myTwoEdgesSelectors->PushButton1->setIcon( mySelectorIcon );
+  myTwoEdgesSelectors->PushButton2->setIcon( mySelectorIcon );
+  myTwoEdgesSelectors->TextLabel1 ->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE_1" ) );
+  myTwoEdgesSelectors->TextLabel2 ->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE_2" ) );
+
+  myThreePointsSelectors->PushButton1->setIcon( mySelectorIcon );
+  myThreePointsSelectors->PushButton2->setIcon( mySelectorIcon );
+  myThreePointsSelectors->PushButton3->setIcon( mySelectorIcon );
+  myThreePointsSelectors->TextLabel1 ->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_1" ) );
+  myThreePointsSelectors->TextLabel2 ->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_2" ) );
+  myThreePointsSelectors->TextLabel3 ->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_3" ) );
+
+  QVBoxLayout* aLayout = new QVBoxLayout( this );
+
+  aLayout->setMargin( 0 );
+  aLayout->addWidget( myTabs );
+
+  SelectionModes anEdgeModes;
+  SelectionModes aPointModes;
+  anEdgeModes << TopAbs_EDGE;
+  aPointModes << TopAbs_VERTEX;
+
+  SetTabWidget( myTabs );
+  RegisterSelector( myTwoEdgesSelectors->LineEdit1,    myTwoEdgesSelectors->PushButton1,    anEdgeModes, TabID_TwoEdges );
+  RegisterSelector( myTwoEdgesSelectors->LineEdit2,    myTwoEdgesSelectors->PushButton2,    anEdgeModes, TabID_TwoEdges );
+  RegisterSelector( myThreePointsSelectors->LineEdit1, myThreePointsSelectors->PushButton1, aPointModes, TabID_ThreePoints );
+  RegisterSelector( myThreePointsSelectors->LineEdit2, myThreePointsSelectors->PushButton2, aPointModes, TabID_ThreePoints );
+  RegisterSelector( myThreePointsSelectors->LineEdit3, myThreePointsSelectors->PushButton3, aPointModes, TabID_ThreePoints );
+}
+
+/* ------------------------------------------------------------------------------*
+ *                                                                               *
+ *                   Argument shape selection logics                             *
+ *                                                                               *
+ * ------------------------------------------------------------------------------*/
+
+//=================================================================================
+// class    : MeasureGUI_CreateDimensionDlg::BaseSelectorPane
+// purpose  : Constructor
+//=================================================================================
+MeasureGUI_CreateDimensionDlg::BaseSelectorPane::BaseSelectorPane( QWidget* theParent )
+: QWidget( theParent ),
+  myTabs( NULL )
+{
+  SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
+  mySelectorIcon = aResMgr->loadPixmap( "GEOM", tr( "ICON_SELECT" ) );
+}
+
+//=================================================================================
+// function : BaseSelectorPane::Reset
+// purpose  : Reset selector line edits and controls
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::Reset( bool theOpenDefaultTab )
+{
+  if ( theOpenDefaultTab && myTabs )
+  {
+    myTabs->setCurrentIndex( 0 );
+  }
+
+  QMap<int, QList<QLineEdit*>>::iterator aTabsIt = mySelectors.begin();
+  for ( ; aTabsIt != mySelectors.end(); ++aTabsIt )
+  {
+    QList<QLineEdit*>& aSelectors = *aTabsIt;
+    QList<QLineEdit*>::iterator aSelectorIt = aSelectors.begin();
+    for ( ; aSelectorIt != aSelectors.end(); ++aSelectorIt )
+    {
+      QLineEdit* aSelector = *aSelectorIt;
+      aSelector->clear();
+      mySelectedShapes[aSelector] = GEOM::GeomObjPtr();
+    }
+  }
+
+  QLineEdit* aFirstSelector = mySelectors[ ActiveTab() ].first();
+
+  mySelectionButtons[aFirstSelector]->click();
+}
+
+//=================================================================================
+// function : BaseSelectorPane::ActiveTab
+// purpose  : Returns active tab
+//=================================================================================
+int MeasureGUI_CreateDimensionDlg::BaseSelectorPane::ActiveTab() const
+{
+  return myTabs != NULL ? myTabs->currentIndex() : 0;
+}
+
+//=================================================================================
+// function : BaseSelectorPane::SelectionIntoArgument
+// purpose  : Populates current selector
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::SelectionIntoArguments( const GEOM::GeomObjPtr& theSelected )
+{
+  if ( theSelected.isNull() )
+  {
+    myCurrentSelector->clear();
+    mySelectedShapes[myCurrentSelector] = GEOM::GeomObjPtr();
+    return;
+  }
+
+  QString aName = GEOMBase::GetName( theSelected.get() );
+
+  myCurrentSelector->setText( aName );
+
+  mySelectedShapes[myCurrentSelector] = theSelected;
+
+  // find next empty selector (iterate to the last)
+  QList<QLineEdit*>& aCurrentSelectors = mySelectors[ ActiveTab() ];
+  int aCurrentPos = aCurrentSelectors.indexOf( myCurrentSelector );
+  int aSelectorIt = aCurrentPos + 1;
+  for ( ; aSelectorIt != aCurrentSelectors.size(); ++aSelectorIt )
+  {
+    QLineEdit* aNextSelector = aCurrentSelectors[aSelectorIt];
+    if ( mySelectedShapes[aNextSelector].isNull() )
+    {
+      mySelectionButtons[aNextSelector]->click();
+      return;
+    }
+  }
+
+  // find next empty selector (itearte from the first)
+  aSelectorIt = 0;
+  for ( ; aSelectorIt != aCurrentPos; ++aSelectorIt )
+  {
+    QLineEdit* aNextSelector = aCurrentSelectors[aSelectorIt];
+    if ( mySelectedShapes[aNextSelector].isNull() )
+    {
+      mySelectionButtons[aNextSelector]->click();
+      return;
+    }
+  }
+
+  // stop selector switching
+  myCurrentSelector->setEnabled( false );
+  mySelectionButtons[myCurrentSelector]->setDown( false );
+
+  // every selector is populated - construct presentation
+  emit StopSelection();
+  emit SelectionDone();
+}
+
+//=================================================================================
+// function : BaseSelectorPane::GetSelection
+// purpose  : 
+//=================================================================================
+GEOM::GeomObjPtr MeasureGUI_CreateDimensionDlg::BaseSelectorPane::GetSelection( QLineEdit* theSelector ) const
+{
+  return mySelectedShapes[theSelector];
+}
+
+//=================================================================================
+// function : BaseSelectorPane::OnSelectorClicked
+// purpose  : Handle activation of selector controls pair {edit, button}
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::OnSelectorClicked()
+{
+  // clicked "selector" button
+  QAbstractButton* aSender = qobject_cast<QAbstractButton*>( sender() );
+  if ( !aSender )
+  {
+    return;
+  }
+
+  // get "selector" controls on the active tab
+  QList<QLineEdit*>& aCurrentSelectors = mySelectors[ ActiveTab() ];
+
+  // iterate over controls on the tab and process them
+  for ( int aSelectorIt = 0; aSelectorIt < aCurrentSelectors.size(); ++aSelectorIt )
+  {
+    QLineEdit* aSelector = aCurrentSelectors[aSelectorIt];
+    QPushButton* aButton = mySelectionButtons[aSelector];
+
+    bool isClickedOnes = (aButton == aSender);
+
+    aSelector->setEnabled( isClickedOnes );
+
+    if ( isClickedOnes )
+    {
+      myCurrentSelector = aSelector;
+      myCurrentSelector->setFocus();
+    }
+
+    aButton->setDown( isClickedOnes );
+  }
+
+  emit StartSelection( mySelectionModes[myCurrentSelector] );
+}
+
+//=================================================================================
+// function : BaseSelectorPane::OnTabChanged
+// purpose  :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::OnTabChanged()
+{
+  QList<QLineEdit*>& aSelectors = mySelectors[ ActiveTab() ];
+  QList<QLineEdit*>::iterator aSelectorIt = aSelectors.begin();
+  for ( ; aSelectorIt != aSelectors.end(); ++aSelectorIt )
+  {
+    QLineEdit* aSelector = *aSelectorIt;
+
+    aSelector->clear();
+
+    mySelectedShapes[aSelector] = GEOM::GeomObjPtr();
+  }
+
+  QLineEdit* aFirstSelector = mySelectors[ ActiveTab() ].first();
+
+  mySelectionButtons[aFirstSelector]->click();
+
+  emit TabChanged();
+}
+
+//=================================================================================
+// function : BaseSelectorPane::SetTabWidget
+// purpose  :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::SetTabWidget( QTabWidget* theTabs )
+{
+  myTabs = theTabs;
+  connect( myTabs, SIGNAL( currentChanged( int ) ), this, SLOT( OnTabChanged() ) );
+}
+
+//=================================================================================
+// function : BaseSelectorPane::RegisterSelector
+// purpose  :
+//=================================================================================
+void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::RegisterSelector( QLineEdit* theSelectorEdit,
+                                                                        QPushButton* theSelectorButton,
+                                                                        const SelectionModes& theSelectorModes,
+                                                                        const int theTab )
+{
+  if ( !mySelectors.contains( theTab ) )
+  {
+    mySelectors.insert( theTab, QList<QLineEdit*>() );
+  }
+  mySelectors[theTab].append( theSelectorEdit );
+
+  mySelectionButtons[theSelectorEdit] = theSelectorButton;
+  mySelectionModes  [theSelectorEdit] = theSelectorModes;
+
+  connect( theSelectorButton, SIGNAL( clicked() ), this, SLOT( OnSelectorClicked() ) );
+}
diff --git a/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.h b/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.h
new file mode 100644 (file)
index 0000000..321276e
--- /dev/null
@@ -0,0 +1,258 @@
+// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File   : MeasureGUI_CreateDimensionDlg.h
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+//
+#ifndef MEASUREGUI_CREATEDIMENSIONDLG_H
+#define MEASUREGUI_CREATEDIMENSIONDLG_H
+
+#include "MeasureGUI_Widgets.h"
+#include "MeasureGUI_DimensionInteractor.h"
+
+// GEOM includes
+#include <GEOMBase_Skeleton.h>
+#include <GEOM_GenericObjPtr.h>
+
+// SUIT includes
+#include <SOCC_ViewModel.h>
+
+// OCCT includes
+#include <AIS_Dimension.hxx>
+#include <gp_Pnt.hxx>
+
+class MeasureGUI_1Sel_Frame;
+class MeasureGUI_2Sel_Frame;
+class MeasureGUI_3Sel_Frame;
+class QAbstractButton;
+class QTabWidget;
+class Bnd_Box;
+class SOCC_Prs;
+
+//=================================================================================
+// class    : MeasureGUI_CreateDimensionDlg
+// purpose  : Dialog invoked from MeasureGUI_ManageDimensionDlg for
+//            creating dimension presentations for the passed onwer object.
+//            Does not use operation logics.
+//=================================================================================
+class MeasureGUI_CreateDimensionDlg : public GEOMBase_Skeleton
+{
+  Q_OBJECT
+
+  class BaseSelectorPane;
+  class LengthPane;
+  class DiameterPane;
+  class AnglePane;
+
+public:
+  // Enumerate dimension type radio buttons
+  enum TypeButtonID
+  {
+    TypeButtonID_Length   = 0,
+    TypeButtonID_Diameter = 1,
+    TypeButtonID_Angle    = 2
+  };
+
+public:
+  MeasureGUI_CreateDimensionDlg( const GEOM::GeomObjPtr&, GeometryGUI*, QWidget* );
+  ~MeasureGUI_CreateDimensionDlg();
+
+public:
+  Handle(AIS_Dimension)               GetCreatedDimension() { return myDimension; }
+
+public:
+  void                                Init();
+
+/* User event logics */
+protected slots:
+  void                                ConstructTypeChanged( int theType );
+  void                                OnArgumentTabChanged();
+  void                                OnStartSelection( const QList<TopAbs_ShapeEnum>& theModes );
+  void                                OnStopSelection();
+  void                                SelectionIntoArgument();
+  void                                OnSelectionDone();
+  void                                ClickOnOk();
+  bool                                ClickOnApply();
+
+/* Commands */
+protected:
+  void                                StartLocalEditing();
+  void                                StopLocalEditing();
+
+/* Construction of preview and interaction */
+protected:
+  Handle(AIS_Dimension)               CreateDimension();
+  GEOM::GeomObjPtr                    GetTopLevel( const GEOM::GeomObjPtr& theObject );
+  bool                                AddDimensionToOwner();
+
+private:
+  BaseSelectorPane*                   ActiveArgs();
+
+private:
+  QString                             GenerateName( const QString& thePrefix );
+
+private:
+  GEOM::GeomObjPtr                    myParentObj;
+  LengthPane*                         myLengthArgs;
+  DiameterPane*                       myDiameterArgs;
+  AnglePane*                          myAngleArgs;
+  QList<TopAbs_ShapeEnum>             mySelectionModes;
+  MeasureGUI_DimensionInteractor*     myDimensionInteractor;
+  Handle(AIS_Dimension)               myDimension;
+  SOCC_Viewer*                        myEditingViewer;
+  int                                 myEditingLayer;
+};
+
+//=================================================================================
+// class    : MeasureGUI_CreateDimensionDlg::BaseSelectorPane
+// purpose  : Base selector pane handles events of switching the selector controls
+//            and changing argument tabs
+//=================================================================================
+class MeasureGUI_CreateDimensionDlg::BaseSelectorPane : public QWidget
+{
+  Q_OBJECT
+
+public:
+  typedef QList<TopAbs_ShapeEnum> SelectionModes;
+
+public:
+  BaseSelectorPane( QWidget* theParent );
+
+signals:
+  void               StartSelection( const QList<TopAbs_ShapeEnum>& theModes );
+  void               StopSelection();
+  void               SelectionDone();
+  void               TabChanged();
+
+public:
+  void               Reset( bool theOpenDefaultTab = false );
+  int                ActiveTab() const;
+  void               SelectionIntoArguments( const GEOM::GeomObjPtr& theSelected );
+  GEOM::GeomObjPtr   GetSelection( QLineEdit* theSelector ) const;
+
+public slots:
+  void               OnSelectorClicked();
+  void               OnTabChanged();
+
+protected:
+  void               SetTabWidget( QTabWidget* theTabs );
+
+  /* Register geometry selector controls at base level to provide
+     automatic handling of button clicks, selector switching and
+     sending start selection events to dialog.
+     - theSelectorEdit  : line edit control with selected geometry name.
+     - theSelectorButton: selector activation button.
+     - theSelectorModes : shape selection modes allowed for the selection.
+     - theTab : the tab index on which the controls are located. */
+  void               RegisterSelector( QLineEdit* theSelectorEdit,
+                                       QPushButton* theSelectorButton,
+                                       const SelectionModes& theSelectorModes,
+                                       const int theTab = 0 );
+
+protected:
+  QTabWidget*                         myTabs;
+  QMap<int, QList<QLineEdit*>>        mySelectors;
+  QMap<QLineEdit*, QPushButton*>      mySelectionButtons;
+  QMap<QLineEdit*, SelectionModes>    mySelectionModes;
+  QMap<QLineEdit*, GEOM::GeomObjPtr>  mySelectedShapes;
+  QPixmap                             mySelectorIcon;
+  QLineEdit*                          myCurrentSelector;
+};
+
+//=================================================================================
+// class    : MeasureGUI_CreateDimensionDlg::LengthPane
+// purpose  : Layout for length arguments pane
+//=================================================================================
+class MeasureGUI_CreateDimensionDlg::LengthPane : public BaseSelectorPane
+{
+  Q_OBJECT
+
+public:
+  enum TabID
+  {
+    TabID_SingleEdge,
+    TabID_TwoPoints,
+    TabID_ParallelEdges
+  };
+
+public:
+  LengthPane( QWidget* theParent );
+  GEOM::GeomObjPtr  GetSingleEdge() const { return GetSelection( mySingleEdgeSelectors->LineEdit1 ); }
+  GEOM::GeomObjPtr  GetPoint1() const     { return GetSelection( myTwoPointsSelectors->LineEdit1 ); }
+  GEOM::GeomObjPtr  GetPoint2() const     { return GetSelection( myTwoPointsSelectors->LineEdit2 ); }
+  GEOM::GeomObjPtr  GetEdge1() const      { return GetSelection( myParallelEdgesSelectors->LineEdit1 ); }
+  GEOM::GeomObjPtr  GetEdge2() const      { return GetSelection( myParallelEdgesSelectors->LineEdit2 ); }
+
+private:
+  QTabWidget* myTabs;
+  MeasureGUI_1Sel_Frame*   mySingleEdgeSelectors;
+  MeasureGUI_2Sel_Frame*   myTwoPointsSelectors;
+  MeasureGUI_2Sel_Frame*   myParallelEdgesSelectors;
+};
+
+//=================================================================================
+// class    : MeasureGUI_CreateDimensionDlg::DiameterPane
+// purpose  : Layout for diameter arguments pane
+//=================================================================================
+class MeasureGUI_CreateDimensionDlg::DiameterPane : public BaseSelectorPane
+{
+  Q_OBJECT
+
+public:
+  DiameterPane( QWidget* theParent );
+  GEOM::GeomObjPtr  GetShape() const { return GetSelection( myShapeSelector->LineEdit1 ); }
+
+private:
+  MeasureGUI_1Sel_Frame*   myShapeSelector;
+};
+
+//=================================================================================
+// class    : MeasureGUI_CreateDimensionDlg::AnglePane
+// purpose  : Layout for angle arguments pane
+//=================================================================================
+class MeasureGUI_CreateDimensionDlg::AnglePane : public BaseSelectorPane
+{
+  Q_OBJECT
+
+public:
+  enum TabID
+  {
+    TabID_TwoEdges,
+    TabID_ThreePoints
+  };
+
+public:
+  AnglePane( QWidget* theParent );
+  GEOM::GeomObjPtr  GetEdge1() const  { return GetSelection( myTwoEdgesSelectors->LineEdit1 ); }
+  GEOM::GeomObjPtr  GetEdge2() const  { return GetSelection( myTwoEdgesSelectors->LineEdit2 ); }
+  GEOM::GeomObjPtr  GetPoint1() const { return GetSelection( myThreePointsSelectors->LineEdit1 ); }
+  GEOM::GeomObjPtr  GetPoint2() const { return GetSelection( myThreePointsSelectors->LineEdit2 ); }
+  GEOM::GeomObjPtr  GetPoint3() const { return GetSelection( myThreePointsSelectors->LineEdit3 ); }
+
+private:
+  QTabWidget* myTabs;
+  MeasureGUI_2Sel_Frame*   myTwoEdgesSelectors;
+  MeasureGUI_3Sel_Frame*   myThreePointsSelectors;
+};
+
+#endif
diff --git a/src/MeasureGUI/MeasureGUI_DimensionCreateTool.cxx b/src/MeasureGUI/MeasureGUI_DimensionCreateTool.cxx
new file mode 100644 (file)
index 0000000..c32d0c9
--- /dev/null
@@ -0,0 +1,650 @@
+// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File   : MeasureGUI_DimensionCreateTool.cxx
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+
+#include "MeasureGUI_DimensionCreateTool.h"
+
+// GEOM includes
+#include <GEOMBase.h>
+
+// GUI includes
+#include <SalomeApp_Application.h>
+
+// SUIT includes
+#include <OCCViewer_ViewModel.h>
+#include <OCCViewer_ViewManager.h>
+#include <OCCViewer_ViewWindow.h>
+#include <OCCViewer_ViewPort3d.h>
+
+// OCCT includes
+#include <Adaptor3d_CurveOnSurface.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepAdaptor_Curve.hxx>
+#include <BRepBndLib.hxx>
+#include <gce_MakeDir.hxx>
+#include <gce_MakePln.hxx>
+#include <GC_MakePlane.hxx>
+#include <Geom_Plane.hxx>
+#include <Geom_ElementarySurface.hxx>
+#include <Geom_Surface.hxx>
+#include <GeomLib.hxx>
+#include <GeomLib_Tool.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TColgp_SequenceOfDir.hxx>
+#include <gp_Pnt.hxx>
+#include <V3d_View.hxx>
+
+//=================================================================================
+// function : Constructor
+// purpose  :
+//=================================================================================
+MeasureGUI_DimensionCreateTool::MeasureGUI_DimensionCreateTool( GeometryGUI* theGeomGUI )
+: myGeomGUI( theGeomGUI )
+{
+}
+
+//=================================================================================
+// function : LengthOnEdge
+// purpose  :
+//=================================================================================
+Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthOnEdge( const GEOM::GeomObjPtr& theEdge )
+{
+  /* ---------------------------------------------------------------- *
+   *                  get the edge and parent shape                   *
+   * ---------------------------------------------------------------- */
+
+  TopoDS_Shape aShapeEdge;
+  TopoDS_Shape aShapeMain;
+  if ( !GEOMBase::GetShape( theEdge.get(), aShapeEdge ) )
+  {
+    return NULL;
+  }
+  if ( !GEOMBase::GetShape( GetMainShape( theEdge ).get(), aShapeMain ) )
+  {
+    return NULL;
+  }
+
+  /* ------------------------------------------------- */
+  /*            check the input geometry               */
+  /* ------------------------------------------------- */
+
+  TopoDS_Edge anEdge = TopoDS::Edge( aShapeEdge );
+
+  TopoDS_Vertex aVertex1;
+  TopoDS_Vertex aVertex2;
+  TopExp::Vertices( anEdge, aVertex1, aVertex2 );
+
+  gp_Pnt aPnt1 = BRep_Tool::Pnt( aVertex1 );
+  gp_Pnt aPnt2 = BRep_Tool::Pnt( aVertex2 );
+  if ( aPnt1.Distance( aPnt2 ) <= Precision::Confusion() )
+  {
+    return NULL;
+  }
+
+  /* ------------------------------------------------- *
+   *   compose list of possible flyout directions      *
+   * ------------------------------------------------- */
+
+  Bnd_Box aBnd;
+  BRepBndLib::AddClose( aShapeMain, aBnd );
+
+  TColgp_SequenceOfDir aSeqOfFlyout;
+  ChooseLengthFlyoutsFromShape( aSeqOfFlyout, anEdge, aShapeMain );
+  ChooseLengthFlyoutsFromBnd( aSeqOfFlyout, aPnt1, aPnt2, aBnd );
+  if ( aSeqOfFlyout.IsEmpty() )
+  {
+    return NULL;
+  }
+
+  gp_Dir aPointDir = gce_MakeDir( aPnt1, aPnt2 );
+
+  // make planes for dimension presentation according to flyout directions
+  NCollection_Sequence<gp_Pln> aSeqOfPlanes;
+  for ( Standard_Integer aFlyoutIt = 1; aFlyoutIt <= aSeqOfFlyout.Length(); ++aFlyoutIt )
+  {
+    gp_Pln aPlane( aPnt1, aPointDir ^ aSeqOfFlyout.Value( aFlyoutIt ) );
+    aSeqOfPlanes.Append( aPlane );
+  }
+
+  /* --------------------------------------------------------------------- *
+   *     select best matching dimension plane for view projection          *
+   * --------------------------------------------------------------------- */
+
+  OCCViewer_ViewWindow* anActiveView = NULL;
+
+  if ( myGeomGUI != NULL )
+  {
+    SalomeApp_Application* anApp = myGeomGUI->getApp();
+    if ( !anApp )
+    {
+      OCCViewer_ViewManager* aViewMgr = (OCCViewer_ViewManager*) anApp->getViewManager( OCCViewer_Viewer::Type(), false );
+      if ( aViewMgr )
+      {
+        anActiveView = (OCCViewer_ViewWindow*)  aViewMgr->getActiveView();
+      }
+    }
+  }
+
+  gp_Pln aChoosenPlane = anActiveView
+    ? SelectPlaneForProjection( aSeqOfPlanes, anActiveView->getViewPort()->getView() )
+    : aSeqOfPlanes.First();
+
+  /* ------------------------------------------------------------------------------------ *
+   *                        construct interactive presentation                            *
+   * ------------------------------------------------------------------------------------ */
+
+  Handle(AIS_LengthDimension) aDimension = new AIS_LengthDimension( anEdge, aChoosenPlane );
+  if ( !aDimension->IsValid() )
+  {
+    return NULL;
+  }
+
+  return aDimension;
+}
+
+//=================================================================================
+// function : LengthByPoints
+// purpose  :
+//=================================================================================
+Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthByPoints( const GEOM::GeomObjPtr& thePoint1,
+                                                                            const GEOM::GeomObjPtr& thePoint2 )
+{
+  TopoDS_Shape aFirstSh;
+  if ( !GEOMBase::GetShape( thePoint1.operator ->(), aFirstSh ) )
+  {
+    return NULL;
+  }
+
+  TopoDS_Shape aSecondSh;
+  if ( !GEOMBase::GetShape( thePoint2.operator ->(), aSecondSh ) )
+  {
+    return NULL;
+  }
+
+  TopoDS_Vertex aFirstVertex  = TopoDS::Vertex( aFirstSh );
+  TopoDS_Vertex aSecondVertex = TopoDS::Vertex( aSecondSh );
+
+  gp_Pnt aPnt1 = BRep_Tool::Pnt( aFirstVertex );
+  gp_Pnt aPnt2 = BRep_Tool::Pnt( aSecondVertex );
+
+  gp_Vec aDir( aPnt1, aPnt2 );
+  gp_Dir aUnitVecs[] = { gp::DZ(), gp::DY(), gp::DX() };
+  int aUnitVecIt = 0;
+  for ( ; aUnitVecIt < 3; ++aUnitVecIt )
+  {
+    if ( aDir.Dot( aUnitVecs[aUnitVecIt] ) <= 0.5 )
+    {
+      break;
+    }
+  }
+
+  gp_Pnt aPnt3 = aPnt2.Translated( aUnitVecs[aUnitVecIt] );
+
+  GC_MakePlane aMkPlane( aPnt1, aPnt2, aPnt3 );
+  Handle(Geom_Plane) aPlane = aMkPlane.Value();
+
+  // check whether it is possible to compute valid dimension
+  Handle(AIS_LengthDimension) aDimension = new AIS_LengthDimension ( aFirstVertex, aSecondVertex, aPlane->Pln() );
+
+  if ( !aDimension->IsValid() )
+  {
+    return NULL;
+  }
+
+  return aDimension;
+}
+
+//=================================================================================
+// function : LengthByParallelEdges
+// purpose  :
+//=================================================================================
+Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthByParallelEdges( const GEOM::GeomObjPtr& theEdge1,
+                                                                                   const GEOM::GeomObjPtr& theEdge2 )
+{
+  TopoDS_Shape aFirstSh;
+  if ( !GEOMBase::GetShape( theEdge1.operator ->(), aFirstSh ) )
+  {
+    return NULL;
+  }
+
+  TopoDS_Shape aSecondSh;
+  if ( !GEOMBase::GetShape( theEdge2.operator ->(), aSecondSh ) )
+  {
+    return NULL;
+  }
+
+  TopoDS_Edge aFirstEdge  = TopoDS::Edge( aFirstSh );
+  TopoDS_Edge aSecondEdge = TopoDS::Edge( aSecondSh );
+
+  // Build plane through three points
+  BRepAdaptor_Curve aCurve1( aFirstEdge );
+  BRepAdaptor_Curve aCurve2( aSecondEdge );
+
+  gp_Pnt aPnt1 = aCurve1.Value( 0.1 );
+  gp_Pnt aPnt2 = aCurve1.Value( 0.9 );
+  gp_Pnt aPnt3 = aCurve2.Value( 0.5 );
+
+  GC_MakePlane aMkPlane( aPnt1, aPnt2, aPnt3 );
+  Handle(Geom_Plane) aPlane = aMkPlane.Value();
+
+  // check whether it is possible to compute valid dimension
+  Handle(AIS_LengthDimension) aDimension = new AIS_LengthDimension ( aFirstEdge, aSecondEdge, aPlane->Pln() );
+
+  if ( !aDimension->IsValid() )
+  {
+    return NULL;
+  }
+
+  return aDimension;
+}
+
+//=================================================================================
+// function : Diameter
+// purpose  :
+//=================================================================================
+Handle(AIS_DiameterDimension) MeasureGUI_DimensionCreateTool::Diameter( const GEOM::GeomObjPtr& theShape )
+{
+  TopoDS_Shape aShape;
+  if ( !GEOMBase::GetShape( theShape.operator ->(), aShape ) )
+  {
+    return NULL;
+  }
+
+  if ( aShape.ShapeType() != TopAbs_EDGE &&
+       aShape.ShapeType() != TopAbs_FACE &&
+       aShape.ShapeType() != TopAbs_WIRE )
+  {
+    return NULL;
+  }
+
+  // check whether it is possible to compute dimension on the passed geometry
+  Handle(AIS_DiameterDimension) aDimension = new AIS_DiameterDimension( aShape );
+
+  if ( !aDimension->IsValid() )
+  {
+    return NULL;
+  }
+
+  return aDimension;
+}
+
+//=================================================================================
+// function : AngleByTwoEdges
+// purpose  :
+//=================================================================================
+Handle(AIS_AngleDimension) MeasureGUI_DimensionCreateTool::AngleByTwoEdges( const GEOM::GeomObjPtr& theEdge1,
+                                                                            const GEOM::GeomObjPtr& theEdge2 )
+{
+  /* --------------------------------------------------- */
+  /*         get construction and parent shapes          */
+  /* --------------------------------------------------- */
+
+  TopoDS_Shape aShapeEdge1;
+  TopoDS_Shape aShapeMain1;
+  if ( !GEOMBase::GetShape( theEdge1.get(), aShapeEdge1 ) )
+  {
+    return NULL;
+  }
+  if ( !GEOMBase::GetShape( GetMainShape( theEdge1 ).get(), aShapeMain1 ) )
+  {
+    return NULL;
+  }
+
+  TopoDS_Shape aShapeEdge2;
+  TopoDS_Shape aShapeMain2;
+  if ( !GEOMBase::GetShape( theEdge2.get(), aShapeEdge2 ) )
+  {
+    return NULL;
+  }
+  if ( !GEOMBase::GetShape( GetMainShape( theEdge2 ).get(), aShapeMain2 ) )
+  {
+    return NULL;
+  }
+
+  /* ---------------------------------------------------- */
+  /*             check construction edges                 */
+  /* ---------------------------------------------------- */
+
+  TopoDS_Edge aFirstEdge  = TopoDS::Edge( aShapeEdge1 );
+  TopoDS_Edge aSecondEdge = TopoDS::Edge( aShapeEdge2 );
+
+  // check whether it is possible to compute dimension on the passed edges
+  Handle(AIS_AngleDimension) aDimension = new AIS_AngleDimension( aFirstEdge, aSecondEdge );
+
+  if ( !aDimension->IsValid() )
+  {
+    return NULL;
+  }
+
+  const gp_Pnt& aFirstPoint  = aDimension->FirstPoint();
+  const gp_Pnt& aSecondPoint = aDimension->SecondPoint();
+  const gp_Pnt& aCenterPoint = aDimension->CenterPoint();
+
+  gp_Vec aVec1( aCenterPoint, aFirstPoint );
+  gp_Vec aVec2( aCenterPoint, aSecondPoint );
+
+  Standard_Real anAngle = aVec2.AngleWithRef( aVec1, aDimension->GetPlane().Axis().Direction() );
+
+  if ( anAngle < 0.0 )
+  {
+    aDimension = new AIS_AngleDimension( aSecondPoint, aCenterPoint, aFirstPoint );
+  }
+
+  return aDimension;
+}
+
+//=================================================================================
+// function : AngleByThreePoints
+// purpose  :
+//=================================================================================
+Handle(AIS_AngleDimension) MeasureGUI_DimensionCreateTool::AngleByThreePoints( const GEOM::GeomObjPtr& thePoint1,
+                                                                               const GEOM::GeomObjPtr& thePoint2,
+                                                                               const GEOM::GeomObjPtr& thePoint3 )
+{
+  TopoDS_Shape aFirstSh;
+  if ( !GEOMBase::GetShape( thePoint1.operator ->(), aFirstSh ) )
+  {
+    return NULL;
+  }
+
+  TopoDS_Shape aSecondSh;
+  if ( !GEOMBase::GetShape( thePoint2.operator ->(), aSecondSh ) )
+  {
+    return NULL;
+  }
+
+  TopoDS_Shape aThirdSh;
+  if ( !GEOMBase::GetShape( thePoint3.operator ->(), aThirdSh ) )
+  {
+    return NULL;
+  }
+
+  TopoDS_Vertex aFirstVertex  = TopoDS::Vertex( aFirstSh );
+  TopoDS_Vertex aSecondVertex = TopoDS::Vertex( aSecondSh );
+  TopoDS_Vertex aThirdVertex  = TopoDS::Vertex( aThirdSh );
+
+  gp_Pnt aPnt1 = BRep_Tool::Pnt( aFirstVertex );
+  gp_Pnt aPnt2 = BRep_Tool::Pnt( aSecondVertex );
+  gp_Pnt aPnt3 = BRep_Tool::Pnt( aThirdVertex );
+
+  // check whether it is possible to compute dimension on the passed points
+  Handle(AIS_AngleDimension) aDimension = new AIS_AngleDimension( aPnt1, aPnt2, aPnt3 );
+
+  if ( !aDimension->IsValid() )
+  {
+    return NULL;
+  }
+
+  return aDimension;
+}
+
+//=================================================================================
+// function : ChooseLengthFlyoutsFromShape
+// purpose  :
+//=================================================================================
+void MeasureGUI_DimensionCreateTool::ChooseLengthFlyoutsFromShape( TColgp_SequenceOfDir& theDirs,
+                                                                   const TopoDS_Vertex& theVertex1,
+                                                                   const TopoDS_Vertex& theVertex2,
+                                                                   const TopoDS_Shape& theShape )
+{
+}
+
+//=================================================================================
+// function : ChooseLengthFlyoutsFromShape
+// purpose  :
+//=================================================================================
+void MeasureGUI_DimensionCreateTool::ChooseLengthFlyoutsFromShape( TColgp_SequenceOfDir& theDirs,
+                                                                   const TopoDS_Edge& theEdge,
+                                                                   const TopoDS_Shape& theShape )
+{
+  TopTools_IndexedDataMapOfShapeListOfShape aRelationMap;
+  TopExp::MapShapesAndAncestors( theShape, TopAbs_EDGE, TopAbs_FACE, aRelationMap );
+  const TopTools_ListOfShape& aRelatedFaces = aRelationMap.FindFromKey( theEdge );
+
+  // get face side directions
+  gp_Dir aSideDir;
+  if ( aRelatedFaces.Extent() > 0 && GetFaceSide( TopoDS::Face( aRelatedFaces.First() ), theEdge, aSideDir ) )
+  {
+    theDirs.Append( aSideDir );
+  }
+  if ( aRelatedFaces.Extent() > 1 && GetFaceSide( TopoDS::Face( aRelatedFaces.Last() ), theEdge, aSideDir ) )
+  {
+    theDirs.Append( aSideDir );
+  }
+
+  // get average direction in case of two non-sharp angled faces
+  if ( theDirs.Length() == 2 )
+  {
+    const gp_Dir& aDir1 = theDirs.First();
+    const gp_Dir& aDir2 = theDirs.Last();
+    Standard_Boolean isSame = aDir1.IsParallel( aDir2, Precision::Angular() );
+    if ( !isSame )
+    {
+      gp_Dir aReferenceDir = aDir1 ^ aDir2;
+      // compute angle between face sides [0 - 2PI]
+      Standard_Real aDirAngle = aDir1.AngleWithRef( aDir2, aReferenceDir );
+      if ( aDirAngle < 0 )
+      {
+        aDirAngle = ( M_PI * 2.0 ) - aDirAngle;
+      }
+
+      // non-sharp angle, use averaged direction
+      if ( aDirAngle > M_PI )
+      {
+        theDirs.Clear();
+        theDirs.Append( aDir1.Rotated( gp_Ax1( gp::Origin(), aReferenceDir ), aDirAngle * 0.5 ) );
+      }
+    }
+  }
+}
+
+//=================================================================================
+// function : ChooseLengthFlyoutsFromBnd
+// purpose  :
+//=================================================================================
+void MeasureGUI_DimensionCreateTool::ChooseLengthFlyoutsFromBnd( TColgp_SequenceOfDir& theDirs,
+                                                                 const gp_Pnt& thePnt1,
+                                                                 const gp_Pnt& thePnt2,
+                                                                 const Bnd_Box& theBnd )
+{
+  // compose a list of axis-aligned planes for lying-in flyouts
+  NCollection_Sequence<gp_Pln> anAAPlanes;
+
+  // the axis-aligned planes for flyouts are built from
+  // three points (P1, P2, and P1 translated in orthogonal
+  // direction dx, dy, dz)
+  gp_Dir anAxes[3] = { gp::DX(), gp::DY(), gp::DZ() };
+
+  for ( int anIt = 0; anIt < 3; ++anIt )
+  {
+    const gp_Dir& anAxisDir = anAxes[anIt];
+    gp_Pnt aPnt3 = thePnt1.Translated( gp_Vec( anAxisDir ) );
+    gce_MakePln aMakePlane( thePnt1, thePnt2, aPnt3 );
+    if ( !aMakePlane.IsDone() )
+    {
+      continue;
+    }
+
+    anAAPlanes.Append( aMakePlane.Value() );
+  }
+
+  // find out what is the closest direction outside of the bounding box
+  NCollection_Sequence<gp_Pln>::Iterator aPlaneIt( anAAPlanes );
+
+  gp_Dir aPointDir = gce_MakeDir( thePnt1, thePnt2 );
+
+  for ( ; aPlaneIt.More(); aPlaneIt.Next() )
+  {
+    const gp_Pln& aPlane = aPlaneIt.Value();
+
+    // transform bounding box to orthogonal coordiantes relative to
+    // dimension points P1, P2 (x-axis) and plane direction (z-axis),
+    // where y coordinates will correspond to flyout direction against
+    // the dimension point line
+    gp_Ax3 aFlyoutSpace( thePnt1, aPlane.Axis().Direction(), aPointDir );
+
+    gp_Trsf aRelativeTransform;
+    aRelativeTransform.SetTransformation( gp_Ax3(), aFlyoutSpace );
+    Bnd_Box aRelativeBounds = theBnd.Transformed( aRelativeTransform );
+
+    Standard_Real aXmin, aXmax, aYmin, aYmax, aZmin, aZmax;
+    aRelativeBounds.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+
+    gp_Dir aPosFlyout = aPlane.Axis().Direction() ^ aPointDir;
+    gp_Dir aNegFlyout = aPosFlyout.Reversed();
+
+    // select positive or negative flyout
+    theDirs.Append( Abs( aYmax ) < Abs( aYmin ) ? aPosFlyout : aNegFlyout );
+  }
+}
+
+//=================================================================================
+// function : SelectPlaneForProjection
+// purpose  : Select best matching plane in current view projection
+//=================================================================================
+gp_Pln MeasureGUI_DimensionCreateTool::SelectPlaneForProjection( const NCollection_Sequence<gp_Pln>& thePlanes,
+                                                                 const Handle(V3d_View)& theView )
+{
+  Quantity_Parameter U[3];
+  Quantity_Parameter N[3];
+  theView->Up( U[0], U[1], U[2] );
+  theView->Proj( N[0], N[1], N[2] );
+
+  gp_Dir aViewN( (Standard_Real)N[0], (Standard_Real)N[1], (Standard_Real)N[2] );
+  gp_Dir aViewU( (Standard_Real)U[0], (Standard_Real)U[1], (Standard_Real)U[2] );
+
+  gp_Pln aBestPlane = thePlanes.First();
+
+  Standard_Real aBestDotProduct = RealFirst();
+
+  for ( Standard_Integer aPlnIt = 1; aPlnIt <= thePlanes.Length(); ++aPlnIt )
+  {
+    const gp_Pln& aPlane = thePlanes.Value( aPlnIt );
+
+    Standard_Real aDotProduct = Abs( aPlane.Axis().Direction() * aViewN );
+
+    // preferred plane is "view parallel"
+    if ( aDotProduct <= aBestDotProduct )
+    {
+      continue;
+    }
+
+    aBestPlane = aPlane;
+
+    aBestDotProduct = aDotProduct;
+  }
+
+  return aBestPlane;
+}
+
+//=================================================================================
+// function : GetMainShape
+// purpose  :
+//=================================================================================
+GEOM::GeomObjPtr MeasureGUI_DimensionCreateTool::GetMainShape( const GEOM::GeomObjPtr& theShape )
+{
+  // iterate over top-level objects to search for main shape
+  GEOM::GeomObjPtr aMainShapeIt = theShape;
+  while ( !aMainShapeIt->IsMainShape() )
+  {
+    aMainShapeIt = aMainShapeIt->GetMainShape();
+  }
+  return aMainShapeIt;
+}
+
+//=================================================================================
+// function : GetFaceSide
+// purpose  :
+//=================================================================================
+bool MeasureGUI_DimensionCreateTool::GetFaceSide( const TopoDS_Face& theFace, const TopoDS_Edge& theEdge, gp_Dir& theDir )
+{
+  // get correctly oriented edge from main shape
+  TopoDS_Edge anEdgeFromFace;
+  TopExp_Explorer anExplorer( theFace.Oriented( TopAbs_FORWARD ), TopAbs_EDGE );
+  for ( ; anExplorer.More(); anExplorer.Next() )
+  {
+    TopoDS_Edge aCurrentEdge = TopoDS::Edge( anExplorer.Current() );
+    if ( theEdge.IsSame( aCurrentEdge ) )
+    {
+      anEdgeFromFace = aCurrentEdge;
+      break;
+    }
+  }
+
+  if ( anEdgeFromFace.IsNull() )
+  {
+    return false;
+  }
+
+  // check out the direction of face extensions from its boundaries at the edge location
+  // made assumption here that for any linear bounding edge the
+  // normals are same on the whole length of that edge
+  Handle(Geom_Surface) aSurface = BRep_Tool::Surface( theFace );
+  if ( aSurface.IsNull() || !aSurface->IsKind( STANDARD_TYPE(Geom_ElementarySurface) ) )
+  {
+    return false;
+  }
+
+  BRepAdaptor_Curve aSurfCurve( anEdgeFromFace, theFace );
+  if ( !aSurfCurve.IsCurveOnSurface() )
+  {
+    return false;
+  }
+
+  Standard_Real aHalfRange = ( aSurfCurve.FirstParameter() + aSurfCurve.LastParameter() ) / 2.0;
+
+  gp_Pnt aPoint = aSurfCurve.Value( aHalfRange );
+
+  Standard_Real aPointU = 0.0;
+  Standard_Real aPointV = 0.0;
+  GeomLib_Tool::Parameters( aSurface, aPoint, Precision::Confusion(), aPointU, aPointV );
+
+  gp_Dir aNorm;
+  if ( GeomLib::NormEstim( aSurface, gp_Pnt2d( aPointU, aPointV ), Precision::Confusion(), aNorm ) > 1 )
+  {
+    return false;
+  }
+
+  gp_Vec aTangent = aSurfCurve.DN( aHalfRange, 1 );
+  if ( aTangent.Magnitude() < Precision::Confusion() )
+  {
+    return false;
+  }
+
+  TopAbs_Orientation anEdgeOrientation = anEdgeFromFace.Orientation();
+  if ( anEdgeOrientation == TopAbs_REVERSED )
+  {
+    aTangent.Reverse();
+  }
+
+  theDir = gp_Dir( aTangent ) ^ aNorm;
+  return true;
+}
diff --git a/src/MeasureGUI/MeasureGUI_DimensionCreateTool.h b/src/MeasureGUI/MeasureGUI_DimensionCreateTool.h
new file mode 100644 (file)
index 0000000..978aaa9
--- /dev/null
@@ -0,0 +1,106 @@
+// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File   : MeasureGUI_DimensionCreateTool.h
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+//
+#ifndef MEASUREGUI_DIMENSIONCREATETOOL_H
+#define MEASUREGUI_DIMENSIONCREATETOOL_H
+
+// GEOM includes
+#include <GeometryGUI.h>
+#include <GEOM_GenericObjPtr.h>
+
+// OCCT includes
+#include <AIS_LengthDimension.hxx>
+#include <AIS_DiameterDimension.hxx>
+#include <AIS_AngleDimension.hxx>
+#include <Bnd_Box.hxx>
+#include <gp_Dir.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TColgp_SequenceOfDir.hxx>
+
+//=================================================================================
+// class    : MeasureGUI_DimensionCreateTool
+// purpose  :
+//=================================================================================
+class MeasureGUI_DimensionCreateTool
+{
+public:
+  MeasureGUI_DimensionCreateTool( GeometryGUI* );
+
+/* construction methods */
+public:
+  Handle(AIS_LengthDimension)   LengthOnEdge( const GEOM::GeomObjPtr& );
+
+  Handle(AIS_LengthDimension)   LengthByPoints( const GEOM::GeomObjPtr&,
+                                                const GEOM::GeomObjPtr& );
+
+  Handle(AIS_LengthDimension)   LengthByParallelEdges( const GEOM::GeomObjPtr&,
+                                                       const GEOM::GeomObjPtr& );
+
+  Handle(AIS_DiameterDimension) Diameter( const GEOM::GeomObjPtr& );
+
+  Handle(AIS_AngleDimension)    AngleByTwoEdges( const GEOM::GeomObjPtr&,
+                                                 const GEOM::GeomObjPtr& );
+
+  Handle(AIS_AngleDimension)    AngleByThreePoints( const GEOM::GeomObjPtr&,
+                                                    const GEOM::GeomObjPtr&,
+                                                    const GEOM::GeomObjPtr& );
+
+/* selecting flyout direction for length dimensions */
+protected:
+
+  void ChooseLengthFlyoutsFromShape( TColgp_SequenceOfDir&,
+                                     const TopoDS_Vertex&,
+                                     const TopoDS_Vertex&,
+                                     const TopoDS_Shape& );
+
+  void ChooseLengthFlyoutsFromShape( TColgp_SequenceOfDir&,
+                                     const TopoDS_Edge&,
+                                     const TopoDS_Shape& );
+
+  void ChooseLengthFlyoutsFromBnd( TColgp_SequenceOfDir&,
+                                   const gp_Pnt&,
+                                   const gp_Pnt&,
+                                   const Bnd_Box& );
+
+/* selecting best flyout direction taking into account view projection */
+protected:
+
+  gp_Pln SelectPlaneForProjection( const NCollection_Sequence<gp_Pln>&,
+                                   const Handle(V3d_View)& );
+
+/* utility */
+protected:
+  GEOM::GeomObjPtr              GetMainShape( const GEOM::GeomObjPtr& );
+  bool                          GetFaceSide( const TopoDS_Face&,
+                                             const TopoDS_Edge&,
+                                             gp_Dir& );
+
+private:
+  GeometryGUI*                  myGeomGUI;
+};
+
+#endif
diff --git a/src/MeasureGUI/MeasureGUI_DimensionFilter.cxx b/src/MeasureGUI/MeasureGUI_DimensionFilter.cxx
new file mode 100644 (file)
index 0000000..b5abe28
--- /dev/null
@@ -0,0 +1,192 @@
+// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File   : MeasureGUI_DimensionFilter.cxx
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+
+#include "MeasureGUI_DimensionFilter.h"
+
+// GEOM includes
+#include <GEOM_AISDimension.hxx>
+
+// SALOME includes
+#include <SALOME_InteractiveObject.hxx>
+
+IMPLEMENT_STANDARD_HANDLE (MeasureGUI_DimensionFilter, SelectMgr_Filter)
+IMPLEMENT_STANDARD_RTTIEXT(MeasureGUI_DimensionFilter, SelectMgr_Filter)
+
+//=======================================================================
+// function : Constructor
+// purpose  : 
+//=======================================================================
+MeasureGUI_DimensionFilter::MeasureGUI_DimensionFilter( const Handle(AIS_InteractiveObject)& theIO )
+: SelectMgr_Filter(), 
+  myFilterIO( theIO ),
+  myFilterEntry(),
+  myFilterId( 0 ),
+  myIsFilterIO( Standard_True ),
+  myIsFilterEntry( Standard_False ),
+  myIsFilterId( Standard_False )
+{
+}
+
+//=======================================================================
+// function : Constructor
+// purpose  : 
+//=======================================================================
+MeasureGUI_DimensionFilter::MeasureGUI_DimensionFilter( const int theId )
+: SelectMgr_Filter(), 
+  myFilterIO(),
+  myFilterEntry(),
+  myFilterId( theId ),
+  myIsFilterIO( Standard_False ),
+  myIsFilterEntry( Standard_False ),
+  myIsFilterId( Standard_True )
+{
+}
+
+//=======================================================================
+// function : Constructor
+// purpose  : 
+//=======================================================================
+MeasureGUI_DimensionFilter::MeasureGUI_DimensionFilter( const std::string& theEntry )
+: SelectMgr_Filter(),
+  myFilterIO( NULL ),
+  myFilterEntry( theEntry ),
+  myFilterId( 0 ),
+  myIsFilterIO( Standard_False ),
+  myIsFilterEntry( Standard_True ),
+  myIsFilterId( Standard_False )
+{
+}
+
+//=======================================================================
+// function : Constructor
+// purpose  : 
+//=======================================================================
+MeasureGUI_DimensionFilter::MeasureGUI_DimensionFilter( const std::string& theEntry, const int theId )
+: SelectMgr_Filter(),
+  myFilterIO( NULL ),
+  myFilterEntry( theEntry ),
+  myFilterId( theId ),
+  myIsFilterIO( Standard_False ),
+  myIsFilterEntry( Standard_True ),
+  myIsFilterId( Standard_True )
+{
+}
+
+//=======================================================================
+// function : SetFilterIO
+// purpose  : 
+//=======================================================================
+void MeasureGUI_DimensionFilter::SetFilterIO( const Handle(AIS_InteractiveObject)& theIO )
+{
+  myFilterIO = theIO;
+  myIsFilterIO = Standard_True;
+}
+
+//=======================================================================
+// function : SetFilterEntry
+// purpose  : 
+//=======================================================================
+void MeasureGUI_DimensionFilter::SetFilterEntry( const std::string& theEntry )
+{
+  myFilterEntry = theEntry;
+  myIsFilterEntry = Standard_True;
+}
+
+//=======================================================================
+// function : SetFilterId
+// purpose  : 
+//=======================================================================
+void MeasureGUI_DimensionFilter::SetFilterId( const int theId )
+{
+  myFilterId = theId;
+  myIsFilterId = Standard_True;
+}
+
+//=======================================================================
+// function : IsOk
+// purpose  : 
+//=======================================================================
+Standard_Boolean MeasureGUI_DimensionFilter::IsOk( const Handle(SelectMgr_EntityOwner)& theEntity ) const
+{
+  Handle(AIS_InteractiveObject) anAIS = Handle(AIS_InteractiveObject)::DownCast( theEntity->Selectable() );
+
+  if ( anAIS.IsNull() || !anAIS->HasOwner() )
+  {
+    return Standard_False;
+  }
+  
+  if ( !anAIS->IsKind( STANDARD_TYPE( AIS_LengthDimension ) )
+    && !anAIS->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) )
+    && !anAIS->IsKind( STANDARD_TYPE( AIS_AngleDimension ) ) )
+  {
+    return Standard_False;
+  }
+
+  if ( myIsFilterIO )
+  {
+    if ( anAIS != myFilterIO )
+    {
+      return Standard_False;
+    }
+  }
+
+  if ( myIsFilterEntry )
+  {
+    Handle(SALOME_InteractiveObject) anIO = Handle(SALOME_InteractiveObject)::DownCast( anAIS->GetOwner() );
+    if ( anIO.IsNull() )
+    {
+      return Standard_False;
+    }
+
+    if ( std::string( anIO->getEntry() ) != myFilterEntry )
+    {
+      return Standard_False;
+    }
+  }
+
+  if ( myIsFilterId )
+  {
+    Handle(GEOM_AISLength) aLength = Handle(GEOM_AISLength)::DownCast( anAIS );
+    if ( !aLength.IsNull() && aLength->GetId() != myFilterId )
+    {
+      return Standard_False;
+    }
+
+    Handle(GEOM_AISDiameter) aDiameter = Handle(GEOM_AISDiameter)::DownCast( anAIS );
+    if ( !aDiameter.IsNull() && aDiameter->GetId() != myFilterId )
+    {
+      return Standard_False;
+    }
+
+    Handle(GEOM_AISAngle) anAngle = Handle(GEOM_AISAngle)::DownCast( anAIS );
+    if ( !anAngle.IsNull() && anAngle->GetId() != myFilterId )
+    {
+      return Standard_False;
+    }
+  }
+
+  return Standard_True;
+}
diff --git a/src/MeasureGUI/MeasureGUI_DimensionFilter.h b/src/MeasureGUI/MeasureGUI_DimensionFilter.h
new file mode 100644 (file)
index 0000000..89071a8
--- /dev/null
@@ -0,0 +1,80 @@
+// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File   : MeasureGUI_DimensionFilter.h
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+//
+#ifndef MEASUREGUI_DIMENSIONFILTER_H
+#define MEASUREGUI_DIMENSIONFILTER_H
+
+// GEOM includes
+#include <GEOM_GenericObjPtr.h>
+
+// OCCT includes
+#include <AIS_InteractiveObject.hxx>
+#include <SelectMgr_Filter.hxx>
+#include <Standard_DefineHandle.hxx>
+
+DEFINE_STANDARD_HANDLE(MeasureGUI_DimensionFilter, SelectMgr_Filter)
+
+//=====================================================================================
+// class    : MeasureGUI_DimensionFilter
+// purpose  : OCC viewer filter for selecting dimensions displayed as part of
+//            presentation of particular GEOM object by its entry (owner of dimension).
+//=====================================================================================
+class MeasureGUI_DimensionFilter : public SelectMgr_Filter
+{
+public:
+
+  DEFINE_STANDARD_RTTI(MeasureGUI_DimensionFilter);
+
+public:
+  Standard_EXPORT MeasureGUI_DimensionFilter( const Handle(AIS_InteractiveObject)& theIO );
+  Standard_EXPORT MeasureGUI_DimensionFilter( const int theId );
+  Standard_EXPORT MeasureGUI_DimensionFilter( const std::string& theEntry );
+  Standard_EXPORT MeasureGUI_DimensionFilter( const std::string& theEntry, const int theId );
+
+  Standard_EXPORT void SetFilterIO( const Handle(AIS_InteractiveObject)& theIO );
+  Standard_EXPORT void SetFilterEntry( const std::string& theEntry );
+  Standard_EXPORT void SetFilterId( const int theId );
+
+  Standard_Boolean IsFilterIO() const { return myIsFilterIO; }
+  Standard_Boolean IsFilterEntry() const { return myIsFilterEntry; }
+  Standard_Boolean IsFilterId() const { return myIsFilterId; }
+
+  void UnsetFilterIO() { myIsFilterIO = Standard_False; }
+  void UnsetFilterEntry() { myIsFilterEntry = Standard_False; }
+  void UnsetFilterId() { myIsFilterId = Standard_False; }
+
+  Standard_EXPORT virtual Standard_Boolean IsOk( const Handle(SelectMgr_EntityOwner)& theEntity ) const;
+
+private:
+  Handle(AIS_InteractiveObject) myFilterIO;
+  std::string                   myFilterEntry;
+  int                           myFilterId;
+  Standard_Boolean              myIsFilterIO;
+  Standard_Boolean              myIsFilterEntry;
+  Standard_Boolean              myIsFilterId;
+};
+
+#endif
diff --git a/src/MeasureGUI/MeasureGUI_DimensionInteractor.cxx b/src/MeasureGUI/MeasureGUI_DimensionInteractor.cxx
new file mode 100644 (file)
index 0000000..48b9dbd
--- /dev/null
@@ -0,0 +1,869 @@
+// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File   : MeasureGUI_DimensionInteractor.cxx
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+
+#include "MeasureGUI_DimensionInteractor.h"
+
+#include <GEOM_Displayer.h>
+#include <SalomeApp_Application.h>
+#include <OCCViewer_ViewManager.h>
+#include <OCCViewer_ViewWindow.h>
+#include <OCCViewer_ViewPort3d.h>
+#include <SUIT_ViewManager.h>
+#include <SUIT_ViewWindow.h>
+#include <SUIT_Desktop.h>
+
+#include <QMouseEvent>
+
+#include <AIS_InteractiveContext.hxx>
+#include <AIS_LengthDimension.hxx>
+#include <AIS_DiameterDimension.hxx>
+#include <AIS_AngleDimension.hxx>
+#include <Prs3d_DimensionAspect.hxx>
+#include <Prs3d_TextAspect.hxx>
+#include <gp_Dir.hxx>
+#include <gp_Vec.hxx>
+#include <gce_MakeDir.hxx>
+#include <ElCLib.hxx>
+#include <ElSLib.hxx>
+#include <Extrema_ExtCC.hxx>
+#include <Extrema_POnCurv.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <GeomAPI_IntCS.hxx>
+#include <Geom_Line.hxx>
+#include <Geom_Plane.hxx>
+#include <NCollection_Sequence.hxx>
+
+//=================================================================================
+// function : Constructor
+// purpose  : 
+//=================================================================================
+MeasureGUI_DimensionInteractor::MeasureGUI_DimensionInteractor( GeometryGUI* theGUI,
+                                                                QObject* theParent )
+: QObject( theParent ),
+  myGeomGUI( theGUI ),
+  myIsEnabled( false ),
+  myVM( NULL ),
+  myViewer( NULL ),
+  myOperation( Operation_None )
+{
+}
+
+//=================================================================================
+// function : Deactivate
+// purpose  : 
+//=================================================================================
+MeasureGUI_DimensionInteractor::~MeasureGUI_DimensionInteractor()
+{
+  Disable();
+}
+
+//=================================================================================
+// function : Enable
+// purpose  : 
+//=================================================================================
+void MeasureGUI_DimensionInteractor::Enable()
+{
+  if ( myIsEnabled )
+  {
+    return;
+  }
+
+  myIsEnabled = true;
+
+  // install event filtering on viewer windows
+  SalomeApp_Application* anApp = myGeomGUI->getApp();
+  if ( !anApp )
+  {
+    return;
+  }
+
+  myVM     = (OCCViewer_ViewManager*) anApp->getViewManager( OCCViewer_Viewer::Type(), false );
+  myViewer = (OCCViewer_Viewer*) myVM->getViewModel();
+  if ( !myVM || !myViewer )
+  {
+    return;
+  }
+
+  connect( myVM, SIGNAL( viewCreated( SUIT_ViewWindow* ) ), SLOT( OnViewCreated( SUIT_ViewWindow* ) ) );
+  connect( myVM, SIGNAL( deleteView ( SUIT_ViewWindow* ) ), SLOT( OnViewRemoved( SUIT_ViewWindow* ) ) );
+
+  QVector<SUIT_ViewWindow*>           aViews  = myVM->getViews();
+  QVector<SUIT_ViewWindow*>::iterator aViewIt = aViews.begin();
+  for ( ; aViewIt != aViews.end(); ++aViewIt )
+  {
+    ConnectView( *aViewIt );
+  }
+}
+
+//=================================================================================
+// function : Disable
+// purpose  : 
+//=================================================================================
+void MeasureGUI_DimensionInteractor::Disable()
+{
+  if ( !myIsEnabled )
+  {
+    return;
+  }
+
+  myIsEnabled = false;
+
+  // remove event filtering from viewer windows
+  QVector<SUIT_ViewWindow*>           aViews  = myVM->getViews();
+  QVector<SUIT_ViewWindow*>::iterator aViewIt = aViews.begin();
+  for ( ; aViewIt != aViews.end(); ++aViewIt )
+  {
+    DisconnectView( *aViewIt );
+  }
+}
+
+//=================================================================================
+// function : GetOperation
+// purpose  : 
+//=================================================================================
+MeasureGUI_DimensionInteractor::Operation
+  MeasureGUI_DimensionInteractor::GetOperation( const Handle(SelectMgr_EntityOwner)& theEntity,
+                                                const Qt::MouseButtons theButtons,
+                                                const Qt::KeyboardModifiers theKeys )
+{
+  if ( ( theButtons & Qt::LeftButton ) == 0 )
+  {
+    return Operation_None;
+  }
+
+  Handle(AIS_DimensionOwner) anOwner = Handle(AIS_DimensionOwner)::DownCast( theEntity );
+  if ( anOwner.IsNull() )
+  {
+    return Operation_None;
+  }
+
+  Standard_Real anAngTolerance = M_PI / 30.0; // 6 degree tolerance
+
+  switch ( anOwner->SelectionMode() )
+  {
+    case AIS_DSM_Line :
+    {
+      if ( ( theKeys & Qt::ControlModifier ) == 0 )
+      {
+        return Operation_MoveFlyoutInPlane;
+      }
+
+      // "free moving" is only available for length and diameter
+      if ( !myInteractedIO->IsKind( STANDARD_TYPE( AIS_LengthDimension ) )
+        && !myInteractedIO->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) )
+      {
+        return Operation_None;
+      }
+
+      return Operation_MoveFlyoutFree;
+    }
+
+    case AIS_DSM_Text : return Operation_MoveText;
+    default :           return Operation_None;
+  }
+}
+
+//=================================================================================
+// function : StartOperation
+// purpose  : 
+//=================================================================================
+bool MeasureGUI_DimensionInteractor::StartOperation( const Operation theOp,
+                                                     const Handle(V3d_View)& theView,
+                                                     const int theX,
+                                                     const int theY )
+{
+  Standard_Real anAngTolerance = M_PI / 30.0; // 6 degree tolerance
+
+  switch ( theOp )
+  {
+    case Operation_MoveFlyoutInPlane :
+    case Operation_MoveText :
+    {
+      // operation can be started if the plane in which the flyout 
+      // or text moved is not completely orthogonal to the screen
+      gp_Pln aPlane = myInteractedIO->GetPlane();
+      gp_Lin aProj  = Projection( theView, theX, theY );
+      Standard_Real aCrossAng = aProj.Direction().Angle( aPlane.Axis().Direction() );
+      return Abs( M_PI * 0.5 - aCrossAng ) > anAngTolerance;
+    }
+
+    case Operation_MoveFlyoutFree :
+    {
+      // operation can be started only for linear dimensions
+      if ( !myInteractedIO->IsKind( STANDARD_TYPE( AIS_LengthDimension ) )
+        && !myInteractedIO->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) )
+      {
+        return false;
+      }
+
+      // determine whether the rotation operation is frontal or side
+      gp_Pnt aFirstPoint;
+      gp_Pnt aSecondPoint;
+
+      // get first and second point from which the flyout line is normally extended
+      Handle(AIS_LengthDimension) aLength = Handle(AIS_LengthDimension)::DownCast( myInteractedIO );
+      if ( !aLength.IsNull() )
+      {
+        aFirstPoint  = aLength->FirstPoint();
+        aSecondPoint = aLength->SecondPoint();
+      }
+
+      Handle(AIS_DiameterDimension) aDiameter = Handle(AIS_DiameterDimension)::DownCast( myInteractedIO );
+      if ( !aDiameter.IsNull() )
+      {
+        const gp_Pnt& aCenter = aDiameter->Circle().Location();
+        aFirstPoint    = aDiameter->AnchorPoint();
+        aSecondPoint   = gp_Pnt( aFirstPoint.XYZ() + gp_Vec( aFirstPoint, aCenter ).XYZ() * 2.0 );
+      }
+
+      gp_Dir aBaseDir = gce_MakeDir( aFirstPoint, aSecondPoint );
+      gp_Pln aPlane   = myInteractedIO->GetPlane();
+      gp_Dir aPlaneN  = aPlane.Axis().Direction();
+      gp_Lin aProj    = Projection( theView, theX, theY );
+
+      const gp_Dir& aProjDir = aProj.Direction();
+
+      // can turn only if looking from side
+      if ( aProjDir.IsParallel( aPlaneN, anAngTolerance ) ||
+           aProjDir.IsNormal( aBaseDir, anAngTolerance ) )
+      {
+        return false;
+      }
+
+      bool isProjected     = false;
+      gp_Pnt aPointOnPlane = ProjectPlane( theView, theX, theY, aPlane, isProjected );
+      if ( !isProjected )
+      {
+        return false;
+      }
+
+      gp_Vec aPointVector( aFirstPoint, aPointOnPlane );
+      gp_Pnt aPointOnBase = gp_Pnt( aFirstPoint.XYZ() + aBaseDir.XYZ() * aPointVector.Dot( aBaseDir ) );
+      myFreeMovePlane = gp_Pln( aPointOnBase, aBaseDir );
+
+      return true;
+    }
+
+    default:
+      return false;
+  }
+}
+
+//=================================================================================
+// function : MoveFlyoutFree
+// purpose  : 
+//=================================================================================
+void MeasureGUI_DimensionInteractor::MoveFlyoutFree( const Handle(V3d_View)& theView,
+                                                     const int theX,
+                                                     const int theY )
+{
+  // project point onto dimension plane
+  bool isProjected     = false;
+  gp_Pln aPlane        = myFreeMovePlane;
+  gp_Pnt aPointOnPlane = ProjectPlane( theView, theX, theY, aPlane, isProjected );
+  if ( !isProjected )
+  {
+    return;
+  }
+
+  gp_Pnt aFirstPoint;
+  gp_Pnt aSecondPoint;
+
+  // get first and second point from which the flyout line is normally extended
+  Handle(AIS_LengthDimension) aLength = Handle(AIS_LengthDimension)::DownCast( myInteractedIO );
+  if ( !aLength.IsNull() )
+  {
+    aFirstPoint  = aLength->FirstPoint();
+    aSecondPoint = aLength->SecondPoint();
+  }
+
+  Handle(AIS_DiameterDimension) aDiameter = Handle(AIS_DiameterDimension)::DownCast( myInteractedIO );
+  if ( !aDiameter.IsNull() )
+  {
+    const gp_Pnt& aCenter = aDiameter->Circle().Location();
+    aFirstPoint    = aDiameter->AnchorPoint();
+    aSecondPoint   = gp_Pnt( aFirstPoint.XYZ() + gp_Vec( aFirstPoint, aCenter ).XYZ() * 2.0 );
+  }
+
+  gp_Vec aPointVector( aFirstPoint, aPointOnPlane );
+  gp_Dir aBaseDir     = gce_MakeDir( aFirstPoint, aSecondPoint );
+  gp_Pnt aPointOnBase = gp_Pnt( aFirstPoint.XYZ() + aBaseDir.XYZ() * aPointVector.Dot( aBaseDir ) );
+
+  // snapping tolerance
+  Quantity_Length aSize[2];
+  theView->Size( aSize[0], aSize[1] );
+  Standard_Real aSnapTolerance = 1e-2 * Max( aSize[0], aSize[1] );
+
+  gp_Dir aFlyoutDir = gce_MakeDir( aPointOnBase, aPointOnPlane );
+
+  // snapping to planes
+  NCollection_Sequence<gp_Pln> aSnapPlanes;
+
+  if ( aPointOnPlane.Distance( aPointOnBase ) > aSnapTolerance )
+  {
+    if ( !aBaseDir.IsParallel( gp::DZ(), Precision::Angular() ) )
+    {
+      aSnapPlanes.Append( gp_Pln( aFirstPoint, gp::DZ().Crossed( aBaseDir ) ) );
+    }
+    if ( !aBaseDir.IsParallel( gp::DX(), Precision::Angular() ) )
+    {
+      aSnapPlanes.Append( gp_Pln( aFirstPoint, gp::DX().Crossed( aBaseDir ) ) );
+    }
+    if ( !aBaseDir.IsParallel( gp::DY(), Precision::Angular() ) )
+    {
+      aSnapPlanes.Append( gp_Pln( aFirstPoint, gp::DY().Crossed( aBaseDir ) ) );
+    }
+  }
+
+  // snap "drag proj" to Flyout plane, relative XOY, YOZ, ZOX planes
+  NCollection_Sequence<gp_Pln>::Iterator aSnapIt( aSnapPlanes );
+
+  for ( ; aSnapIt.More(); aSnapIt.Next() )
+  {
+    const gp_Pln& aSnapPln = aSnapIt.Value();
+
+    // project direction into plane
+    gp_Vec aPlaneDir = gp_Vec( aSnapPln.Axis().Direction() );
+    gp_Vec aFlyoutProj = gp_Vec( aFlyoutDir ) - aPlaneDir * gp_Vec( aFlyoutDir ).Dot( aPlaneDir );
+
+    // snapping is not applicable
+    if ( aSnapPln.Contains( gp_Lin( aFirstPoint, aFlyoutDir ), Precision::Confusion(), Precision::Angular() ) )
+    {
+      continue;
+    }
+    if ( Abs( gp_Vec( aPointOnBase, aPointOnPlane ).Dot( aPlaneDir ) ) > aSnapTolerance )
+    {
+      continue;
+    }
+    if ( aFlyoutProj.Magnitude() <= Precision::Confusion() )
+    {
+      continue;
+    }
+
+    aFlyoutDir = gp_Dir( aFlyoutProj );
+
+    break;
+  }
+  
+  Standard_Real aNewFlyout = aPointOnPlane.Distance( aPointOnBase );
+
+  if ( aNewFlyout <= Precision::Confusion() )
+  {
+    myInteractedIO->SetFlyout( 0.0 );
+    myViewer->getAISContext()->Redisplay( myInteractedIO );
+    return;
+  }
+
+  gp_Pln aNewPlane = gp_Pln( aFirstPoint, aBaseDir.Crossed( aFlyoutDir ) );
+
+  myInteractedIO->SetFlyout( aNewFlyout );
+  myInteractedIO->SetCustomPlane( aNewPlane );
+
+  myViewer->getAISContext()->Redisplay( myInteractedIO );
+}
+
+//=================================================================================
+// function : MoveFlyoutInPlane
+// purpose  : 
+//=================================================================================
+void MeasureGUI_DimensionInteractor::MoveFlyoutInPlane( const Handle(V3d_View)& theView,
+                                                        const int theX,
+                                                        const int theY )
+{
+  // project point onto dimension plane
+  bool isProjected     = false;
+  gp_Pln aPlane        = myInteractedIO->GetPlane();
+  gp_Pnt aPointOnPlane = ProjectPlane( theView, theX, theY, aPlane, isProjected );
+  if ( !isProjected )
+  {
+    return;
+  }
+
+  const gp_Dir& aPlaneN = aPlane.Axis().Direction();
+
+  // new flyout value
+  Standard_Real aFlyout = 0.0;
+
+  // extend flyout of linear dimension
+  if ( myInteractedIO->IsKind( STANDARD_TYPE( AIS_LengthDimension ) )
+    || myInteractedIO->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) )
+  {
+    gp_Pnt aFirstPoint;
+    gp_Pnt aSecondPoint;
+
+    // get first and second point from which the flyout line is normally extended
+    Handle(AIS_LengthDimension) aLength = Handle(AIS_LengthDimension)::DownCast( myInteractedIO );
+    if ( !aLength.IsNull() )
+    {
+      aFirstPoint  = aLength->FirstPoint();
+      aSecondPoint = aLength->SecondPoint();
+    }
+
+    Handle(AIS_DiameterDimension) aDiameter = Handle(AIS_DiameterDimension)::DownCast( myInteractedIO );
+    if ( !aDiameter.IsNull() )
+    {
+      const gp_Pnt& aCenter = aDiameter->Circle().Location();
+      aFirstPoint    = aDiameter->AnchorPoint();
+      aSecondPoint   = gp_Pnt( aFirstPoint.XYZ() + gp_Vec( aFirstPoint, aCenter ).XYZ() * 2.0 );
+    }
+
+    gp_Lin aBaseLine( aFirstPoint, gce_MakeDir( aFirstPoint, aSecondPoint ) );
+
+    // check if the negative value is expected
+    gp_Dir aPositiveDir = aPlaneN.Crossed( aBaseLine.Direction() );
+    gp_Dir aPointDir    = gce_MakeDir( aBaseLine.Location(), aPointOnPlane );
+    Standard_Boolean isPositive = aPointDir.Dot( aPositiveDir ) > 0;
+
+    aFlyout = isPositive 
+      ?  aBaseLine.Distance( aPointOnPlane )
+      : -aBaseLine.Distance( aPointOnPlane );
+  }
+
+  // exten flyout of angular dimension
+  if ( myInteractedIO->IsKind( STANDARD_TYPE( AIS_AngleDimension ) ) )
+  {
+    Handle(AIS_AngleDimension) anAngle = Handle(AIS_AngleDimension)::DownCast( myInteractedIO );
+
+    const gp_Pnt& aCenterPoint = anAngle->CenterPoint();
+    const gp_Pnt& aFirstPoint  = anAngle->FirstPoint();
+    const gp_Pnt& aSecondPoint = anAngle->SecondPoint();
+
+    gp_Dir aFirstDir  = gce_MakeDir( aCenterPoint, aFirstPoint );
+    gp_Dir aSecondDir = gce_MakeDir( aCenterPoint, aSecondPoint );
+
+    Standard_Real aDirAngle = aFirstDir.Angle( aSecondDir );
+
+    //                 p1 center p2
+    //                   \ dir /
+    // the direction are: \ | /
+    //            first    \|/   second
+    //             dir      c      dir
+    // 
+
+    gp_Dir aCenterDir = aFirstDir.Rotated( gp_Ax1( aCenterPoint, aPlaneN ), -aDirAngle * 0.5 );
+
+    gp_Dir aPointDir  = gce_MakeDir( aCenterPoint, aPointOnPlane );
+
+    Standard_Boolean isPositive = aPointDir.Dot( aCenterDir ) > 0;
+
+    Standard_Real aPointAngle = aPointDir.AngleWithRef(  aCenterDir,  aPlaneN );
+    if ( !isPositive )
+    {
+      aPointAngle = ( M_PI - Abs( aPointAngle ) ) * ( -Sign( 1.0, aPointAngle ) );
+    }
+
+    gp_Vec aPointVec = gp_Vec( aCenterPoint, aPointOnPlane );
+
+    // calculate flyout for each separate case of point location
+    if ( aPointAngle < -aDirAngle * 0.5 ) // outside of second dir
+    {
+      aFlyout = aPointVec.Dot( aFirstDir );
+    }
+    else if ( aPointAngle > aDirAngle * 0.5 ) // outside of first dir
+    {
+      aFlyout = aPointVec.Dot( aSecondDir );
+    }
+    else // between first and second direction
+    {
+      aFlyout = isPositive
+        ?  aPointVec.Magnitude()
+        : -aPointVec.Magnitude();
+    }
+  }
+
+  myInteractedIO->SetFlyout( aFlyout );
+
+  myViewer->getAISContext()->Redisplay( myInteractedIO );
+}
+
+//=================================================================================
+// function : MoveText
+// purpose  : 
+//=================================================================================
+void MeasureGUI_DimensionInteractor::MoveText( const Handle(V3d_View)& theView,
+                                               const int theX,
+                                               const int theY )
+{
+  // project point onto dimension plane
+  bool isProjected     = false;
+  gp_Pln aPlane        = myInteractedIO->GetPlane();
+  gp_Pnt aPointOnPlane = ProjectPlane( theView, theX, theY, aPlane, isProjected );
+  if ( !isProjected )
+  {
+    return;
+  }
+
+  const gp_Dir& aPlaneN = aPlane.Axis().Direction();
+
+  Prs3d_DimensionTextHorizontalPosition aHPos = myInteractedIO->DimensionAspect()->TextHorizontalPosition();
+  Prs3d_DimensionTextVerticalPosition   aVPos = myInteractedIO->DimensionAspect()->TextVerticalPosition();
+
+  Standard_Real aHeight = myInteractedIO->DimensionAspect()->TextAspect()->Height() * 0.5;
+
+  // move text of linear dimension
+  if ( myInteractedIO->IsKind( STANDARD_TYPE( AIS_LengthDimension ) )
+    || myInteractedIO->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) )
+  {
+    gp_Pnt aFirstPoint;
+    gp_Pnt aSecondPoint;
+
+    // get first and second point from which the flyout line is normally extended
+    Handle(AIS_LengthDimension) aLength = Handle(AIS_LengthDimension)::DownCast( myInteractedIO );
+    if ( !aLength.IsNull() )
+    {
+      aFirstPoint  = aLength->FirstPoint();
+      aSecondPoint = aLength->SecondPoint();
+    }
+
+    Handle(AIS_DiameterDimension) aDiameter = Handle(AIS_DiameterDimension)::DownCast( myInteractedIO );
+    if ( !aDiameter.IsNull() )
+    {
+      const gp_Pnt& aCenter = aDiameter->Circle().Location();
+      aFirstPoint    = aDiameter->AnchorPoint();
+      aSecondPoint   = gp_Pnt( aFirstPoint.XYZ() + gp_Vec( aFirstPoint, aCenter ).XYZ() * 2.0 );
+    }
+
+    // get flyout line
+    Standard_Real aFlyout   = myInteractedIO->GetFlyout();
+    gp_Dir aBaseDir         = gce_MakeDir( aFirstPoint, aSecondPoint );
+    gp_Dir aFlyoutDir       = aFlyout >= 0.0 
+      ?  aPlaneN.Crossed( gce_MakeDir( aFirstPoint, aSecondPoint ) )
+      : -aPlaneN.Crossed( gce_MakeDir( aFirstPoint, aSecondPoint ) );
+    gp_Vec aFlyoutTranslate = gp_Vec( aFlyoutDir ) * Abs( myInteractedIO->GetFlyout() );
+    gp_Lin aFlyoutLine      = gp_Lin( aFirstPoint, aBaseDir ).Translated( aFlyoutTranslate );
+
+    // check if positive or negative offset along flyout line
+    gp_Vec aFlyout2Point = gp_Vec( aFlyoutLine.Location(), aPointOnPlane );
+
+    Standard_Real aPosY = aFlyout2Point.Dot( aFlyoutDir );
+    Standard_Real aPosX = aFlyout2Point.Dot( aFlyoutLine.Direction() );
+
+    if ( aPosX < 0.0 )
+    {
+      aHPos = Prs3d_DTHP_Left;
+    }
+    else if ( aPosX > aFirstPoint.Distance( aSecondPoint ) )
+    {
+      aHPos = Prs3d_DTHP_Right;
+    }
+    else
+    {
+      aHPos = Prs3d_DTHP_Center;
+    }
+
+    if ( aPosY > aHeight )
+    {
+      aVPos = Prs3d_DTVP_Above;
+    }
+    else if ( aPosY < -aHeight )
+    {
+      aVPos = Prs3d_DTVP_Below;
+    }
+    else
+    {
+      aVPos = Prs3d_DTVP_Center;
+    }
+  }
+
+  // move text of angular dimension
+  if ( myInteractedIO->IsKind( STANDARD_TYPE( AIS_AngleDimension ) ) )
+  {
+    Handle(AIS_AngleDimension) anAngle = Handle(AIS_AngleDimension)::DownCast( myInteractedIO );
+
+    const gp_Pnt& aCenterPoint = anAngle->CenterPoint();
+    const gp_Pnt& aFirstPoint  = anAngle->FirstPoint();
+    const gp_Pnt& aSecondPoint = anAngle->SecondPoint();
+
+    gp_Dir aFirstDir  = gce_MakeDir( aCenterPoint, aFirstPoint );
+    gp_Dir aSecondDir = gce_MakeDir( aCenterPoint, aSecondPoint );
+
+    Standard_Real aDirAngle = aFirstDir.Angle( aSecondDir );
+
+    //                 p1 center p2
+    //                   \ dir /
+    // the direction are: \ | /
+    //            first    \|/   second
+    //             dir      c      dir
+    // 
+
+    gp_Dir aCenterDir = aFirstDir.Rotated( gp_Ax1( aCenterPoint, aPlaneN ), -aDirAngle * 0.5 );
+
+    gp_Dir aPointDir  = gce_MakeDir( aCenterPoint, aPointOnPlane );
+
+    Standard_Boolean isPositive = aPointDir.Dot( aCenterDir ) > 0;
+
+    Standard_Real aPointAngle = aPointDir.AngleWithRef(  aCenterDir,  aPlaneN );
+    if ( !isPositive )
+    {
+      aPointAngle = ( M_PI - Abs( aPointAngle ) ) * ( -Sign( 1.0, aPointAngle ) );
+    }
+
+    gp_Vec aPointVec = gp_Vec( aCenterPoint, aPointOnPlane );
+
+    Standard_Real aPosY = 0.0;
+
+    // the point should lie within the dimension flyout area
+    if (  isPositive && aPointVec.Dot( aFirstDir ) < 0.0
+      || !isPositive && aPointVec.Dot( aFirstDir ) > 0.0 )
+    {
+      return;
+    }
+
+    // calculate flyout for each separate case of point location
+    if ( aPointAngle < -aDirAngle * 0.5 ) // outside of second dir
+    {
+      aHPos = Prs3d_DTHP_Left;
+      aPosY = Abs( aPointVec.Dot( aFirstDir ) ) - Abs( myInteractedIO->GetFlyout() );
+    }
+    else if ( aPointAngle > aDirAngle * 0.5 ) // outside of first dir
+    {
+      aHPos = Prs3d_DTHP_Right;
+      aPosY = Abs( aPointVec.Dot( aSecondDir ) ) - Abs( myInteractedIO->GetFlyout() );
+    }
+    else // between first and second direction
+    {
+      aHPos = Prs3d_DTHP_Center;
+      aPosY = Abs( aPointVec.Magnitude() ) - Abs( myInteractedIO->GetFlyout() );
+    }
+
+    if ( aPosY > aHeight )
+    {
+      aVPos = Prs3d_DTVP_Above;
+    }
+    else if ( aPosY < -aHeight )
+    {
+      aVPos = Prs3d_DTVP_Below;
+    }
+    else
+    {
+      aVPos = Prs3d_DTVP_Center;
+    }
+  }
+
+  myInteractedIO->DimensionAspect()->SetTextVerticalPosition( aVPos );
+  myInteractedIO->DimensionAspect()->SetTextHorizontalPosition( aHPos );
+  myInteractedIO->SetToUpdate();
+
+  myViewer->getAISContext()->Redisplay( myInteractedIO );
+}
+
+//=================================================================================
+// function : eventFilter
+// purpose  : 
+//=================================================================================
+bool MeasureGUI_DimensionInteractor::eventFilter( QObject* theObject, QEvent* theEvent )
+{
+  OCCViewer_ViewPort3d* aViewPort = (OCCViewer_ViewPort3d*) theObject;
+
+  Handle(V3d_View) aView3d = aViewPort->getView();
+
+  switch ( theEvent->type() )
+  {
+    // check whether it is the "dimension modify" operation or not.
+    case QEvent::MouseButtonPress :
+    {
+      Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext();
+
+      QMouseEvent* aMouseEv = dynamic_cast<QMouseEvent*>( theEvent );
+
+      // init detection
+      anAISContext->MoveTo( aMouseEv->x(), aMouseEv->y(), aView3d );
+      if ( !anAISContext->HasDetected() )
+      {
+        return false;
+      }
+
+      // check that there is only one detected entity
+      anAISContext->InitDetected();
+      if ( anAISContext->MoreDetected() )
+      {
+        return false;
+      }
+
+      Handle(SelectMgr_EntityOwner) aDetectedOwner = anAISContext->DetectedOwner();
+
+      myInteractedIO = Handle(AIS_Dimension)::DownCast( aDetectedOwner->Selectable() );
+
+      // try to start operation for the detected entity
+      Operation aStartOp = GetOperation( aDetectedOwner, aMouseEv->buttons(), aMouseEv->modifiers() );
+      if ( aStartOp == Operation_None )
+      {
+        return false;
+      }
+
+      if ( !StartOperation( aStartOp, aView3d, aMouseEv->x(), aMouseEv->y() ) )
+      {
+        return false;
+      }
+
+      myOperation = aStartOp;
+
+      mySelection.Clear();
+
+      for ( anAISContext->InitSelected(); anAISContext->MoreSelected(); anAISContext->NextSelected() )
+      {
+        mySelection.Append( anAISContext->SelectedOwner() );
+      }
+
+      anAISContext->ClearSelected( Standard_False );
+      anAISContext->AddOrRemoveSelected( aDetectedOwner );
+
+      emit InteractionStarted( myInteractedIO );
+
+      return true;
+    }
+
+    // stop event processing on mouse release
+    case QEvent::MouseButtonRelease :
+    {
+      if ( myOperation != Operation_None )
+      {
+        Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext();
+
+        anAISContext->ClearSelected( Standard_False );
+        SeqOfOwners::Iterator anIt( mySelection );
+        for( ; anIt.More(); anIt.Next() )
+        {
+          anAISContext->AddOrRemoveSelected( anIt.Value(), Standard_False );
+        }
+
+        anAISContext->UpdateCurrentViewer();
+
+        mySelection.Clear();
+
+        myOperation = Operation_None;
+
+        emit InteractionFinished( myInteractedIO );
+
+        return true;
+      }
+
+      return false;
+    }
+
+    // perform operation
+    case QEvent::MouseMove :
+    {
+      QMouseEvent* aMouseEv = (QMouseEvent*) theEvent;
+      switch( myOperation )
+      {
+        case Operation_MoveFlyoutFree    : MoveFlyoutFree   ( aView3d, aMouseEv->x(), aMouseEv->y() ); return true;
+        case Operation_MoveFlyoutInPlane : MoveFlyoutInPlane( aView3d, aMouseEv->x(), aMouseEv->y() ); return true;
+        case Operation_MoveText          : MoveText         ( aView3d, aMouseEv->x(), aMouseEv->y() ); return true;
+        default : return false;
+      }
+    }
+
+    default: return false;
+  }
+}
+
+//=================================================================================
+// function : ConnectView
+// purpose  : 
+//=================================================================================
+void MeasureGUI_DimensionInteractor::ConnectView( SUIT_ViewWindow* theView )
+{
+  ( (OCCViewer_ViewWindow*) theView )->getViewPort()->installEventFilter( this );
+}
+
+//=================================================================================
+// function : DisconnectView
+// purpose  : 
+//=================================================================================
+void MeasureGUI_DimensionInteractor::DisconnectView( SUIT_ViewWindow* theView )
+{
+  ( (OCCViewer_ViewWindow*) theView )->getViewPort()->removeEventFilter( this );
+}
+
+//=================================================================================
+// function : Projection
+// purpose  : 
+//=================================================================================
+gp_Lin MeasureGUI_DimensionInteractor::Projection( const Handle(V3d_View)& theView,
+                                                   const int theMouseX,
+                                                   const int theMouseY )
+{
+  Standard_Real P[3], D[3];
+  theView->ConvertWithProj( theMouseX, theMouseY, P[0], P[1], P[2], D[0], D[1], D[2] );
+  return gp_Lin( gp_Pnt( P[0], P[1], P[2] ), gp_Dir( D[0], D[1], D[2] ) );
+}
+
+//=================================================================================
+// function : ProjectPlane
+// purpose  : 
+//=================================================================================
+gp_Pnt MeasureGUI_DimensionInteractor::ProjectPlane( const Handle(V3d_View)& theView,
+                                                     const int theMouseX,
+                                                     const int theMouseY,
+                                                     const gp_Pln& thePlane,
+                                                     bool& theIsDone )
+{
+  gp_Lin aProjection = Projection( theView, theMouseX, theMouseY );
+
+  Handle(Geom_Line)  aCrossLine  = new Geom_Line( aProjection );
+  Handle(Geom_Plane) aCrossPlane = new Geom_Plane( thePlane );
+
+  GeomAPI_IntCS aFindCross( aCrossLine, aCrossPlane );
+  if ( !aFindCross.IsDone() || aFindCross.NbPoints() == 0 )
+  {
+    theIsDone = false;
+    return gp::Origin();
+  }
+
+  theIsDone = true;
+  return aFindCross.Point( 1 );
+}
+
+//=================================================================================
+// function : SensitivityTolerance
+// purpose  : 
+//=================================================================================
+Standard_Real MeasureGUI_DimensionInteractor::SensitivityTolerance( const Handle(V3d_View)& theView )
+{
+  // snapping tolerance
+  Quantity_Length aSize[2];
+  theView->Size( aSize[0], aSize[1] );
+  return 1e-2 * Max( aSize[0], aSize[1] );
+}
+
+//=================================================================================
+// function : OnViewCreated
+// purpose  : 
+//=================================================================================
+void MeasureGUI_DimensionInteractor::OnViewCreated( SUIT_ViewWindow* theView )
+{
+  ConnectView( theView );
+}
+
+//=================================================================================
+// function : OnViewRemoved
+// purpose  : 
+//=================================================================================
+void MeasureGUI_DimensionInteractor::OnViewRemoved( SUIT_ViewWindow* theView )
+{
+  DisconnectView( theView );
+}
diff --git a/src/MeasureGUI/MeasureGUI_DimensionInteractor.h b/src/MeasureGUI/MeasureGUI_DimensionInteractor.h
new file mode 100644 (file)
index 0000000..4ed77c2
--- /dev/null
@@ -0,0 +1,177 @@
+// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File   : MeasureGUI_DimensionEditor.h
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+//
+#ifndef MEASUREGUI_DIMENSIONINTERACTOR_H
+#define MEASUREGUI_DIMENSIONINTERACTOR_H
+
+#include <GeometryGUI.h>
+#include <QObject>
+
+#include <SelectMgr_EntityOwner.hxx>
+#include <NCollection_Sequence.hxx>
+#include <AIS_ListOfInteractive.hxx>
+#include <AIS_InteractiveObject.hxx>
+#include <AIS_Dimension.hxx>
+#include <gp_Pln.hxx>
+
+class OCCViewer_ViewManager;
+class OCCViewer_Viewer;
+class SUIT_ViewWindow;
+class Handle(V3d_View);
+
+//=================================================================================
+// class    : MeasureGUI_DimensionInteractor
+// purpose  : Interactive editor of dimension presentations
+//=================================================================================
+class MeasureGUI_DimensionInteractor : public QObject
+{
+  Q_OBJECT
+
+public:
+  enum Operation
+  {
+    Operation_MoveFlyoutFree,
+    Operation_MoveFlyoutInPlane,
+    Operation_MoveText,
+    Operation_None
+  };
+
+public:
+  MeasureGUI_DimensionInteractor( GeometryGUI*, QObject* );
+  ~MeasureGUI_DimensionInteractor();
+
+public:
+  void                   Enable();
+  void                   Disable();
+
+protected:
+  /*!
+   * \brief Identify interactive operation by picked entity and pressed buttons with modifiers
+   *
+   * \param theEntity [in] the picked entity.
+   * \param theButtons [in] the mouse buttons.
+   * \param theKeys [in] the keyboard modifiers.
+   */
+  Operation              GetOperation( const Handle(SelectMgr_EntityOwner)& theEntity,
+                                       const Qt::MouseButtons theButtons,
+                                       const Qt::KeyboardModifiers theKeys );
+
+  /*!
+   * \brief Prepare for interactive operation.
+   * 
+   * \param theOp [in] the operation.
+   * \param theView [in] the interacted view.
+   * \param theX [in] the mouse position x.
+   * \param theY [in] the mouse position y.
+   * \return TRUE if operation can be started.
+   */
+  bool                  StartOperation( const Operation theOperation,
+                                        const Handle(V3d_View)& theView,
+                                        const int theX,
+                                        const int theY );
+
+  /*!
+   * \brief Perform "Operation_MoveFlyoutFree".
+   * Modify flyout of interactive dimension so as the flyout follows
+   * the mouse by its length and orientation.
+   *
+   * \param theView [in] the interacted view.
+   * \param theX [in] the mouse position x.
+   * \param theY [in] the mouse position y.
+   */
+  void                   MoveFlyoutFree( const Handle(V3d_View)& theView, const int theX, const int theY );
+
+  /*!
+   * \brief Perform "Operation_MoveFlyoutInPlane".
+   * Modify flyout of interactive dimension so as the flyout is extended
+   * to the mouse point location in the presentation plane.
+   *
+   * \param theView [in] the interacted view.
+   * \param theX [in] the mouse position x.
+   * \param theY [in] the mouse position y.
+   */
+  void                   MoveFlyoutInPlane( const Handle(V3d_View)& theView, const int theX, const int theY );
+
+  /*!
+   * \brief Perform "Operation_MoveText". 
+   * Modify text of interactive dimension so as the text is moved to its fixed positions.
+   *
+   * \param theView [in] the interacted view.
+   * \param theX [in] the mouse position x.
+   * \param theY [in] the mouse position y.
+   */
+  void                   MoveText( const Handle(V3d_View)& theView, const int theX, const int theY );
+
+signals:
+  void                   InteractionStarted( Handle_AIS_InteractiveObject theIO );
+  void                   InteractionFinished( Handle_AIS_InteractiveObject theIO );
+
+protected:
+  void                   ConnectView( SUIT_ViewWindow* );
+  void                   DisconnectView( SUIT_ViewWindow* );
+  gp_Lin                 Projection( const Handle(V3d_View)&, const int, const int );
+  gp_Pnt                 ProjectPlane( const Handle(V3d_View)&, 
+                                       const int,
+                                       const int,
+                                       const gp_Pln&,
+                                       bool& );
+  Standard_Real          SensitivityTolerance( const Handle(V3d_View)& );
+
+protected:
+  /*!
+   * \brief Process events from OCC viewer prior to their coming into the base viewer class.
+   *
+   * It handles the events coming to viewport and identifies whether the events correspond to
+   * interactive operation on dimension. If yes, the operation is performed within the
+   * interactor class and events are "accepted". Otherwise, the events are passed to
+   * viewer subroutines.
+   *
+   * The method manages internal workflow related to starting and stopping interactive 
+   * operations to modify the presentations which were passed for this interactor class.
+   *
+   */
+  virtual bool           eventFilter( QObject*, QEvent* );
+
+protected slots:
+  void                   OnViewCreated( SUIT_ViewWindow* );
+  void                   OnViewRemoved( SUIT_ViewWindow* );
+
+private:
+  typedef NCollection_Sequence<Handle(SelectMgr_EntityOwner)> SeqOfOwners;
+
+private:
+  GeometryGUI*            myGeomGUI;
+  bool                    myIsEnabled;
+  OCCViewer_ViewManager*  myVM;
+  OCCViewer_Viewer*       myViewer;
+  Operation               myOperation;
+  bool                    myOperationStarted;
+  gp_Pln                  myFreeMovePlane;
+  Handle(AIS_Dimension)   myInteractedIO;
+  SeqOfOwners             mySelection;
+};
+
+#endif
diff --git a/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx b/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx
new file mode 100644 (file)
index 0000000..a072417
--- /dev/null
@@ -0,0 +1,1183 @@
+// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File   : MeasureGUI_ManageDimensionsDlg.cxx
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+
+#include "MeasureGUI_ManageDimensionsDlg.h"
+#include "MeasureGUI_CreateDimensionDlg.h"
+#include "MeasureGUI_DimensionFilter.h"
+
+#include <GEOMUtils_DimensionProperty.hxx>
+#include <GEOMUtils.hxx>
+#include <GEOMGUI_OCCSelector.h>
+#include <GEOM_AISDimension.hxx>
+#include <GEOM_Constants.h>
+#include <GEOMBase.h>
+#include <DlgRef.h>
+
+#include <SOCC_ViewModel.h>
+#include <SOCC_Prs.h>
+#include <SalomeApp_Application.h>
+#include <SalomeApp_Study.h>
+#include <LightApp_SelectionMgr.h>
+#include <SUIT_ViewManager.h>
+#include <SUIT_ResourceMgr.h>
+#include <SUIT_Session.h>
+#include <SUIT_MessageBox.h>
+
+#include <AIS_ListOfInteractive.hxx>
+#include <AIS_ListIteratorOfListOfInteractive.hxx>
+#include <AIS_InteractiveContext.hxx>
+#include <SelectMgr_Filter.hxx>
+#include <SelectMgr_ListOfFilter.hxx>
+#include <SelectMgr_ListIteratorOfListOfFilter.hxx>
+
+#include <QTreeWidget>
+#include <QPushButton>
+#include <QGroupBox>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QPixmap>
+
+//=================================================================================
+// function : Constructor
+// purpose  :
+//=================================================================================
+MeasureGUI_ManageDimensionsDlg::MeasureGUI_ManageDimensionsDlg( GeometryGUI* theGUI, QWidget* theParent )
+: GEOMBase_Skeleton( theGUI, theParent ),
+  myOperatedViewer( NULL ),
+  myCurrentSelection( Selection_None )
+{
+  SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
+
+  QPixmap aSelectorIcon = aResMgr->loadPixmap( "GEOM", tr( "ICON_SELECT" ) );
+
+  setWindowTitle( tr( "MANAGE_DIMENSIONS_TITLE" ) );
+
+  mainFrame()->GroupConstructors->setVisible( false );
+  mainFrame()->GroupBoxName->setVisible( false );
+
+  // construct object selector pane
+  myObjectSelector = new DlgRef_1Sel( centralWidget() );
+  myObjectSelector->TextLabel1->setText( tr( "OBJECT_LABEL" ) );
+  myObjectSelector->LineEdit1->setReadOnly( true );
+  myObjectSelector->PushButton1->setIcon( aSelectorIcon );
+  myObjectSelector->PushButton1->setCheckable( true );
+
+  // construct dimension list view pane
+  myDimensionView = new MeasureGUI_1TreeWidget_4Button( centralWidget() );
+  myDimensionView->GroupBox->setTitle( tr( "DIMENSIONS_GROUP" ) );
+  myDimensionView->PushButton1->setText( tr( "ADD_BTN" ) );
+  myDimensionView->PushButton2->setText( tr( "REMOVE_BTN" ) );
+  myDimensionView->PushButton3->setText( tr( "SHOW_ALL_BTN" ) );
+  myDimensionView->PushButton4->setText( tr( "HIDE_ALL_BTN" ) );
+  myDimensionView->TreeWidget->setMinimumHeight( 250 );
+  myDimensionView->setEnabled( false );
+
+  connect( myDimensionView->PushButton1, SIGNAL( clicked() ), SLOT( OnAdd() ) );
+  connect( myDimensionView->PushButton2, SIGNAL( clicked() ), SLOT( OnRemove() ) );
+  connect( myDimensionView->PushButton3, SIGNAL( clicked() ), SLOT( OnShowAll() ) );
+  connect( myDimensionView->PushButton4, SIGNAL( clicked() ), SLOT( OnHideAll() ) );
+  connect( myDimensionView->TreeWidget, 
+           SIGNAL( itemChanged( QTreeWidgetItem*, int ) ),
+           SLOT( OnChangeItem( QTreeWidgetItem* ) ) );
+  connect( myDimensionView->TreeWidget,
+           SIGNAL( currentItemChanged( QTreeWidgetItem*, QTreeWidgetItem* ) ),
+           SLOT( OnSelectItem() ) );
+
+  // populate tree with top-level items
+  myDimensionView->TreeWidget->setHeaderItem( new QTreeWidgetItem( (QTreeWidget*)NULL, QStringList( QString() ) ) );
+
+  // construct main frame layout
+  QVBoxLayout* aMainLayout = new QVBoxLayout( centralWidget() );
+  aMainLayout->setMargin( 0 );
+  aMainLayout->addWidget( myObjectSelector, 0 );
+  aMainLayout->addWidget( myDimensionView, 1 );
+
+  // signals and slots connections
+  connect( myObjectSelector->PushButton1, SIGNAL( clicked() ), SLOT( StartObjectSelection() ) );
+  connect( buttonOk(),    SIGNAL( clicked() ), SLOT( ClickOnOk() ) );
+  connect( buttonApply(), SIGNAL( clicked() ), SLOT( ClickOnApply() ) );
+
+  connect( this, SIGNAL( finished( int ) ), SLOT( OnFinish() ) );
+
+  myDimensionInteractor = new MeasureGUI_DimensionInteractor( theGUI, theParent ),
+
+  SelectionIntoArgument( Selection_Object );
+
+  if ( myEditObject.isNull() )
+  {
+    myObjectSelector->PushButton1->click();
+  }
+}
+
+//=================================================================================
+// function : Destructor
+// purpose  :
+//=================================================================================
+MeasureGUI_ManageDimensionsDlg::~MeasureGUI_ManageDimensionsDlg()
+{
+  StopSelection();
+}
+
+//=================================================================================
+// function : StartSelection
+// purpose  : Starts specific selection
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::StartSelection( const Selection theSelection )
+{
+  StopSelection();
+
+  myCurrentSelection = theSelection;
+
+  if ( theSelection == Selection_Object && WarnUnsaved() )
+  {
+    /* -----------------------------------------------  *
+     *               selection of object                *
+     * ------------------------------------------------ */
+
+    globalSelection( GEOM_ALLSHAPES );
+    connect( myGeomGUI->getApp()->selectionMgr(),
+             SIGNAL( currentSelectionChanged() ),
+             this,
+             SLOT( OnSelection() ) );
+  }
+  else if ( theSelection == Selection_Dimension && !myEditObject.isNull() )
+  {
+    /* -----------------------------------------------  *
+     *               selection of dimension             *
+     * ------------------------------------------------ */
+
+    SalomeApp_Application* anApp = myGeomGUI->getApp();
+    if ( !anApp )
+    {
+      return;
+    }
+
+    SUIT_ViewManager* aViewMgr = anApp->activeViewManager();
+    if ( aViewMgr->getType() != SOCC_Viewer::Type() )
+    {
+      return;
+    }
+
+    myOperatedViewer = dynamic_cast<SOCC_Viewer*>( aViewMgr->getViewModel() );
+
+    globalSelection();
+
+    Handle(AIS_InteractiveContext) anAISContext = myOperatedViewer->getAISContext();
+
+    anAISContext->ClearCurrents( Standard_False );
+    anAISContext->ClearSelected( Standard_False );
+    anAISContext->OpenLocalContext( Standard_True, Standard_False );
+
+    Handle(MeasureGUI_DimensionFilter) aFilter = new MeasureGUI_DimensionFilter( myEditObject->GetStudyEntry() );
+
+    anAISContext->AddFilter( aFilter );
+
+    LightApp_SelectionMgr* aSelectionMgr = myGeomGUI->getApp()->selectionMgr();
+
+    QList<SUIT_Selector*> aSelectors;
+    aSelectionMgr->selectors( aSelectors );
+    QList<SUIT_Selector*>::iterator aSelectorIt = aSelectors.begin();
+    for ( ; aSelectorIt != aSelectors.end(); ++aSelectorIt )
+    {
+      SUIT_Selector* aSelector = *aSelectorIt;
+
+      GEOMGUI_OCCSelector* aGeomSelector = dynamic_cast<GEOMGUI_OCCSelector*>( aSelector );
+      if ( !aGeomSelector )
+      {
+        continue;
+      }
+
+      aGeomSelector->setEnabled( false );
+    }
+
+    connect( myOperatedViewer,
+             SIGNAL( selectionChanged() ),
+             this,
+             SLOT( OnSelection() ) );
+
+    myDimensionInteractor->Enable();
+
+    connect( myDimensionInteractor,
+             SIGNAL( InteractionFinished( Handle_AIS_InteractiveObject ) ),
+             this,
+             SLOT( OnInteractionFinished( Handle_AIS_InteractiveObject ) ) );
+
+    anAISContext->UpdateCurrentViewer();
+  }
+}
+
+//=================================================================================
+// function : StopObjectSelection
+// purpose  : Stops specific selection
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::StopSelection()
+{
+  if ( myCurrentSelection == Selection_Object )
+  {
+    /* -----------------------------------------------  *
+     *               selection of object                *
+     * ------------------------------------------------ */
+
+    myObjectSelector->PushButton1->setChecked( false );
+    disconnect( myGeomGUI->getApp()->selectionMgr(),
+                SIGNAL( currentSelectionChanged() ),
+                this,
+                SLOT( OnSelection() ) );
+  }
+  else if ( myCurrentSelection == Selection_Dimension && myOperatedViewer )
+  {
+    /* -----------------------------------------------  *
+     *               selection of dimension             *
+     * ------------------------------------------------ */
+
+    Handle(AIS_InteractiveContext) anAISContext = myOperatedViewer->getAISContext();
+
+    anAISContext->CloseLocalContext();
+
+    LightApp_SelectionMgr* aSelectionMgr = myGeomGUI->getApp()->selectionMgr();
+
+    QList<SUIT_Selector*> aSelectors;
+    aSelectionMgr->selectors( aSelectors );
+    QList<SUIT_Selector*>::iterator aSelectorIt = aSelectors.begin();
+    for ( ; aSelectorIt != aSelectors.end(); ++aSelectorIt )
+    {
+      SUIT_Selector* aSelector = *aSelectorIt;
+
+      GEOMGUI_OCCSelector* aGeomSelector = dynamic_cast<GEOMGUI_OCCSelector*>( aSelector );
+      if ( !aGeomSelector )
+      {
+        continue;
+      }
+
+      aGeomSelector->setEnabled( true );
+    }
+
+    disconnect( myOperatedViewer,
+                SIGNAL( selectionChanged() ),
+                this,
+                SLOT( OnSelection() ) );
+
+    myDimensionInteractor->Disable();
+
+    disconnect( myDimensionInteractor,
+                SIGNAL( InteractionFinished( Handle_AIS_InteractiveObject ) ),
+                this,
+                SLOT( OnInteractionFinished( Handle_AIS_InteractiveObject ) ) );
+  }
+
+  myCurrentSelection = Selection_None;
+
+  globalSelection();
+}
+
+//=================================================================================
+// function : OnSelection
+// purpose  : 
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnSelection()
+{
+  SelectionIntoArgument( myCurrentSelection );
+}
+
+//=================================================================================
+// function : SelectionIntoArgument
+// purpose  : 
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::SelectionIntoArgument( const Selection theSelection  )
+{
+  if ( theSelection == Selection_Object )
+  {
+    /* -----------------------------------------------  *
+     *               selection of object                *
+     * ------------------------------------------------ */
+
+    LightApp_SelectionMgr* aSelectionMgr = myGeomGUI->getApp()->selectionMgr();
+    SALOME_ListIO aSelection;
+    aSelectionMgr->selectedObjects( aSelection );
+
+    GEOM::GeomObjPtr aSelected;
+
+    if ( aSelection.Extent() == 1 )
+    {
+      aSelected = GEOMBase::ConvertIOinGEOMObject( aSelection.First() );
+    }
+
+    SetEditObject( aSelected );
+    StartSelection( Selection_Dimension );
+  }
+  else if ( theSelection == Selection_Dimension && myOperatedViewer )
+  {
+    /* -----------------------------------------------  *
+     *               selection of dimension             *
+     * ------------------------------------------------ */
+
+    QTreeWidget* aDimensionList = myDimensionView->TreeWidget;
+
+    Handle(AIS_InteractiveContext) anAISContext = myOperatedViewer->getAISContext();
+
+    // non-single selection is prohibited
+    if ( anAISContext->NbSelected() != 1 )
+    {
+      aDimensionList->setCurrentIndex( QModelIndex() );
+      return;
+    }
+
+    anAISContext->InitSelected();
+
+    Handle(AIS_InteractiveObject) anAIS;
+
+    if ( anAISContext->HasOpenedContext() )
+    {
+      Handle(SelectMgr_EntityOwner) anAISOwner = anAISContext->SelectedOwner();
+      anAIS = Handle(AIS_InteractiveObject)::DownCast( anAISOwner->Selectable() );
+    }
+    else
+    {
+      anAIS = anAISContext->Current();
+    }
+
+    int aDimensionId = IdFromPrs( anAIS );
+
+    SelectInList( aDimensionId );
+
+    if ( aDimensionId >= 0 )
+    {
+      SelectInViewer( myOperatedViewer, aDimensionId );
+    }
+  }
+}
+
+//=================================================================================
+// function : OnAdd
+// purpose  :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnAdd()
+{
+  QWidget* aParent = qobject_cast<QWidget*>( this->parent() );
+
+  this->Suspend();
+
+  MeasureGUI_CreateDimensionDlg* aCreateDlg = new MeasureGUI_CreateDimensionDlg( myEditObject, myGeomGUI, aParent );
+
+  connect( aCreateDlg, SIGNAL( finished( int ) ), this, SLOT( Resume() ) );
+
+  // this is necessary as the GEOMBase_Helper switches selection mode on destruction
+  connect( aCreateDlg, SIGNAL( destroyed( QObject* ) ), this, SLOT( Resume() ) );
+
+  aCreateDlg->updateGeometry();
+  aCreateDlg->resize( aCreateDlg->minimumSizeHint() );
+  aCreateDlg->show();
+}
+
+//=================================================================================
+// function : OnRemove
+// purpose  :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnRemove()
+{
+  int aDimensionId = IdFromItem( myDimensionView->TreeWidget->currentItem() );
+  if ( aDimensionId < 0 )
+  {
+    return;
+  }
+
+  SalomeApp_Application* anApp = myGeomGUI->getApp();
+  if ( !anApp )
+  {
+    return;
+  }
+
+  SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( anApp->activeStudy() );
+  if ( !aStudy )
+  {
+    return;
+  }
+
+  // get property data to change
+  GEOMUtils_DimensionProperty aProp =
+    aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+                               myEditObject->GetStudyEntry(),
+                               GEOM::propertyName( GEOM::Dimensions ),
+                               QVariant() )
+                               .value<GEOMUtils_DimensionProperty>();
+
+  aProp.RemoveRecord( aDimensionId );
+
+  // store modified property data
+  aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+                             myEditObject->GetStudyEntry(),
+                             GEOM::propertyName( GEOM::Dimensions ),
+                             aProp );
+
+  PopulateList();
+
+  RedisplayObject();
+}
+
+//=================================================================================
+// function : OnChangeItem
+// purpose  :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnChangeItem( QTreeWidgetItem* theItem )
+{
+  int aDimensionId = IdFromItem( theItem );
+  if ( aDimensionId < 0 )
+  {
+    return;
+  }
+
+  SalomeApp_Application* anApp = myGeomGUI->getApp();
+  if ( !anApp )
+  {
+    return;
+  }
+
+  SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( anApp->activeStudy() );
+  if ( !aStudy )
+  {
+    return;
+  }
+
+  // get property data to change
+  GEOMUtils_DimensionProperty aProp =
+    aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+                               myEditObject->GetStudyEntry(),
+                               GEOM::propertyName( GEOM::Dimensions ),
+                               QVariant() )
+                               .value<GEOMUtils_DimensionProperty>();
+
+  // change property data
+  bool isAnythingChanged = false;
+
+  QString aName = theItem->text( 0 );
+  if ( aProp.GetName( aDimensionId ) != aName )
+  {
+    isAnythingChanged = true;
+    aProp.SetName( aDimensionId, aName );
+  }
+
+  bool isVisible = theItem->checkState( 0 ) == Qt::Checked;
+  if ( aProp.IsVisible( aDimensionId ) != isVisible )
+  {
+    isAnythingChanged = true;
+    aProp.SetVisible( aDimensionId, isVisible );
+  }
+
+  // store property data
+  if ( !isAnythingChanged )
+  {
+    return;
+  }
+
+  // store modified property data
+  aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+                             myEditObject->GetStudyEntry(),
+                             GEOM::propertyName( GEOM::Dimensions ),
+                             aProp );
+
+  RedisplayObject();
+}
+
+//=================================================================================
+// function : OnSelectItem
+// purpose  :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnSelectItem()
+{
+  if ( !myOperatedViewer )
+  {
+    return;
+  }
+
+  QTreeWidgetItem* aSelectedItem = myDimensionView->TreeWidget->currentItem();
+
+  SelectInViewer( myOperatedViewer, IdFromItem( aSelectedItem ) );
+}
+
+//=================================================================================
+// function : OnShowAll
+// purpose  :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnShowAll()
+{
+  // read propety data
+  SalomeApp_Application* anApp = myGeomGUI->getApp();
+  if ( !anApp )
+  {
+    return;
+  }
+
+  SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( anApp->activeStudy() );
+  if ( !aStudy )
+  {
+    return;
+  }
+
+  // get property data to change
+  GEOMUtils_DimensionProperty aProp =
+    aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+                               myEditObject->GetStudyEntry(),
+                               GEOM::propertyName( GEOM::Dimensions ),
+                               QVariant() )
+                               .value<GEOMUtils_DimensionProperty>();
+
+  QTreeWidget* aDimensionList = myDimensionView->TreeWidget;
+
+  bool isBlocked = aDimensionList->blockSignals( true );
+
+  for ( int anIt = 0; anIt < aProp.GetNumber(); ++anIt )
+  {
+    aProp.SetVisible( anIt, true );
+  }
+
+  // store modified property data
+  aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+                             myEditObject->GetStudyEntry(),
+                             GEOM::propertyName( GEOM::Dimensions ),
+                             aProp );
+
+  PopulateList();
+
+  RedisplayObject();
+
+  aDimensionList->blockSignals( isBlocked );
+}
+
+//=================================================================================
+// function : OnHideAll
+// purpose  :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnHideAll()
+{
+  // read propety data
+  SalomeApp_Application* anApp = myGeomGUI->getApp();
+  if ( !anApp )
+  {
+    return;
+  }
+
+  SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( anApp->activeStudy() );
+  if ( !aStudy )
+  {
+    return;
+  }
+
+  // get property data to change
+  GEOMUtils_DimensionProperty aProp =
+    aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+                               myEditObject->GetStudyEntry(),
+                               GEOM::propertyName( GEOM::Dimensions ),
+                               QVariant() )
+                               .value<GEOMUtils_DimensionProperty>();
+
+  QTreeWidget* aDimensionList = myDimensionView->TreeWidget;
+
+  bool isBlocked = aDimensionList->blockSignals( true );
+
+  for ( int anIt = 0; anIt < aProp.GetNumber(); ++anIt )
+  {
+    aProp.SetVisible( anIt, false );
+  }
+
+  // store modified property data
+  aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+                             myEditObject->GetStudyEntry(),
+                             GEOM::propertyName( GEOM::Dimensions ),
+                             aProp );
+
+  PopulateList();
+
+  RedisplayObject();
+
+  aDimensionList->blockSignals( isBlocked );
+}
+
+//=================================================================================
+// function : OnInteractionFinished
+// purpose  :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnInteractionFinished( Handle(AIS_InteractiveObject) theIO )
+{
+  // update property data
+  SalomeApp_Application* anApp = myGeomGUI->getApp();
+  if ( !anApp )
+  {
+    return;
+  }
+
+  SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( anApp->activeStudy() );
+  if ( !aStudy )
+  {
+    return;
+  }
+
+  gp_Ax3 aLCS;
+  TopoDS_Shape anParentSh;
+  if ( GEOMBase::GetShape( myEditObject.get(), anParentSh ) )
+  {
+    aLCS = GEOMUtils::GetPosition( anParentSh );
+  }
+
+  int aDimensionId = IdFromPrs( theIO );
+
+  // get property data to change
+  GEOMUtils_DimensionProperty aProp =
+    aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+                               myEditObject->GetStudyEntry(),
+                               GEOM::propertyName( GEOM::Dimensions ),
+                               QVariant() )
+                               .value<GEOMUtils_DimensionProperty>();
+
+  aProp.SetRecord( aDimensionId, Handle(AIS_Dimension)::DownCast( theIO ), aLCS );
+
+  // store modified property data
+  aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+                             myEditObject->GetStudyEntry(),
+                             GEOM::propertyName( GEOM::Dimensions ),
+                             aProp );
+}
+
+//=================================================================================
+// function : Suspend
+// purpose  :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::Suspend()
+{
+  StopSelection();
+  hide();
+}
+
+//=================================================================================
+// function : Suspend
+// purpose  :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::Resume()
+{
+  this->show();
+  if ( !myEditObject.isNull() )
+  {
+    PopulateList();
+    StartSelection( Selection_Dimension );
+  }
+}
+
+//=================================================================================
+// function : ClickOnOk
+// purpose  : 
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::ClickOnOk()
+{
+  setIsApplyAndClose( true );
+  if ( ClickOnApply() )
+  {
+    ClickOnCancel();
+  }
+}
+
+//=================================================================================
+// function : ClickOnCancel
+// purpose  : 
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::ClickOnCancel()
+{
+  if ( !WarnUnsaved() )
+  {
+    return;
+  }
+
+  GEOMBase_Skeleton::ClickOnCancel();
+}
+
+//=================================================================================
+// function : ClickOnApply
+// purpose  : 
+//=================================================================================
+bool MeasureGUI_ManageDimensionsDlg::ClickOnApply()
+{
+  if ( myEditObject.isNull() )
+  {
+    return true;
+  }
+
+  SalomeApp_Application* anApp = myGeomGUI->getApp();
+  if ( !anApp )
+  {
+    return true;
+  }
+
+  SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( anApp->activeStudy() );
+  if ( !aStudy )
+  {
+    return true;
+  }
+
+  mySavedPropertyState = 
+    aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+                               myEditObject->GetStudyEntry(),
+                               GEOM::propertyName( GEOM::Dimensions ),
+                               QVariant() )
+                               .value<GEOMUtils_DimensionProperty>();
+
+  mySavedPropertyState.SaveToAttribute( aStudy, myEditObject->GetStudyEntry() );
+
+  return true;
+}
+
+//=================================================================================
+// function : OnFinish
+// purpose  : 
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::OnFinish()
+{
+  if ( myEditObject.isNull() )
+  {
+    GEOMBase_Skeleton::ClickOnCancel();
+    return;
+  }
+
+  SalomeApp_Application* anApp = myGeomGUI->getApp();
+  if ( !anApp )
+  {
+    GEOMBase_Skeleton::ClickOnCancel();
+    return;
+  }
+
+  SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( anApp->activeStudy() );
+  if ( !aStudy )
+  {
+    GEOMBase_Skeleton::ClickOnCancel();
+    return;
+  }
+
+  // reset preview property state
+  aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+                             myEditObject->GetStudyEntry(),
+                             GEOM::propertyName( GEOM::Dimensions ),
+                             QVariant() );
+
+  redisplay( myEditObject.get() );
+}
+
+//=================================================================================
+// function : SetEditObject
+// purpose  :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::SetEditObject( const GEOM::GeomObjPtr& theObj )
+{
+  RestoreState();
+
+  QString aName = GEOMBase::GetName( theObj.get() );
+
+  myObjectSelector->LineEdit1->setText( aName );
+
+  myEditObject = theObj;
+
+  if ( myEditObject.isNull() )
+  {
+    myDimensionView->setEnabled( false );
+
+    return;
+  }
+
+  SalomeApp_Application* anApp = myGeomGUI->getApp();
+  if ( !anApp )
+  {
+    return;
+  }
+
+  SUIT_ViewManager* aViewMgr = anApp->activeViewManager();
+  if ( aViewMgr->getType() != SOCC_Viewer::Type() )
+  {
+    return;
+  }
+
+  SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( anApp->activeStudy() );
+  if ( !aStudy )
+  {
+    return;
+  }
+
+  mySavedPropertyState.LoadFromAttribute( getStudy(), myEditObject->GetStudyEntry() );
+
+  // set property state for preview
+  aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+                             myEditObject->GetStudyEntry(),
+                             GEOM::propertyName( GEOM::Dimensions ),
+                             mySavedPropertyState );
+
+  PopulateList();
+
+  myDimensionView->setEnabled( true );
+}
+
+//=================================================================================
+// function : RestoreState
+// purpose  :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::RestoreState()
+{
+  if ( myEditObject.isNull() )
+  {
+    return;
+  }
+
+  SalomeApp_Application* anApp = myGeomGUI->getApp();
+  if ( !anApp )
+  {
+    return;
+  }
+
+  SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( anApp->activeStudy() );
+  if ( !aStudy )
+  {
+    return;
+  }
+
+  QString aEntry = myEditObject->GetStudyEntry();
+
+  // reset preview property state
+  aStudy->setObjectProperty( GEOM::sharedPropertiesId(),
+                             myEditObject->GetStudyEntry(),
+                             GEOM::propertyName( GEOM::Dimensions ),
+                             QVariant() );
+
+  RedisplayObject();
+}
+
+//=================================================================================
+// function : PopulateList
+// purpose  :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::PopulateList()
+{
+  QTreeWidget* aListView = myDimensionView->TreeWidget;
+
+  // clear list completely if object is null
+  if ( myEditObject.isNull() )
+  {
+    aListView->clear();
+    return;
+  }
+
+  // clear only groups data if object is ok
+  QTreeWidgetItem* aDistanceGroupItem = aListView->topLevelItem( GroupItem_Distance );
+  QTreeWidgetItem* aDiameterGroupItem = aListView->topLevelItem( GroupItem_Diameter );
+  QTreeWidgetItem* anAngleGroupItem   = aListView->topLevelItem( GroupItem_Angle );
+
+  // create group items if not exist yet
+  if ( !aDistanceGroupItem || !aDiameterGroupItem || !anAngleGroupItem )
+  {
+    aDistanceGroupItem = new QTreeWidgetItem( (QTreeWidget*)NULL, QStringList( tr( "DISTANCE_ITEM" ) ) );
+    aDiameterGroupItem = new QTreeWidgetItem( (QTreeWidget*)NULL, QStringList( tr( "DIAMETER_ITEM" ) ) );
+    anAngleGroupItem   = new QTreeWidgetItem( (QTreeWidget*)NULL, QStringList( tr( "ANGLE_ITEM" ) ) );
+
+    aListView->clear();
+
+    aListView->addTopLevelItem( aDistanceGroupItem );
+    aListView->addTopLevelItem( aDiameterGroupItem );
+    aListView->addTopLevelItem( anAngleGroupItem );
+    aListView->expandAll();
+  }
+
+  qDeleteAll( aDistanceGroupItem->takeChildren() );
+  qDeleteAll( aDiameterGroupItem->takeChildren() );
+  qDeleteAll( anAngleGroupItem->takeChildren() );
+
+  // collect all groupped items
+  QList<QTreeWidgetItem*> aDistItems;
+  QList<QTreeWidgetItem*> aDiamItems;
+  QList<QTreeWidgetItem*> anAngItems;
+
+  SalomeApp_Application* anApp = myGeomGUI->getApp();
+  if ( !anApp )
+  {
+    return;
+  }
+
+  SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( anApp->activeStudy() );
+  if ( !aStudy )
+  {
+    return;
+  }
+
+  QString aEntry = myEditObject->GetStudyEntry();
+
+  // get property data to change
+  GEOMUtils_DimensionProperty aProp =
+    aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+                               myEditObject->GetStudyEntry(),
+                               GEOM::propertyName( GEOM::Dimensions ),
+                               QVariant() )
+                               .value<GEOMUtils_DimensionProperty>();
+
+  // read dimension records from property
+  for ( int anIt = 0; anIt < aProp.GetNumber(); ++anIt )
+  {
+    QString aName  = aProp.GetName( anIt );
+    bool isVisible = aProp.IsVisible( anIt );
+    int aType      = aProp.GetType( anIt );
+
+    QTreeWidgetItem* anItem = new QTreeWidgetItem;
+    anItem->setText( 0, aName );
+    anItem->setCheckState( 0, isVisible ? Qt::Checked : Qt::Unchecked );
+    anItem->setData( 0, Qt::UserRole, anIt );
+    anItem->setFlags( Qt::ItemIsUserCheckable
+                    | Qt::ItemIsSelectable
+                    | Qt::ItemIsEditable
+                    | Qt::ItemIsEnabled );
+
+    switch ( aType )
+    {
+      case GEOMUtils_DimensionProperty::DimensionType_Length   : aDistItems << anItem; break;
+      case GEOMUtils_DimensionProperty::DimensionType_Diameter : aDiamItems << anItem; break;
+      case GEOMUtils_DimensionProperty::DimensionType_Angle    : anAngItems << anItem; break;
+    }
+  }
+
+  aDistanceGroupItem->addChildren( aDistItems );
+  aDiameterGroupItem->addChildren( aDiamItems );
+  anAngleGroupItem->addChildren( anAngItems );
+
+  aListView->setItemHidden( aDistanceGroupItem, aDistItems.isEmpty() );
+  aListView->setItemHidden( aDiameterGroupItem, aDiamItems.isEmpty() );
+  aListView->setItemHidden( anAngleGroupItem,   anAngItems.isEmpty() );
+}
+
+//=================================================================================
+// function : WarnUnsaved
+// purpose  :
+//=================================================================================
+bool MeasureGUI_ManageDimensionsDlg::WarnUnsaved()
+{
+  if ( myEditObject.isNull() )
+  {
+    return true;
+  }
+
+  SalomeApp_Application* anApp = myGeomGUI->getApp();
+  if ( !anApp )
+  {
+    return true;
+  }
+
+  SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( anApp->activeStudy() );
+  if ( !aStudy )
+  {
+    return true;
+  }
+
+  GEOMUtils_DimensionProperty aCurrentState =
+    aStudy->getObjectProperty( GEOM::sharedPropertiesId(),
+                               myEditObject->GetStudyEntry(),
+                               GEOM::propertyName( GEOM::Dimensions ),
+                               QVariant() )
+                               .value<GEOMUtils_DimensionProperty>();
+
+  if ( aCurrentState == mySavedPropertyState )
+  {
+    return true;
+  }
+
+  int aResponse = SUIT_MessageBox::warning( this,
+                                            tr( "WRN_TITLE_UNSAVED" ),
+                                            tr( "WRN_MSG_UNSAVED" ),
+                                            QMessageBox::Ok,
+                                            QMessageBox::Cancel );
+
+  return aResponse == QMessageBox::Ok;
+}
+
+//=================================================================================
+// function : IdFromItem
+// purpose  :
+//=================================================================================
+int MeasureGUI_ManageDimensionsDlg::IdFromItem( QTreeWidgetItem* theItem )
+{
+  if ( !theItem )
+  {
+    return -1;
+  }
+
+  bool isIdOK = false;
+  const int anId = theItem->data( 0, Qt::UserRole ).toInt( &isIdOK );
+
+  return isIdOK ? anId : -1;
+}
+
+//=================================================================================
+// function : IdFromPrs
+// purpose  :
+//=================================================================================
+int MeasureGUI_ManageDimensionsDlg::IdFromPrs( const Handle(AIS_InteractiveObject)& theAIS )
+{
+  Handle(SALOME_InteractiveObject) anIO = Handle(SALOME_InteractiveObject)::DownCast( theAIS->GetOwner() );
+
+  if ( anIO.IsNull() )
+  {
+    return -1;
+  }
+
+  QString anIOEntry   = anIO->getEntry();
+  QString anEditEntry = myEditObject->GetStudyEntry();
+  if ( anIOEntry != anEditEntry )
+  {
+    return -1;
+  }
+
+  Handle(GEOM_AISLength) aLength = Handle(GEOM_AISLength)::DownCast( theAIS );
+  if ( !aLength.IsNull() )
+  {
+    return aLength->GetId();
+  }
+
+  Handle(GEOM_AISDiameter) aDiameter = Handle(GEOM_AISDiameter)::DownCast( theAIS );
+  if ( !aDiameter.IsNull() )
+  {
+    return aDiameter->GetId();
+  }
+
+  Handle(GEOM_AISAngle) anAngle = Handle(GEOM_AISAngle)::DownCast( theAIS );
+  if ( !anAngle.IsNull() )
+  {
+    return anAngle->GetId();
+  }
+
+  return -1;
+}
+
+//=================================================================================
+// function : SelectInList
+// purpose  :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::SelectInList( const Handle(AIS_InteractiveObject)& theIO )
+{
+  SelectInList( IdFromPrs( theIO ) );
+}
+
+//=================================================================================
+// function : SelectInList
+// purpose  :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::SelectInList( const int theId )
+{
+  QTreeWidget* aListOfDimension = myDimensionView->TreeWidget;
+
+  QAbstractItemModel* aModel = aListOfDimension->model();
+  QModelIndexList aIndexes = aModel->match( aModel->index(0, 0),
+                                            Qt::UserRole,
+                                            QVariant( theId ),
+                                            -1, Qt::MatchRecursive );
+
+  if ( aIndexes.isEmpty() )
+  {
+    aListOfDimension->setCurrentIndex( QModelIndex() );
+    return;
+  }
+
+  bool isBlocked = aListOfDimension->blockSignals( true );
+  aListOfDimension->setCurrentIndex( aIndexes.first() );
+  aListOfDimension->blockSignals( isBlocked );
+}
+
+//=================================================================================
+// function : SelectInViewer
+// purpose  :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::SelectInViewer( SOCC_Viewer* theViewer, const int theId )
+{
+  Handle(AIS_InteractiveContext) anAISContext = theViewer->getAISContext();
+  if ( anAISContext.IsNull() )
+  {
+    return;
+  }
+
+  Standard_Boolean isLocal = anAISContext->HasOpenedContext();
+  if ( isLocal )
+  {
+    anAISContext->ClearSelected( Standard_False );
+  }
+  else
+  {
+    anAISContext->ClearCurrents( Standard_False );
+  }
+
+  SOCC_Prs* aPrs = dynamic_cast<SOCC_Prs*>( theViewer->CreatePrs( myEditObject->GetStudyEntry() ) );
+
+  AIS_ListOfInteractive aListOfIO;
+  aPrs->GetObjects( aListOfIO );
+
+  AIS_ListIteratorOfListOfInteractive anIt( aListOfIO );
+  for ( ; anIt.More(); anIt.Next() )
+  {
+    const Handle(AIS_InteractiveObject)& anIO = anIt.Value();
+    if ( IdFromPrs( anIO ) != theId )
+    {
+      if ( isLocal )
+      {
+        anAISContext->Deactivate( anIO, AIS_DSM_Line );
+        anAISContext->Deactivate( anIO, AIS_DSM_Text );
+      }
+      continue;
+    }
+
+    if ( isLocal )
+    {
+      anAISContext->AddOrRemoveSelected( anIO, Standard_False );
+      anAISContext->Activate( anIO, AIS_DSM_Line );
+      anAISContext->Activate( anIO, AIS_DSM_Text );
+    }
+    else
+    {
+      anAISContext->AddOrRemoveCurrentObject( anIO, Standard_False );
+    }
+
+    anAISContext->UpdateCurrentViewer();
+  }
+}
+
+//=================================================================================
+// function : RedisplayObject
+// purpose  :
+//=================================================================================
+void MeasureGUI_ManageDimensionsDlg::RedisplayObject()
+{
+  redisplay( myEditObject.get() );
+
+  if ( !myOperatedViewer )
+  {
+    return;
+  }
+
+  QTreeWidgetItem* aSelectedItem = myDimensionView->TreeWidget->currentItem();
+  if ( !aSelectedItem )
+  {
+    return;
+  }
+
+  StartSelection( myCurrentSelection );
+
+  SelectInViewer( myOperatedViewer, IdFromItem( aSelectedItem ) );
+}
diff --git a/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.h b/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.h
new file mode 100644 (file)
index 0000000..c6d2d70
--- /dev/null
@@ -0,0 +1,116 @@
+// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// GEOM GEOMGUI : GUI for Geometry component
+// File   : MeasureGUI_ManageDimensionsDlg.h
+// Author : Anton POLETAEV, Open CASCADE S.A.S.
+//
+#ifndef MEASUREGUI_MANAGEDIMENSIONSDLG_H
+#define MEASUREGUI_MANAGEDIMENSIONSDLG_H
+
+#include <GEOMBase_Skeleton.h>
+#include "MeasureGUI_DimensionInteractor.h"
+#include "MeasureGUI_Widgets.h"
+#include <GEOMUtils_DimensionProperty.hxx>
+
+class DlgRef_1Sel;
+class QTreeWidget;
+class QPushButton;
+class SOCC_Viewer;
+
+//=================================================================================
+// class    : MeasureGUI_ManageDimensionsDlg
+// purpose  : The dialog provides interactive management of measurement
+//            dimension presentations and the "dimension" property state of
+//            GEOM shape objects.
+//=================================================================================
+class MeasureGUI_ManageDimensionsDlg : public GEOMBase_Skeleton
+{
+  Q_OBJECT
+
+public:
+  MeasureGUI_ManageDimensionsDlg( GeometryGUI*, QWidget* );
+  ~MeasureGUI_ManageDimensionsDlg();
+
+protected:
+  enum Selection
+  {
+    Selection_None,
+    Selection_Object,
+    Selection_Dimension
+  };
+
+/* User event logics */
+protected slots:
+  void                            StartObjectSelection() { StartSelection( Selection_Object ); }
+  void                            StartSelection( const Selection theSelection );
+  void                            StopSelection();
+  void                            OnSelection();
+  void                            SelectionIntoArgument( const Selection theSelection );
+  void                            OnAdd();
+  void                            OnRemove();
+  void                            OnChangeItem( QTreeWidgetItem* theItem );
+  void                            OnSelectItem();
+  void                            OnShowAll();
+  void                            OnHideAll();
+  void                            OnInteractionFinished( Handle_AIS_InteractiveObject theIO );
+  void                            Suspend();
+  void                            Resume();
+  void                            ClickOnOk();
+  virtual void                    ClickOnCancel();
+  bool                            ClickOnApply();
+  void                            OnFinish();
+
+/* Utils */
+private:
+  void                            SetEditObject( const GEOM::GeomObjPtr& );
+  void                            RestoreState();
+  void                            PopulateList();
+  bool                            WarnUnsaved();
+  int                             IdFromItem( QTreeWidgetItem* theItem );
+  int                             IdFromPrs( const Handle(AIS_InteractiveObject)& theAIS );
+  void                            SelectInList( const Handle(AIS_InteractiveObject)& theIO );
+  void                            SelectInList( const int theId );
+  void                            SelectInViewer( SOCC_Viewer* theViewer, const int theId );
+  void                            RedisplayObject();
+
+private:
+  enum GroupItems
+  {
+    GroupItem_Distance = 0,
+    GroupItem_Diameter = 1,
+    GroupItem_Angle    = 2
+  };
+
+private:
+  GEOM::GeomObjPtr                myEditObject;
+
+private:
+  DlgRef_1Sel*                    myObjectSelector;
+  MeasureGUI_1TreeWidget_4Button* myDimensionView;
+  MeasureGUI_DimensionInteractor* myDimensionInteractor;
+  GEOMUtils_DimensionProperty     mySavedPropertyState;
+  SOCC_Viewer*                    myOperatedViewer;
+  Selection                       myCurrentSelection;
+};
+
+#endif
index c9fb4ad5c2c0dc40c82f1ea78461376cc2f0907e..de83d236a543a181a0fb85313e97f079c8e36bb0 100644 (file)
@@ -107,6 +107,34 @@ MeasureGUI_1Sel6LineEdit::~MeasureGUI_1Sel6LineEdit()
 {
 }
 
+//////////////////////////////////////////
+// MeasureGUI_1Sel_Frame
+//////////////////////////////////////////
+
+MeasureGUI_1Sel_Frame::MeasureGUI_1Sel_Frame( QWidget* parent, Qt::WindowFlags f )
+: QWidget( parent, f )
+{
+  setupUi( this );
+}
+
+MeasureGUI_1Sel_Frame::~MeasureGUI_1Sel_Frame()
+{
+}
+
+//////////////////////////////////////////
+// MeasureGUI_1TreeWidget_4Button
+//////////////////////////////////////////
+
+MeasureGUI_1TreeWidget_4Button::MeasureGUI_1TreeWidget_4Button( QWidget* parent, Qt::WindowFlags f )
+: QWidget( parent, f )
+{
+  setupUi( this );
+}
+
+MeasureGUI_1TreeWidget_4Button::~MeasureGUI_1TreeWidget_4Button()
+{
+}
+
 //////////////////////////////////////////
 // MeasureGUI_2Sel1LineEdit
 //////////////////////////////////////////
@@ -121,6 +149,35 @@ MeasureGUI_2Sel1LineEdit::~MeasureGUI_2Sel1LineEdit()
 {
 }
 
+//////////////////////////////////////////
+// MeasureGUI_2Sel_Frame
+//////////////////////////////////////////
+
+MeasureGUI_2Sel_Frame::MeasureGUI_2Sel_Frame( QWidget* parent, Qt::WindowFlags f )
+: QWidget( parent, f )
+{
+  setupUi( this );
+}
+
+MeasureGUI_2Sel_Frame::~MeasureGUI_2Sel_Frame()
+{
+}
+
+
+//////////////////////////////////////////
+// MeasureGUI_3Sel_Frame
+//////////////////////////////////////////
+
+MeasureGUI_3Sel_Frame::MeasureGUI_3Sel_Frame( QWidget* parent, Qt::WindowFlags f )
+: QWidget( parent, f )
+{
+  setupUi( this );
+}
+
+MeasureGUI_3Sel_Frame::~MeasureGUI_3Sel_Frame()
+{
+}
+
 //////////////////////////////////////////
 // MeasureGUI_SkeletonBox
 //////////////////////////////////////////
index c90e33841bb97df515a42e96f6c67ee3a3a0f3ce..b96201529aa734d9a68e0ab5aedaca5751ccd17b 100644 (file)
@@ -119,6 +119,38 @@ public:
   ~MeasureGUI_1Sel6LineEdit();
 };
 
+//////////////////////////////////////////
+// MeasureGUI_1Sel_Frame
+//////////////////////////////////////////
+
+#include "ui_MeasureGUI_1Sel_Frame_QTD.h"
+
+class MeasureGUI_1Sel_Frame : public QWidget, 
+                              public Ui::MeasureGUI_1Sel_Frame_QTD
+{
+  Q_OBJECT
+
+public:
+  MeasureGUI_1Sel_Frame( QWidget* = 0, Qt::WindowFlags = 0 );
+  ~MeasureGUI_1Sel_Frame();
+};
+
+//////////////////////////////////////////
+// MeasureGUI_1TreeWidget_4Buttons
+//////////////////////////////////////////
+
+#include "ui_MeasureGUI_1TreeWidget_4Button_QTD.h"
+
+class MeasureGUI_1TreeWidget_4Button : public QWidget,
+                                       public Ui::MeasureGUI_1TreeWidget_4Button_QTD
+{
+  Q_OBJECT
+
+public:
+  MeasureGUI_1TreeWidget_4Button( QWidget* = 0, Qt::WindowFlags = 0 );
+  ~MeasureGUI_1TreeWidget_4Button();
+};
+
 //////////////////////////////////////////
 // MeasureGUI_2Sel1LineEdit
 //////////////////////////////////////////
@@ -135,6 +167,38 @@ public:
   ~MeasureGUI_2Sel1LineEdit();
 };
 
+//////////////////////////////////////////
+// MeasureGUI_2Sel_Frame
+//////////////////////////////////////////
+
+#include "ui_MeasureGUI_2Sel_Frame_QTD.h"
+
+class MeasureGUI_2Sel_Frame : public QWidget, 
+                              public Ui::MeasureGUI_2Sel_Frame_QTD
+{
+  Q_OBJECT
+
+public:
+  MeasureGUI_2Sel_Frame( QWidget* = 0, Qt::WindowFlags = 0 );
+  ~MeasureGUI_2Sel_Frame();
+};
+
+//////////////////////////////////////////
+// MeasureGUI_3Sel_Frame
+//////////////////////////////////////////
+
+#include "ui_MeasureGUI_3Sel_Frame_QTD.h"
+
+class MeasureGUI_3Sel_Frame : public QWidget, 
+                              public Ui::MeasureGUI_3Sel_Frame_QTD
+{
+  Q_OBJECT
+
+public:
+  MeasureGUI_3Sel_Frame( QWidget* = 0, Qt::WindowFlags = 0 );
+  ~MeasureGUI_3Sel_Frame();
+};
+
 //////////////////////////////////////////
 // MeasureGUI_SkeletonBox
 //////////////////////////////////////////
index 7f8ac53dd356b0754514dd7519ed8dbd65ef8842..ea4cd46af2f55abd0732b0d9aaf52709bcb60e64 100755 (executable)
@@ -86,6 +86,7 @@ SET(OBJECT_HEADERS
   GEOM_PainterPolyDataMapper.h
   GEOM_DeviceActor.h
   GEOM_Constants.h
+  GEOM_AISDimension.hxx
   )
 # --- sources ---
 
@@ -102,6 +103,7 @@ SET(OBJECT_SOURCES
   GEOM_PainterPolyDataMapper.cxx
   GEOM_DeviceActor.cxx
   GEOM_Constants.cxx
+  GEOM_AISDimension.cxx
   )
 
 # --- rules ---
diff --git a/src/OBJECT/GEOM_AISDimension.cxx b/src/OBJECT/GEOM_AISDimension.cxx
new file mode 100755 (executable)
index 0000000..80ba581
--- /dev/null
@@ -0,0 +1,141 @@
+// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  GEOM OBJECT : interactive object for Geometry entities visualization
+//  File   : GEOM_AISDimension.cxx
+//  Module : GEOM
+
+#include "GEOM_AISDimension.hxx"
+
+IMPLEMENT_STANDARD_HANDLE (GEOM_AISLength,   AIS_LengthDimension)
+IMPLEMENT_STANDARD_RTTIEXT(GEOM_AISLength,   AIS_LengthDimension)
+IMPLEMENT_STANDARD_HANDLE (GEOM_AISDiameter, AIS_DiameterDimension)
+IMPLEMENT_STANDARD_RTTIEXT(GEOM_AISDiameter, AIS_DiameterDimension)
+IMPLEMENT_STANDARD_HANDLE (GEOM_AISAngle,    AIS_AngleDimension)
+IMPLEMENT_STANDARD_RTTIEXT(GEOM_AISAngle,    AIS_AngleDimension)
+
+/* ****************************************************************************** *
+ *                                                                                *
+ *                                GEOM_AISLength                                  *
+ *                                                                                *
+ * ****************************************************************************** */
+
+//=================================================================================
+// function : Constructor
+// purpose  : 
+//=================================================================================
+GEOM_AISLength::GEOM_AISLength( const Standard_Integer theId ) 
+: AIS_LengthDimension( gp::Origin(),
+                       gp::Origin(),
+                       gp_Pln( gp::XOY() ) ),
+  myId( theId )
+{
+}
+
+//=================================================================================
+// function : GetId
+// purpose  : 
+//=================================================================================
+Standard_Integer GEOM_AISLength::GetId() const
+{
+  return myId;
+}
+
+//=================================================================================
+// function : SetId
+// purpose  : 
+//=================================================================================
+void GEOM_AISLength::SetId( const Standard_Integer theId )
+{
+  myId = theId;
+}
+
+
+/* ****************************************************************************** *
+ *                                                                                *
+ *                              GEOM_AISDiameter                                  *
+ *                                                                                *
+ * ****************************************************************************** */
+
+//=================================================================================
+// function : Constructor
+// purpose  : 
+//=================================================================================
+GEOM_AISDiameter::GEOM_AISDiameter( const Standard_Integer theId )
+: AIS_DiameterDimension( gp_Circ() ),
+  myId( theId )
+{
+}
+
+//=================================================================================
+// function : GetId
+// purpose  : 
+//=================================================================================
+Standard_Integer GEOM_AISDiameter::GetId() const
+{
+  return myId;
+}
+
+//=================================================================================
+// function : SetId
+// purpose  : 
+//=================================================================================
+void GEOM_AISDiameter::SetId( const Standard_Integer theId )
+{
+  myId = theId;
+}
+
+/* ****************************************************************************** *
+ *                                                                                *
+ *                              GEOM_AISAngle                                     *
+ *                                                                                *
+ * ****************************************************************************** */
+
+//=================================================================================
+// function : Constructor
+// purpose  : 
+//=================================================================================
+GEOM_AISAngle::GEOM_AISAngle( const Standard_Integer theId ) 
+: AIS_AngleDimension( gp::Origin(),
+                      gp::Origin(),
+                      gp::Origin() ),
+  myId( theId )
+{
+}
+
+//=================================================================================
+// function : GetId
+// purpose  : 
+//=================================================================================
+Standard_Integer GEOM_AISAngle::GetId() const
+{
+  return myId;
+}
+
+//=================================================================================
+// function : SetId
+// purpose  : 
+//=================================================================================
+void GEOM_AISAngle::SetId( const Standard_Integer theId )
+{
+  myId = theId;
+}
diff --git a/src/OBJECT/GEOM_AISDimension.hxx b/src/OBJECT/GEOM_AISDimension.hxx
new file mode 100755 (executable)
index 0000000..e85fe5e
--- /dev/null
@@ -0,0 +1,92 @@
+// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  GEOM OBJECT : interactive object for Geometry entities visualization
+//  File   : GEOM_AISDimension.hxx
+//  Module : GEOM
+//
+#ifndef GEOM_AISDimension_HeaderFile
+#define GEOM_AISDimension_HeaderFile
+
+#include <AIS_LengthDimension.hxx>
+#include <AIS_DiameterDimension.hxx>
+#include <AIS_AngleDimension.hxx>
+
+DEFINE_STANDARD_HANDLE(GEOM_AISLength,   AIS_LengthDimension)
+DEFINE_STANDARD_HANDLE(GEOM_AISDiameter, AIS_DiameterDimension)
+DEFINE_STANDARD_HANDLE(GEOM_AISAngle,    AIS_AngleDimension)
+
+//=================================================================================
+// class    : GEOM_AISLength
+// purpose  : presentation of length dimension property
+//=================================================================================
+class GEOM_AISLength : public AIS_LengthDimension
+{
+public:
+  DEFINE_STANDARD_RTTI(GEOM_AISLength)
+
+public:
+  Standard_EXPORT                    GEOM_AISLength( const Standard_Integer theId );
+  Standard_EXPORT  Standard_Integer  GetId() const;
+  Standard_EXPORT  void              SetId( const Standard_Integer theId );
+
+private:
+  Standard_Integer                   myId;
+};
+
+//=================================================================================
+// class    : GEOM_AISDiameter
+// purpose  : presentation of diameter dimension property
+//=================================================================================
+class GEOM_AISDiameter : public AIS_DiameterDimension
+{
+public:
+  DEFINE_STANDARD_RTTI(GEOM_AISDiameter)
+
+public:
+  Standard_EXPORT                     GEOM_AISDiameter( const Standard_Integer theId );
+  Standard_EXPORT  Standard_Integer   GetId() const;
+  Standard_EXPORT  void               SetId( const Standard_Integer theId );
+
+private:
+  Standard_Integer                    myId;
+};
+
+//=================================================================================
+// class    : GEOM_AISAngle
+// purpose  : presentation of angle dimension property
+//=================================================================================
+class GEOM_AISAngle : public AIS_AngleDimension
+{
+public:
+  DEFINE_STANDARD_RTTI(GEOM_AISAngle)
+
+public:
+  Standard_EXPORT                     GEOM_AISAngle( const Standard_Integer theId );
+  Standard_EXPORT  Standard_Integer   GetId() const;
+  Standard_EXPORT  void               SetId( const Standard_Integer theId );
+
+private:
+  Standard_Integer                    myId;
+};
+
+#endif
index 95a5840c2c7ae5717322aa479a8216e630bd3b16..0afd2f258e92029a3011ad51dc15093cd90be3e5 100644 (file)
@@ -95,8 +95,17 @@ namespace GEOM
       "IsosColor",       // -
       // outlines color
       "OutlineColor",    // -
+      // dimensions
+      "Dimensions"
     };
     return ( type >= GEOM::Visibility && type <= GEOM::LastProperty ) ? names[type] : QString();
   }
 
+  /*!
+    \brief Id used for storing properties of objects in study shared between viewers.
+  */
+  int sharedPropertiesId()
+  {
+    return INT_MIN;
+  }
 } // namespace GEOM
index 19b0c514fc4ba5989c5ae9b7621f0d0743d7463f..c166e3a0dcc914dd9e86d0f03bdcac77f7d35f2f 100644 (file)
@@ -54,7 +54,8 @@ namespace GEOM
     PointColor,
     IsosColor,
     OutlineColor,
-    LastProperty = OutlineColor,
+    Dimensions,
+    LastProperty = Dimensions,
   };
 
   GEOM_OBJECT_EXPORT double minDeflection();
@@ -63,6 +64,8 @@ namespace GEOM
   GEOM_OBJECT_EXPORT QString subSectionSeparator();
 
   GEOM_OBJECT_EXPORT QString propertyName( Property );
+
+  GEOM_OBJECT_EXPORT int sharedPropertiesId();
 }